当前位置: 首页 > article >正文

【第七节】windows sdk编程:Windows 中的对话框

目录

引言

一、对话框简介

1.1 对话框的创建

1.2 基本函数

1.3 模态对话框与非模态对话框

1.4 对话框与窗口的区别

二、模态对话框编程方法

2.1 模态对话框编程

2.2 消息框

三、非模态对话框编程方法

四、综合代码案例


引言

        在Windows应用程序开发中,对话框是用户交互的重要组件,能够简化复杂界面的设计和实现。通过资源编辑器,开发者可以快速创建对话框资源,并通过`DialogBox`或`CreateDialog`函数将其集成到应用程序中。模态对话框要求用户先关闭对话框才能操作主窗口,而非模态对话框则允许用户同时与主窗口和对话框交互。无论是简单的消息框还是复杂的自定义对话框,Windows提供了丰富的API和资源管理机制,帮助开发者高效构建用户友好的界面。

一、对话框简介

1.1 对话框的创建

        虽然可以使用 `CreateWindow` 创建 `POPUP` 风格的窗口,但对话框程序通常包含多个控件,逐个创建控件会非常繁琐。因此,微软提供了更为便捷的方式来创建对话框程序。

        通过资源编辑器,我们可以直接创建对话框资源,并通过资源 ID 来标识。在对话框上,可以拖拽各种控件(如 `Button`、`Edit`、`Static` 等),并通过属性调整对话框和控件的风格。随后,调用 `DialogBox` 或 `CreateDialog` 函数,利用资源创建出对话框。

        在资源视图中,右键单击 `.rc` 文件,选择“添加资源”,然后新建一个对话框,即可创建对话框资源。通过“视图 -> 工具箱”可以向对话框上添加控件。

1.2 基本函数

常用的对话框创建函数有两个:

INT_PTR WINAPI DialogBox(
    _In_opt_ HINSTANCE hInstance,
    _In_ LPCTSTR lpTemplate,
    _In_opt_ HWND hWndParent,
    _In_opt_ DLGPROC lpDialogFunc
);

HWND WINAPI CreateDialog(
    _In_opt_ HINSTANCE hInstance,
    _In_ LPCTSTR lpTemplate,
    _In_opt_ HWND hWndParent,
    _In_opt_ DLGPROC lpDialogFunc
);

- `DialogBox`:用于生成模态窗口。
- `CreateDialog`:用于创建非模态窗口。

        两者都会调用 `CreateWindow` 来创建窗口。非模态对话框需要程序员自己实现消息循环,而模态对话框自带消息循环,消息循环在函数内部进行。退出模态对话框需要使用 `EndDialog`。

参数对比:

`DialogBox` 和 `CreateDialog` 的参数相同:
(1)当前程序实例句柄
(2)资源 ID
(3)父实例句柄(通常为空)
(4)回调函数指针(需要用 `DLGPROC` 转换)

        两者的主要区别在于模态与非模态,`CreateDialog` 的消息循环需要程序员自己实现。

1.3 模态对话框与非模态对话框

- 模态对话框:创建后,用户必须关闭对话框,父窗口才能响应用户操作。否则,父窗口无法响应任何用户操作。
- 非模态对话框:创建后,父窗口不需要等待对话框关闭即可响应用户操作,即使对话框未关闭,父窗口仍可响应用户操作。

1.4 对话框与窗口的区别

对话框处理的主要消息:

- `WM_INITDIALOG`:对话框初始化时执行的操作。
- `WM_COMMAND`:响应对话框上控件的操作。
- `WM_NOTIFY`:响应对话框上控件的复杂操作。

二、模态对话框编程方法

2.1 模态对话框编程

(1)定义对话框资源
   在资源中添加一个对话框,并拖拽一些控件。

(2)调用 `DialogBox` 显示对话框
   定义资源后,调用 `DialogBox` 函数显示对话框:

int DialogBox(HINSTANCE hInstance, LPCTSTR lpszDialogName, HWND hwnd, WNDPROC lpDialogFunc);

(3)构造对话框消息处理函数
   对话框消息处理函数的一般形式:

BOOL CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
       switch(message) {
           case WM_INITDIALOG: return 1;
           case WM_COMMAND:
               switch(LOWORD(wParam)) {
                   case ...: break;
                   case ...: break;
               }
               break;
           ...
       }
       return 0;
   }


   在消息处理函数中,主要处理以下两类消息:
   - `WM_INITDIALOG`:对话框初始化时执行的操作。
   - `WM_COMMAND`:响应对话框上控件的操作。

