C++ 调用GetOpenFileNameA会导致常见对话框错误2

C++ 调用GetOpenFileNameA会导致常见对话框错误2,c++,winapi,C++,Winapi,我正在尝试使用GetOpenFileNameA打开一个对话框。但是,该对话框不会打开。相反,我得到了一个很好的通讯错误2。在Google和StackOverflow中搜索此错误并没有产生任何有用的结果 令人困惑的是,这段代码在同样使用VisualStudio的学校计算机上运行,尽管版本不同 注意:此代码块中未声明的所有变量都是“全局”变量,只能在主代码模块中访问 void GetInputFile() { char szFileNameIN[MAX_PATH]; char szF

我正在尝试使用GetOpenFileNameA打开一个对话框。但是,该对话框不会打开。相反,我得到了一个很好的通讯错误2。在Google和StackOverflow中搜索此错误并没有产生任何有用的结果

令人困惑的是,这段代码在同样使用VisualStudio的学校计算机上运行,尽管版本不同

注意:此代码块中未声明的所有变量都是“全局”变量,只能在主代码模块中访问

void GetInputFile()
{
    char szFileNameIN[MAX_PATH];
    char szFileNameOUT[MAX_PATH];

    // get the input file name
    OPENFILENAME ofn;
    ZeroMemory(&fInputPath, sizeof(fInputPath));
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = NULL;
    ofn.lpstrFilter = LPWSTR("Any File\0*.*\0");
    ofn.lpstrFile = LPWSTR(fInputPath);
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFileTitle = LPWSTR(szFileNameIN);
    ofn.nMaxFileTitle = MAX_PATH;
    ofn.lpstrTitle = LPWSTR("Select an input File");
    ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
    if (GetOpenFileNameA(LPOPENFILENAMEA(&ofn))) // user selected an input file
    {
    }
    else {
        // Get error
        TCHAR error[MAX_LOADSTRING];
        wsprintf(error,TEXT("%i"),CommDlgExtendedError());
        MessageBox(NULL,error,TEXT("ERROR"),MB_OK);
    }

}
那些糟糕的
(LPWSTR)
类型转换告诉我,您正在使用定义的
UNICODE
进行编译,因此您使用的
OPENFILENAME
结构实际上是
OPENFILENAMEW
;如果您使用的是
GetOpenFileNameA
,则必须使用
OPENFILENAMEA
(或者使用带有宽字符串的直接
GetOpenFileName

(请记住,根据经验法则,如果您必须从不同于
void*
或类似对象的任何对象强制转换指针,则可能是做错了什么;添加指针强制转换只会使编译器沉默,而不会使错误消失)

那些可怕的
(LPWSTR)
cast告诉我您是使用定义的
UNICODE
编译的,因此您使用的
OPENFILENAME
结构实际上是
OPENFILENAMEW
;如果您使用的是
GetOpenFileNameA
,则必须使用
OPENFILENAMEA
(或者使用带有宽字符串的直接
GetOpenFileName


(请记住,根据经验法则,如果您必须从不同于
void*
或类似的对象中投射指针,则可能是做错了什么;添加指针投射只会使编译器静音,而不会使错误消失)

您使用的是
OPENFILENAME
版本的
TCHAR
。由于您将Unicode字符串指针分配给其字段,这意味着您的项目是在定义了
Unicode
的情况下编译的,因此
TCHAR
映射到
wchar\u t
OPENFILENAME
映射到
OPENFILENAMEW
。但是您使用的是ANSI字符缓冲区和ANSI版本的
GetOpenFileName()
,并且到处都使用不正确的类型转换

因此,请删除所有类型强制转换,然后:

  • 对所有内容使用适当的
    TCHAR
    类型和API:

    void GetInputFile()
    {
        TCHAR szFileNameIN[MAX_PATH];
        TCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAME ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = TEXT("Any File\0*.*\0");
        ofn.lpstrFile = fInputPath; // must be TCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = TEXT("Select an input File");
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileName(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            TCHAR error[MAX_LOADSTRING];
            wsprintf(error, TEXT("%i"), CommDlgExtendedError());
            MessageBox(NULL, error, TEXT("ERROR"), MB_OK);
        }
    }
    
    void GetInputFile()
    {
        WCHAR szFileNameIN[MAX_PATH];
        WCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAMEW ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = L"Any File\0*.*\0";
        ofn.lpstrFile = fInputPath; // must be WCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = L"Select an input File";
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileNameW(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            WCHAR error[MAX_LOADSTRING];
            wsprintfW(error, L"%i", CommDlgExtendedError());
            MessageBoxW(NULL, error, L"ERROR", MB_OK);
        }
    }
    
  • 对所有内容使用适当的
    CHAR
    /
    WCHAR
    类型和API:

    void GetInputFile()
    {
        TCHAR szFileNameIN[MAX_PATH];
        TCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAME ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = TEXT("Any File\0*.*\0");
        ofn.lpstrFile = fInputPath; // must be TCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = TEXT("Select an input File");
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileName(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            TCHAR error[MAX_LOADSTRING];
            wsprintf(error, TEXT("%i"), CommDlgExtendedError());
            MessageBox(NULL, error, TEXT("ERROR"), MB_OK);
        }
    }
    
    void GetInputFile()
    {
        WCHAR szFileNameIN[MAX_PATH];
        WCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAMEW ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = L"Any File\0*.*\0";
        ofn.lpstrFile = fInputPath; // must be WCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = L"Select an input File";
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileNameW(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            WCHAR error[MAX_LOADSTRING];
            wsprintfW(error, L"%i", CommDlgExtendedError());
            MessageBoxW(NULL, error, L"ERROR", MB_OK);
        }
    }
    


  • 您使用的是
    TCHAR
    版本的
    OPENFILENAME
    。由于您将Unicode字符串指针分配给其字段,这意味着您的项目是在定义了
    Unicode
    的情况下编译的,因此
    TCHAR
    映射到
    wchar\u t
    OPENFILENAME
    映射到
    OPENFILENAMEW
    。但是您使用的是ANSI字符缓冲区和ANSI版本的
    GetOpenFileName()
    ,并且到处都使用不正确的类型转换

    因此,请删除所有类型强制转换,然后:

  • 对所有内容使用适当的
    TCHAR
    类型和API:

    void GetInputFile()
    {
        TCHAR szFileNameIN[MAX_PATH];
        TCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAME ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = TEXT("Any File\0*.*\0");
        ofn.lpstrFile = fInputPath; // must be TCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = TEXT("Select an input File");
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileName(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            TCHAR error[MAX_LOADSTRING];
            wsprintf(error, TEXT("%i"), CommDlgExtendedError());
            MessageBox(NULL, error, TEXT("ERROR"), MB_OK);
        }
    }
    
    void GetInputFile()
    {
        WCHAR szFileNameIN[MAX_PATH];
        WCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAMEW ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = L"Any File\0*.*\0";
        ofn.lpstrFile = fInputPath; // must be WCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = L"Select an input File";
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileNameW(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            WCHAR error[MAX_LOADSTRING];
            wsprintfW(error, L"%i", CommDlgExtendedError());
            MessageBoxW(NULL, error, L"ERROR", MB_OK);
        }
    }
    
  • 对所有内容使用适当的
    CHAR
    /
    WCHAR
    类型和API:

    void GetInputFile()
    {
        TCHAR szFileNameIN[MAX_PATH];
        TCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAME ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = TEXT("Any File\0*.*\0");
        ofn.lpstrFile = fInputPath; // must be TCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = TEXT("Select an input File");
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileName(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            TCHAR error[MAX_LOADSTRING];
            wsprintf(error, TEXT("%i"), CommDlgExtendedError());
            MessageBox(NULL, error, TEXT("ERROR"), MB_OK);
        }
    }
    
    void GetInputFile()
    {
        WCHAR szFileNameIN[MAX_PATH];
        WCHAR szFileNameOUT[MAX_PATH];
    
        // get the input file name
        OPENFILENAMEW ofn;
        ZeroMemory(&fInputPath, sizeof(fInputPath));
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = NULL;
        ofn.lpstrFilter = L"Any File\0*.*\0";
        ofn.lpstrFile = fInputPath; // must be WCHAR[]...
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szFileNameIN;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrTitle = L"Select an input File";
        ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
        if (GetOpenFileNameW(&ofn)) // user selected an input file
        {
        }
        else
        {
            // Get error
            WCHAR error[MAX_LOADSTRING];
            wsprintfW(error, L"%i", CommDlgExtendedError());
            MessageBoxW(NULL, error, L"ERROR", MB_OK);
        }
    }
    


  • 使用LPWSTR和LPOPENFILENAMEA强制转换只会阻止编译器告诉您您做错了,而不会阻止您做错。如果您真的不关心本地化,那么使用OPENFILENAMEA。并删除强制转换。您正在使用为Unicode版本设置的结构调用函数的ANSI版本。你为什么期望它不会失败?@HansPassant:谢谢你的输入。@KenWhite:我从我教授的样本中提取了这段代码。如果它是直接从你教授的样本中提取的,你应该问你的教授为什么他们的代码不起作用,而不是问我们。使用LPWSTR和LPOPENFILENAMEA强制转换只会阻止编译器告诉你你做错了,而不会阻止你做错。如果您真的不关心本地化,那么使用OPENFILENAMEA。并删除强制转换。您正在使用为Unicode版本设置的结构调用函数的ANSI版本。你为什么认为这不会失败?@HansPassant:谢谢你的输入。@KenWhite:我从我教授的样本中提取了这段代码。如果它是直接从你教授的样本中提取的,你应该问你教授为什么他们的代码不起作用,而不是问我们。实际上,这是
    UNICODE
    预处理器符号,它控制Windows API的通用文本映射<代码>\u UNICODE用于CRT。如果您希望使用宽字符串,那么要调用的API是
    GetOpenFileNameW
    GetOpenFileName
    是一个宏,它应该只与通用文本映射一起使用(或者实际上根本不应该使用)。
    \uUnicode
    /
    UNICODE
    :wops,修复了,我总是忘记谁是谁
    TCHAR
    :15年前我会同意,今天除了与旧代码保持一致外,
    TCHAR
    再也没有任何好处了
    TCHAR
    s有感染代码的倾向,不像库代码中的
    wchar\t
    那样得到广泛支持(有
    wstring
    ,但没有
    tstring
    ),CRT映射看起来很难看(
    \tcslen
    ,严重吗?还有,
    \t
    )。因此,除非您仍然以Win 9x为目标,否则我要么使用“未修饰”的API(更易于阅读),假设它们是W,要么编写自己的UTF8->UTF16包装器,并在其他地方使用UTF8字符。实际上,控制Windows API的通用文本映射的是
    UNICODE
    预处理器符号<代码>\u UNICODE用于CRT。如果您希望使用宽字符串,那么要调用的API是
    GetOpenFileNameW
    GetOpenFileName
    是一个宏,只应与通用文本映射一起使用(或者实际上根本不应使用)