1. 模态对话框与非模态对话框对比
- 模态对话框是通过DialogBox函数生成窗口,且函数的返回值是EndDialog函数传递的。EndDialog是销毁窗口
- 非模态对话框CreateDialog 和ShowWindow 显示一个窗口,使用DestroyWindow来销毁对话框。EndDialog是隐藏窗口,没有真正的销毁
需要注意
- 非模态对话框作为主窗口时,需要写消息循环,且需要PostQuitMessage来退出主循环。
- 如果模态对话框作为主窗口,不需要写消息循环
- 一般是模态对话框来启动非模态对话框
2. 计算器项目练习模态与非模态对话框
平台windows 工具Visual Studio2022
resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 Calc.rc 使用
//
#define IDD_MAIN_CALC 101
#define IDI_ICON1 103
#define IDC_BNT_REM 1002
#define IDC_BNT_DELEAT 1003
#define IDC_BNT_CLEAR 1004
#define IDC_BNT_DIV 1005
#define IDC_BNT_NUM7 1006
#define IDC_BNT_NUM8 1007
#define IDC_BNT_SUB 1008
#define IDC_BNT_NUM9 1009
#define IDC_BNT_NUM4 1010
#define IDC_BNT_NUM5 1011
#define IDC_BNT_MIN 1012
#define IDC_BNT_NUM6 1013
#define IDC_BNT_NUM1 1014
#define IDC_BNT_NUM2 1015
#define IDC_BNT_ADD 1016
#define IDC_BNT_NUM3 1017
#define IDC_BNT_ADDORMIN 1018
#define IDC_BNT_NUM0 1019
#define IDC_BNT_RET 1020
#define IDC_BNT_POINT 1021
#define IDC_STATIC_PERTEXT 1022
#define IDC_STATIC_SHOWTEXT 1023
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1023
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
Calc.h
#pragma once
#include<Windows.h>
#include"resource.h"
#include<string>
#include<map>
#include <functional>
HINSTANCE g_hInstance;
std::wstring ShowText;//保存计算器显示的字符串
std::wstring PreText;
bool init = false;//判断字符串是否删除到0
bool is_op = false;//判断是否按下操作按钮
char op = 0;//记录要的操作
double num = 0.0;//记录被操作数
double ret = 0.0;
INT_PTR CALLBACK CalcProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_INITDIALOG:
{
//加载窗口图标
HICON Hicon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON1));
//发送设置窗口图标的消息
SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)Hicon);//设置大图标
SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)Hicon);//设置小图标
//设置字体
HFONT hfont=CreateFont(32, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET
, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH
, L"黑体");
HFONT hfont_pre = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET
, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH
, L"黑体");
//获取控件
HWND text_hwnd=GetDlgItem(hwnd, IDC_STATIC_SHOWTEXT);
HWND pre_hwnd = GetDlgItem(hwnd, IDC_STATIC_PERTEXT);
SendMessage(text_hwnd, WM_SETFONT, WPARAM(hfont), 0);
SendMessage(pre_hwnd, WM_SETFONT, WPARAM(hfont_pre), 0);
break;
}
case WM_COMMAND:
{
init = false;
//包装器,包装运算
std::map<char, std::function<float(float, float)>>opMap =
{
{'+',[](float x,float y) {return x + y; }},
{'-',[](float x,float y) {return x - y; }},
{'*',[](float x,float y) {return x * y; }},
{'/',[](float x,float y) {return x / y; }},
};
switch (LOWORD(wParam))
{
case IDC_BNT_NUM0:
//宽字符连接
ShowText += L"0";
break;
case IDC_BNT_NUM1:
ShowText += L"1";
break;
case IDC_BNT_NUM2:
ShowText += L"2";
break;
case IDC_BNT_NUM3:
ShowText += L"3";
break;
case IDC_BNT_NUM4:
ShowText += L"4";
break;
case IDC_BNT_NUM5:
ShowText += L"5";
break;
case IDC_BNT_NUM6:
ShowText += L"6";
break;
case IDC_BNT_NUM7:
ShowText += L"7";
break;
case IDC_BNT_NUM8:
ShowText += L"8";
break;
case IDC_BNT_NUM9:
ShowText += L"9";
break;
case IDC_BNT_CLEAR:
PreText.clear();
ShowText.clear();
ret = 0;
num = 0;
op = 0;
SetDlgItemText(hwnd, IDC_STATIC_SHOWTEXT, L"0");
init = true;
break;
case IDC_BNT_DELEAT:
{
if (ShowText.size() == 0) {
SetDlgItemText(hwnd, IDC_STATIC_SHOWTEXT, L"0");
init = true;
}
else if (ShowText.size() > 0) {
ShowText.pop_back();
if (ShowText.size() == 0) {
SetDlgItemText(hwnd, IDC_STATIC_SHOWTEXT, L"0");
init = true;
}
}
break;
}
case IDC_BNT_ADD:
{
if (ShowText.size() != 0) {
if (op != 0) {
//此时已经有操作符,说明没有按=号,需要计算
//这里先不处理
break;
}
op = '+';
ret = _wtoi(PreText.c_str());
PreText = ShowText;
PreText += L"+";
ShowText.clear();
}
break;
}
case IDC_BNT_MIN:
{
if (ShowText.size() != 0) {
if (op != 0) {
break;
}
op = '-';
PreText = ShowText;
ret = _wtoi(PreText.c_str());
PreText += L"-";
ShowText.clear();
}
break;
}
case IDC_BNT_SUB:
{
if (ShowText.size() != 0) {
if (op != 0) {
break;
}
op = '*';
PreText = ShowText;
ret = _wtoi(PreText.c_str());
PreText += L"×";
ShowText.clear();
}
break;
}
case IDC_BNT_DIV:
{
if (ShowText.size() != 0) {
if (op != 0) {
break;
}
op = '/';
PreText = ShowText;
ret = _wtoi(PreText.c_str());
PreText += L"÷";
ShowText.clear();
}
break;
}
case IDC_BNT_RET:
{
if (op != 0) {
num = _wtoi(ShowText.c_str());
PreText += std::to_wstring(num);
ret = opMap[op](ret, num);
ShowText = std::to_wstring(ret);
//清空符号
op = 0;
}
break;
}
/*case IDC_BNT_REM:
{
double num= _wtoi(ShowText.c_str());
ShowText = std::to_wstring((int)num*100);
break;
}
case IDC_BNT_POINT:
ShowText += L".";
break;*/
default:
break;
}
//设置文本
if (init == false) {
SetDlgItemText(hwnd, IDC_STATIC_SHOWTEXT, ShowText.c_str());
}
SetDlgItemText(hwnd, IDC_STATIC_PERTEXT, PreText.c_str());
break;
}
case WM_CLOSE:
EndDialog(hwnd, IDOK);
break;
default:
break;
}
return FALSE;
}
Calc.cpp
#include"Calc.h"
extern HINSTANCE g_hInstance;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow) {
g_hInstance = hInstance;
//主窗口
DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN_CALC), nullptr, CalcProc);
return 0;
}

本文介绍了模态与非模态对话框的区别,并通过一个计算器项目的实现,展示了如何在Windows环境下使用Visual Studio 2022创建这两种对话框。文章详细解析了代码流程,包括对话框的初始化、消息处理、按键事件及计算逻辑,并提供了资源文件和头文件的内容。通过这个项目,读者可以深入理解模态与非模态对话框在实际开发中的运用。
1097

被折叠的 条评论
为什么被折叠?



