Windows资源是一种二进制数据,由链接器链接进程序成为程序的一部分,通过资源的方式可以很方便的对应用程序进行扩展。在Windows中资源可以是系统自定义的,也可以是用户自定义的。在本篇文章中为大家讲解菜单资源,上下文菜单,图标资源,光标资源,加速键资源的创建方法,这里我使用的编译器为visual studio2022版本。
一.菜单资源
1.菜单分类
- 窗口顶层菜单
- 弹出式菜单
- 系统菜单
- HMENU类型表示菜单,ID表示菜单项
2.如何创建菜单资源
对于目前的编译器,我们自己添加资源还是非常容易的,我们只需要使用可视化图形界面就可以。
- 1.添加菜单资源
- <1>.右键单击资源文件,选择添加–>资源
- <2>.选择添加Menu资源
- <3>.添加想要的菜单资源,并且设置消息ID
- 2.获取本进程菜单句柄
HMENU LoadMenu( HINSTANCE hInstance; //包含要加载的菜单资源模块的句柄 LPCSTR lpMenuName //菜单资源的名称 );
- 3.加载菜单资源
- <1>.注册窗口类时设置菜单(lpszMenuName)
- <2>.创建窗口时,传参设置菜单
- <3>.在主窗口WM_CREATE消息中使用SetMenu函数设置菜单
SetMenu( HWND hWnd, //窗口句柄 HMENU hMenu, //菜单句柄 );设置成功,返回非零
在这里对SetMenu函数不做过多的解释了,大家可以到MSDN官方文档解释SetMenu函数中查看该函数的详细介绍。
- 4.处理菜单消息在学习处理菜单消息之前,我们来学习一种常见的消息类型:WM_COMMAND
- 发出时间:当用户从菜单中选择命令项,空间将通知消息发送到其父窗口或翻译快捷键击时发送。
- 附加信息
- wParam:
- HIWORD:对于菜单为0
- LOWORD:菜单项的ID
- lParam:对于菜单为0
3.实操展示
我们来使用WM_COMMAND消息来处理菜单按钮:
设置菜单:
回调函数处理:
LRESULT CALLBACK WindowProc( IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam ) { char output[256] = { 0 }; switch (uMsg) { //常见消息 case WM_DESTROY: { PostQuitMessage(0); break; } case WM_SYSCOMMAND: { sprintf(output, TEXT("检测到WM_COMMAND消息\n")); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_CREATE: { sprintf(output, "检测到WM_CREATE消息,将创建窗口。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_SIZE: { sprintf(output, "lParam:窗口宽变化为:%d,窗口高变化为:%d \n", HIWORD(lParam), LOWORD(lParam)); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } //菜单命令消息 case WM_COMMAND: { switch(LOWORD(wParam)) { case MY_OPEN: { sprintf(output, "打开按钮被点击,请到回调函数中做具体处理。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case MY_QUIT: { sprintf(output, "退出按钮被点击,请到回调函数中做具体处理。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case IDM_ABOUT: { sprintf(output, "帮助按钮被点击,请到回调函数中做具体处理。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); } case MY_NEWFILE: { sprintf(output, "打开新文件按钮被点击,请到回调函数中做具体处理。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case MY_LASTTIMEFILE: { sprintf(output, "上次打开文件按钮被点击,请到回调函数中做具体处理。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } } break; } //键盘消息 case WM_KEYDOWN: { sprintf(output, "检测到WM_KEYDOWN消息,键码值:%d.\n", wParam); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_KEYUP: { sprintf(output, "检测到WM_KEYUP消息,键码值:%d.该按键被放开\n", wParam); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } //鼠标消息 case WM_LBUTTONDOWN: { sprintf(output, "检测到WM_LBUTTONDOWN消息,鼠标左键被按下。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_LBUTTONUP: { sprintf(output, "检测到WM_LBUTTONUP消息,鼠标左键被放开。\n"); WriteConsole(g_hOUTPUT, output, strlen(output),0,0); break; } case WM_RBUTTONDOWN: { sprintf(output, "检测到WM_RBUTTON消息,鼠标右键被按下。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_RBUTTONUP: { sprintf(output, "检测到WM_RBUTTON消息,鼠标右键被放开。\n"); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); } case WM_MOUSEMOVE: { sprintf(output, "检测到WM_MOUSEMOVE消息,鼠标移动中,鼠标位置(%d,%d).\n", LOWORD(lParam), HIWORD(lParam)); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } case WM_MOUSEWHEEL: { sprintf(output, "鼠标滚轮滚动中,偏移量:%d,鼠标当前位置(%d,%d)\n",HIWORD(wParam), LOWORD(lParam), HIWORD(lParam)); WriteConsole(g_hOUTPUT, output, strlen(output), 0, 0); break; } } return DefWindowProc(hwnd, uMsg, wParam, lParam); }
我们来看看处理效果: