2

我在打开按钮上带有“打开”和“打开只读”选项的通用文件打开对话框之后。

我已经按照...中的示例进行了操作

添加 IFileDialogCustomize PushButton 事件

(下面转载的大部分代码来自 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.

我在每个方法上都设置了断点,一旦用户选择“以只读方式打开”,我只看到 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!;)

4

1 回答 1

1

查看原型EnableOpenDropDown

HRESULT EnableOpenDropDown(
  [in]  DWORD dwIDCtl
);

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

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

所以,在你的情况下,当你打电话时你通过0了。然后,您在添加这两个项目时使用了与第一个参数相同的值。这两个项目的 ID 为和。dwIDCtlEnableOpenDropDownAddControlItem01

要找出在关闭对话框时选择了哪一个,请调用GetSelectedControlItem

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

您需要传入0fordwIDCtl以识别您的下拉菜单。选定的控制项通过 回来pdwIDItem

假设您正在使用IFileDialogCustomizefrom的声明,Winapi.ShlObj那么您的代码将如下所示:

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

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

如果您需要在显示对话框之前设置选定的下拉项,请使用SetSelectedControlItem.

于 2013-11-04T11:17:18.150 回答