当前位置: 首页 > news >正文

MFC简单入门学习

     1. 基本概念

        (1) SDK 和 API

        SDK:软件开发工具包(Software Development Kit),第三方写好了写好的东西,花点儿钱你去使用就好了

        API: 程序接口(Application Programming Interface),我们工作基本上都是些API

       (2)窗口和句柄

        窗口是Windows应用程序中非常重要的一个元素,一个Windows应用程序至少要有一个窗口,称为主窗口。

        句柄(HANDLE)是Windows应用程序中一个非常重要的概念,在Windows程序中,有各种各样的资源(窗口、图标、光标、画刷),系统在创建这些资源时会为他们分配内存,并返回标识这些资源的标识号,即句柄。比如有图标句柄(HICO)、光标句柄(HCURSOR)和画刷句柄(HBRUSH)。在Windows应用程序中,窗口是通过窗口句柄(HWND)来标识的。我们要对某个窗口进行操作,首先就要得到这个窗口的句柄。

        (3)消息和消息队列

        

        例:用户在窗口中画图的时候,按下鼠标左键,此时,操作系统会感知到一件事,于是将这个事件包装成一个消息,投递到应用程序的消息队列中,等待应用程序的处理。

注意:所有以xxxWindows结尾的函数发出来的消息都不会进入到消息队列,而是直接走到窗口过程中。所以如果一个函数发出了消息不会回到消息队列中,而是会直接进行④处理相应的窗口过程。

(4)WinMain函数

        WinMain是Windows程序的入口点函数,与DOS程序的入口点函数main的作用相同,当WinMain 函数结束或返回时,Windows应用程序结束。

2. Windows编程模型

        (1)创建项目(visual studio 2022)


        (2)WinMain函数的定义

       define WINAPI __stdcall 参数的传递顺序,从右到左依次入栈,并且在函数返回前清空堆栈 

        (3)创建一个窗口

                ① 设计窗口 ② 注册窗口 ③ 创建窗口 ④ 显示和更新窗口 ⑤ 通过循环取消息 ⑥ 处理消息(窗口过程)

                  示例代码:

