1

1、という名前のポップアップメニューを追加しますPopupMenu1

2、という名前のメニュー項目を追加しますTestMI

3、ボタンを追加

とコード:

procedure TForm1.Button1Click(Sender: TObject);
var
  MItems: array of TMenuItem;
  SList: TStringList;
  FileRec: TSearchrec;
  i: integer;
begin

  SList := TStringList.Create;
 //3000+ files 
  if FindFirst('C:\Windows\System32\*', faNormal or faDirectory, FileRec) = 0
    then
    repeat
      if (FileRec.Name = '.') or (FileRec.Name = '..') then
        Continue;

      SList.Add(FileRec.Name);

    until FindNext(FileRec) <> 0;
  FindClose(FileRec);

  if SList.Count > 0 then
  begin
    SetLength(MItems, SList.Count);
    for i := 0 to SList.Count - 1 do
    begin

      MItems[i] := TMenuItem.Create(TestMI);
      MItems[i].Caption := SList[i];

    end;

    TestMI.Add(MItems);

  end;
end;

ボタンをクリックするとOKですが、ポップアップ PopupMenu1して次に進むと TestMI、ファイルが多すぎるため応答しません。

それを解決する方法はありますか?

アップデータ:

これを行うには、PopupMenuを使用する必要があります。

私はプログラムを見つけました、それを速くすることができます、150msかかります

https://docs.google.com/open?id=0B1sDNMAzGE2oZWpTWlpWNHJGZzQ

BarMenuコンポーネントを使用します

しかし、Delphi 2009ではコンパイルできません。エラー:

lib \ BarMenus:

{$IFDEF MSWINDOWS}
  {$IFNDEF DFS_COMPILER_5_UP}
     {$MESSAGE FATAL 'You need Delphi 5 or higher in order to compile this unit.'}
  {$ENDIF}
  Windows, SysUtils, Classes, Graphics, Menus, Forms;
{$ENDIF}

@SertacAkyuzに更新

最初のケースでは、ソリューションが役立ちます。どうもありがとうございました。そして私はそのケースコードを変更します:

unit Unit1;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  StdCtrls,
  Menus;

type
  TForm1 = class(TForm)
    Button1: TButton;
    PopupMenu1: TPopupMenu;
    TestMI: TMenuItem;
    procedure Button1Click(Sender: TObject);
    procedure CreMI(MI: TMenuItem);
    procedure IMonClick(Sender: TObject);
    procedure AddSubEmpItem(MI: TMenuItem);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.IMonClick(Sender: TObject);
begin

  CreMI(TMenuItem(Sender));

end;

procedure TForm1.AddSubEmpItem(MI: TMenuItem);
var
  EmpIM: TMenuItem;
begin

  EmpIM := TMenuItem.Create(MI);
  with EmpIM do
  begin
    Caption := '(Folder empty)';
    Enabled := False;
    Hint := '';
    MI.Add(EmpIM);
  end;

end;

procedure TForm1.CreMI(MI: TMenuItem);
var
  MItems: array of TMenuItem;
  SList: TStringList;
  FileRec: TSearchrec;
  i: integer;
begin

  if (MI.Items[0].Caption = '(Folder empty)') and (MI.Count = 1) then
  begin

    SList := TStringList.Create;

    if FindFirst(MI.Hint + '\*', faNormal or faDirectory, FileRec) = 0
      then
      repeat
        if (FileRec.Name = '.') or (FileRec.Name = '..') then
          Continue;

        SList.Add(FileRec.Name);

      until FindNext(FileRec) <> 0;

    FindClose(FileRec);

    if SList.Count > 0 then
    begin

      SetLength(MItems, SList.Count);
      for i := 0 to SList.Count - 1 do
      begin

        MItems[i] := TMenuItem.Create(MI);
        MItems[i].Caption := SList[i];
        MItems[i].Hint := MI.Hint + SList[i] + PathDelim;
        AddSubEmpItem(MItems[i]);
        MItems[i].OnClick := IMonClick;
        MItems[i].AutoHotkeys := maManual;

      end;

      MI.Add(MItems);
      MI.AutoHotkeys := maManual;

    end;
  end;
  //Button1.Caption := IntToStr(MI.Count);

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

  AddSubEmpItem(TestMI);
  CreMI(TestMI);


end;

end.

セットするTestMI.Hint := C:\

ボタンをクリックすると、ボタンをクリックしC:\ -> Windows -> System32 ても応答しません。アドバイスをいただけますか?

4

3 に答える 3

3

簡単なテストでは、 で費やされた時間が示されInternalRethinkHotkeysます。ホット キーは、3000 項目を超えるメニューでは役に立ちません。無効にするだけです:

    ..
    TestMI.Add(MItems);
    TestMI.AutoHotkeys := maManual; // <--

  end;
end;

そうは言っても、リスト ボックスなどの他の GUI 要素を使用することも検討してください。メニュー内の多くの項目をスクロールすることは事実上不可能です。

于 2012-10-29T14:28:51.390 に答える
0

あなたが言った:

ボタンをクリックするとOKです

したがって、ファイル検索は迅速であり、メニューオプションが迅速に追加されるため、バックグラウンドスレッドで問題を解決することはできないと思います。あなたの問題は、何千ものエントリをメニューに詰め込んでいることですが、それは機能しません。あなたは再考する必要があります。たぶんリストボックスの方がいいでしょう。必ずBeginUpdate/EndUpdateを使用してループを囲んでください。

于 2012-10-29T14:33:52.187 に答える
0

まず、100万個のアイテムを含むメニューを作成するのはばかげていることを知っているほど賢いと仮定しましょう。すべてのコメント投稿者が言うように、あなたのアイデアはそうではないので、これを技術的な問題について話し合う機会として取り上げましょう。実行可能ですが、実際のプログラムでは、コンピューター上のフォルダーにのみ単語文書のリストを作成するため、説明のためにWindowsフォルダーを選択しました。それでは次に進みましょう:

初心者のDelphiプログラマーはおそらくApplication.ProcessMessagesそこに呼び出しを挿入しますが、アプリケーションは「応答しない」と表示されませんが、残りの部分で何が起こっているかに応じて、悪いことが起こる可能性があります(クラッシュを含む)。応用。これが使い捨てプログラムの場合、「Application.ProcessMessages」呼び出しを追加したくなるだけで(ループ全体で100回程度)、アプリに「応答なし」と表示されません。

ただし、実際の安定した本番コード環境では、UI構築コード(ビュービルダー)をバックグラウンドワーカースレッドから分離する必要があります。

また、バックグラウンドスレッドからアクセスすることを想定していないVCLクラスを使用してメニューを効果的に構築しているため、ワーカースレッドの実装も簡単ではありません。100,000個のアイテムを含むポップアップメニューを本当に生成したい場合、それを実行するための優れた高速な方法はありません。

オブジェクト指向の設計について考える必要があることをお勧めします。

  1. 作成するアイテムのリストの大きさに制限があるワーカースレッド。
  2. ワーカースレッドがFindFirstループを完了し、メニューアイテムの作成に移ったら、TThread.Synchronize()またはその他の安全な手段を使用して、バックグラウンドスレッドから呼び出されるメニューアイテムを追加するメソッドが安全に実行できることを確認することを検討してください。

この質問の更新編集により、この回答はかなり古くなっています。悲しいことに、問題は動く標的です。

于 2012-10-29T14:25:54.517 に答える