(4)关闭对话框函数
   在消息处理函数中调用 `EndDialog` 关闭对话框。

2.2 消息框

        消息框是模态对话框的一种特殊形式。应用程序可以通过调用 `MessageBox` 函数快速生成一些简单但常用的 Windows 消息框。函数原型为:

int MessageBox(HWND hwnd, LPCTSTR lpszText, LPCTSTR lpszCaption, DWORD dwType);

- `hwnd`:拥有该消息的窗口。
- `lpszText`:消息框中显示的字符串。
- `lpszCaption`:作为标题的字符串。
- `dwType`:指定消息框的内容。

常用标识及说明:

用户操作与 `MessageBox` 返回值的对应关系:

三、非模态对话框编程方法

(1)定义对话框资源
   与非模态对话框相同。

(2)创建对话框
   非模态对话框的创建由 `CreateDialog` 函数完成:

HWND CreateDialog(HINSTANCE hInstance, LPCTSTR lpszDialogName, HWND hwndParent, WNDPROC lpDialogFunc);

(3)消息循环部分的处理
   由于非模态对话框不禁止应用程序向其他窗口发送消息,因此在 `WinMain` 函数的消息循环中,必须包含截获发往非模态对话框的消息,并将其发往相应的对话框处理函数处理。消息循环的一般形式为:

 while (GetMessage(&Msg, NULL, 0, 0)) {
       if (!IsDialogMessage(hdlg, &Msg)) {
           TranslateMessage(&Msg);
           DispatchMessage(&Msg);
       }
   }

(4)关闭对话框函数
   在消息处理函数中调用 `DestroyWindow` 关闭对话框:

BOOL DestroyWindow(HWND hwnd);

四、综合代码案例

        以下是一个综合性的C++代码案例,展示了如何在Windows应用程序中使用模态对话框和非模态对话框。代码包括创建对话框、处理对话框消息、使用消息框等功能。

完整代码示例

#include <windows.h>

// 资源ID定义
#define IDD_MAIN_DIALOG 101
#define IDD_MODAL_DIALOG 102
#define IDD_MODELESS_DIALOG 103
#define IDC_BUTTON_OPEN_MODAL 104
#define IDC_BUTTON_OPEN_MODELESS 105
#define IDC_BUTTON_CLOSE 106

// 全局变量
HWND g_hModelessDialog = NULL; // 非模态对话框句柄

// 对话框过程函数(主对话框)
INT_PTR CALLBACK MainDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;

        case WM_COMMAND:
            switch (LOWORD(wParam)) {
                case IDC_BUTTON_OPEN_MODAL:
                    // 打开模态对话框
                    DialogBox((HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE),
                              MAKEINTRESOURCE(IDD_MODAL_DIALOG),
                              hDlg, ModalDialogProc);
                    break;

                case IDC_BUTTON_OPEN_MODELESS:
                    // 打开非模态对话框
                    if (!g_hModelessDialog) {
                        g_hModelessDialog = CreateDialog((HINSTANCE)GetWindowLongPtr(hDlg, GWLP_HINSTANCE),
                                                         MAKEINTRESOURCE(IDD_MODELESS_DIALOG),
                                                         hDlg, ModelessDialogProc);
                        ShowWindow(g_hModelessDialog, SW_SHOW);
                    }
                    break;

                case IDC_BUTTON_CLOSE:
                    // 关闭主对话框
                    EndDialog(hDlg, LOWORD(wParam));
                    break;
            }
            break;

        case WM_DESTROY:
            if (g_hModelessDialog) {
                DestroyWindow(g_hModelessDialog); // 关闭非模态对话框
            }
            break;
    }
    return (INT_PTR)FALSE;
}

// 模态对话框过程函数
INT_PTR CALLBACK ModalDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;

        case WM_COMMAND:
            if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
                // 关闭模态对话框
                EndDialog(hDlg, LOWORD(wParam));
                return (INT_PTR)TRUE;
            }
            break;
    }
    return (INT_PTR)FALSE;
}

// 非模态对话框过程函数
INT_PTR CALLBACK ModelessDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_INITDIALOG:
            return (INT_PTR)TRUE;

        case WM_COMMAND:
            if (LOWORD(wParam) == IDCANCEL) {
                // 关闭非模态对话框
                DestroyWindow(hDlg);
                g_hModelessDialog = NULL;
                return (INT_PTR)TRUE;
            }
            break;
    }
    return (INT_PTR)FALSE;
}

