[C.C++] c++之windows窗口的两种创建方式

3721 0
小菜鸟一枚 2021-6-26 19:35:56 | 显示全部楼层 |阅读模式
0x1通过代码手动创建窗口
  1.先放上代码:
  1. #include <Windows.h>

  2. //全局hInstance句柄
  3. HINSTANCE hWindowInstance;

  4. //添加一个确认按钮
  5. void CreateButton1(HWND hwnd);

  6. //添加一个取消按钮
  7. void CreateButton2(HWND hwnd);

  8. //添加一个文本框
  9. void CreateTextBox(HWND hwnd);

  10. //消息循环函数
  11. LRESULT CALLBACK WndProc(
  12.     HWND hwnd,
  13.     UINT message,
  14.     WPARAM wParam,
  15.     LPARAM lParam
  16. );

  17. int WINAPI WinMain(
  18.     HINSTANCE hInstance, // handle to current instance
  19.     HINSTANCE hPrevInstance, // handle to previous instance
  20.     LPSTR lpCmdLine, // command line
  21.     int nCmdShow // show state
  22. )
  23. {
  24.     hWindowInstance = hInstance;

  25.     TCHAR lpszClassName[] = TEXT("my_window");

  26.     //创建一个自己的窗口
  27.     WNDCLASS wndclass = { 0 };//给所有成员默认赋值0,必须每一个成员赋值才能创建窗口,哪怕我们不需要使用它。

  28.     //给成员赋值
  29.     wndclass.hbrBackground = (HBRUSH)COLOR_MENU;//窗口背景色
  30.     wndclass.lpszClassName = lpszClassName;// 窗口类名
  31.     wndclass.hInstance = hInstance;//实例句柄
  32.     wndclass.lpfnWndProc = WndProc;//消息循环函数

  33.     //注册窗口类
  34.     RegisterClass(&wndclass);

  35.     //创建窗口
  36.     HWND hwnd = CreateWindow(
  37.         lpszClassName,//LPCTSTR lpClassName
  38.         TEXT("小菜鸟一枚的窗口"),//LPCTSTR lpWindowName
  39.         WS_OVERLAPPEDWINDOW,//DWORD dwStyle
  40.         100,//int x:指定窗口的初始水平位置
  41.         100,//int y:指定窗口的初始垂直位置
  42.         300,//int nWidth
  43.         300,//int nHeight
  44.         NULL,//HWND hWndParent
  45.         NULL,//HMENU hMenu
  46.         hWindowInstance,//HANDLE hlnstance
  47.         NULL//LPVOID lpParam
  48.     );

  49.     if (hwnd == NULL)//判断窗口是否创建成功
  50.     {
  51.         return 0;
  52.     }

  53.     CreateButton1(hwnd);//添加确认按钮
  54.     CreateButton2(hwnd);//添加取消按钮
  55.     CreateTextBox(hwnd);//添加一个文本框

  56.     //显示窗口
  57.     ShowWindow(hwnd, SW_SHOW);//hWnd:窗口句柄,nCmdShow:指定窗口如何显示。

  58.     MSG msg;//定义一个消息结构体

  59.     /*lpMsg:指向MSG结构的指针,该结构从线程的消息队列里接收消息信息。
  60.     hWnd:取得其消息的窗口的句柄。这是一个有特殊含义的值(NULL)。GetMessage为任何属于调用线程的窗口检索消息,线程消息通过PostThreadMessage寄送给调用线程。
  61.     wMsgFilterMin:指定被检索的最小消息值的整数。
  62.     wMsgFilterMax:指定被检索的最大消息值的整数。*/
  63.     while (GetMessage(&msg, NULL, 0, 0))
  64.     {
  65.         TranslateMessage(&msg);//翻译消息
  66.         DispatchMessage(&msg);//分发消息
  67.     }

  68.     return 0;
  69. }

  70. //消息循环函数
  71. LRESULT CALLBACK WndProc(
  72.     HWND hwnd,
  73.     UINT message,
  74.     WPARAM wParam,
  75.     LPARAM lParam
  76. )
  77. {
  78.     //处理消息
  79.     switch (message)
  80.     {
  81.     case WM_DESTROY://关闭窗口
  82.         ExitProcess(0);//进程结束
  83.     default:
  84.         break;
  85.     }
  86.     return DefWindowProc(hwnd, message, wParam, lParam);
  87. }

  88. //添加一个确认按钮
  89. void CreateButton1(HWND hwnd)
  90. {
  91.     HWND buttonHwnd = CreateWindow(
  92.         TEXT("button"),//LPCTSTR lpClassName
  93.         TEXT("确认"),//LPCTSTR lpWindowName
  94.         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_DEFPUSHBUTTON,//DWORD dwStyle
  95.         10,//int x:指定窗口的初始水平位置
  96.         100,//int y:指定窗口的初始垂直位置
  97.         80,//int nWidth
  98.         30,//int nHeight
  99.         hwnd,//HWND hWndParent
  100.         (HMENU)1001,//HMENU hMenu
  101.         hWindowInstance,//HANDLE hlnstance
  102.         NULL//LPVOID lpParam
  103.     );
  104. }

  105. //添加一个取消按钮
  106. void CreateButton2(HWND hwnd)
  107. {
  108.     HWND buttonHwnd = CreateWindow(
  109.         TEXT("button"),//LPCTSTR lpClassName
  110.         TEXT("取消"),//LPCTSTR lpWindowName
  111.         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_DEFPUSHBUTTON,//DWORD dwStyle
  112.         100,//int x:指定窗口的初始水平位置
  113.         100,//int y:指定窗口的初始垂直位置
  114.         80,//int nWidth
  115.         30,//int nHeight
  116.         hwnd,//HWND hWndParent
  117.         (HMENU)1002,//HMENU hMenu
  118.         hWindowInstance,//HANDLE hlnstance
  119.         NULL//LPVOID lpParam
  120.     );
  121. }

  122. //添加一个文本框
  123. void CreateTextBox(HWND hwnd)
  124. {
  125.     HWND hEditResult = CreateWindow(
  126.         TEXT("EDIT"), //建立文本框
  127.         NULL,
  128.         WS_CHILD | WS_VISIBLE | ES_RIGHT | WS_BORDER,
  129.         10, 50,
  130.         200, 30,
  131.         hwnd,
  132.         (HMENU)1003,
  133.         hWindowInstance,
  134.         NULL);
  135. }
