C++;在窗口中打开文件对话框 我有C++代码来显示对话框选择器文件。我希望用户只能选择指定的文件类型。“我的”对话框可以显示指定的类型文件,但用户可以在文件名中输入其他类型文件,如“我的图片”

C++;在窗口中打开文件对话框 我有C++代码来显示对话框选择器文件。我希望用户只能选择指定的文件类型。“我的”对话框可以显示指定的类型文件,但用户可以在文件名中输入其他类型文件,如“我的图片”,c++,winapi,C++,Winapi,那么,如何让用户只输入lpstrFilter中指定的文件名和搜索类型文件?或者我可以禁用文件名框吗 这是我的代码: const wchar_t* ChooserFile(const char* typeFile) { try { ZeroMemory( &sfn , sizeof( sfn)); sfn.lStructSize = sizeof ( sfn ); sfn.hwndOwner = NULL ;

那么,如何让用户只输入
lpstrFilter
中指定的文件名和搜索类型文件?或者我可以禁用文件名框吗

这是我的代码

const wchar_t* ChooserFile(const char* typeFile)
{
    try
    {
        ZeroMemory( &sfn , sizeof( sfn));
        sfn.lStructSize = sizeof ( sfn );
        sfn.hwndOwner = NULL ;
        wchar_t w_syFile[MAX_PATH];
        //mbstowcs(w_syFile, syFile, strlen(syFile)+1);//Plus null
        size_t convertedChars = 0;
        mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
        sfn.lpstrFile = w_syFile ;
        sfn.lpstrFile[0] = _T('\0');
        sfn.nMaxFile = sizeof( syFile );

        //TypeFile
        sfn.lpstrFilter = TEXT("Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0");

        sfn.nFilterIndex =1;
        sfn.lpstrFileTitle = NULL ;
        sfn.nMaxFileTitle = 0 ;
        sfn.lpstrInitialDir=NULL;

        //sfn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT|OFN_EXPLORER | OFN_ENABLEHOOK ;
        sfn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_NOVALIDATE|OFN_HIDEREADONLY  ;
        if (GetOpenFileName( &sfn ) != TRUE)
        {
            wstrPathFile = TEXT("");
            return wstrPathFile.c_str();
        }

        DWORD  retval=0;
        //BOOL   success; 
        TCHAR  buffer[BUFSIZE]=TEXT(""); 
        TCHAR  buf[BUFSIZE]=TEXT(""); 
        TCHAR** lppPart={NULL};

        wchar_t wstrPath[BUFSIZE];
        retval = GetFullPathNameW(sfn.lpstrFile,sfn.nMaxFile,wstrPath,lppPart);
        if (retval==0)
        {
            wstrPathFile = TEXT("");
            return wstrPathFile.c_str();
        }
        std::wstring s(wstrPath);
        wstrPathFile = s;
        wcout<<wstrPathFile<<endl;
        return wstrPathFile.c_str();
    }
    catch (...)
    {
        PrintToFile("ChooserFile","Error");
        wstrPathFile = TEXT("");
        return wstrPathFile.c_str();
    }
}
const wchar\u t*ChooserFile(const char*typeFile)
{
尝试
{
零内存(&sfn,sizeof(sfn));
sfn.lStructSize=sizeof(sfn);
sfn.hwndOwner=NULL;
wchar_t w_syFile[MAX_PATH];
//mbstowcs(w_syFile,syFile,strlen(syFile)+1);//加null
大小\u t convertedChars=0;
mbstowcs_s(&convertedChars,w_syFile,MAX_PATH,syFile,_TRUNCATE);
sfn.lpstrFile=w_syFile;
sfn.lpstrFile[0]=_T('\0');
sfn.nMaxFile=sizeof(syFile);
//打字文件
sfn.lpstrFilter=TEXT(“Microsoft Office Word文档(*.xlsx)\0*.xlsx\0”);
sfn.nFilterIndex=1;
sfn.lpstrFileTitle=NULL;
sfn.nMaxFileTitle=0;
sfn.lpstrInitialDir=NULL;
//sfn.Flags=OFN_路径必须存在| OFN_覆盖比较| OFN_资源管理器| OFN_启用挂钩;
sfn.Flags=OFN_路径必须存在| OFN_文件必须存在| OFN新数据| OFN隐藏;
如果(GetOpenFileName(&sfn)!=TRUE)
{
wstrPathFile=文本(“”);
返回wstrPathFile.c_str();
}
DWORD-retval=0;
//成功;
TCHAR缓冲区[BUFSIZE]=文本(“”);
TCHAR buf[BUFSIZE]=文本(“”);
TCHAR**lppPart={NULL};
wchar_t wstrPath[BUFSIZE];
retval=GetFullPathNameW(sfn.lpstrFile、sfn.nMaxFile、wstrPath、lppPart);
如果(retval==0)
{
wstrPathFile=文本(“”);
返回wstrPathFile.c_str();
}
std::wstring s(wstrPath);
wstrPathFile=s;
wcout
我希望用户只能选择指定的文件类型

您不能通过在文件名编辑控件中键入来阻止用户选择他们喜欢的任何文件。因此,您应该让他们这样做,并验证文件名是否符合您的要求

您有两种选择可以做到这一点:

  • 让对话框返回,如果文件名不符合您的要求,则向用户提供一个错误对话框,让他们知道出现了什么问题

  • OPENFILENAME
    结构的
    lpfnHook
    成员中提供一个钩子过程。当用户尝试接受文件时,该钩子过程将被发送一条通知消息。执行验证以响应该消息。如果文件名不符合要求,则显示一条消息,并将非零值返回给f强制对话框保持打开状态

  • 您的代码正在注释出OFN_EXPLORER的
    和OFN_ENABLEHOOK的
    标志,因此您必须已经知道存在。正如其他人告诉您的,您可以使用该挂钩捕获接受/拒绝所选文件名的通知。例如:

    UINT_PTR CALLBACK MyOFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
    {
        if (uiMsg == WM_NOTIFY)
        {
            LPOFNOTIFY ofn = (LPOFNOTIFY) lParam;    
            if (ofn->hdr.code == CDN_FILEOK)
            {
                LPOPENFILENAMEW lpOFN = (LPOPENFILENAMEW) ofn->lpOFN;
    
                LPWSTR lpExt = PathFindExtensionW(lpOFN->lpstrFile);
                if (lstrcmpiW(lpExt, L".XLSX") != 0)
                {
                    SetWindowLongPtr(hdlg, DWL_MSGRESULT, 1);
                    return 1;
                }
            }
        }
    
        return 0;
    }
    
    std::wstring ChooserFile(const char* typeFile)
    {
        OPENFILEAMEW sfn = {0};
        wchar_t w_syFile[MAX_PATH+1] = {0};
        size_t convertedChars = 0;
    
        sfn.lStructSize = sizeof(sfn);
        sfn.hwndOwner = NULL;
        mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
        sfn.lpstrFile = w_syFile;
        sfn.nMaxFile = MAX_PATH;
    
        //TypeFile
        sfn.lpstrFilter = L"Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0";
    
        sfn.nFilterIndex = 1;
        sfn.lpstrFileTitle = NULL;
        sfn.nMaxFileTitle = 0;
        sfn.lpstrInitialDir = NULL;
    
        sfn.lpfnHook = &MyOFNHookProc;
    
        sfn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOVALIDATE | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
    
        if (!GetOpenFileNameW(&sfn))
            return L"";
    
        WCHAR szPath[MAX_PATH+1] = {0};
    
        DWORD retval = GetFullPathNameW(sfn.lpstrFile, MAX_PATH, szPath, NULL);
        if ((retval == 0) || (retval > MAX_PATH))
            return L"";
    
        std::wstring wstrPath(szPath, retval);
        std::wcout << wstrPath << endl;
        return wstrPath;
    }
    
    UINT\u PTR回调MyOFNHookProc(HWND hdlg、UINT uiMsg、WPARAM WPARAM、LPARAM LPARAM)
    {
    如果(uiMsg==WM\U NOTIFY)
    {
    LPOFNOTIFY ofn=(LPOFNOTIFY)lParam;
    如果(ofn->hdr.code==CDN\U文件确定)
    {
    LPOPENFILENAMEW lpOFN=(LPOPENFILENAMEW)ofn->lpOFN;
    LPWSTR lpExt=PathFindExtensionW(lpOFN->lpstrFile);
    如果(lstrcmpiW(lpExt,L“.XLSX”)!=0)
    {
    SetWindowLongPtr(hdlg,DWL_MSGRESULT,1);
    返回1;
    }
    }
    }
    返回0;
    }
    std::wstring选择器文件(const char*typeFile)
    {
    OPENFILEAMEW sfn={0};
    wchar_t w_syFile[MAX_PATH+1]={0};
    大小\u t convertedChars=0;
    sfn.lStructSize=sizeof(sfn);
    sfn.hwndOwner=NULL;
    mbstowcs_s(&convertedChars,w_syFile,MAX_PATH,syFile,_TRUNCATE);
    sfn.lpstrFile=w_syFile;
    sfn.nMaxFile=最大路径;
    //打字文件
    sfn.lpstrFilter=L“Microsoft Office Word文档(*.xlsx)\0*.xlsx\0”;
    sfn.nFilterIndex=1;
    sfn.lpstrFileTitle=NULL;
    sfn.nMaxFileTitle=0;
    sfn.lpstrInitialDir=NULL;
    sfn.lpfnHook=&MyOFNHookProc;
    sfn.Flags=of n_PATHMUSTEXIST | of n_FILEMUSTEXIST | of n_NOVALIDATE | of n_hidderadonly | of n_EXPLORER | of n_ENABLEHOOK;
    如果(!GetOpenFileNameW(&sfn))
    返回“L”;
    WCHAR szPath[MAX_PATH+1]={0};
    DWORD retval=GetFullPathNameW(sfn.lpstrFile,MAX_PATH,szPath,NULL);
    如果((retval==0)| |(retval>MAX_路径))
    返回“L”;
    std::wstring wstrPath(szPath,retval);
    
    std::wcout使用拒绝您不喜欢的文件名。如果您的目标是Vista或更高版本,您应该使用“公用项”对话框。然后您可以使用
    IFileDialogEvents::OnFileOk
    回调方法。如果您喜欢文件名,请返回
    S_OK
    ,或者
    S_FALSE
    拒绝。谢谢@nwp,但我不知道如何使用FI你能给我举个例子吗?谢谢B,但我想在win XP中使用它!有什么想法吗?还有一个选项可以减少用户选择非法文件名的动机:调整文件名编辑控件的自动完成(请参阅)。在OPENFILENAME结构的lpfnHook成员中提供一个钩子过程。当用户尝试接受文件时,将向该钩子过程发送一条CDN_FILEOK通知消息。执行验证以响应该消息。如果文件名不符合要求,则显示一条消息,并返回一个非零值以强制对话框关闭保持打开状态。=>谢谢David,你能给我举个例子吗?我相信你自己能做到。非常感谢Remy,它成功了。你能告诉我如何将这个对话框设置为最顶端吗?我已经搜索过了,但我没有找到任何想法!你可以访问钩子内部的对话框HWND(
    GetParent(hdlg)
    ),因此您可以调用
    SetWindowPos()