一提到对话框,相信对它熟悉的人不在少数,更不用说码农们了,你可能会问,对话框和窗口有什么区别吗?本质上是没有区别的,对话框也是一种窗口(前面也说过,控件也可视为子窗口)。

最简单的对话框要数MessageBox弹出来的对话框了,是吧?这个函数我有信心,大家都会用的,毕竟很简单。

好的,废话不多扯了,马上开始本文第一件事,创建一个对话框。

对话框作为一种资源,它存放在资源文件中(.rc),如果项目中没有rc文件,第一种方法是在“解决方案资源管理器”中在“资源文件”节点右击,从菜单中选择“添加”-“新建项”来加入一个rc文件。第二种方法,可以从VS的“视图”菜单中打开“资源视图”,在资源视图中,在项目名节点上右击,从菜单中找到“添加”-“资源”。

然后,选择对话框,点新建按钮。

在属性窗口中为这个对话框名命一个ID,随便你喜欢,我把它设为IDD_MYDLG。

OK,现在,我们就可以利用可视化设计器来玩了,看看,还不错的,虽然没有WinForm的设计器那么猛。

把默认两个按钮删掉,我们从工具箱中拖放一些控件。记得为控件的ID命名,就像在WinForm里面要设置Name属性一样。

大概就这样,拖一个Static Text和Button控件,随后我们尝试实现一个功能:点击按钮后,在静态文本框中显示文本。这个编辑器怎么用,就就不说了。

保存资源文件,下面我们开始写代码。

1、在主窗口的消息处理程序中响应WM_CREATE消息,用CreateDialog函数创建并显示非模态对话框。

  1. LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam)
  2. {
  3. HWND hdlg;
  4. switch (msg)
  5. {
  6. case WM_CREATE:
  7. hdlg = CreateDialog(hgapp,MAKEINTRESOURCE(IDD_MYDLG),hwnd,(DLGPROC)DlgProc);
  8. if(hdlg)
  9. {
  10. //显示对话框
  11. ShowWindow(hdlg, SW_NORMAL);
  12. }
  13. return 0;
  14. case WM_DESTROY:
  15. PostQuitMessage(0);
  16. return 0;
  17. default:
  18. return DefWindowProc(hwnd,msg,wParam,LParam);
  19. }
  20. return 0;
  21. }

CreateDialog的最后一个参数是一个CALLBACK,这个和我们的WindowProc是一鸟样的,注意在定义该函数时,一定要先在头文件或源文件的前面声明一下,不然到这里会找不到,通常我们会把这些函数都放到WinMain函数后面来写,只是通常这样,并不是说一定要这样。

DlgProc如下:

  1. // 处理对话框中的数据
  2. INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  3. {
  4. return (INT_PTR)FALSE;
  5. }

和WindowProc一样,也有一个DefDlgProc,但是这里最好不要调用,注意MSDN上关于这函数说明的最后一段话。

The DefDlgProc function must not be called by a dialog box procedure; doing so results in recursive execution.

如果在DialogProc中调用DefDlgProc会导致死循环。其实,我们为窗口写的消息循环也是死循环,GetMessage是不断执行,除非接到WM_QUIT消息让它返回假(0)就跳出循环,而对于对话框,我们并没有为它写GetMessage,也不向它PostQuitMessage,它有可能会无法跳出循环。

现在,程序是可以运行的。

不过,无论你怎么操作,对话框还是没返应,因为现在我们还没处理相关消息。

当用户操作系统菜单或者点击标题栏的 最大化, 最小化 或 关闭 按钮,都会收到WM_SYSCOMMAND消息,如果不响应WM_SYSCOMMAND,就会放到WM_COMMAND,但WM_COMMAND通常要处理控件的消息,故最好用WM_SYSCOMMAND消息。

2、在对话框的DlgProc中响应WM_SYSCOMMAND。

  1. case WM_SYSCOMMAND:
  2. if(wParam == SC_CLOSE)
  3. {
  4. // 如果执行了关闭
  5. // 销毁对话框,将收到WM_DESTROY消息
  6. DestroyWindow(hdlg);
  7. }
  8. return 0;

3、我们已经知道响应按钮单击是处理WM_COMMAND。要改变静态文本中的文本,一可以用 Static_SetText宏,二可以用SetWindowText,三可以发送WM_SETTEXT消息。但是,无论采用哪种方法,我们都得解决一个问题——怎么获取到静态文本控件的句柄。所以,认识一下这个函数:

  1. HWND WINAPI GetDlgItem(
  2. _In_opt_  HWND hDlg,
  3. _In_      int nIDDlgItem
  4. );

