share
Stack OverflowAdd a IFileDialogCustomize PushButton Event
[+3] [2] Bill
[2012-06-04 21:55:28]
[ delphi ]
[ https://stackoverflow.com/questions/10888934/add-a-ifiledialogcustomize-pushbutton-event ]

I can create a Pushbutton with FileSaveDialog1.Dialog.QueryInterface as shown below. How do you setup and handle the OnPushButton click event so I can respond to the button click?

procedure TForm1.FileSaveDialog1Execute(Sender: TObject);
const
  dwVisualGroup1ID: DWORD = 1900;
var
  c: IFileDialogCustomize;
  d: IFileDialogControlEvents;
begin
  if FileSaveDialog1.Dialog.QueryInterface(IFileDialogCustomize, c) = S_OK then
  begin
    // Add a Advanced Button
    c.AddPushButton(dwVisualGroup1ID, 'Advanced');
    c.MakeProminent(dwVisualGroup1ID);
    // Setup the PushButton Click event?

  end;
[+9] [2012-06-04 23:09:48] Remy Lebeau [ACCEPTED]

The following works fine for me in XE2:

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; 

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;

.

var
  FileDialog: IFileDialog = nil;
  MyEvents: IFileDialogEvents = nil; 
  MyEventsCookie: DWORD = 0;

procedure TForm1.FileSaveDialog1Execute(Sender: TObject); 
var 
  c: IFileDialogCustomize; 
  d: IFileDialogEvents; 
  cookie: DWORD;
begin 
  if Supports(FileSaveDialog1.Dialog, IFileDialogCustomize, c) then 
  begin 
    // Add a Advanced Button 
    c.AddPushButton(dwVisualGroup1ID, 'Advanced'); 
    c.MakeProminent(dwVisualGroup1ID); 

    // Setup the PushButton Click event 
    d := TMyFileDialogEvents.Create; 
    if Succeeded(FileSaveDialog1.Dialog.Advise(d, cookie)) then
    begin
      FileDialog := FileSaveDialog1.Dialog
      MyEvents := d;
      MyEventsCookie := cookie;
    end;
  end; 
end;

procedure TForm1.Button1Click(Sender: TObject); 
var
  Ok: Boolean;
begin
  FileDialog := nil;
  MyEvents := nil; 
  MyEventsCookie := 0;

  try
    Ok := FileSaveDialog1.Execute;
  finally
    if (FileDialog <> nil) and (MyEventsCookie <> 0) then
      FileDialog.Unadvise(MyEventsCookie);
    FileDialog := nil;
    MyEvents := nil; 
    MyEventsCookie := 0;
  end;

  if Ok then ...
end;

Thank-you .. the event is executing nicely. Should I call FileSaveDialog1.Dialog.Unadvise()? - Bill
Microsoft does say you are supposed to call Unadvise(). However, to do that with TFileSaveDialog, you have to save a reference to the TFileSaveDialog.Dialog interface in your OnExecute event so the dialog does not get freed when Execute() exits. Then you can Unadvise() your handler and release your reference to finish freeing the dialog. I will update my answer to show that. - Remy Lebeau
@MasonWheeler I can't imagine why I wrote that. The documentation is clear. I removed the comment. - David Heffernan
1
[+2] [2012-06-04 22:06:02] David Heffernan

You need to implement IFileDialogControlEvents. Then call IFileDialog.Advise passing your IFileDialogControlEvents interface. Your IFileDialogControlEvents.OnButtonClicked method will be called when the button is clicked.


(2) No I cannot. You can do the rest yourself. At this point you have all you need. You now know all the relevant interfaces and methods. Use MSDN docs to fill in the details. - David Heffernan
How Do you setup the event class? type TTestEvent = class(TInterfacedObject, IFileDialogEvents, IFileDialogControlEvents) function OnButtonClicked(pfdc: cardinal; dwIDCtl: cardinal): HResult; - Bill
2