Win32编程之资源文件(三)
一、菜单资源的使用
1.菜单的分类
- 窗口的顶层菜单
- 弹出式菜单
- 系统菜单
HMENU类型表示菜单,ID表示菜单项
2、菜单资源的使用
(1).注册窗口类时设置菜单
(2).创建窗口传参设置菜单
(3).在主窗口WM_CREATE消息中利用SetMenu函数设置菜单
加载菜单资源
1 2 3 4 | HMENU LoadMenu( HINSTANCE hInstance, LPCTSTR lpMenuName ); |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | #include <Windows.h> #include <stdio.h> #include "resource.h" HINSTANCE g_hIns = NULL; //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_CREATE: { HMENU hMenu = LoadMenu(g_hIns, ( LPCWSTR )IDR_MENU1); SetMenu(hWnd, hMenu); break ; } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } //入口函数 int CALLBACK WinMain( HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { g_hIns = hIns; //设计窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = ( HBRUSH )(COLOR_WINDOW + 1); wc.hCursor = NULL; wc.hIcon = NULL; wc.hInstance = hIns; wc.lpfnWndProc = WindProc; wc.lpszClassName = TEXT( "Main" ); //1.注册窗口类时设置菜单 //wc.lpszMenuName = (LPCWSTR)IDR_MENU1; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //2.创建窗口传参设置菜单 //HMENU hMenu = LoadMenu(hIns, (LPCWSTR)IDR_MENU1); //注册窗口类 RegisterClass(&wc); //将以上所有赋值全部写入操作系统 //在内存中创建窗口 //HWND hWnd = CreateWindowEx(0, wc.lpszClassName, TEXT("Window"), WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, hMenu, hIns, NULL); HWND hWnd = CreateWindowEx(0, wc.lpszClassName, TEXT( "Window" ), WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //消息循环 MSG nMsg = { 0 }; while ( true ) { if ((PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } else { break ; } } } return 0; } |
3、菜单命令消息处理
菜单消息:WM_COMMAND
附带参数信息:
wPARAM:HIWORD:对于菜单为0,LOWORD:菜单项的ID
lPARAM:对于菜单为0
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | void onCommand( HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case ID_NEW: MessageBox(hWnd, TEXT( "新建被点击" ), TEXT( "提示" ), MB_OK); break ; case ID_EXIT: MessageBox(hWnd, TEXT( "退出被点击" ), TEXT( "提示" ), MB_OK); break ; case ID_ABOUT: MessageBox(hWnd, TEXT( "关于被点击" ), TEXT( "提示" ), MB_OK); break ; default : break ; } } //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_CREATE: { HMENU hMenu = LoadMenu(g_hIns, ( LPCWSTR )IDR_MENU1); SetMenu(hWnd, hMenu); break ; } case WM_COMMAND: { onCommand(hWnd, wParam); break ; } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } |
二、图标资源的使用
添加资源:注意图标的大小,一个图标文件中,可以有多个不同大小的图标
加载函数:
1 2 3 4 5 | HICON LoadIcon( HINSTANCE hInstance, LPCTSTR lpIconName ); 成功返回 HICON 句柄 |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <Windows.h> #include "resource.h" //窗口处理函数(自定义,处理消息) LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hWnd, msgID, wParam, lParam); } //入口函数 int CALLBACK WinMain( HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { //设计窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = ( HBRUSH )(COLOR_WINDOW + 1); wc.hCursor = NULL; wc.hIcon = LoadIcon(hIns, ( LPCWSTR )IDI_ICON1); wc.hInstance = hIns; wc.lpfnWndProc = WindProc; wc.lpszClassName = TEXT( "Main" ); wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //2.创建窗口传参设置菜单 //HMENU hMenu = LoadMenu(hIns, (LPCWSTR)IDR_MENU1); //注册窗口类 RegisterClass(&wc); //将以上所有赋值全部写入操作系统 HWND hWnd = CreateWindowEx(0, wc.lpszClassName, TEXT( "Window" ), WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //消息循环 MSG nMsg = { 0 }; while ( true ) { if ((PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } else { break ; } } } return 0; } |
三、光标资源
添加光标资源:光标的大小默认是32x32像素,每个光标都有HotSpot,是当前鼠标的热点
加载资源:
1 2 3 4 5 | HCURSOR LoadCursor( HINSTANCE hInstance, LPCTSTR lpCursorName ); hInstance可以为NULL,获取系统默认的Cursor |
设置资源:在注册窗口时,设置光标
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | //入口函数 int CALLBACK WinMain( HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { //设计窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = ( HBRUSH )(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(hIns, ( LPCWSTR )IDC_CURSOR1); wc.hIcon = LoadIcon(hIns, ( LPCWSTR )IDI_ICON1); wc.hInstance = hIns; wc.lpfnWndProc = WindProc; wc.lpszClassName = TEXT( "Main" ); wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //2.创建窗口传参设置菜单 //HMENU hMenu = LoadMenu(hIns, (LPCWSTR)IDR_MENU1); //注册窗口类 RegisterClass(&wc); //将以上所有赋值全部写入操作系统 HWND hWnd = CreateWindowEx(0, wc.lpszClassName, TEXT( "Window" ), WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //消息循环 MSG nMsg = { 0 }; while ( true ) { if ((PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } else { break ; } } } return 0; } |
使用SetCursor设置光标:
1 2 3 4 5 6 7 | HCURSOR SetCursor( HCURSOR hCursor ); WN_SETCURSOR: 消息参数;wPARAM:当前使用的光标句柄, IPARAM:LOWORD 当前区域的代码,HTCLIENT(客户区域)/HTCAPTION(标题栏区域)...;HIWORD:当前鼠标消息ID |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_SETCURSOR: { HCURSOR hCur = LoadCursor(g_hIns, ( LPCWSTR )IDC_CURSOR2); if (LOWORD(lParam) == HTCLIENT) { //鼠标如果在窗口的客户区活动 SetCursor(hCur); return 0; } } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } |
四、字符串资源
添加字符串资源:添加字符串表,在表中增减字符串
字符串资源的使用:
1 2 3 4 5 6 7 | int LoadString( HINSTANCE hInstance, UINT uID, //字符串ID LPTSTR lpBuffer, //存放字符串BUFF int nBUfferMax //字符串BUFF长度 ); 成功返回字符串长度,失败0 |
示例资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | //入口函数 int CALLBACK WinMain( HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { g_hIns = hIns; //设计窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = ( HBRUSH )(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(hIns, ( LPCWSTR )IDC_CURSOR1); wc.hIcon = LoadIcon(hIns, ( LPCWSTR )IDI_ICON1); wc.hInstance = hIns; wc.lpfnWndProc = WindProc; wc.lpszClassName = TEXT( "Main" ); wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //2.创建窗口传参设置菜单 //HMENU hMenu = LoadMenu(hIns, (LPCWSTR)IDR_MENU1); //注册窗口类 RegisterClass(&wc); //将以上所有赋值全部写入操作系统 WCHAR szTitle[256] = { 0 }; LoadString(hIns, IDS_WND, szTitle, 256); HWND hWnd = CreateWindowEx(0, wc.lpszClassName, szTitle, WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); //消息循环 MSG nMsg = { 0 }; while ( true ) { if ((PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { TranslateMessage(&nMsg); DispatchMessage(&nMsg); } else { break ; } } } return 0; } |
五、加速键资源
1.资源添加加速键表,增加命令ID对应的加速键
2.使用加速键表:
1 2 3 4 5 6 7 8 9 10 11 12 | 加载加速键表: HACCEL LoadAccelerators( HINSTANCE hInstance, LPCTSTR lpTableName );返回加速键句柄 翻译加速键: int TranslateAccelerator( HWND hWnd, //处理消息的窗口句柄 HACCEL hAccTable, //加速键句柄 LPMSG lpMsg //消息 );如果是加速键,返回非0 |
1 2 3 | 在WM_COMMAND中相应消息中,消息参数: wPARAM:HIWORD为1表示加速键,为0表示菜单 lParam:为0 |
示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #include <Windows.h> #include "resource.h" HINSTANCE g_hIns = NULL; LRESULT CALLBACK WindProc( HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam) { switch (msgID) { case WM_COMMAND: { if (LOWORD(wParam) == ID_NEW) { if (HIWORD(wParam) == 0) { MessageBox(hWnd, TEXT( "新建菜单被点击" ), TEXT( "提示" ), MB_OK); } else if (HIWORD(wParam) == 1) { MessageBox(hWnd, TEXT( "CTRL+M被点击" ), TEXT( "提示" ), MB_OK); } } break ; } default : break ; } return DefWindowProc(hWnd, msgID, wParam, lParam); } //入口函数 int CALLBACK WinMain( HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow) { g_hIns = hIns; //设计窗口类 WNDCLASS wc = { 0 }; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hbrBackground = ( HBRUSH )(COLOR_WINDOW + 1); wc.hCursor = LoadCursor(hIns, ( LPCWSTR )IDC_CURSOR1); wc.hIcon = LoadIcon(hIns, ( LPCWSTR )IDI_ICON1); wc.hInstance = hIns; wc.lpfnWndProc = WindProc; wc.lpszClassName = TEXT( "Main" ); wc.lpszMenuName = ( LPCWSTR )IDR_MENU1; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; //注册窗口类 RegisterClass(&wc); //将以上所有赋值全部写入操作系统 WCHAR szTitle[256] = { 0 }; LoadString(hIns, IDS_WND, szTitle, 256); HWND hWnd = CreateWindowEx(0, wc.lpszClassName, szTitle, WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL); //显示窗口 ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); HACCEL hAccel = LoadAccelerators(hIns, ( LPCWSTR )IDR_ACCELERATOR1); //消息循环 MSG nMsg = { 0 }; while ( true ) { if ((PeekMessage(&nMsg, NULL, 0, 0, PM_NOREMOVE))) { //有消息 if (GetMessage(&nMsg, NULL, 0, 0)) { if (!TranslateAccelerator(hWnd, hAccel, &nMsg)) { //非加速键才需要翻译和派发 TranslateMessage(&nMsg); DispatchMessage(&nMsg); } } else { break ; } } } return 0; } |
分类:
Windows核心编程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?