ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

初识MFC,一个简单的窗口程序

2022-07-31 23:32:58  阅读:151  来源: 互联网

标签:MFC 窗口 函数 hwnd WM wndcls 初识 消息


说明(期间写代码使用的VS2015,写博时用的VS2017,有些许差异,见谅)

1.字符问题
照着书上抄代码都发现了问题,书上使用的是VC++,本人使用的VS2015,存在着一些字符格式问题。
VS2015默认的是Unicode字符集,VC使用多字符字符集,当然你也可以去VS里面改设置,这是后话,暂且不表。
在其中,遇到了(wchar_t)类型的数据,都知道,char占一个字节,而wchar_t占两个字节,就是char的扩展类型,它自己也有一套函数集,比如求wchar_t数组长度的函数为wcslen,虽有变化,大致相同,熟悉就好了。

 

2.Win32 Application 和 Win32 Console Application 之间的区别
(不记得是哪里抄的一段话了。。。。)
1、程序不同
Win32 Application 是标准windows程序,完全拥有windows的特性,可以通过鼠标点击窗口来完成控制。(入口函数--WinMain)
Win32 Console Application是控制台应用程序,类似于MS-DOS窗口,只能运行命令行程序,不具备消息响应机制。(入口函数--main)
2、入口函数不同
Win32 Application 入口函数是WinMain(),它具有消息响应机制,可以运行图形化的C++程序。
Win32 Console Application入口函数是main(),可以访问部分windows API函数,如果你编写传统的C程序,必须建立Win32 Console程序。
3、Win32 Application它通过GUI(Graphics User Interface图形用户接口)可以把窗口界面做得比较个性化,比如圆形的、不规则形状的等等,另外,我们还可以通过鼠标点击来完成控制。所以说它是基于WINDOWS平台的32位开发环境开发应用程序(即,SDK程序)。入口函数为WinMain()。Win32 Console Application(win32控制台应用程序)往往是像MS-DOS窗口(XP中叫命令提示符)的样子出现,我们得用键盘输入各种命令来使用它,它与纯dos程序区别是:它是32位的;或者叫CUI(Character User Interface字符用户接口)。console程序以main()为入口,可以访问部分windows API函数,比如创建窗口、对话框等等。

 

3.第一个Windows程序--WinMain
VS(文件 -> 新建 -> 项目 -> windows桌面 -> Windows桌面应用程序 )反正就是创建一个win32项目的空项目(没有初始代码的那种,VS版本不同显示的新建项也不同,不过总而言之,建一个空白Windows桌面应用程序(Win32 Application)就可以了)建不了空白的也无妨,把文件删一下就可以。
首先新建一个cpp文件,用于编写代码(因为建的是一个空项目),如下图所示:

 

 

然后开始编写代码: 可以划分为以下七步--->>>
1.编写Win Main函数 ---------------- 类似于编写main函数,都是入口函数
2.设计窗口类,WNDCLASS ------------ 有过封装,直接使用,设置参数
3.注册窗口类 ----------- 需要先注册
4.创建窗口 -------------- 创建
5.显示并更新窗口 -------- 显示
6.编写消息循环 ----------- 循环查询消息队列,处理消息,针对不同的消息做出不同响应(由此实现一个应用程序)
7.编写窗口过程函数 ------ 怎么响应消息(对消息做出对应的处理)

其中使用的各个函数在代码中有相应注释:

_T(),主要就是解决字符编码问题,真麻烦,感觉 (可以去链接看一下)

MSG可以直接理解为一个消息结构体,存储着不同的消息。

