C++windows内核编程笔记day06 代码创建菜单
2023-09-27 14:29:33 时间
BOOL AppendMenu( HMENU hMenu, // handle to menu
UINT uFlags, // menu-item options
UINT_PTR uIDNewItem, // identifier, menu, or submenu
LPCTSTR lpNewItem // menu-item content
);
uFlags:
MF_POPUP -有子菜单的菜单项目,uIDNewItem要设置为子菜单的句柄(转换为uint)
MF_SEPARATOR -分隔线
MF_STRING -一般菜单项,被点击后会发送消息 WM_COMMAND
MF_MENUBREAK -换一列
把菜单加到窗口:
BOOL SetMenu( HWND hWnd, // handle to window HMENU hMenu // handle to menu
);
//修改菜单的勾选状态
DWORD CheckMenuItem( HMENU hmenu, // handle to menu
UINT uIDCheckItem, // menu item to check or uncheck
UINT uCheck // menu item options
);
uCheck:
MF_BYCOMMAND -填写菜单id
MF_BYPOSITION -填写菜单索引
MF_CHECKED/MF_UNCHECKED //1/0 --是否选中
//触发菜单点击事件
case WM_COMMAND:
On_Command(hwnd,wparam);
break;
//点击事件处理
void On_Command(HWND hwnd,WPARAM wparam)
{
bool IsFromMenu=(HIWORD(wparam)==0?true:false);//点击菜单:0,加速键:1
unsigned int id=LOWORD(wparam);//被点的控件id
switch(id)
{
case 10011:
//MessageBox(NULL,"打开","info",MB_OK);
if(isChecked)
{
CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_UNCHECKED);isChecked=false;
}
else{ CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_CHECKED);isChecked=true;
//MessageBox(NULL,"1","info",MB_OK);
}
break;
}
}
//设置可用或不可用,与CheckMenuItem用法一样
BOOL EnableMenuItem(HMENU hMenu,// handle to menu
UINT uIDEnableItem, // menu item to update
UINT uEnable // options
);
WM_INITMENUPOPUP //弹出菜单在被点击还未弹出来之前触发的消息
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_INITMENUPOPUP
WPARAM wParam, // handle to menu (HMENU)
LPARAM lParam // item position and indicator
);
lParam:
LOWORD 被点击菜单的索引
HIWORD 将要显示的菜单是否为窗口菜单(弹出式菜单不属于窗口菜单)
系统菜单的操作,消息:WM_SYSCOMMAND,不太重要,一般不用。
HMENU GetSystemMenu( HWND hWnd, // handle to window
BOOL bRevert // 是否返回默认菜单
);
AppendMenu //前面用过
//删除菜单,根据位置删除时,删除前一个,后面一个会改变位置。
BOOL DeleteMenu( HMENU hMenu, // handle to menu
UINT uPosition, // menu item identifier or position
UINT uFlags // option(MF_BYPOSITION/MF_BYCOMMAND)
);
右键菜单:弹出式菜单,前面用过,这里主要在右键时显示菜单。
BOOL TrackPopupMenu(
HMENU hMenu, // handle to shortcut menu
UINT uFlags, // options
int x, // horizontal position
int y, // vertical position
int nReserved, // reserved, must be zero
HWND hWnd, // handle to owner window
CONST RECT *prcRect // ignored
);
uFlags:
TPM_RETURNCMD -点击菜单项,不发出WM_COMMAND消息,但有返回值(被点击菜单的ID)
//右键消息处理函数,也可以在WM_CONTEXTMENU消息中处理(专门处理)
//WM_CONTEXTMENU 在 WM_RBUTTONUP之后触发的
//WM_CONTEXTMENU 中的坐标不需要转换
void OnRButtonUp(HWND hwnd,LPARAM lparam)
{
HMENU menucontext=CreatePopupMenu();
AppendMenu(menucontext,MF_STRING,103,"查看");
AppendMenu(menucontext,MF_STRING,104,"放大");
AppendMenu(menucontext,MF_STRING,105,"缩小");
POINT pt={0};
pt.y=HIWORD(lparam);
pt.x=LOWORD(lparam);
ClientToScreen(hwnd, pt);//将客户区坐标转换为相对于屏幕的坐标
int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,
hwnd,NULL);//在鼠标位置显示菜单
char txt[30]={0};
sprintf(txt,"被点的菜单ID:%d\n",cmdid);
MessageBox(hwnd,txt,"info",MB_OK);
}
UINT uFlags, // menu-item options
UINT_PTR uIDNewItem, // identifier, menu, or submenu
LPCTSTR lpNewItem // menu-item content
);
uFlags:
MF_POPUP -有子菜单的菜单项目,uIDNewItem要设置为子菜单的句柄(转换为uint)
MF_SEPARATOR -分隔线
MF_STRING -一般菜单项,被点击后会发送消息 WM_COMMAND
MF_MENUBREAK -换一列
把菜单加到窗口:
BOOL SetMenu( HWND hWnd, // handle to window HMENU hMenu // handle to menu
);
//修改菜单的勾选状态
DWORD CheckMenuItem( HMENU hmenu, // handle to menu
UINT uIDCheckItem, // menu item to check or uncheck
UINT uCheck // menu item options
);
uCheck:
MF_BYCOMMAND -填写菜单id
MF_BYPOSITION -填写菜单索引
MF_CHECKED/MF_UNCHECKED //1/0 --是否选中
//触发菜单点击事件
case WM_COMMAND:
On_Command(hwnd,wparam);
break;
//点击事件处理
void On_Command(HWND hwnd,WPARAM wparam)
{
bool IsFromMenu=(HIWORD(wparam)==0?true:false);//点击菜单:0,加速键:1
unsigned int id=LOWORD(wparam);//被点的控件id
switch(id)
{
case 10011:
//MessageBox(NULL,"打开","info",MB_OK);
if(isChecked)
{
CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_UNCHECKED);isChecked=false;
}
else{ CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_CHECKED);isChecked=true;
//MessageBox(NULL,"1","info",MB_OK);
}
break;
}
}
//设置可用或不可用,与CheckMenuItem用法一样
BOOL EnableMenuItem(HMENU hMenu,// handle to menu
UINT uIDEnableItem, // menu item to update
UINT uEnable // options
);
WM_INITMENUPOPUP //弹出菜单在被点击还未弹出来之前触发的消息
LRESULT CALLBACK WindowProc(
HWND hwnd, // handle to window
UINT uMsg, // WM_INITMENUPOPUP
WPARAM wParam, // handle to menu (HMENU)
LPARAM lParam // item position and indicator
);
lParam:
LOWORD 被点击菜单的索引
HIWORD 将要显示的菜单是否为窗口菜单(弹出式菜单不属于窗口菜单)
系统菜单的操作,消息:WM_SYSCOMMAND,不太重要,一般不用。
HMENU GetSystemMenu( HWND hWnd, // handle to window
BOOL bRevert // 是否返回默认菜单
);
AppendMenu //前面用过
//删除菜单,根据位置删除时,删除前一个,后面一个会改变位置。
BOOL DeleteMenu( HMENU hMenu, // handle to menu
UINT uPosition, // menu item identifier or position
UINT uFlags // option(MF_BYPOSITION/MF_BYCOMMAND)
);
右键菜单:弹出式菜单,前面用过,这里主要在右键时显示菜单。
BOOL TrackPopupMenu(
HMENU hMenu, // handle to shortcut menu
UINT uFlags, // options
int x, // horizontal position
int y, // vertical position
int nReserved, // reserved, must be zero
HWND hWnd, // handle to owner window
CONST RECT *prcRect // ignored
);
uFlags:
TPM_RETURNCMD -点击菜单项,不发出WM_COMMAND消息,但有返回值(被点击菜单的ID)
//右键消息处理函数,也可以在WM_CONTEXTMENU消息中处理(专门处理)
//WM_CONTEXTMENU 在 WM_RBUTTONUP之后触发的
//WM_CONTEXTMENU 中的坐标不需要转换
void OnRButtonUp(HWND hwnd,LPARAM lparam)
{
HMENU menucontext=CreatePopupMenu();
AppendMenu(menucontext,MF_STRING,103,"查看");
AppendMenu(menucontext,MF_STRING,104,"放大");
AppendMenu(menucontext,MF_STRING,105,"缩小");
POINT pt={0};
pt.y=HIWORD(lparam);
pt.x=LOWORD(lparam);
ClientToScreen(hwnd, pt);//将客户区坐标转换为相对于屏幕的坐标
int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0,
hwnd,NULL);//在鼠标位置显示菜单
char txt[30]={0};
sprintf(txt,"被点的菜单ID:%d\n",cmdid);
MessageBox(hwnd,txt,"info",MB_OK);
}
ScreenToClient();//坐标转换函数
代码示例:
同样创建win32 application
主要cpp代码修改为:
// win32app.cpp : Defines the entry point for the application. #include "stdafx.h" #include stdio.h HINSTANCE g_hinstance=0;//全局句柄 HMENU menu1=0,menu2=0; HANDLE g_houtput=0; void OnCreate(HWND hwnd,LPARAM lparam) HMENU menu=CreateMenu(); menu1=CreatePopupMenu(); AppendMenu(menu1,MF_STRING|MF_CHECKED,10011,"打开"); AppendMenu(menu1,MF_STRING,10012,"保存"); AppendMenu(menu1,MF_SEPARATOR,0,NULL); AppendMenu(menu1,MF_STRING|MF_MENUBREAK,10013,"退出"); menu2=CreatePopupMenu(); AppendMenu(menu2,MF_STRING,10021,"复制"); AppendMenu(menu2,MF_STRING|MF_GRAYED,10022,"粘贴"); AppendMenu(menu,MF_POPUP,(UINT)menu1,"文件"); AppendMenu(menu,MF_SEPARATOR,0,NULL); AppendMenu(menu,MF_POPUP,(UINT)menu2,"编辑"); SetMenu(hwnd,menu);
char txt[200]={0}; sprintf(txt,"OnInitMenuPopUp:menu:%d,Index:%d,IsWindow:%d\n",wParam,index,IsWindowMenu); WriteConsole(g_houtput,txt,strlen(txt),NULL,NULL); return 0; bool isChecked=true; void On_Command(HWND hwnd,WPARAM wparam) bool IsFromMenu=(HIWORD(wparam)==0?true:false); unsigned int id=LOWORD(wparam); switch(id) case 10011: //MessageBox(NULL,"打开","info",MB_OK); if(isChecked) CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_UNCHECKED);isChecked=false; else{ CheckMenuItem(menu1,id,MF_BYCOMMAND|MF_CHECKED);isChecked=true; //MessageBox(NULL,"1","info",MB_OK); break; void OnSysCommand(HWND hwnd,WPARAM wparam) bool IsFromMenu=(HIWORD(wparam)==0?true:false); unsigned int id=LOWORD(wparam); switch(id) case 101: MessageBox(hwnd,"我的菜单","info",MB_OK); break; default: //MessageBox(hwnd,"我的菜单1","info",MB_OK); break; void OnRButtonUp(HWND hwnd,LPARAM lparam) // HMENU menucontext=CreatePopupMenu(); // AppendMenu(menucontext,MF_STRING,103,"查看"); // AppendMenu(menucontext,MF_STRING,104,"放大"); // AppendMenu(menucontext,MF_STRING,105,"缩小"); // POINT pt={0}; // pt.y=HIWORD(lparam); // pt.x=LOWORD(lparam); // ClientToScreen(hwnd, pt);//将客户区坐标转换为相对于屏幕的坐标 // int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0, // hwnd,NULL);//在鼠标位置显示菜单 // char txt[30]={0}; // sprintf(txt,"被点的菜单ID:%d\n",cmdid); // MessageBox(hwnd,txt,"info",MB_OK); void OnContextMenu(HWND hwnd,LPARAM lparam) HMENU menucontext=CreatePopupMenu(); AppendMenu(menucontext,MF_STRING,103,"查看"); AppendMenu(menucontext,MF_STRING,104,"放大"); AppendMenu(menucontext,MF_STRING,105,"缩小"); POINT pt={0}; pt.y=HIWORD(lparam); pt.x=LOWORD(lparam); //ClientToScreen(hwnd, pt);//将客户区坐标转换为相对于屏幕的坐标 int cmdid= TrackPopupMenu(menucontext,TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RETURNCMD,pt.x,pt.y,0, hwnd,NULL);//在鼠标位置显示菜单 if(cmdid!=0){ char txt[30]={0}; sprintf(txt,"被点的菜单ID:%d\n",cmdid); MessageBox(hwnd,txt,"info",MB_OK); //回调函数 LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam) switch(msg) case WM_SYSCOMMAND: if(wparam==SC_CLOSE){ int ret=MessageBox(NULL,"是否退出","info",MB_YESNO); if(ret==IDYES){ //下面代码会自动关闭和销毁 //PostQuitMessage(0); else return 0;//不执行下面代码 OnSysCommand(hwnd,wparam); break; //在创建窗口之后还未显示的时候 case WM_CREATE: OnCreate(hwnd,lparam); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_COMMAND: On_Command(hwnd,wparam); break; case WM_INITMENUPOPUP: OnInitMunuPopUp(hwnd,msg,wparam,lparam); break; case WM_RBUTTONUP: OnRButtonUp(hwnd,lparam); break; case WM_CONTEXTMENU: OnContextMenu(hwnd,lparam); break; return DefWindowProc(hwnd,msg,wparam,lparam); //注册窗口类 BOOL Register(LPSTR lpClassName,WNDPROC wndproc) WNDCLASSEX wce={0}; wce.cbSize=sizeof(wce); wce.cbClsExtra=200; wce.cbWndExtra=200; wce.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); wce.hCursor=NULL; wce.hIcon=NULL; wce.hIconSm=NULL; wce.hInstance=g_hinstance; wce.lpfnWndProc=wndproc; wce.lpszClassName=lpClassName; wce.lpszMenuName=NULL; wce. "注册失败","info",MB_OK); return FALSE; return TRUE; //创建窗口 HWND CreateMain(LPSTR lpClassName,LPSTR lpWndName) HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,g_hinstance,"hello create"); return hwnd; //创建子窗口 HWND CreateChild(HWND phwnd,LPSTR lpClassName,LPSTR lpWndName) if(Register(lpClassName,DefWindowProc)==0) MessageBox(phwnd,"创建子窗口失败","info",MB_OK); return NULL; //子窗口风格,都要 WS_CHILD|WS_VISIBLE HWND hwnd=CreateWindowEx(0,lpClassName,lpWndName,WS_CHILD|WS_VISIBLE|WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 200,200,phwnd,NULL,g_hinstance,NULL); return hwnd; //显示窗口 void Display(HWND hwnd) ShowWindow(hwnd,SW_SHOW); UpdateWindow(hwnd); //处理消息 void MSGdeal() MSG msg={0}; while(GetMessage( msg,NULL,0,0)){ TranslateMessage( msg);//翻译消息 DispatchMessage( msg);//派发给 WinProc 处理消息
进程是一个容器,包含程序执行需要的代码、数据、资源等信息, windows进程的特点:每个进程都有自己的ID号每个进程都有自己的地址空间,进程之间无法访问对方的地址空间。
windows库程序:静态库: 源代码被链接到调用的程序或动态库,被调用时,代码最少有1份,文件后缀.LIB 动态库: 函数被程序或其他动态库调用,被调用时,代码只有1份,文件后缀.
相关文章
- c++编码习惯
- 【数据库开发】在Windows上利用C++开发MySQL的初步
- C++-Cmake指令:set
- C/C++:VSCode配置C++开发环境【Windows系统】
- C++反汇编第二讲,不同作用域下的构造和析构的识别
- Windows C++ 对拍
- C++007-C++循环结构
- 使用Windows计数器的方法(c++)
- Windows Sqlserver Automatic Log Audit Via C/C++
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- Windows C++ 应用程序通用日志组件(组件及测试程序下载)
- c++ GDI 中SelectObject使用方法和注意事项
- RPC与实践(thrift在windows的编译/安装--c++版)
- 【OpenGL】一、Visual Studio 2019 创建 Windows 桌面程序 ( Visual Studio Installer 安装 C++ 桌面开发库 | 创建桌面程序 )
- C++多线程中调用python api函数
- Windows使用VSCode远程Linux(ConteOS)开发/调试C/C++(超详细)
- (Windbg调试二)Windows下c++程序崩溃问题定位
- 【一】ODB - C++ 访问数据库的利器--Hello World On Windows(Version-24)
- 在Windows下用Eclipse+CDT+MinGW搭建C++开发平台
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- C++ 中string数组怎么求长度(元素个数)
- C++windows内核编程笔记day14 其他线程同步技术
- C++windows内核编程笔记day13 进程、线程与信号量