复制代码

&#8195;&#8195;2.首先创建一个窗口类,然后设置窗口类的属性,接着注册窗口,然后创建窗口,最后将窗口显示出来。
&#8195;&#8195;3.windows是事件驱动模式,基于消息处理各种事件。所以有了窗口后需要循环接收窗口传来的消息,将消息翻译和转发。在创建窗口类的时候我们要指定消息循环处理函数,所以我们要实现一个消息循环函数。
1)可以通过if-else,也可以switch-case处理消息
2)消息处理完后需要return返回,告诉window这条消息已经处理过了
3)我们没有处理的消息可以由window帮我们处理,return DefWindowProc(hwnd, message, wParam, lParam);
&#8195;&#8195;4.有了窗口为我们就能往里面添加组件了,与创建父窗口不一样,子窗口直接调用CreateWindow创建窗口。
1)TEXT("button"),window会帮我们创建一个这样的类
2)需要将窗口样式设置为WS_CHILD,并将父窗口句柄传进来
3)HMENU,可以直接给一个常量,强制转换即可,作为菜单标识。
&#8195;&#8195;5.如果要添加多个组件只需按照需要往里面添加即可,最终形成如上代码,运行结果见下图。

0x2通过资源文件创建窗口
&#8195;&#8195;1.首先还是创建一个空的win32项目,添加WinMain函数:
  1. #include<Windows.h>

  2. int WINAPI WinMain(
  3.     HINSTANCE hInstance, // handle to current instance
  4.     HINSTANCE hPrevInstance, // handle to previous instance
  5.     LPSTR lpCmdLine, // command line
  6.     int nCmdShow // show state
  7. )
  8. {

  9.     return 0;
  10. }
复制代码

&#8195;&#8195;3.添加一个.rc资源文件,然后在资源视图-》添加资源-》新建dialog,如下图所示。