你猜都猜到了,参数一是对话框的句柄,参数二是要返回句柄的控件的ID。好,我们试试。

  1. case WM_COMMAND:
  2. {
  3. if(LOWORD(wParam) == IDC_BTN)
  4. {
  5. nCount ++; //每点击一次,就+1
  6. // 获取控件句柄
  7. HWND hStatic = GetDlgItem(hdlg,IDC_DISP);
  8. // 设置控件文本
  9. WCHAR str[MAXCHAR];
  10. // 格式化字符串
  11. int n = wsprintf(str, L"你点击了%d次按钮。", nCount);
  12. //在最后一个字符后加上结止符
  13. str[n] = '\0';
  14. SetWindowText(hStatic, str);
  15. }
  16. }
  17. return 0;

现在来运行一下,每点击一次按钮,就会在静态文本控件中显示“你点击了X次按钮。

好,大功告成。

下面是完整的代码清单。

    1. #include <Windows.h>
    2. #include "resource.h"
    3. LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam);
    4. INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);
    5. HINSTANCE hgapp; //当前应用程序句柄
    6. int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow)
    7. {
    8. LPCWSTR cn = L"My";
    9. WNDCLASS wc = {sizeof(WNDCLASS)};
    10. wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    11. wc.hInstance = hThisApp;
    12. wc.lpfnWndProc = WinMainProc;
    13. wc.lpszClassName = cn;
    14. wc.style = CS_HREDRAW | CS_VREDRAW;
    15. //注册窗口类
    16. RegisterClass(&wc);
    17. //创建窗口
    18. HWND hwnd = CreateWindow(cn,L"主窗口",WS_OVERLAPPEDWINDOW,
    19. 30,22,360,280,NULL,NULL,hThisApp,NULL);
    20. if(!hwnd)
    21. return 0;
    22. hgapp = hThisApp;
    23. //显示窗口
    24. ShowWindow(hwnd,nShow);
    25. //更新窗口
    26. UpdateWindow(hwnd);
    27. //消息循环
    28. MSG msg;
    29. while (GetMessage(&msg,NULL,0,0))
    30. {
    31. TranslateMessage(&msg);
    32. DispatchMessage(&msg);
    33. }
    34. return 0;
    35. }
    36. LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam)
    37. {
    38. HWND hdlg;
    39. switch (msg)
    40. {
    41. case WM_CREATE:
    42. hdlg = CreateDialog(hgapp,MAKEINTRESOURCE(IDD_MYDLG),hwnd,(DLGPROC)DlgProc);
    43. if(hdlg)
    44. {
    45. //显示对话框
    46. ShowWindow(hdlg, SW_NORMAL);
    47. }
    48. return 0;
    49. case WM_DESTROY:
    50. PostQuitMessage(0);
    51. return 0;
    52. default:
    53. return DefWindowProc(hwnd,msg,wParam,LParam);
    54. }
    55. return 0;
    56. }
    57. // 处理对话框中的数据
    58. INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
    59. {
    60. static int nCount = 0;//点击按钮的次数
    61. switch(msg)
    62. {
    63. case WM_SYSCOMMAND:
    64. if(wParam == SC_CLOSE)
    65. {
    66. // 如果执行了关闭
    67. // 销毁对话框,将收到WM_DESTROY消息
    68. DestroyWindow(hdlg);
    69. }
    70. return 0;
    71. case WM_COMMAND:
    72. {
    73. if(LOWORD(wParam) == IDC_BTN)
    74. {
    75. nCount ++; //每点击一次,就+1
    76. // 获取控件句柄
    77. HWND hStatic = GetDlgItem(hdlg,IDC_DISP);
    78. // 设置控件文本
    79. WCHAR str[MAXCHAR];
    80. // 格式化字符串
    81. int n = wsprintf(str, L"你点击了%d次按钮。", nCount);
    82. //在最后一个字符后加上结止符
    83. str[n] = '\0';
    84. SetWindowText(hStatic, str);
    85. }
    86. }
    87. return 0;
    88. }
    89. return (INT_PTR)FALSE;
    90. }