// 应用程序入口函数
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // 显示主对话框
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN_DIALOG), NULL, MainDialogProc);
    return 0;
}

资源文件(`.rc`文件)

在资源文件中定义对话框和控件:

#include "resource.h"

// 主对话框资源
IDD_MAIN_DIALOG DIALOGEX 0, 0, 200, 100
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "主对话框"
FONT 9, "宋体"
BEGIN
    DEFPUSHBUTTON "打开模态对话框", IDC_BUTTON_OPEN_MODAL, 10, 10, 120, 20
    PUSHBUTTON "打开非模态对话框", IDC_BUTTON_OPEN_MODELESS, 10, 40, 120, 20
    PUSHBUTTON "关闭", IDC_BUTTON_CLOSE, 10, 70, 120, 20
END

// 模态对话框资源
IDD_MODAL_DIALOG DIALOGEX 0, 0, 150, 80
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "模态对话框"
FONT 9, "宋体"
BEGIN
    PUSHBUTTON "确定", IDOK, 30, 40, 80, 20
    PUSHBUTTON "取消", IDCANCEL, 30, 70, 80, 20
END

// 非模态对话框资源
IDD_MODELESS_DIALOG DIALOGEX 0, 0, 150, 80
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "非模态对话框"
FONT 9, "宋体"
BEGIN
    PUSHBUTTON "关闭", IDCANCEL, 30, 40, 80, 20
END

头文件(`resource.h`)

定义资源ID:

#define IDD_MAIN_DIALOG 101
#define IDD_MODAL_DIALOG 102
#define IDD_MODELESS_DIALOG 103
#define IDC_BUTTON_OPEN_MODAL 104
#define IDC_BUTTON_OPEN_MODELESS 105
#define IDC_BUTTON_CLOSE 106

代码说明

(1)主对话框:
   - 包含三个按钮:打开模态对话框、打开非模态对话框、关闭主对话框。
   - 点击“打开模态对话框”按钮,弹出模态对话框。
   - 点击“打开非模态对话框”按钮,弹出非模态对话框。
   - 点击“关闭”按钮,关闭主对话框。

(2)模态对话框:
   - 包含“确定”和“取消”按钮。
   - 点击按钮后关闭对话框。

(3)非模态对话框:
   - 包含“关闭”按钮。
   - 点击按钮后关闭对话框。

(4)全局变量:
   - `g_hModelessDialog` 用于保存非模态对话框的句柄。

(5)消息循环:
   - 主对话框使用 `DialogBox` 创建,自带消息循环。
   - 非模态对话框使用 `CreateDialog` 创建,需要主对话框的消息循环处理非模态对话框的消息。

运行效果

1. 主对话框显示后,点击“打开模态对话框”按钮,弹出模态对话框。在模态对话框关闭之前,主对话框无法响应操作。
2. 点击“打开非模态对话框”按钮,弹出非模态对话框。非模态对话框和主对话框可以同时操作。
3. 点击“关闭”按钮,关闭主对话框。

        通过这个案例,您可以掌握如何在Windows应用程序中使用模态对话框、非模态对话框以及消息框。

原文地址:https://blog.csdn.net/linshantang/article/details/146230661
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/585285.html

相关文章:

  • 计算机安全 第四节:访问控制(中)
  • 学习threejs,使用MeshFaceMaterial面材质容器
  • pom.xml中配置的repository,在编译器下载依赖包没生效,怎么解决
  • CNN 稠密任务经典结构
  • 市场趋势分析与策略优化
  • DeepSeek 加持!IvorySQL 文档智能助手正式上线!
  • 疗养院管理系统设计与实现(代码+数据库+LW)
  • 【Rust基础】Rust后端开发常用库
  • linux 命令 case
  • CNN的激活函数
  • 印刷店常用的PDF批量页码统计软件
  • 网络测试工具:涵盖网络测速、密码查看、故障判断与网络监测
  • Linux--普通文件的管理
  • 演员官凡正式加入创星演员出道计划,打开演员事业新篇章
  • Spring Boot:如何在业务项目中覆盖基础项目的默认实现
  • 【C++项目实战】校园公告搜索引擎:完整实现与优化指南
  • 笔记:记一次使用RabbitMq的x-delayed-message延迟消息插件,出现消息立即消费,延迟时间后再次消费,引发的重复消费问题
  • 群发邮件前的邮箱预热:构建良好发件信誉的关键步骤
  • 数据可信、隐私可控:CESS 如何打造波卡生态数据新基建?
  • VS性能分析工具