ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

MFC入门

2021-05-25 10:32:39  阅读:187  来源: 互联网

标签:stHwnd MFC 窗口 入门 WM stWndClass CMfcTestDlg NULL


一. Win32的界面编写

  1. 实现一个带按钮并响应点击事件的界面,代码如下:

 1 #include <tchar.h>
 2 #include <windows.h>
 3 #include "CommCtrl.h"
 4 
 5 #define IDC_BTN_TEST (101)
 6 
 7 //窗口过程函数 
 8 LRESULT CALLBACK pfnWndProc(HWND stHwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 9 {
10     switch (uiMsg)
11     {
12     case WM_CREATE:
13         ::CreateWindow(WC_BUTTON, _T("按钮测试"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 200, 200, 120, 50, stHwnd, (HMENU)IDC_BTN_TEST, NULL, NULL);
14         break;
15     case WM_COMMAND:
16         if ((IDC_BTN_TEST == LOWORD(wParam)) && (BN_CLICKED == HIWORD(wParam)))//点击按钮响应
17         {
18             ::MessageBox(NULL, _T("你点击了测试按钮"), _T("点击测试"), MB_OK);
19         }
20         break;
21     case WM_DESTROY:
22         PostQuitMessage(0);
23         break;
24     default:
25         return DefWindowProc(stHwnd, uiMsg, wParam, lParam);
26     }
27 
28     return 0;
29 }
30 
31 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
32 {
33     MSG stMsg;
34     memset(&stMsg, 0, sizeof (stMsg));
35     HWND stHwnd;
36     memset(&stHwnd, 0, sizeof (stHwnd));
37     WNDCLASS stWndClass;
38     memset(&stWndClass, 0, sizeof (stWndClass));
39     const TCHAR szAppName[] = _T("windowsUI");
40 
41     stWndClass.style = CS_HREDRAW | CS_VREDRAW;
42     stWndClass.lpfnWndProc = pfnWndProc;
43     stWndClass.cbClsExtra = 0;
44     stWndClass.cbWndExtra = 0;
45 
46     stWndClass.hInstance = hInstance;
47     stWndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
48     stWndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
49     stWndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
50     stWndClass.lpszMenuName = NULL;
51     stWndClass.lpszClassName = szAppName;
52 
53     if (!RegisterClass(&stWndClass))//注册窗口类
54     {
55         MessageBox(NULL, _T("Regiester failure"), szAppName, MB_ICONERROR);
56         return 0;
57     }
58 
59     stHwnd = CreateWindow(szAppName, //创建窗口
60         _T("windows UI"),
61         WS_OVERLAPPEDWINDOW,
62         CW_USEDEFAULT,
63         CW_USEDEFAULT,
64         800,
65         600,
66         NULL,
67         NULL,
68         hInstance,
69         NULL);
70 
71     ShowWindow(stHwnd, iCmdShow); //显示窗口
72     UpdateWindow(stHwnd);
73 
74     while (GetMessage(&stMsg, NULL, 0, 0))//消息循环
75     {
76         TranslateMessage(&stMsg);
77         DispatchMessage(&stMsg);
78     }
79 
80     return stMsg.wParam;
81 }
View Code

  2. 代码量大?记不住?为嘛不使用MFC实现?

    • 不用记这些参数什么的,但是UI流程必须要理解:注册窗口类---->创建窗口---->显示窗口---->消息循环---->窗口过程;
    • MFC本质是对windows的原生控件进行了封装,为了更好地使用MFC,可以多熟悉CommCtrl.h文件;  

二. MFC界面编写

  1. 同样实现一个带按钮并点击事件的界面(代码就不贴了,比较简单),生成两个重要文件MfcTest.cpp和MfcTestDlg.cpp

  2. 代码入口在哪?也就是WinMain函数在哪?我要怎么写界面?

    • CUI(控制台)入口函数:main   GUI(win32)入口函数:WinMain          Dll(动态库)入口函数:DllMain;
    • MFC除了对原生界面进行封装外,还对线程,文件,网络,字符串,STL等都进行了封装,但本质是win32程序;
    • MfcTest.cpp主线程类,MfcTestDlg.cpp主窗口类;

   3. MfcTest.cpp主线程类分析:

    • 通过“调用堆栈”可以追溯到WinMain函数,通过一步步调用,最后调用到MfcTest.cpp的InitInstance函数,那我们就可以认为InitInstance == WinMain
1 _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
2     _In_ LPTSTR lpCmdLine, int nCmdShow)
3 #pragma warning(suppress: 4985)
4 {
5     // call shared/exported WinMain
6     return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
7 }
View Code
    • 入口函数找到了,那么像win32那样的界面是怎么创建的呢?在主线程里我们继续分析,可以找到窗口生成的如下代码:
1     CMfcTestDlg dlg;
2     m_pMainWnd = &dlg;
3     INT_PTR nResponse = dlg.DoModal();
4     
View Code

  4. MfcTestDlg.cpp主窗口类分析:

    • 窗口是怎么生成的?我们看下代码对比:
 1 //win32
 2     if (!RegisterClass(&stWndClass))//注册窗口类
 3     {
 4         MessageBox(NULL, _T("Regiester failure"), szAppName, MB_ICONERROR);
 5         return 0;
 6     }
 7 
 8     stHwnd = CreateWindow(szAppName, //创建窗口
 9         _T("windows UI"),
10         WS_OVERLAPPEDWINDOW,
11         CW_USEDEFAULT,
12         CW_USEDEFAULT,
13         800,
14         600,
15         NULL,
16         NULL,
17         hInstance,
18         NULL);
19 
20     ShowWindow(stHwnd, iCmdShow); //显示窗口
21     UpdateWindow(stHwnd);
22 
23 ... ...
24 
25 //MFC
26     CMfcTestDlg dlg;
27     m_pMainWnd = &dlg;
28     INT_PTR nResponse = dlg.DoModal();
29 
30 //这里不纠结模态与非模态对面框
View Code
    • 那么窗口过程呢?怎么找不到,我们再来对比下:
 1 //窗口过程函数 
 2 LRESULT CALLBACK pfnWndProc(HWND stHwnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 3 {
 4     switch (uiMsg)
 5     {
 6     case WM_CREATE:
 7         OnInitDialog();//CMfcTestDlg
 8         break;
 9     case WM_COMMAND:
10         OnSysCommand();//CMfcTestDlg,先不作判断,只是简单对比
11         break;
12     case WM_PAINT:
13         OnPaint();//CMfcTestDlg
14         break;
15     case WM_QUERYDRAGICON:
16         OnQueryDragIcon();//CMfcTestDlg
17         break;
18     case WM_DESTROY:
19         PostQuitMessage(0);
20         break;
21     default:
22         return DefWindowProc(stHwnd, uiMsg, wParam, lParam);
23     }
24 
25     return 0;
26 }
View Code
    • 通过对比,我们知道MFC只是对win32的窗口生成和窗口消息进行了二次封装,最后我们再分析下消息列表是怎么回事:
1 BEGIN_MESSAGE_MAP(CMfcTestDlg, CDialogEx)
2     ON_WM_SYSCOMMAND()
3     ON_WM_PAINT()
4     ON_WM_QUERYDRAGICON()
5     ON_BN_CLICKED(IDC_BTN_TEST1, &CMfcTestDlg::OnBnClickedBtnTest)
6     ON_BN_CLICKED(IDC_BTN_TEST2, &CMfcTestDlg::OnBnClickedBtnTest2)
7     ON_MESSAGE(WM_USER_BTN, &CMfcTestDlg::OnUserBtnTest)
8 END_MESSAGE_MAP()
View Code
    • F12跟进里面各种宏头都看晕了,但是说白了就是将消息ID与消息处理函数绑定起来,想想C11里的std::bind性能或者委托模式的CDelegate实现;

  5. 窗口消息之间的相互传递

    • 在这里只说下自定义消息的传递SendMessage(同步)和PostMessage(异步),代码如下:
 1 //自定义消息
 2 #define WM_USER_BTN (WM_USER + 100)
 3 
 4 ... ...
 5 
 6 BEGIN_MESSAGE_MAP(CMfcTestDlg, CDialogEx)
 7         ... ...
 8     ON_MESSAGE(WM_USER_BTN, &CMfcTestDlg::OnUserBtnTest)
 9 END_MESSAGE_MAP()    
10 
11 ... ... 
12 
13 LRESULT CMfcTestDlg::OnUserBtnTest(WPARAM wParam, LPARAM lParam)
14 {
15     MessageBox(_T("收到自定义消息"));
16 
17     return NULL;
18 }
View Code    

标签:stHwnd,MFC,窗口,入门,WM,stWndClass,CMfcTestDlg,NULL
来源: https://www.cnblogs.com/zhoushen4576/p/14807602.html

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

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

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

ICode9版权所有