返回使用IFileDialogCustomize.EnableOpenDropDown时选择的DropDown项

时间:2013-11-04 11:06:45

标签: delphi

我正在打开Common文件打开对话框,打开按钮上的“打开”和“打开只读”选项。

我已经按照......中的例子了。

Add a IFileDialogCustomize PushButton Event

(下面转载的大部分代码来自Remy Lebeau的回答)

...和...的MSDN信息

http://msdn.microsoft.com/en-us/library/windows/desktop/bb776913(v=vs.85).aspx#OnFileOk

该对话框有效,但我找不到的是如何确定哪个下拉菜单打开所选用户。

    (* this is skeleton implementation of the interfaces *)
    type
      TMyFileDialogEvents = class(TInterfacedObject, IFileDialogEvents, IFileDialogControlEvents)
      public
        { IFileDialogEvents }
        function OnFileOk(const pfd: IFileDialog): HResult; stdcall;
        function OnFolderChanging(const pfd: IFileDialog; const psiFolder: IShellItem): HResult; stdcall;
        function OnFolderChange(const pfd: IFileDialog): HResult; stdcall;
        function OnSelectionChange(const pfd: IFileDialog): HResult; stdcall;
        function OnShareViolation(const pfd: IFileDialog; const psi: IShellItem;  out pResponse: DWORD): HResult; stdcall;
        function OnTypeChange(const pfd: IFileDialog): HResult; stdcall;
        function OnOverwrite(const pfd: IFileDialog; const psi: IShellItem; out pResponse: DWORD): HResult; stdcall;
        { IFileDialogControlEvents }
        function OnItemSelected(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD; dwIDItem: DWORD): HResult; stdcall;
        function OnButtonClicked(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD): HResult; stdcall;
        function OnCheckButtonToggled(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD; bChecked: BOOL): HResult; stdcall;
        function OnControlActivating(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD): HResult; stdcall;
      end;

    const
      dwVisualGroup1ID: DWORD = 1900;

    implementation

    function TMyFileDialogEvents.OnFileOk(const pfd: IFileDialog): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnFolderChange(const pfd: IFileDialog): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnFolderChanging(const pfd: IFileDialog;
      const psiFolder: IShellItem): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnOverwrite(const pfd: IFileDialog;
      const psi: IShellItem; out pResponse: DWORD): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnSelectionChange(const pfd: IFileDialog): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnShareViolation(const pfd: IFileDialog;
      const psi: IShellItem; out pResponse: DWORD): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnTypeChange(const pfd: IFileDialog): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnItemSelected(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD; dwIDItem: DWORD): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnButtonClicked(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD): HResult;
    begin
      if dwIDCtl = dwVisualGroup1ID then begin
        // ...
        Result := S_OK;
      end else begin
        Result := E_NOTIMPL;
      end;
    end;

    function TMyFileDialogEvents.OnCheckButtonToggled(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD; bChecked: BOOL): HResult;
    begin
      Result := E_NOTIMPL;
    end;

    function TMyFileDialogEvents.OnControlActivating(const pfdc: IFileDialogCustomize; dwIDCtl: DWORD): HResult;
    begin
      Result := E_NOTIMPL;
    end;
    end.

我在每个方法上都加了断点,一旦用户选择“Open read-only”,我只看到FileOpenOK方法调用。

    (* This is the test code hooking up the dialog *)
    procedure TForm1.Button1Click(Sender: TObject);
    var       Ok: Boolean;
    begin
         FileDialog := nil;
         MyEvents := nil;
         MyEventsCookie := 0;
         try
            Ok := FileOpenDialog1.Execute;
         finally
            if (FileDialog <> nil) and (MyEventsCookie <> 0)
             then FileDialog.Unadvise(MyEventsCookie);
            FileDialog := nil;
            MyEvents := nil;
            MyEventsCookie := 0;
         end;
         if OK
          then ; // open the file
    end;

    procedure TForm1.FileOpenDialog1Execute(Sender: TObject);
    var       c: IFileDialogCustomize;
              d: IFileDialogEvents;
              cookie: DWORD;
    begin
         if Supports(FileOpenDialog1.Dialog, IFileDialogCustomize, c)
          then begin
               c.EnableOpenDropDown(0);
               c.AddControlItem(0,0,'&Open');
               c.AddControlItem(0,1,'Open &read-only');
               d:= TMyFileDialogEvents.Create;
               if Succeeded(FileOpenDialog1.Dialog.Advise(d, cookie))
                then begin
                     FileDialog := FileOpenDialog1.Dialog;
                     MyEvents := d;
                     MyEventsCookie := cookie;
                end;
        end;
    end;

特别喜欢(不是)MSDN示例建议如何使用与ComboBox相同的机制,并且在ComboBox示例中将代码留下 “完整”样本包括EnableOpenDropDown! ;)

1 个答案:

答案 0 :(得分:1)

查看EnableOpenDropDown的原型:

HRESULT EnableOpenDropDown(
  [in]  DWORD dwIDCtl
);

您传入的参数是下拉按钮的ID。然后,在添加项目时重新使用该ID:

HRESULT AddControlItem(
  [in]  DWORD dwIDCtl,
  [in]  DWORD dwIDItem,
  [in]  LPCWSTR pszLabel
);

因此,在您的情况下,当您致电0时,您dwIDCtl已通过EnableOpenDropDown。然后,在添加两个项目时,使用与AddControlItem的第一个参数相同的值。这两个项的ID为01

要确定对话框关闭时选择了哪一个,请拨打GetSelectedControlItem

HRESULT GetSelectedControlItem(
  [in]   DWORD dwIDCtl,
  [out]  DWORD *pdwIDItem
);

您需要传递0 dwIDCtl以确定您的下拉列表。选定的控制项目通过pdwIDItem返回。

假设您使用的是来自IFileDialogCustomize的{​​{1}}声明,那么您的代码将如下所示:

Winapi.ShlObj

您可能需要考虑为这些ID声明一些常量,而不是依赖于魔术文字值。

如果您需要在显示对话框之前设置所选的下拉项,请使用var fdc: IFileDialogCustomize; dwIDItem: DWORD; .... // this code executes after the call to IFileDialog.Show returns OleCheck(fdc.GetSelectedControlItem(0, dwIDItem)); // dwIDItem will be 0 for Open and 1 for Open read-only