#include <windows.h> // 底层的窗口实现
#include <stdlib.h>// 6 . 处理窗口函数
// define CALLBACK __stdcall 参数的传递顺序,从右到左依次入栈,并且在函数返回前清空堆栈
LRESULT CALLBACK Wndproc(HWND hwnd, // 消息所属的窗口句柄UINT uMsg, // 具体的消息名称 WM_XXXX消息名WPARAM wParm, // 附加参数, 键盘附加消息LPARAM lParm // 鼠标附加消息
)
{switch (uMsg){case WM_CLOSE:// 所有以xxxWindows结尾的函数都不会进入到消息队列,而是直接走到窗口过程中DestroyWindow(hwnd); //DestroyWindow 执行后会发送一个新的消息,WM_DESTROYbreak;case WM_DESTROY:PostQuitMessage(0);break;case WM_LBUTTONDOWN: // 鼠标左键按下{int xPos = LOWORD(lParm);int yPos = HIWORD(lParm);WCHAR buf[1024] = { 0 };wsprintf(buf,TEXT("x = %d,y = %d"),xPos,yPos);MessageBox(hwnd, buf, TEXT("鼠标左键按下"), MB_OK);break;}case WM_KEYDOWN: // 键盘{MessageBox(hwnd, TEXT("键盘按下"), TEXT("键盘按下标题"), MB_OK);break;}case WM_PAINT: // 绘图{PAINTSTRUCT ps;// 绘图结构体HDC hdc = BeginPaint(hwnd,&ps);TextOut(hdc, 100, 100, TEXT("hello world"), strlen("hello world"));EndPaint(hwnd, &ps);}}// 返回值使用默认处理方式return DefWindowProc(hwnd, uMsg, wParm, lParm);
}
// 程序入口函数// define WINAPI __stdcall 参数的传递顺序,从右到左依次入栈,并且在函数返回前清空堆栈
int WINAPI WinMain(HINSTANCE hInstance, // 应用程序的实例句柄HINSTANCE hPrevInstance, // 上一个应用程序句柄,在win32环境下,参数一般都为NULL,不起作用了LPSTR lpCmdLine, // char* argv[] 命令行参数int nShowCmd) // 显示命令,比如最大化,最小化,正常
{/* 创建窗口的步骤// 1. 设计窗口// 2. 注册窗口// 3. 创建窗口// 4. 显示和更新// 5. 通过循环取消息// 6. 处理消息(窗口过程)*/// 1. 设计窗口WNDCLASS wc = { 0 };wc.cbClsExtra = 0; // 类的额外内存wc.cbWndExtra = 0; // 窗口的额外内存wc.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); // 设置背景,wc.hCursor = LoadCursor(NULL, IDC_HAND); // 设置光标,如果parm1为NULL,代表使用系统提供的光标wc.hIcon = LoadIcon(NULL, IDI_ERROR);// 图标,如果parm1为NULL,代表使用系统提供的图标wc.hInstance = hInstance; // 应用程序实例句柄,传入WinMain中的形参即可wc.lpfnWndProc = Wndproc;// 窗口过程,回调函数wc.lpszClassName = TEXT("WIN");// 指定窗口的类名称wc.lpszMenuName = NULL;// 菜单名称wc.style = 0;// 显示风格,0代表默认风格// 2. 注册窗口RegisterClass(&wc);// 3. 创建窗口/*lpClassName, # 类名lpWindowName, 标题名dwStyle, 风格,WS_OVERLAPPEDWINDOW混合风格x, y, 窗口的显示坐标,CW_USEDEFAULT默认值nWidth, nHeight, 窗口的宽高 CW_USEDEFAULT默认值hWndParent, 父窗口hMenu, 菜单hInstance, 实例句柄lpParam 附加值,*/HWND hwnd = CreateWindow(wc.lpszClassName, TEXT("windows"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wc.hInstance, NULL);// 4. 显示和更新ShowWindow(hwnd, SW_SHOWNORMAL);UpdateWindow(hwnd);// 5. 通过循环取消息MSG msg;/*HWND        hwnd; 主窗口句柄UINT        message; 具体的消息名称WPARAM      wParam; 附加消息,键盘消息LPARAM      lParam; 附加消息,鼠标消息,判断左右键中键DWORD       time; 消息产生的时间POINT       pt; 附加消息,鼠标消息 x,y位置信息*/while (1){/*_Out_ LPMSG lpMsg, 消息_In_opt_ HWND hWnd, 捕获窗口,填NULL捕获所有的窗口_In_ UINT wMsgFilterMin, // 最小和最大的过滤消息,一般填0_In_ UINT wMsgFilterMax // 填0表示捕获所有的消息*/if (FALSE == GetMessage(&msg, NULL, 0, 0)) // 如果点 x 则退出{break;}else{// 翻译消息(比如有组合键Ctrl + C的时候,如果需要翻译,然后取消息队列再取消息,在分发)TranslateMessage(&msg);// 分发消息DispatchMessage(&msg);}}// 6. 处理窗口的过程return 0;
}

3. MFC入门

        (1)MFC基本概念

        MFC:微软基础类库(英语:Microsoft Foundation Classes),C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含的类包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。

        (2)第一个MFC应用程序 

注:如果visual studio2022中#include <afxwin.h>找不到,需要更新配置,链接:visual Studio2022 无法打开源文件 <afxwin.h>的解决办法

调整好之后编译通不过起不来,需要进行项目配置设置,如下图

        (3)程序执行流程

                ① 程序开始时,先实例化应用程序对象(有且只有一个)

                ② 执行程序的入口函数InitInstance()

                ③ 给框架类MyFrame对象动态分配空间(自动调用它的构造函数),在其构造函数内部,通过CWnd::Create创建窗口

                ④ 框架类对象显示窗口CWnd::ShowWindow

                ⑤ 框架类对象更新窗口CWnd::UpdateWindow

                ⑥ 保存框架类对象指针CWinThread::m_pMainWnd

示例代码:

#include <afxwin.h>// 应用程序类
class MyApp : public CWinApp
{
public:// 重写MFC的程序入口函数virtual BOOL InitInstance() override;
};// 框架类
class MyFrame : public CFrameWnd
{
public:MyFrame();
};
#include "mfc.h"MyApp app; // 全局应用程序对象
BOOL MyApp::InitInstance()
{// 创建窗口MyFrame* myFrame = new MyFrame;// 显示和更新myFrame->ShowWindow(SW_SHOWNORMAL);myFrame->UpdateWindow();this->m_pMainWnd = myFrame;return TRUE;
}MyFrame::MyFrame()
{Create(NULL, TEXT("MFC"));}

        (4)消息映射

        消息映射是一个将消息和成员函数相互关联的表。比如,框架窗口接收到一个鼠标左击消息,MFC将搜索该窗口的消息映射,如果存在一个处理WM_LBUTTONDOWN消息的处理程序,然后就调用OnLButtonDown。

        操作步骤:

        ① 声明消息映射宏(写在CFrameWnd的派生类中)

        

        ② 标识宏(BEGIN_MESSAGE_MAP和END_MESSAGE_MAP的调用之间处理消息)

        

        ③ 对应消息处理函数分别在类中声明,类外定义:

        

代码示例:

#include <afxwin.h> // mfc头文件// 应用程序类
class MyApp:public CWinApp // CWinApp应用程序类
{
public:// 程序入口virtual BOOL InitInstance() override;};// 框架类
class MyFrame :public CFrameWnd // 窗口框架类
{
public:MyFrame();afx_msg void OnLButtonUp(UINT, CPoint);afx_msg void OnLButtonDown(UINT, CPoint);afx_msg void OnChar(UINT, UINT, UINT);DECLARE_MESSAGE_MAP()};
#include "mfc.h"MyApp app; // 全局应用程序对象
BOOL MyApp::InitInstance()
{// 创建窗口MyFrame* myFrame = new MyFrame;// 显示和更新myFrame->ShowWindow(SW_SHOWNORMAL);myFrame->UpdateWindow();this->m_pMainWnd = myFrame;return TRUE;
}BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd)ON_WM_LBUTTONUP()ON_WM_LBUTTONDOWN()ON_WM_CHAR()
END_MESSAGE_MAP()MyFrame::MyFrame()
{Create(NULL,TEXT("MFC"));}void MyFrame::OnLButtonUp(UINT, CPoint)
{MessageBox(TEXT("松开鼠标左键"));
}void MyFrame::OnLButtonDown(UINT, CPoint point)
{CString str;str.Format(TEXT("当前光标的坐标为: X=%d,Y=%d"), point.x, point.y);MessageBox(str);
}void MyFrame::OnChar(UINT key, UINT, UINT)
{CString str;str.Format(TEXT("按下了%c键"), key);MessageBox(str);
}

        (5)Windows字符集

                ① 多字节字符集

                        一个字符代表一个字节,比如ASCII字符集

                ② 宽字符集(Unicode字符集)

                        UTF8:一个字符占3个字节

                        GBK:一个字符占2个字节

                a. 多字节转宽字节,在字符串前加L     

                b. 关于MFC中的TEXT函数(自适应字符集,无论系统设置的事多字符集还是宽字符集TEXT函数有个宏可以自动适应)           

                c. 统计宽字符的长度

                        比如多字节:char * str = "abc", strlen(str)就是字符串长度了

                        宽字节:wchar_t str = L"abc", wcslen(str)就是宽字节下的字符串长度

                d. char* 与 CString之间的转换

                        char* -> CString: char* p = "abc";CString str(p);

                        CString -> char*: CstringA tmp; tmp = str;char* pp = tmp.GetBuffer();

                

http://www.dtcms.com/a/532458.html

相关文章:

  • HD 钱包- MetaMask
  • 米拓做的网站如何改代码互联网站备案登记表
  • 【Go】--抛出和处理异常
  • Word转PDF工具,免费生成图片型文档
  • [sam2图像分割] MemoryAttentionLayer._forward_ca | 交叉注意力
  • 孝感网站建设公司电子商务平台内经营者享有公平交易的权利
  • Go语言:常量计数器iota的意义
  • 27-Scikit Learn:讲解Python中经典的机器学习工具库
  • 做网站运营工作流程网络营销概念
  • nnUNetv2
  • Android Studio新手开发第三十二天
  • 《神领物流》day08-作业范围微服务_完整代码【简单易懂注释版】
  • 西安网站定制开发h5课件制作软件
  • ABAP 调用接口传输文件(multipart form-data)
  • 联邦学习:现状与展望!
  • Linux IPC 为什么要这么架构
  • 实验室PRCV 2025论文分享|如何利用大模型自动生成高质量英语阅读理解练习题
  • C 转 C++:高效上手的核心容器与函数指南
  • 网站建设人员岗位设置网站建设职业兴趣要求
  • MyBatis操作数据库入门
  • 美团网站开发北京网站建设外包公司
  • [nanoGPT] 编排训练 | `get_batch` | AdamW | `get_lr` | 分布式训练(DDP)
  • 2.2.1.1 大数据方法论与实践指南-公司产品功能命名管理
  • Spring Boot3零基础教程,@SpringBootApplication 注解详细说明,笔记63
  • Flutter 响应式 + Clean Architecture / MVU 模式 实战指南
  • 免费注册二级域名的网站网站制作哪些公司好
  • 【Go】--time包的使用
  • VR 工业组装案例
  • 网络运维管理
  • 使用STM32H723VGT6芯片驱动达妙电机