【问题标题】:Save/Open Common Dialog boxes in win32 without MFC在没有 MFC 的 win32 中保存/打开常用对话框
【发布时间】:2011-12-05 11:50:42
【问题描述】:

如何使用纯非托管 Win32 API 创建默认的“保存/打开”对话框? 遵循指南here,在主窗口的消息循环中处理WM_CREATE消息时执行以下代码: 我也有included <Commdlg.h>。

            OPENFILENAMEA ofn;
        char Buffer[300];
        fill(Buffer, Buffer + 300, '\0');
        ofn.lStructSize = sizeof(OPENFILENAMEA);
        ofn.hwndOwner = hWnd;
        ofn.lpstrFile = Buffer;
        ofn.nMaxFile = 300;
        ofn.Flags = OFN_EXPLORER;
        ofn.lpstrFilter = NULL;
        ofn.lpstrCustomFilter = NULL;
        ofn.nFilterIndex = 0;
        ofn.lpstrFileTitle = NULL;
        ofn.lpstrInitialDir = NULL;
        ofn.lpstrTitle = NULL;
        out << GetOpenFileNameA(&ofn) << endl;
        out << Buffer << (int)CommDlgExtendedError();

然而,这段代码给出了 NO 输出。救命?!

【问题讨论】:

  • 你为什么要把返回值流出来!!!
  • 嗯,因为项目设置为 Win 32 类型,没有控制台,我不想创建一个标签来显示它。这就是您流式传输返回值的原因。
  • 没有,但是我可以看到主程序

标签: c++ file winapi dialog


【解决方案1】:

GetOpenFileName 阻塞(一段时间),如果对话框被“OK”关闭,则返回 TRUE,如果被取消,则返回 FALSE。

实际结果(目录/文件路径)可以从OPENFILENAME结构中读取。

【讨论】:

  • 但是没有打开对话框,为什么会返回?
【解决方案2】:

以下代码在处理 WM_CREATE 消息时执行

查看“输出”窗口并观察 0xc0000005 的第一次机会异常通知,这是一个 AccessViolation 异常。在 WM_CREATE 被调度时,Wow64 模拟器中有一个支持吞下异常。

该异常是由于未完全初始化 OPENFILENAMEA 结构引起的。快速修复:

 OPENFILENAMEA ofn = {0};

并且倾向于在调用 ShowWindow() 而不是 WM_CREATE 消息处理程序之前显示对话框。

【讨论】:

    【解决方案3】:

    总体思路是对的,但是如果您将正在创建的窗口的句柄作为所有者传递,那么它还不会被初始化。

    对于诊断,请考虑创建变量来存储 API 函数返回值并在调试器中检查它们。

    将结构初始化为零也更方便且不易出错,而不是将不需要的成员显式归零,如下所示:

    OPENFILENAME ofn = { 0 };
    

    【讨论】:

      【解决方案4】:

      从https://docs.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes#opening-a-file 我们得到了一个 utf-16 版本,我做了一些小的改动:

      OPENFILENAME ofn = { 0 };       // common dialog box structure
      WCHAR szFile[260];       // buffer for file name 
      HWND hwnd;              // owner window
      HANDLE hf;              // file handle
      
      // Initialize OPENFILENAME
      ZeroMemory(&ofn, sizeof(ofn));
      ofn.lStructSize = sizeof(ofn);
      ofn.hwndOwner = hwnd;
      ofn.lpstrFile = szFile;
      // Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
      // use the contents of szFile to initialize itself.
      ofn.lpstrFile[0] = '\0';
      ofn.nMaxFile = sizeof(szFile);
      ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
      ofn.nFilterIndex = 1;
      ofn.lpstrFileTitle = NULL;
      ofn.nMaxFileTitle = 0;
      ofn.lpstrInitialDir = NULL;
      ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
      
      // Display the Open dialog box. 
      
      if (GetOpenFileName(&ofn)==TRUE) 
          hf = CreateFile(ofn.lpstrFile, 
                          GENERIC_READ,
                          0,
                          (LPSECURITY_ATTRIBUTES) NULL,
                          OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          (HANDLE) NULL);
      

      【讨论】:

      • nMaxFile 是“lpstrFile 指向的缓冲区的大小(以字符为单位)”,但您将其设置为缓冲区的字节大小。这会导致缓冲区溢出。
      猜你喜欢
      • 1970-01-01
      • 2023-03-25
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多