Tutorial: Adding Controls to CFileDialog in Vista

Posted by Matt | Filed under , , ,

Download Project: VistaFileOpenSample.zip (68.88 kb)

You may have noticed that after you've migrated your application to Visual Studio 2008 from Visual Studio 2005 or earlier, that your application has this great new File Open dialog on Vista.  However, you soon notice that your custom template was not added to the dialog like it was with the old compiler.

As it turns out, if your application uses CFileDialog, moving to the new compiler automatically converted your File Open dialog on Vista to the new Vista-Style dialog.  This is because Microsoft added a new default parameter to the CFileDialog contructor:  bVistaStyle = TRUE.

On Vista, if bVistaStyle is TRUE, then CFileDialog will attempt to use the IFileDialog COM interface behind the scenes.  You don't have to lift a finger to take advantage of it.  However, if you're File Open dialog has a custom template, then you need to do 1 of 2 things:

  1. Deliberately set bVistaStyle to FALSE in the constructor.  This will totally disable the Vista dialogs on Vista, but you'll get your custom template back, or
  2. Detect when CFileDialog is using the Vista COM objects and add your custom controls using that system.

This article will show you how to do #2.

Once you have your CFileDialog created, call CFileDialog::GetIFileOpenDialog() to get the COM interface.

CFileDialog dlg(TRUE);
IFileOpenDialog *p = dlg.GetIFileOpenDialog();

Test p against NULL.  If p is NULL, then either (a) you're not on Vista, or (b) the COM object cannot be created.  I've had the latter happen to be before when I was initializing COM like this:

CoInitializeEx(NULL,COINIT_MULTITHREADED);

CFileDialog didn't like it, so I had to change it to:

CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);

Anyways, back to the topic at hand.  If p is not NULL, then you can query the IFileDialogCustomize interface against p.

IFileDialogCustomize *pC = NULL;
HRESULT hr = p->QueryInterface(
    __uuidof(IFileDialogCustomize), 
    (LPVOID*)&pC);

Once you have this interface, you can add all the controls you want.

The full interface is described here.  But below are some examples.

To add a checkbox to the dialog:

HRESULT hr = pCustomize->AddCheckButton(107, L"Read-only", FALSE);

To add a combobox to the dialog and fill it with some choices:

HRESULT hr = pCustomize->AddComboBox(101);
hr = pCustomize->AddControlItem(101, 0, L"Choice A");
hr = pCustomize->AddControlItem(101, 1, L"Choice B");
hr = pCustomize->SetSelectedControlItem(101, 0);

To add a button to the bottom of the dialog (next to "Open" and "Cancel"):

HRESULT hr = pCustomize->AddPushButton(106, L"Another button");
hr = pCustomize->MakeProminent(106);

You can only have one "prominent" control.

After you have added all of your controls, call CFileDialog::DoModal() like you normally would.

Some additional notes:

  • You cannot control the layout or sizes of the controls.  You can control the order in which they appear on the dialog, but not where they appear.  This is because they move around as the dialog is resized.
  • You can use IFileDialogCustomize::StartVisualGroup() and IFileDialogCustomize::EndVisualGroup() to group controls together so as they move around, they are moved together.

Responding to control events requires creating a class derived from IFileDialogControlEvents and passing a reference to this class to IFileDialog::Advise().

To handle a button click, you could have the following in your IFileDialogControlEvents-derived class:

virtual HRESULT STDMETHODCALLTYPE OnButtonClicked(
    /* [in] */ __RPC__in_opt IFileDialogCustomize *pfdc,
    /* [in] */ DWORD dwIDCtl)
{
    if (dwIDCtl == 102)
    {
        CWnd *pWnd = CWnd::FromHandle(GetHwnd());
        CSettingsDialog dlg(pWnd);
        dlg.DoModal();
    }

    return S_OK;
}

where dwIDCtl will match the id of the control you created (the id parameter to AddPushButton());

A sample project can be downloaded at the top of this article.

If you have additional questions, please let me know.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading