C++windows内核编程笔记day06 代码创建菜单

创建菜单:
HMENU CreateMenu(VOID);
添加菜单项:
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);
}

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);

   HMENU menusys=GetSystemMenu(hwnd,FALSE);
   for(int i=0;i<6;i++)
   {
	  // DeleteMenu(menusys,0,MF_BYPOSITION);//删除系统菜单项
   }
   AppendMenu(menusys,MF_STRING,101,"我的菜单");

}
LRESULT CALLBACK OnInitMunuPopUp(
							HWND hwnd,       // handle to window
							UINT uMsg,       // WM_INITMENUPOPUP
							WPARAM wParam,   // handle to menu (HMENU)
							LPARAM lParam    // item position and indicator
)
{
	unsigned int index=LOWORD(lParam);
	int IsWindowMenu=HIWORD(lParam);
	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.style=CS_HREDRAW|CS_VREDRAW;
	ATOM atom= RegisterClassEx(&wce);
	if(atom==0){
		MessageBox(NULL,"注册失败","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 处理消息
	}
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
	AllocConsole();//调试程序方法
	g_houtput=GetStdHandle(STD_OUTPUT_HANDLE);
	g_hinstance=hInstance;
 	// TODO: Place code here.
	if(Register("main",WinProc)==0)
	{
		MessageBox(NULL,"注册失败","提示",MB_OK);
		return 0;
	}
	HWND hwnd= CreateMain("main","pro1");

	Display(hwnd);

	MSGdeal();
	return 0;
}
时间: 2024-09-20 04:08:54

C++windows内核编程笔记day06 代码创建菜单的相关文章

C++windows内核编程笔记day07_day08,可视化建菜单、加速键使用、绘图等

可视化操作创建的菜单,加载到窗口. 方法1:注册时指定菜单 wce.lpszMenuName=MAKEINTRESOURCE(IDR_MENUMAIN);//数字形式的资源ID转换为字符串形式的资源 方法2: //创建窗口时加载菜单资源 HMENU menumain= LoadMenu(g_hinstance,MAKEINTRESOURCE(IDR_MENUMAIN)); menumain 传入 CreateWindowEx();//倒数第三个参数 窗口指定小图标: 1.注册时指定 wce.hI

C++windows内核编程笔记day14 其他线程同步技术

线程同步技术: 原子锁 临界区(段) 互斥 事件 信号量(线程示例时已经使用过) 可等候定时器 使用范围:原子锁<临界区<互斥 效率:    原子锁>临界区(用户态)>互斥(内核态) 一般用临界区. //等候多个信号 DWORD WaitForMultipleObjects(   DWORD nCount,             // number of handles in array   CONST HANDLE *lpHandles,  // object-handle a

C++windows内核编程笔记day01_day02

windows编程介绍.windows 库和头文件介绍 exe文件:.exe,可执行文件 静态库文件:*.lib,调用时,源代码嵌入到调用位置 动态库文件:*.dll,调用时,函数地址被传入 --写编译软件,要懂编译原理. windows 库和头文件 kernel32.dll-提供了核心的API,例如进程.线程.内存管理等 user32.dll-提供了窗口消息等API gdi32.dll-绘图相关的API windows.h-所有windows头文件的集合 windef.h-windows数据类

C++windows内核编程笔记day09_day10,对话框和窗口基本控件等的使用

//设置字体颜色 SetTextColor(hdc,RGB(255,0,0)); //窗口背景 //wce.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); //wce.hbrBackground=CreateSolidBrush(RGB(0,0,255)); //设置字体背景 SetBkColor(hdc,RGB(0,0,200)); //设置字体背景模式 SetBkMode(hdc,TRANSPARENT);//字体背景透明 //创建字体,成功返回字体,失败返回

C++windows内核编程笔记day11 win32静态库和动态库的使用

windows库程序: 静态库: 源代码被链接到调用的程序或动态库,被调用时,代码最少有1份,文件后缀.LIB 动态库: 函数被程序或其他动态库调用,被调用时,代码只有1份,文件后缀.DLL 静态库(C语言): 创建时,选择文本类型文件,输入Clib.c,设置输出路径 ../lib/Clib.lib int Clib_add(int a,int b) {return a+b; } 同一上工作区,建立控制台程序(.c文件)调用静态库: #include<STDIO.H> #pragma comm

c++windows内核编程笔记day12 硬盘逻辑分区管理、文件管理、内存管理

windows系统磁盘文件存储: 分区格式:NTFS / FAT32 GetSystemDirectory();//获取系统路径 GetWindowsDirectory();//获取windows路径 GetCurrentDirectory();//获取当前工作目录 SetCurrentDirectory();//修改当前工作目录 CreateFile/ReadFile/WriteFile/GetFileSize/SetFilePointer //返回文件大小的低32位 DWORD GetFil

C++windows内核编程笔记day03_day04_day05

windows消息机制.消息格式和消息处理1 unicode支持,windows下用: 1.先在#include<windows.h>上面,定义 UNICODE #define UNICODE 2.定义字符串 TCHAR * ptxt=TEXT("学习hello c++"); 3.根据需要,打印不同格式字符串 #ifdef UNICODE     wprintf(L"%s\n",ptxt); #else     printf("%s\n&quo

C++windows内核编程笔记day13 进程、线程与信号量

Windows进程 进程是一个容器,包含程序执行需要的代码.数据.资源等信息, windows进程的特点:每个进程都有自己的ID号每个进程都有自己的地址空间,进程之间无法访问对方的地址空间.每个进程都有自己的安全属性每个进程至少包含一个线程. 获取和释放环境信息 GetEnvironmentStrings FreeEnvironmentStrings 获取或设置 本程序的环境变量 GetEnvironmentVariable SetEnvironmentVariable 示例:char* env

linux内核编程笔记【原创】

以下为本人学习笔记,如有转载请注明出处,谢谢   1. service用法 oneshot DEFINE_MUTEX(buzzer_mutex);   mutex_lock(&buzzer_mutex); mutex_unlock(&buzzer_mutex);   static void WriteNumber(const char *fileName, int number) {