C语言中OpenFileName如何使用?

99ANYc3cd6
预计阅读时长 21 分钟
位置: 首页 C语言 正文

它通常与 GetOpenFileNameGetSaveFileName 这两个函数配合使用。

c语言openfilename
(图片来源网络,侵删)

核心概念

OpenFileName 本身不是一个函数,而是一个结构体,它的作用是向 Windows 系统传递“你希望这个文件选择对话框长什么样、有什么功能”的配置信息,当用户在对话框中点击“确定”或“取消”后,这个结构体里的一些成员变量会被系统填充上用户的选择结果。

使用它的完整流程是:

  1. 定义一个 OPENFILENAME 结构体变量。
  2. 初始化这个结构体的各个成员,告诉你的需求(比如对话框标题、默认文件类型等)。
  3. 调用 GetOpenFileName()GetSaveFileName() 函数,并将这个结构体变量的地址作为参数传入。
  4. 检查函数的返回值,并根据结构体中被填充的成员来获取用户的选择。

必需的头文件和库

在使用之前,请确保你的代码包含了正确的头文件,并且在链接时指定了正确的库。

#include <windows.h>  // 包含 OPENFILENAME 结构体和相关函数的定义
#include <commdlg.h> // 包含一些对话框相关的常量定义
#pragma comment(lib, "comdlg32.lib") // 告诉链接器链接 comdlg32.lib 这个库

OPENFILENAME 结构体的关键成员

这个结构体有很多成员,但大部分情况下,你只需要设置其中几个核心的即可。

c语言openfilename
(图片来源网络,侵删)
成员 类型 描述
lStructSize DWORD 必须设置,结构体的大小(以字节为单位),这有助于 Windows API 处理不同版本的兼容性,通常设置为 sizeof(OPENFILENAME)
hwndOwner HWND 可选,对话框所有者窗口的句柄,如果设置为 NULL,对话框没有所有者,如果设置了,对话框会居中于该窗口。
lpstrFilter LPCSTR 非常重要,文件类型过滤器,这是一个以双 NULL 结尾的字符串数组,格式为:"描述1\0过滤器1\0描述2\0过滤器2\0\0""Text Files\0*.txt\0All Files\0*.*\0\0"
lpstrFile LPSTR 非常重要,用于存放用户选择的文件路径的缓冲区,你必须预先分配足够大的空间(char szFile[MAX_PATH];),对话框打开时,这里可以显示默认路径。
nMaxFile DWORD 必须设置lpstrFile 缓冲区的大小,通常设置为 MAX_PATH
lpstrFileTitle LPSTR 可选,用于存放用户选择的文件名(不带路径)的缓冲区,如果为 NULL,则系统会自动计算。
nMaxFileTitle DWORD 必须设置lpstrFileTitle 不为 NULL)。lpstrFileTitle 缓冲区的大小。
lpstrInitialDir LPCSTR 可选,对话框打开时显示的初始目录,如果为 NULL,则使用当前工作目录。
lpstrTitle LPCSTR 可选,对话框窗口的标题,如果为 NULL,则使用默认标题(如“打开”或“另存为”)。
Flags DWORD 非常重要,控制对话框行为的标志位,可以使用 组合多个标志,常用值见下方表格。
nFilterIndex WORD 可选,默认选中的过滤器索引(从1开始),如果用户选择了“所有文件”,这个值不会改变。

Flags 常用标志位:

标志位 描述
OFN_FILEMUSTEXIST 0x00001000 强制用户只能输入已存在的文件名。
OFN_PATHMUSTEXIST 0x00000800 强制用户只能输入有效的路径。
OFN_HIDEREADONLY 0x00000004 隐藏“只读”复选框。
OFN_OVERWRITEPROMPT 0x00000002 在保存对话框中,如果文件已存在,则提示是否覆盖。
OFN_EXPLORER 0x00080000 使用新的资源管理器风格的对话框(默认)。
OFN_READONLY 0x00000001 如果用户勾选了“只读”复选框,则此标志位在返回时会被设置。

完整示例代码

下面是一个完整的示例,演示如何创建一个“打开文件”对话框。