&#8195;&#8195;4.创建完成会自带两个按钮,我们也可以自己添加,加入两个按钮长宽,不一样,水平没对齐,可以右上角的调整按钮,自动对齐和保持长宽一直。
&#8195;&#8195;5.在对话框窗口找到右侧的工具箱添加static text和edit control(一定不要在上面右键添加控件),例如标签文本,文本框等等,然后右键在属性里面设置它的标题等等,然后我们在看自动帮我们生成的资源头文件:
#define IDD_DIALOG1                     101
#define IDC_EDIT1                       1002
#define IDC_EDIT2                       1003
#define IDC_BUTTON1                     1004
#define IDC_BUTTON2                     1005
这几个宏定义就是我们前面第一种方式创建窗口添加组件用到的(HMENU)。
&#8195;&#8195;6.对话框消息需要用WM_COMMAND和wParam组合获取,这里我使用的是edit control文本框,可以通过GetDlgItem和GetWindowText函数获取文本框的内容。
&#8195;&#8195;7.最后的代码如下:
  1. #include <Windows.h>
  2. #include "resource.h"

  3. //对话框消息循环函数
  4. BOOL CALLBACK DialogProc(HWND hwndDlg, UINT UMsg, WPARAM wParam, LPARAM IParam);

  5. int WINAPI WinMain(
  6.     HINSTANCE hInstance, // handle to current instance
  7.     HINSTANCE hPrevInstance, // handle to previous instance
  8.     LPSTR lpCmdLine, // command line
  9.     int nCmdShow // show state
  10. )
  11. {
  12.     /*
  13.     hlnstance:标识一个模块的事例该模块的可执行文件含有对话框模板。
  14.     IpTemplate:标识对话框模板。用MAKEINTRESOURCE宏指令创建此值。
  15.     hWndParent:指定拥有对话框的窗口。
  16.     IpDialogFunc:指向对话框过程的指针。
  17.     */
  18.     DialogBox( hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);

  19.     return 0;
  20. }

  21. //对话框消息循环函数
  22. BOOL CALLBACK DialogProc(HWND hwndDlg, UINT UMsg, WPARAM wParam, LPARAM IParam)
  23. {
  24.     HWND hwndUser = NULL;
  25.     HWND hwndPass = NULL;

  26.     switch (UMsg)
  27.     {
  28.     case WM_COMMAND:
  29.         switch (wParam)
  30.         {
  31.         case IDC_BUTTON1:
  32.             TCHAR userBuf[50];
  33.             TCHAR passBuf[50];
  34.             hwndUser = GetDlgItem(hwndDlg, IDC_EDIT1);//获取第一个文本框句柄
  35.             hwndPass = GetDlgItem(hwndDlg, IDC_EDIT2);//获取第二个文本框句柄
  36.             //获取句柄里面的内容
  37.             GetWindowText(hwndUser, userBuf, 50);
  38.             GetWindowText(hwndPass, passBuf, 50);

  39.             MessageBox(hwndDlg, TEXT("您点击了确认按钮!"), TEXT("小菜鸟提醒您:"), MB_ICONWARNING);
  40.             return TRUE;
  41.         case IDC_BUTTON2:
  42.             MessageBox(hwndDlg, TEXT("您点击了取消按钮!"), TEXT("小菜鸟提醒您:"), MB_ICONWARNING);
  43.             return TRUE;
  44.         case IDCANCEL:
  45.             ExitProcess(0);
  46.         }
  47.     }

  48.     return FALSE;
  49. }
复制代码


0x3总结
&#8195;&#8195;1.通过dialogbox创建的窗口不能调用DefWindowProc,而是通过TRUE代表已经处理,FALSE代表交给系统处理。
&#8195;&#8195;2.Window窗口如果不处理需要调用DefWindowProc函数,由系统处理消息。
&#8195;&#8195;3.通过dialogBOX创建的对话框省略了窗口类的创建、注册和消息循环。
&#8195;&#8195;4.通过PS将图片存储为ico格式文件,添加资源-》icon即可给生成的exe文件加上图标
0x4参考资料:
WinAPI大全
&#8195;&#8195S:善于总结,善于发现,找到分析问题的思路和解决问题的办法。虽然我现在还是零基础的小菜鸟一枚,也许逆天改命我会失败,但也有着成功的可能,只要还有希望,就决不放弃!

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行