【问题标题】:GetOpenFileName() kills my background open streams :(GetOpenFileName() 杀死我的后台打开流:(
【发布时间】:2009-12-22 10:48:41
【问题描述】:

有点奇怪。好的,所以我正在使用 OGRE 游戏引擎,它有一个“SceneManager”类,可以让一些文件流在后台打开。如果我在使用 GetOpenFileName() 之前使用这些流,则这些流工作正常,但是如果我尝试在 GetOpenFileName() 之后使用这些流,则发现这些流已关闭。有人能解释一下为什么 GetOpenFileName() 会杀死我的后台流吗?

String Submerge::showFileDialog(char* filters, bool savedialog, char* title)
// need to tweak flags for open/save
{
OPENFILENAME ofn ;
char szFile[255] ;
HWND hwnd = NULL;
//getOgre()->getAutoCreatedWindow()->getCustomAttribute("WINDOW", &hwnd);

ZeroMemory( &ofn , sizeof(ofn) );
ofn.hwndOwner = hwnd;
ofn.lStructSize = sizeof ( ofn );
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof( szFile );
ofn.lpstrFilter = filters ? filters : "All files\0*.*\0";
ofn.nFilterIndex =1;
ofn.lpstrFileTitle = NULL ;
ofn.nMaxFileTitle = 0 ;
ofn.lpstrInitialDir=NULL ;
if(title!=NULL)
    ofn.lpstrTitle=title;
//ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST ;

MeshLoadTest(); // this is where i use background file streams
bool success = false;
if(savedialog)
    success = GetSaveFileName( &ofn );
else
    success = GetOpenFileName( &ofn );
MeshLoadTest(); // this is where i use background file streams

if(!success)
    return "";
String str;
str.append(ofn.lpstrFile);
return str;
return "";
}

【问题讨论】:

    标签: c++ getopenfilename


    【解决方案1】:

    注意GetOpenFileName() 可以并且将会改变你整个进程的当前目录。这可能会干扰您正在进行的其他任何事情。

    有一个选项叫OFN_NOCHANGEDIR,但是根据documentation,是无效的:

    如果用户在搜索文件时更改了目录,则将当前目录恢复为其原始值。 Windows NT 4.0/2000/XP:此标志对 GetOpenFileName 无效。

    你应该在调用之前和之后检查当前目录;如果它改变了,那么这可能是你的问题。在这种情况下,添加代码以保存和恢复调用 GetOpenFileName() 周围的当前目录。

    【讨论】:

    • 嗯,听起来很有趣,那么如何阻止这种行为呢?
    • 完美,有道理。我正在使用winXP,是的,由于我浏览的文件总是在不同的目录中,所以目录确实发生了变化。我是win32编程的小菜鸟,所以只有你能告诉我如何记录并稍后恢复工作目录,请:)
    • 查找GetCurrentDirectorySetCurrentDirectory 函数。
    【解决方案2】:

    谢谢大家,我又发现了一个问题,我使用了 OFN_NOCHANGEDIR,问题实际上已经解决了(WinXP SP3),也许他们需要不时更新 MSDN 文档:P

    【讨论】:

    • 不要依赖未记录的功能:它们可能在未来的任何时候发生变化,您的应用程序将突然停止在任何未来版本的 Windows 中工作。我会选择保存/恢复目录解决方案。
    【解决方案3】:

    (这其实是另一个答案的一个答案,问题的根源是在当前目录的变化中找到的)

    保存当前目录:

    #define ARRSIZE(arr) (sizeof(arr)/sizeof(*(arr)))
    
    //...
    
    TCHAR curDir[MAX_PATH];
    DWORD ret;
    ret=GetCurrentDirectory(ARRSIZE(curDir),curDir);
    if(ret==0)
    {
        // The function falied for some reason (see GetLastError), handle the error
    }
    else if(ret>ARRSIZE(curDir))
    {
        // The function failed because the buffer is too small, implementation of a function that uses dynamic allocation left to the reader
    }
    else
    {
        // Now the current path is in curDir
    }
    

    要恢复路径,只需这样做

    if(!SetCurrentDirectory(curDir))
    {
        // The function failed, handle the error
    }
    

    .

    提示:在应用程序开始时使用 TCHARS 和通用文本映射函数而不是 chars:这将避免您在以后的应用程序需要时遇到很多麻烦与 Unicode 路径兼容。

    【讨论】:

    • 如果您必须使用大量输出字符串的 Windows API,您会习惯它……但这不是 WinAPI 的错,而是 C 的错:C 字符串可能真的很可怕。 :-S
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多