#include <windows.h>
#include <tchar.h> // 为了方便使用 TCHAR,推荐使用
#include <commdlg.h>
#pragma comment(lib, "comdlg32.lib")
// 简单的 Windows 程序,只显示一个消息框
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 1. 定义并初始化 OPENFILENAME 结构体
    OPENFILENAME ofn;
    TCHAR szFile[MAX_PATH] = { 0 }; // 用于存放完整文件路径的缓冲区
    // 清零结构体
    ZeroMemory(&ofn, sizeof(ofn));
    // 2. 设置结构体成员
    ofn.lStructSize = sizeof(ofn);         // 结构体大小
    ofn.hwndOwner = NULL;                  // 所有者窗口句柄
    ofn.lpstrFile = szFile;                // 文件路径缓冲区
    ofn.nMaxFile = MAX_PATH;               // 缓冲区大小
    ofn.lpstrFilter = _T("Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"); // 过滤器
    ofn.nFilterIndex = 1;                  // 默认选择第一个过滤器
    ofn.lpstrFileTitle = NULL;             // 不需要单独的文件名缓冲区
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = _T("C:\\");      // 初始目录
    ofn.lpstrTitle = _T("请选择一个文本文件"); // 对话框标题
    ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; // 标志位
    // 3. 调用 GetOpenFileName 函数
    // 如果用户点击“确定”,函数返回 TRUE
    // 如果用户点击“取消”或出错,函数返回 FALSE
    if (GetOpenFileName(&ofn)) {
        // 4. 处理用户的选择
        MessageBox(NULL, szFile, _T("你选择的文件"), MB_OK);
    } else {
        // 用户取消或出错
        // CommDlgExtendedError() 函数可以获取具体的错误码
        DWORD err = CommDlgExtendedError();
        if (err == 0) {
            // 用户点击了“取消”
            MessageBox(NULL, _T("用户取消了操作。"), _T("提示"), MB_OK);
        } else {
            // 发生了其他错误
            TCHAR errMsg[256];
            _stprintf_s(errMsg, _T("发生错误,错误码: %d"), err);
            MessageBox(NULL, errMsg, _T("错误"), MB_OK | MB_ICONERROR);
        }
    }
    return 0;
}

代码解释:

  1. TCHAR_T():为了代码能同时支持 ASCII 和 Unicode,Windows 推荐使用 TCHAR 类型。_T() 宏会根据项目设置自动转换为普通字符串(char)或宽字符字符串(wchar_t)。
  2. ZeroMemory(&ofn, sizeof(ofn)):这是一个好习惯,可以将结构体所有成员初始化为 0,避免使用未初始化的内存。
  3. GetOpenFileName(&ofn):这是核心函数调用,它是一个模态对话框,会阻塞你的程序,直到用户关闭它。
  4. szFile:在调用 GetOpenFileName 之前,szFile 通常是空的,调用成功后,它会被填充上用户选择的完整文件路径,C:\my_folder\my_document.txt
  5. 错误处理GetOpenFileName 返回 FALSE 不一定代表用户取消,也可能是发生了错误(比如内存不足),需要调用 CommDlgExtendedError() 来区分:
    • 返回 0:用户点击了“取消”。
    • 返回非 0:发生了具体错误。

GetSaveFileName 的用法

GetSaveFileName 的用法和 GetOpenFileName 几乎完全一样,只是它用于“保存文件”对话框,主要区别在于 Flags 的使用。

保存文件示例片段:

OPENFILENAME ofn;
TCHAR szFile[MAX_PATH] = { 0 };
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.nMaxFile = MAX_PATH;
// ... (其他成员设置)
// 保存对话框通常需要提示覆盖
ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT; // 关键标志位
// 调用 GetSaveFileName
if (GetSaveFileName(&ofn)) {
    // 用户点击了“保存”,szFile 中是用户想保存的文件名
    // 注意:这个文件此时还不存在,你需要自己创建并写入内容
    MessageBox(NULL, szFile, _T("你将保存为文件"), MB_OK);
}
步骤 动作 关键点
1 包含头文件 #include <windows.h>, #include <commdlg.h>
2 链接库 #pragma comment(lib, "comdlg32.lib")
3 定义缓冲区 TCHAR szFile[MAX_PATH];
4 定义并清零结构体 OPENFILENAME ofn; ZeroMemory(&ofn, sizeof(ofn));
5 配置结构体 设置 lStructSize, lpstrFile, nMaxFile, lpstrFilter, Flags 等。
6 调用函数 GetOpenFileName(&ofn)GetSaveFileName(&ofn)
7 检查返回值 如果为 TRUE,从 lpstrFile 获取路径,如果为 FALSE,用 CommDlgExtendedError() 检查原因。

掌握了 OPENFILENAME 结构体的用法,你就可以在 C 语言程序中轻松实现标准的文件打开和保存功能了。

c语言openfilename
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
dede如何调用当前顶级栏目链接?
« 上一篇 01-03
如何为织梦系统自定义favicon.ico图标?
下一篇 » 01-03

相关文章

取消
微信二维码
支付宝二维码

目录[+]