我有以下代码(摘录)来显示另存为对话框:
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;
...
例如。 - 用户确实保存为默认文件名=“TestImage.jpg”,默认文件类型= JPG - 用户将文件类型更改为PNG,文件名控件保留在“TestImage.jpg”而不是更改为“TestImage.png”
我做错了吗?是否可以指示GetSaveFileName()更改扩展名,或者我是否必须将自定义另存为对话框(任何示例?)
我正在使用Win32 API,VC6。
更新:这里是Hook功能:
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;
}
请注意,钩子函数在断点处停止。我故意不再继续处理CDN_TYPECHANGE,直到我能弄明白为什么在启用钩子时对话框的外观会发生变化以及如何修复它。
答案 0 :(得分:2)
为建议的文件名使用缓冲区,而不是静态字符串。
char szFile[MAX_PATH];
szFile[0] = '\0';
lpofn.lpstrFile= szFile;
lpofn.nMaxFile = sizeof(szFile)/ sizeof(*szFile);
除此之外,这是一个默认的Windows行为,可以追溯到Win95天。当您使用VS6.0时,您仍然拥有这些DLL。我当时做的是使用:
lpofn.lpstrDefExt = (LPSTR)NULL
这可以防止添加任何扩展名。然后我在返回时检查了 lpofn.nFileExtension 以找出选择了哪个扩展名。
if (lpofn.nFileExtension == 0)
{
// add default extension, no extension was selected/entered by user
}
else
{
// there is an extension, save as entered.
}
答案 1 :(得分:0)
为了在对话框仍在运行时更新对话框,您需要在lpfnHook
结构中提供指向OPENFILENAME
回调的指针,并让回调处理CDN_TYPECHANGE
通知。它可以向对话框发送CDM_GETFILEPATH
或CDM_GETSPEC
消息以获取当前文件名,根据需要进行调整,然后发送CDM_SETCONTROLTEXT
消息以更新编辑字段(文件名的ID)编辑字段为0x442
),带有新值。
更新:您的挂钩代码没有任何问题。 {J}从Windows Vista开始被弃用,由Common Item Dialog取代(并成为包装)。GetSaveFileName()
。 XPF中的挂钩不会更改GSFN对话框UI,因此您必须使用Vista +,在这种情况下启用挂钩只会导致包装器在内部调用CID时使用不同的设置。许多新的CID功能都基于IShellItem
,而不是文件名字符串,因此包装器会删除任何无法表示为旧式文件名的内容,并使对话框看起来像XP中的旧式GSFN对话框而且更早。所以你看到的是Vista +下GetSaveFileName()
的正常行为!如果您不喜欢它,请不要再使用GetSaveFileName()
。请改用新的IFileSaveDialog
界面。实际上,如果您配置多个文件类型,将它们中的一个指定为默认扩展名,然后设置与默认扩展名匹配的初始文件名,它本身会为您更改文件扩展名。但是,如果您愿意,您也可以在代码中实现IFileDialogEvents
接口以接收OnTypeChange
通知,然后使用IFileDialog::SetFileName()
方法更新已显示的文件名。