zoukankan      html  css  js  c++  java
  • 跟我一起玩Win32开发(13):握手对话框

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

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

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

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

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

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

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

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

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

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

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

    [cpp] view plain copy
     
    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如下:

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


    和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。

    [cpp] view plain copy
     
    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消息。但是,无论采用哪种方法,我们都得解决一个问题——怎么获取到静态文本控件的句柄。所以,认识一下这个函数:

    [cpp] view plain copy
     
    1. HWND WINAPI GetDlgItem(  
    2.   _In_opt_  HWND hDlg,  
    3.   _In_      int nIDDlgItem  
    4. );  

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

    [cpp] view plain copy
     
    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] = '';  
    14.             SetWindowText(hStatic, str);  
    15.         }  
    16.     }  
    17.     return 0;  


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

    好,大功告成。

    下面是完整的代码清单。

    [cpp] view plain copy
     
      1. #include <Windows.h>  
      2. #include "resource.h"  
      3.   
      4. LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam);  
      5. INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam);  
      6.   
      7. HINSTANCE hgapp; //当前应用程序句柄  
      8. int WINAPI WinMain(HINSTANCE hThisApp, HINSTANCE hPrevApp, LPSTR lpCmd, int nShow)  
      9. {  
      10.     LPCWSTR cn = L"My";  
      11.     WNDCLASS wc = {sizeof(WNDCLASS)};  
      12.     wc.hbrBackground = (HBRUSH)COLOR_WINDOW;  
      13.     wc.hInstance = hThisApp;  
      14.     wc.lpfnWndProc = WinMainProc;  
      15.     wc.lpszClassName = cn;  
      16.     wc.style = CS_HREDRAW | CS_VREDRAW;  
      17.     //注册窗口类  
      18.     RegisterClass(&wc);  
      19.     //创建窗口  
      20.     HWND hwnd = CreateWindow(cn,L"主窗口",WS_OVERLAPPEDWINDOW,  
      21.         30,22,360,280,NULL,NULL,hThisApp,NULL);  
      22.     if(!hwnd)  
      23.         return 0;  
      24.     hgapp = hThisApp;  
      25.     //显示窗口  
      26.     ShowWindow(hwnd,nShow);  
      27.     //更新窗口  
      28.     UpdateWindow(hwnd);  
      29.     //消息循环  
      30.     MSG msg;  
      31.     while (GetMessage(&msg,NULL,0,0))  
      32.     {  
      33.         TranslateMessage(&msg);  
      34.         DispatchMessage(&msg);  
      35.     }  
      36.     return 0;  
      37. }  
      38.   
      39. LRESULT CALLBACK WinMainProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM LParam)  
      40. {  
      41.     HWND hdlg;  
      42.     switch (msg)  
      43.     {  
      44.     case WM_CREATE:  
      45.         hdlg = CreateDialog(hgapp,MAKEINTRESOURCE(IDD_MYDLG),hwnd,(DLGPROC)DlgProc);  
      46.         if(hdlg)  
      47.         {  
      48.             //显示对话框  
      49.             ShowWindow(hdlg, SW_NORMAL);  
      50.         }  
      51.         return 0;  
      52.     case WM_DESTROY:  
      53.         PostQuitMessage(0);  
      54.         return 0;  
      55.     default:  
      56.         return DefWindowProc(hwnd,msg,wParam,LParam);  
      57.     }  
      58.     return 0;  
      59. }  
      60.   
      61. // 处理对话框中的数据  
      62. INT_PTR CALLBACK DlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)  
      63. {  
      64.     static int nCount = 0;//点击按钮的次数  
      65.     switch(msg)  
      66.     {  
      67.     case WM_SYSCOMMAND:  
      68.         if(wParam == SC_CLOSE)  
      69.         {  
      70.             // 如果执行了关闭  
      71.             // 销毁对话框,将收到WM_DESTROY消息  
      72.             DestroyWindow(hdlg);  
      73.         }  
      74.         return 0;  
      75.     case WM_COMMAND:  
      76.         {  
      77.             if(LOWORD(wParam) == IDC_BTN)  
      78.             {  
      79.                 nCount ++; //每点击一次,就+1  
      80.                 // 获取控件句柄  
      81.                 HWND hStatic = GetDlgItem(hdlg,IDC_DISP);  
      82.                 // 设置控件文本  
      83.                 WCHAR str[MAXCHAR];  
      84.                 // 格式化字符串  
      85.                 int n = wsprintf(str, L"你点击了%d次按钮。", nCount);  
      86.                 //在最后一个字符后加上结止符  
      87.                 str[n] = '';  
      88.                 SetWindowText(hStatic, str);  
      89.             }  
      90.         }  
      91.         return 0;  
      92.     }  
      93.     return (INT_PTR)FALSE;  
      94. }  
  • 相关阅读:
    最小二乘拟合(scipy实现)
    接口实例
    类的继承:员工和老板
    设计模式(Design Patterns)
    创建类
    面向对象1
    java随机数:彩票抽奖 + 验证码
    判断字符串中字符出现的次数+去除空格
    输出二维数组所有元素的和
    输出 一维数组中最大的数+数组遍历
  • 原文地址:https://www.cnblogs.com/weekbo/p/8681916.html
Copyright © 2011-2022 走看看