TShellListView で複数ファイルのプロパティ参照や「送る」

解決


けど  2010-06-19 23:14:48  No: 38694

Delphi2009 TShellListView でプロパティ参照や「送る」を使った時
複数ファイルを選択していてもフォーカスのあるファイルしか送ら
れないので修正したいのです

そーすでは TCustomListView.Selected.Index で「リストで選択され
ている最初の項目」しか送っていないようで、

TShellFolderList =  array of TShellFolder;
とか定義して
function TCustomShellListView.GetSelectedFolders: TShellFolderList;
var
  i,Index:integer;
begin
  SetLength(Result,SelCount);
  Index:=0;
  for i:=0 to Items.Count-1 do
  begin
    if i>SelCount then Break;
    if Items[i].Selected then
    begin
      FFolders[Index]:=TShellFolder(Folders[i]);
      Inc(Index);
    end;
  end;
end;
とかして DoContextMenuVerb に放り込もうとしたのですがどうにも
根本的に間違っているようで(Interface の知識がない)うまくいきません

どなたかこのあたりを修正されている方はおられませんでしょうか?
どうかよろしくお願いします


monaa  2010-06-20 00:41:17  No: 38695

試しに、TShellListViewをインストールしたら
そもそもこのコンポーネント私の環境では右クリックでフリーズします。
原因究明まで頑張る元気はないです。
とりあえず報告。
Windows7 64bit + Delphi2009

TShellListViewのインストール方法
http://www.ipentec.com/document/document.aspx?page=delphi2007-shell


けど  2010-06-20 01:02:11  No: 38696

monaa さんありがとうございます
多分に Demo フォルダは放置プレイされてますから困りものです

Vista + vsIcon で複数選択での枠線の色のこりという問題もあるんですが
ListView だとOKなんでバーチャル化と XPMan あたりの相性かもしれません

また、ファイルのWクリックで Hidden になってしまうバグ
procedure TCustomShellListView.DblClick;
……
      else
{        ShellExecute(Handle, nil, PChar(PathName), nil,
          PChar(ExtractFilePath(PathName)), 0);}
        SelectedFolder.ExecuteDefault;


tor  2010-06-21 20:43:50  No: 38697

まず、提示されたGetSelectedFoldersのコードで
> if i>SelCount then Break;
この行が不要なのと
> FFolders[Index]:=TShellFolder(Folders[i]);
は Result[Index] に代入しないといけませんね。

で、取得した複数のファイルのPIDLを配列に詰めてGetUIObjectOfに渡してやれば、複数ファイルに対するIContextMenuが得られます。
GetUIObjectOfの第2引数はファイル・フォルダの個数で、第3引数はPIDLの配列のアドレスです。
ただ、Delphi側ではこの引数をポインタでなくvarで宣言しているので少しややこしいです。たぶんこんな感じ。
procedure DoContextMenuVerbMulti(const Folders: TShellFolderList; Verb: PChar);
var
  aPIDL: packed array of PItemIDList; // ITEMIDLISTへのポインタの配列
  i, count: Integer;
  ...
begin
  // Folders[]の中身をPIDLの配列に詰め直す
  count := Length(Folders);
  if count = 0 then Exit;
  SetLength(aPIDL, count);
  for i := Low(Folders) to High(Folders) do aPIDL[i] := Folders[i].RelativeID;
  // 配列の先頭を渡してIContextMenuを取得
  Folders[0].ParentShellFolder.GetUIObjectOf(0, count, aPIDL[0], IID_IContextMenu, nil, CM);
  ... 後はDoContextMenuVerbと同じ ...
end;


けど  2010-06-22 08:43:21  No: 38698

tor さんありがとうございます
SelCount の一文はファイル数が数千となった時には有効かと思い入れていました。不要なんですね
Result[Index] は私が馬鹿でしたorz

ご呈示いただいたコードで明日確認してみますm(_ _)m


けど  2010-06-23 03:26:42  No: 38699

tor さんのコードで解決しました
TCustomShellListView.DoContextPopup 内部からの
procedure InvokeContextMenu でも同様の処理をしました

↑の
> if i>SelCount then Break;
これは
if Index>SelCount then Break;
でした
ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加