1.原理
1.1设计窗口
wc.cbClsExtra = 0; //类的额外内存 wc.cbWndExtra = 0; //窗口额外内存 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景 - 白色 wc.hCursor = LoadCursor(NULL, IDC_HAND); // 设置光标,如果第一个参数为NULL , 代表使用系统提供的光标 wc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标 如果第一个参数为NULL 代表使用系统提供的图标 wc.hInstance = hInstance; // 应用程序实例句柄, 传入WinMain 中的形参即可 //wc.IpfnWndProc = WindowProc; //回调函数 窗口过程 wc.lpszClassName = TEXT("WIN"); // 指定窗口类名称 wc.lpszMenuName = NULL; //菜单名称 wc.style = 0;//显示风格 0代表默认风格
1.2 注册窗口类
RegisterClass(&wc);
1.3创建窗口
HWND hwnd = CreateWindow( wc.lpszClassName, //类名 TEXT("WINDOWS"), //标题名 WS_OVERLAPPEDWINDOW, //风格 CW_USEDEFAULT, // x坐标 默认 CW_USEDEFAULT, // y坐标 默认 CW_USEDEFAULT, // 宽 默认 CW_USEDEFAULT, // 高 默认 NULL, //父窗口 NULL, // hMeanu 菜单 hInstance, // 实例句柄 hInstance NULL //附加值 );
1.4显示和更新
ShowWindow(hwnd, SW_SHOWNORMAL); //显示 UpdateWindow(hwnd); //更新
1.5通过循环获取消息
MSG msg; while (true) { // 消息 //第二个参数为NULL, 表示处理所有窗口的消息 // 最小和最大的过滤的消息 , 填入0 // 填0代表捕获所有消息 if (GetMessage(&msg, NULL, 0, 0) == FALSE) { break; } //翻译消息 TranslateMessage(&msg); //不为false //分发消息 DispatchMessage(&msg); }
1.6处理窗口过程
//6. 处理消息(窗口过程) 使用回调函数 LRESULT CALLBACK WindowProc( HWND hwnd, // 消息所属的窗口句柄 UINT uMsg, //具体消息名称 WM_XXX消息名 WPARAM wParam, // 键盘附加消息 LPARAM lParam //鼠标附加消息 ) { switch (uMsg) { case WM_CLOSE: DestroyWindow(hwnd); // 发送另一个消息 WM_DESTROY break; case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN: // 鼠标左键按下 int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); wchar_t buf[1024]; wsprintf(buf,TEXT("x = %d , y = %d"), xPos, yPos); MessageBox(hwnd,TEXT("aaa"),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", strlen("HELLO"))); EndPaint(hwnd,&ps); } return DefWindowProc(hwnd, uMsg, wParam, lParam); //返回值用默认处理方式 }
1.7完整代码
#include<Windows.h> //6. 处理消息(窗口过程) 使用回调函数 LRESULT CALLBACK WindowProc( HWND hwnd, // 消息所属的窗口句柄 UINT uMsg, //具体消息名称 WM_XXX消息名 WPARAM wParam, // 键盘附加消息 LPARAM lParam //鼠标附加消息 ) { switch (uMsg) { case WM_CLOSE: DestroyWindow(hwnd); // 发送另一个消息 WM_DESTROY break; case WM_DESTROY: PostQuitMessage(0); break; case WM_LBUTTONDOWN: // 鼠标左键按下 { int xPos = LOWORD(lParam); int yPos = HIWORD(lParam); wchar_t buf[1024]; wsprintf(buf, TEXT("x = %d , y = %d"), xPos, yPos); MessageBox(hwnd, TEXT("aaa"), 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"), strlen("HELLO")); EndPaint(hwnd, &ps); } } return DefWindowProc(hwnd, uMsg, wParam, lParam); //返回值用默认处理方式 } int WINAPI WinMain( HINSTANCE hInstance, // 应用程序实例句柄 HINSTANCE hPrevInstance, //上一个应用程序句柄 在Win32环境下 一般为NULL 不起作用了 LPSTR lpCmdLine, int nShowCmd // 显示命令 最大化 最小化 正常 ) { //1. 设计窗口 WNDCLASS wc; wc.cbClsExtra = 0; //类的额外内存 wc.cbWndExtra = 0; //窗口额外内存 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //设置背景 - 白色 wc.hCursor = LoadCursor(NULL, IDC_HAND); // 设置光标,如果第一个参数为NULL , 代表使用系统提供的光标 wc.hIcon = LoadIcon(NULL, IDI_ERROR); //图标 如果第一个参数为NULL 代表使用系统提供的图标 wc.hInstance = hInstance; // 应用程序实例句柄, 传入WinMain 中的形参即可 wc.lpfnWndProc = WindowProc; //回调函数 窗口过程 wc.lpszClassName = TEXT("WIN"); // 指定窗口类名称 wc.lpszMenuName = NULL; //菜单名称 wc.style = 0;//显示风格 0代表默认风格 //2. 注册窗口 RegisterClass(&wc); //3. 创建窗口 HWND hwnd = CreateWindow( wc.lpszClassName, //类名 TEXT("WINDOWS"), //标题名 WS_OVERLAPPEDWINDOW, //风格 CW_USEDEFAULT, // x坐标 默认 CW_USEDEFAULT, // y坐标 默认 CW_USEDEFAULT, // 宽 默认 CW_USEDEFAULT, // 高 默认 NULL, //父窗口 NULL, // hMeanu 菜单 hInstance, // 实例句柄 hInstance NULL //附加值 ); //4. 显示和更新 ShowWindow(hwnd, SW_SHOWNORMAL); //显示 UpdateWindow(hwnd); //更新 //5. 通过循环取消息 MSG msg; while (1) { // 消息 //第二个参数为NULL, 表示处理所有窗口的消息 // 最小和最大的过滤的消息 , 填入0 // 填0代表捕获所有消息 if (GetMessage(&msg, NULL, 0, 0) == FALSE) { break; } //翻译消息 TranslateMessage(&msg); //不为false //分发消息 DispatchMessage(&msg); } return 0; }
2.MFC
2.1 包含头文件
2.2 简单的一个MFC应用
2.2.1 代码简略
2.2.2 在vs中设置使用共享DLL的MFC
2.2.3 头文件代码
#include<afxwin.h> class MyApp:public CWinApp //CWinApp应用程序类 { public: //基类的虚函数 派生类只是重写 //程序入口 virtual BOOL InitInstance(); }; //框架类 CFrameWnd 子类 class MyFrame:public CFrameWnd //窗口框架类 { public: MyFrame(); };
2.2.4 cpp文件代码
#include"mfc.h" MyApp app;//有且只有一个全局的应用程序窗口类对象 BOOL MyApp::InitInstance() { //1.创建框架类对象 创建窗口 MyFrame* frame = new MyFrame; //显示和更新 frame->ShowWindow(SW_SHOWNORMAL); // 显示窗口 frame->UpdateWindow(); //更新窗口 m_pMainWnd = frame; //保存指向应用程序的主窗口的指针 return TRUE; } MyFrame::MyFrame() { Create(NULL, TEXT("mfc")); }
2.3 消息映射
2.3.1 简介
2.3.2 简略代码
2.3.3消息映射宏
2.3.4示例代码头文件
#include<afxwin.h> class MyApp:public CWinApp //CWinApp应用程序类 { public: //基类的虚函数 派生类只是重写 //程序入口 virtual BOOL InitInstance(); }; //框架类 CFrameWnd 子类 class MyFrame:public CFrameWnd //窗口框架类 { public: MyFrame(); //声明宏 提供消息映射机制 DECLARE_MESSAGE_MAP() afx_msg void OnLButtonDown(UINT, CPoint); afx_msg void OnChar(UINT, UINT, UINT); afx_msg void OnPaint(); };
2.3.5示例代码cpp文件
#include"mfc.h" MyApp app;//有且只有一个全局的应用程序窗口类对象 BOOL MyApp::InitInstance() { //1.创建框架类对象 创建窗口 MyFrame* frame = new MyFrame; //显示和更新 frame->ShowWindow(SW_SHOWNORMAL); // 显示窗口 frame->UpdateWindow(); //更新窗口 m_pMainWnd = frame; //保存指向应用程序的主窗口的指针 return TRUE; } //分界宏 BEGIN_MESSAGE_MAP(MyFrame, CFrameWnd) ON_WM_LBUTTONDOWN() //鼠标左键按下 ON_WM_CHAR() //键盘 ON_WM_PAINT()//绘图宏 END_MESSAGE_MAP() MyFrame::MyFrame() { Create(NULL, TEXT("mfc")); } void MyFrame::OnLButtonDown(UINT, CPoint point) { //mfc里的字符数组 TCHAR buf[1024]; //wsprintf(buf, TEXT("x = %d, y = %d"), point.x, point.y); ////对话框 //MessageBox(buf); //mfc 中的字符串 CString 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 键"), (char)key); MessageBox(str); } void MyFrame::OnPaint() { CPaintDC dc(this); //指定绘图的设备 dc.TextOutW(100, 100, TEXT("为了部落")); //画椭圆 dc.Ellipse(10, 10, 100, 100); }
2.4 字符编码
2.4.1 统计宽字节的字符串长度
2.4.2 char*与CString之间的转换
2.5 利用向导创建MFC
通过vs创建
2.6 使用
选择所需要的窗口事件 , 右键添加
如果有了OnDraw 再有OnPaint 会覆盖掉
- MFC中后缀名为Ex的函数都是扩展函数
- MFC中以Afx为前缀的函数都是全局函数 , 可以在程序的任何地方调用他们
view 视类 相片 MainFram类 相框
OnCreate相应创建窗口-设置风格属性等 Create创建窗口 WM_CREATE 消息是由Create函数调用的 一个窗口(Create)后会向系统发送WM_CREATE消息,OnCreate响应此消息
2.7 基于对话框进行操作
2.7.1 查找主窗口路径
2.7.2 模态对话框
创建类 , 去创建一个和该按钮对应的类
三种添加事件的方法
右键属性 - 控件事件
右键 - 添加事件处理程序
双击该按钮
在头文件引入刚才创建的那个对话框的类的头文件
//弹出模态对话框 CDlgExec dlg; dlg.DoModal();
2.7.3 非模态对话框
-
创建视图对应类
-
添加触发事件
-
导入头文件
-
写弹出的方法
void CMFCApplication2Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 //弹出非模态对话框 CDlgShow dlg; //创建 dlg.Create(IDD_DIALOG2);//创建一个窗口只能创建一次 , 多次会崩 //显示 dlg.ShowWindow(SW_SHOWNORMAL); }
因为生存周期的问题 , 方法执行完这个窗口类会释放, 所以需要在大对话框的头文件中去申明他
同时 大的对话框的头文件中, 需要引入这个非模态对话框的头文件
而且这只能创建一次 , 再创建一次会崩溃
所以需要放到初始化函数里,防止二次执行创建操作
找到初始化方法
后面其他UI组件的用法其实大差不差直接看着文档写或者就看着demo代码来写就行了,懒得记录了,有一说一 , 这玩意是真的辣鸡
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY