I have the following code (extract) to display Save As dialog:
char FileName[MAX_PATH] = "TestImage.jpg"
...
lpofn.lStructSize = sizeof(OPENFILENAME);
lpofn.hwndOwner = hWnd;
lpofn.hInstance = GetWindowInstance (hWnd);
lpofn.lpstrFilter = "JPG - JPEG File\0*.JPG\0TIF - TIFF File\0*.TIF\0PNG File\0*.PNG\0BMP - Bitmat File\0*.BMP\0";
lpofn.lpstrCustomFilter = NULL;
lpofn.nMaxCustFilter = NULL;
lpofn.nFilterIndex = 0;
lpofn.lpstrFile = FileName;
lpofn.nMaxFile = MAX_PATH;
lpofn.lpstrFileTitle = NULL;
lpofn.nMaxFileTitle = NULL;
lpofn.lpstrInitialDir = NULL;
lpofn.lpstrTitle = NULL;
lpofn.Flags = OFN_HIDEREADONLY | OFN_ENABLEHOOK | OFN_EXPLORER;
lpofn.nFileOffset = 0;
lpofn.nFileExtension = 0;
lpofn.lpstrDefExt = NULL;
lpofn.lCustData = NULL;
lpofn.lpfnHook = &UpdateFilename;
lpofn.lpTemplateName = NULL;
if(!GetSaveFileName(&lpofn)) return;
...
eg. - User does save as, default File name = "TestImage.jpg", default Files of Type = JPG - User changes Files of Type to PNG, File name control remains at "TestImage.jpg" instead of changing to "TestImage.png"
Am I doing something wrong? Is it possible to instruct GetSaveFileName() to change the extension, or do I have to have a custom save as dialog (any examples?)
I'm using Win32 API, VC6.
Update: here is the Hook function:
UINT CALLBACK UpdateFilename(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
switch (uiMsg)
{
case WM_NOTIFY:
// Check for CDN_TYPECHANGE etc
return FALSE;
}
return FALSE;
}
Note that the hook function does stop on breakpoints. I've purposely not proceeded further with handling CDN_TYPECHANGE until I can figure out why the look of the dialog changes when the hook is enabled and how to fix it.
In order to update the dialog while it is still running, you need to provide a pointer to an
lpfnHook
callback in theOPENFILENAME
struct, and have the callback handle theCDN_TYPECHANGE
notification. It can send the dialog aCDM_GETFILEPATH
orCDM_GETSPEC
message to get the current filename, tweak it as needed, and then send aCDM_SETCONTROLTEXT
message to update the edit field (the ID of the filename edit field is0x442
) with the new value.Update: There is nothing wrong with your hook code.
GetSaveFileName()
is deprecated starting in Windows Vista, replaced by (and becoming a wrapper around) the Common Item Dialog. The GSFN dialog UI is not altered by a hook in XP, so you must be using Vista+, in which case enabling the hook simply causes the wrapper to use different settings when invoking the CID internally. A lot of the new CID features are based onIShellItem
, not filename strings, so the wrapper removes anything that cannot be represented as a old-style filename, and makes the dialog look like the old-style GSFN dialog in XP and earlier. So what you are seeing is normal behavior forGetSaveFileName()
under Vista+! If you do not like it, then do not useGetSaveFileName()
anymore. Use the newIFileSaveDialog
interface instead. In fact, it natively changes the file extension for you if you configure multiple file types, designate one of them as the default extension, and then set an initial filename that matches the default extension. But if you wanted to, you can alternatively implement theIFileDialogEvents
interface in your code to receiveOnTypeChange
notifications and then use theIFileDialog::SetFileName()
method to update the displayed filename as neded.Use a buffer for your suggested file name, not a static string.
Besides that, it is a default Windows behaviour going well back to Win95 days. As you are using VS6.0, you stil have these DLLs. What I did then was to use:
That prevents any extension from being added. I then checked lpofn.nFileExtension upon return to find out which extension was selected.