跟我一起玩Win32开发(13):握手对话框的更多相关文章

  1. 跟我一起玩Win32开发(转自CSDN-东邪独孤)

    跟我一起玩Win32开发(1):关于C++的几个要点 跟我一起玩Win32开发(2):完整的开发流程 跟我一起玩Win32开发(3):窗口的重绘 跟我一起玩Win32开发(4):创建菜单 跟我一起玩W ...

  2. 跟我一起玩Win32开发(17):启动和结束进程

    这里我再次说明一下,我不知道为什么,现在的人那么喜欢走极端,估计是价值观都“升级”了的缘故吧. 我撰写这一系列Win32相关的文章,并不是叫大家一定要用Win32去开发项目,仅仅是给大家了解一下,Wi ...

  3. 跟我一起玩Win32开发(18):使用对话框的两个技巧

    相信大家知道对话框怎么用了,就是先用“资源编辑器”设计一个对话框,然后在代码中加载处理.今天,我向大家分享两个使用对话框的技巧,还是比较实用的.不用担心,先喝杯茶,很简单的,一点也不复杂,总之,看俺写 ...

  4. 跟我一起玩Win32开发(19):浏览和打开文件

    在应用程序中,我们很经常要实现的功能,是Open文件或保存文件对话框,让用户来选择一个或N个文件.本文我将介绍两种思路,第一种方法较为复杂,第二种方法较为简单. 方法一:老规矩 这是一种传统方法,使用 ...

  5. 跟我一起玩Win32开发(12):使用控件——单选按钮

    今天,咱们还是接着玩“控件斗地主”,这是我原创的超级游戏,有益身心健康,玩一朝,十年少. 哦,对,脑细胞极速运动了一下,想起了一个问题,这个破问题虽然网上有很多种解决方案,但是,并没有让所有人都解决问 ...

  6. 跟我一起玩Win32开发(21):复制&粘贴&剪贴板操作

    我要提醒一下大家,看了我的博文学到的知识,千万不要用于实际开发,不然你会被你的上司骂:“妈的,这些东西哪来的,从来没有人这样做过.”不信你试试,脑细胞被冻结的经理或者技术总监们肯定会这样说的. 如果是 ...

  7. 跟我一起玩Win32开发(4):创建菜单

    也不知道发生什么事情,CSDN把我的文章弄到首页,结果有不少说我在误人子弟,是啊,我去年就说过了,如果你要成为砖家级人物,请远离我的博客,我这个人没什么特长,唯一厉害的一点就是不相信权威,鄙视砖家,所 ...

  8. 跟我一起玩Win32开发(2):完整的开发流程

    上一篇中我给各位说了一般人认为C++中较为难的东西——指针.其实对于C++,难点当然不局限在指针这玩意儿上,还有一些有趣的概念,如模板类.虚基类.纯虚函数等,这些都是概念性的东西,几乎每一本C++书上 ...

  9. 跟我一起玩Win32开发(25):监视剪贴板

    自从郭大侠和蓉儿离开桃花岛后,最近岛比较寂静,有一种“门前冷落鞍马稀”的感觉.于是,老邪就拿出<九阴真经>认真阅读,同时用迅雷下载经典大剧<汉武大帝>晚上睡觉前看上几集,老邪一 ...

随机推荐

  1. 为activity添加左右手势识别

    android开发中为activity添加左右手势识别.如右滑关闭当前页面 /* * for左右手势 * 1.复制以下的内容到目标Activity * 2.目标Activity的onCreate()调 ...

  2. bootstrap-Table服务端分页,获取到的数据怎么再页面的表格里显示

    <table class="table table-hover" id="userTable" > <thead> <tr> ...

  3. 在git push前怎样遗弃掉历史commit

    今天写了一天代码,然后 git hub commit 了 多达 7 次. 可是都没有把改动正式推送上去. 结果最后要推送的时候发现中间有一个提交文件超过了100M. 是 vs 的代码性能分析报告 .v ...

  4. 有奖试读&amp;征文——我们在互联网上奋斗的故事 获奖名单发布

    互联网是一个年轻的行业,同一时候也是一个推陈出新.不断进化的行业. 中国互联网行业在近期的十五年里.以如何的方式在"进化".我相信非常多奋斗在互联网战线上的你们最深有感触.读一读& ...

  5. MySQL基本语句优化10个原则

    在数据库应用中,程序员们通过不断的实践总结了很多经验,这些经验是一些普遍适用的规则.每一个程序员都应该了解并记住它们,在构造SQL语句时,养成良好的习惯.以下10条比较重要的原则供大家参考. 原则1: ...

  6. maven安装的详细步骤

    1.下载maven的bin,在apache官方网站下载.window系统下的下载红色方框的 2.解压后, 把bin的位置设在环境变量里,新建环境变量 MAVEN_HOME.这个配置是方便以后更换mav ...

  7. WPF之Binding深入探讨 转载:http://blog.csdn.net/fwj380891124/article/details/8107646

    1,Data Binding在WPF中的地位 程序的本质是数据+算法.数据会在存储.逻辑和界面三层之间流通,所以站在数据的角度上来看,这三层都很重要.但算法在3层中的分布是不均匀的,对于一个3层结构的 ...

  8. 理解iOS Event Handling

    写在前面 最近的一个iOS App项目中遇到了这么问题:通过App访问服务器的大多数资源不需要登录,但是访问某些资源是需要用户提供验证的,一般来说,通常App的做法(譬如美团App)将这些资源放在“我 ...

  9. BZOJ1499 单调队列+DP

    1499: [NOI2005]瑰丽华尔兹 Time Limit: 3 Sec  Memory Limit: 64 MBSubmit: 1560  Solved: 949[Submit][Status] ...

  10. 【POJ 1151】 Altlantis

    [题目链接] 点击打开链接 [算法] 线段树扫描线 推荐一篇比较容易理解的线段树扫描线的文章 : https://blog.csdn.net/u013480600/article/details/22 ...