最后可以发现,程序关闭时的消息传递是:WM_CLOSE -> WM_DESTROY -> WM_QUIT,后面还会遇到,暂且不表。

  1 #include <windows.h>
  2 #include <stdio.h>
  3 
  4 #include <tchar.h>
  5 
  6 /*
  7     窗口过程函数的声明 WinSunProc
  8 */
  9 LRESULT CALLBACK WinSunProc(
 10     HWND hwnd,        // 窗口句柄
 11     UINT uMsg,        // 消息标识符
 12     WPARAM wParam,    // unsigned int 
 13     LPARAM lParam    // long  两个附加信息
 14 );
 15 
 16 
 17 /*
 18     WinMain(),入口函数
 19     HINSTANCE hInstance;程序当前运行的实例的句柄
 20     HINSTANCE hPrevInstance;当前实例的前一个实例的句柄,win32环境hPrevInstance = null,参数无用
 21     LPSTR lpCmdLine;传递应用程序的命令行参数,以空终止的字符串
 22     int nCmdShow;窗口显示效果,最大/最小/隐藏
 23 */
 24 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 25 {
 26     /*
 27         设计窗口类
 28     */
 29     WNDCLASS wndcls;        // 定义一个窗口类
 30     // 设置该窗口的各个参数
 31     wndcls.cbClsExtra = 0;
 32     wndcls.cbWndExtra = 0;
 33     wndcls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
 34     wndcls.hCursor = LoadCursor(NULL, IDC_CROSS);
 35     wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);
 36     wndcls.hInstance = hInstance;
 37     wndcls.lpfnWndProc = WinSunProc;                // 窗口过程函数
 38     wndcls.lpszClassName = _T("sunxin2006");        // 窗口类名
 39     wndcls.lpszMenuName = NULL;                        // 菜单
 40     wndcls.style = CS_HREDRAW | CS_VREDRAW;
 41 
 42     /*
 43         注册窗口类
 44     */
 45     RegisterClass(&wndcls);                            // 注册窗口类
 46 
 47     /*
 48         创建窗口类
 49     */
 50     HWND hwnd;        // 窗口句柄
 51     // 创建窗口
 52     hwnd = CreateWindow(_T("sunxin2006"), _T("Windows程序"), WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL, hInstance, NULL);
 53 
 54     /*
 55         显示与更新窗口
 56     */
 57     ShowWindow(hwnd, SW_SHOWNORMAL);        // 激活并显示,窗口正常大小,(第一次显示
 58     // 目前,整个客户区无效, UpdateWindow 会检查窗口的 Update Region无效区域,当其不为空时才发送 WM_PAINT 消息
 59     // 所谓无效区域就是需要应用程序重新绘制的区域,反之则为有效区域 => 有无效区域时,发送WM_PAINT消息
 60     UpdateWindow(hwnd);                        // 会发送一个WM_PAINT信息
 61 
 62     MSG msg;            // 消息结构体
 63     // 消息循环代码
 64     while (GetMessage(&msg, NULL, 0, 0))        // GetMessage函数接收WM_QUIT返回0,此外非0,出错-1
 65     {
 66         // GetMessage函数 要检索其消息的窗口的句柄。该窗口必须属于当前线程。
 67         // 如果 hWnd 为 NULL,则 GetMessage 将检索属于当前线程的任何窗口的消息,以及当前线程的消息队列中hwnd 值为 NULL 的任何消息。
 68         // 因此,如果 hWnd 为 NULL,则同时处理窗口消息和线程消息。
 69         // 如果 hWnd 为 - 1,则 GetMessage 仅检索当前线程的消息队列中hwnd值为 NULL 的消息
 70         TranslateMessage(&msg);                    // 把快捷键消息转换为字符消息,并将转换后的新消息投递到调用线程的消息队列中
 71         DispatchMessage(&msg);
 72         // DispatchMessage函数分发一个消息给窗口程序,通常消息从GetMessage函数获得或者TranslateMessage函数传递的
 73         // 消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。
 74 
 75         // 函数DispatchMessage()负责将消息派送到相应的窗口函数。它根据msg结构中的hWnd窗口句柄成员找到相应的窗口类,
 76         // 然后根据注册窗口时wndcls类结构找到相应的窗口函数WinSunProc。由消息传递函数将消息传递给窗口函数WinSunProc进行消息处理。
 77     }
 78     return msg.wParam;
 79 }
 80 
 81 LRESULT CALLBACK WinSunProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 82 {
 83     switch (uMsg)
 84     {
 85     case WM_CHAR:        //字符信息    char * -> WCHAR *
 86         // char szChar[20];
 87         // sprintf(szChar, "char code is %d", wParam);
 88         // MessageBox(hwnd, _T(szChar), _T("char"), 0);
 89         wchar_t szChar[20];
 90         swprintf(szChar, 100, L"char code is %d", wParam);
 91         MessageBox(hwnd, szChar, _T("char"), 0);
 92         break;
 93     case WM_LBUTTONDOWN:        // 鼠标左键信息
 94         MessageBox(hwnd, _T("mouse clicked"), _T("message"), 0);
 95         HDC hdc;                // 为 DVTARGETDEVICE 结构中指定的设备创建设备上下文, TextOut等函数所需参数
 96         hdc = GetDC(hwnd);        //不能在响应MWM_PAINT时调用    
 97         TextOut(hdc, 0, 50, _T("中文有什么问题吗?"), wcslen(_T("中文有什么问题吗?")));            // 位置坐标(0,50)
 98         // 中文乱码问题,wchar 与 char 所占空间不同,故而计算空间需要使用wcslen函数,
 99         ReleaseDC(hwnd,hdc);    // GteDC 配套函数,释放资源
100         break;
101     case WM_PAINT:                // 系统会在多个不同的时机发送 WM_PAINT 消息:当第一次创建窗口,改变窗口大小,把窗口移出,最大化,最小化时
102         HDC hDC;
103         PAINTSTRUCT ps;            // 绘图信息结构
104         hDC = BeginPaint(hwnd, &ps);        // BeginPaint只能在响应MWM_PAINT时调用    
105         // BeginPaint 的一个作用就是把该 Update Region(即无效区域) 置为空, => 全部为有效区域
106         // 这样如果不调用 BeginPaint,窗口的Update Region 就一直不为空,系统就会一直发送 WM_PAINT 消息。
107         TextOut(hDC, 100, 0, _T("http://www.qutuku.com"), strlen("http://www.qutuku.com"));
108         EndPaint(hwnd, &ps);        // 释放 hDC
109         break;
110     case WM_CLOSE:
111         if (IDYES == MessageBox(hwnd, _T("是否真的结束?"), _T("message"), MB_YESNO))
112         {
113             DestroyWindow(hwnd);
114         }
115         break;
116     case WM_DESTROY:                // DestroyWindow销毁后会发送一个WM_DESTROY消息,
117         PostQuitMessage(0);            // PostQuitMessage向应用程序的消息队列中投递一条 WM_QUIT 消息,并返回
118         break;                        // GetMessage(&msg, NULL, 0, 0)收到 WM_QUIT 消息,循环结束
119     default:
120         return DefWindowProc(hwnd, uMsg, wParam, lParam);
121         // DefWindowProc这个函数是默认的窗口处理函数,我们可以把不关心的消息都丢给它来处理
122     }
123     return 0;
124 }
主要还是熟悉整个运行流程,搞清楚有哪几步,每一步都是做一些什么样的工作,即可。

2022-07-31(07-13的工作,拖延症晚期。。)

标签:MFC,窗口,函数,hwnd,WM,wndcls,初识,消息
来源: https://www.cnblogs.com/2015-16/p/16530813.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有