win32Day04菜单

目录

一、菜单分类:

二、系统菜单

三、顶层菜单(菜单栏菜单)

四、右键菜单


在case里面定义了变量一定要加大括号!

一、菜单分类:

  • 系统菜单:点击窗口图标出来的菜单
  • 右键菜单(弹出式菜单):在应用程序的客户区,单击鼠标右键弹出的菜单
  • 顶层菜单(菜单栏菜单)

菜单和菜单项的区别:

  • 菜单:整个
  • 菜单项:菜单中的一项

二、系统菜单

创建系统菜单:

  1. 获取菜单句柄:GetSystemMenu
    HMENU hSystemMenu = GetSystemMenu(hwnd,false);

     

  2. 添加菜单项:AppendMenu
    BOOL AppendMenu(
        HMENU hMenu,//菜单句柄(添加到那个菜单下)
        UINT uFlags,//设置方式
        UINT_PTR uIDNewItem,//设置该菜单项id
        LPCSTR lpNewItem//新菜单项指针
    );
    //方式有两种:
    /*
    MF_SEPARATOR分隔符(对应的第四个菜单项为NULL) 
    MF_STRING字符串(对应的第四个参数为字符串的内容)
    */
    void OnCreate(HWND hwnd){
        HMENU hSystemMenu = GetSystemMenu(hwnd,false);
        AppendMenu(hSystemMenu,MF_STRING,1,"菜单项1"); 
        AppendMenu(hSystemMenu,MF_STRING,2,"菜单项2");
        AppendMenu(hSystemMenu,MF_STRING,3,"菜单项3");  
    }
    #include <windows.h>
    HMENU g_hPopupMenu;
    void OnCreate(HWND hwnd){
    	g_hPopupMenu = CreatePopupMenu();
    	AppendMenu(g_hPopupMenu,MF_STRING,1,"功能1"); 
    	AppendMenu(g_hPopupMenu,MF_STRING,2,"功能2");
    	AppendMenu(g_hPopupMenu,MF_STRING,3,"功能3"); 
    	AppendMenu(g_hPopupMenu,MF_STRING,4,"功能4"); 
    
    }
    POINT getPos(LPARAM lParam){
    	POINT pos;
    	pos.x = LOWORD(lParam);
    	pos.y = HIWORD(lParam);
    	return pos;
    }
    void displayMenu(HWND hwnd,int x,int y){
    	RECT rect = {0}; 
    	TrackPopupMenu(g_hPopupMenu,TPM_CENTERALIGN,x,y,0,hwnd,&rect); 
    	
    }
    /* This is where all the input to the window goes to */
    LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    	switch(Message) {
    		case WM_CREATE:
    			OnCreate(hwnd);
    			break;
    		case WM_RBUTTONUP:{
    			POINT pos = getPos(lParam);
    			displayMenu(hwnd,pos.x,pos.y);
    			break;
    		}
    		/* trap the WM_CLOSE (clicking X) message, and actually tell the window to close */
    		case WM_CLOSE: {
    			DestroyWindow(hwnd);
    			break;
    		}
    		
    		/* Upon destruction, tell the main thread to stop */
    		case WM_DESTROY: {
    			PostQuitMessage(0);
    			break;
    		}
    		
    		/* All other messages (a lot of them) are processed using default procedures */
    		default:
    			return DefWindowProc(hwnd, Message, wParam, lParam);
    	}
    	return 0;
    }

     

  3. 删除菜单项:DeleteMenu
  4. 菜单项对应的消息处理
    1. 虽然是鼠标点击动作,但是所有的点击菜单项的动作,触发的都是WM_COMMAND消息!特别注意系统菜单触发的是WM_SYSCOMMAND;我们的消息处理函数的思路就是通过ID来辨别用户点击了那个菜单项
    2. WM_COMMAND(WM_SYSCOMMAND)的附加消息
      1. id = LOWORD(wParam)
      2. event = HIWORD(wParam)
    3. case WM_SYSCOMMAND:
      	Id = LOWORD(wParam);
      	switch(Id){
                  case 1:
                      MessageBox(hwnd,"点击了菜单项1","系统菜单项",MB_OK);
                      break;
                  case 2:
                      MessageBox(hwnd,"点击了菜单项2","系统菜单项",MB_OK);
                      break;
                  case 3:
                      MessageBox(hwnd,"点击了菜单项3","系统菜单项",MB_OK);
                      break;
                  default:
                      return DefWindowProc(hwnd,Message,wParam,lParam); 
      			}
      	break;

      注意:一定要在default中设置其他情况调用默认的消息处理函数,否则,系统菜单的其他功能将无法使用,比如说从系统菜单关闭窗口应用程序。

使用系统菜单

  • 设置菜单项的处理函数:做对应消息处理
  • 追加菜单项 AppendMenu
  • 删除菜单项 DeleteMenu
    • DeleteMenu(
          HMENU hMenu,菜单句柄
          UINT uPosition,位置
          UINT uFlags); 方式

      • 方式有两种:索引(MF_BYPOSITION):第几个 从0开始 下标(MY_BYCOMMAND):

      • WM_COMMAND消息:wParam保存菜单项id

      • WM_SYSCOMMAND消息:点击系统菜单项就会产生WM_SYSCOMMAND消息,不同的系统菜单项会产生不同的WM_SYSCOMMAND消息,这些消息的wParam中保存的菜单项id号不同

三、顶层菜单(菜单栏菜单)

  1. 创建顶层菜单 HMENU hTopMenu = CreateMenu();
  2. 创建顶层菜单的子菜单(弹出式菜单)HMENU hPopMenu = CreatePopupMenu();
  3. 把弹出式菜单添加到顶层菜单的子菜单中 AppendMenu(hTopMenu,MF_POPUP,(UINT_PTR)hPopMenu,"pop1");弹出式菜单并不需要设置消息处理函数,因为只要风格设置MF_POPUP,那么当我们点击这个弹出菜单时,默认的响应动作就是弹出子菜单!
  4. 添加弹出式菜单的菜单项 AppendMenu(hPopMenu,MF_STRING,设置其ID号,设置其名字);只有风格为MF_STRING类型的菜单项才需要设置ID号,并且设置ID号对应的消息处理函数(WM_COMMAND)。
  5. 显示 设置 SetMenu(hwnd,hTopMenu);
  6. 获取弹出式菜单的子菜单句柄
    1. HMENU hTop = GetMenu(hwnd) ;用来获取顶层菜单的句柄,有人要奇怪,我们在创建顶层菜单时不是已经得到了顶层菜单的句柄了吗?其实这个函数是用来在消息处理函数中使用的。当用户执行了某些操作后,我们需要对顶层菜单进行操作,就需要得到顶层菜单的句柄,只有在得到顶层菜单的句柄后,才能进一步得到其子菜单的句柄。
    2. HMENU hChild = GetSubMenu(hTop,第几个子菜单)获取顶层菜单的第x个子菜单的句柄。
    3. GetSubMenu(hChild,xxx)获取子菜单的第几个子子菜单的句柄。
      1. case WM_COMMAND:{
        			int id = LOWORD(wParam);
        			switch(id){
        				case 7:{
        					MyPrintf("%s","菜单项1");
        					HMENU hTop = GetMenu(hwnd);//获取顶层菜单的句柄 
        					HMENU hChild1 = GetSubMenu(hTop,0);
        					CheckMenuItem(hChild1,0,MF_CHECKED|MF_BYPOSITION); 
        					break;
        				}
        					
        				case 8:
        					MyPrintf("%s","菜单项2");
        					break; 
        			} 
        			break;
        		}

         

  7. 设置弹出式菜单的子菜单 
    1. CheckMenuItem(句柄,位置,风格)设置句柄(应该是要选中的菜单项的上一级菜单)的第位置个子菜单被选中
      1. MF_CHECKED 设置被选中
      2. MF_UNCHECKED 取消被选中
      3. 注意位置下标是从0 开始的。
    2. EnabelMenuItem(上层菜单句柄,菜单项ID,MF_GRAYD)非使能菜单项(灰色,不能选中,设置是否可选中)
  8. void OnCreate(HWND hwnd){
    HMENU hTopMenu = CreateMenu();
    HMENU hChild = CreatePopupMenu();
    AppendMenu(hTopMenu,MF_POPUP,(UINT_PTR)hChild,“子菜单1”); 
    AppendMenu(hChild,MF_STRING,007,“孙子菜单”);
    SetMenu(hwnd,hTopMenu);
    }
    

    方法二:在添加资源时,添加菜单,然后设置菜单ID,在注册窗口类时,设置显示。具体操作方法见,《重要消息》第二部分10分。实际开发中,方法二应用的更多,因为更加方便。

四、右键菜单

  1. 在WM_CREATE的时候创建弹出式菜单
    1. CreatePopupMenu
    2. HMENU hPopupMenu = CreatePopupMenu();

       

  2. 在WM_CREATE的时候添加菜单项
    1. AppendMenu
    2. DeleteMenu
  3. 右键单击的时候显示菜单
    1. TrackPopupMenu
    2. BOOL  TrackPopupMenu(
      HMENU hMenu, //菜单句柄
      UINT  uFlags,//方式    
      int x, int y,//坐标
      int nReserved, //保留的,为了以后给函数加参数方便
      HWND hWnd, //窗口句柄
      LPCRECT prcRect //矩形 
      );

       

  4. 消息处理
    1. WM_CONTEXTMENU触发:当你单击右键并弹起的时候,两种消息都会发送。但是右键消息中附加消息lParam记录的是当前光标右键弹起处的屏幕坐标(低位x,高位y),WM_CONTEXTMENU中附加消息lParam记录的是右键弹起时的光标的窗口客户区坐标。
      1. #include <windows.h>
        #include "stdafx.h"
        #include "Resource.h"
        #include <stdio.h>
        #include <cstdio>
        #include <string.h>
        #include <cstring>
        
        HINSTANCE g_hInstance;
        HCURSOR g_hCursor1, g_hCursor2;//光标句柄
        MSG msg;//声明一个MSG类型的消息结构体
        HANDLE g_hConsole;//定义一个HANDLE类型的全局变量,之后要将命令行窗口句柄赋值给它,命名时养成习惯:如果是全局变量以g_开头命名它。
        HMENU hRight;
        int flag = 0;
        //写一个windows窗口 
        //5定义消息处理函数 
        void OnCreate(HWND hWnd,WPARAM wParam,LPARAM lParam) {
        #if 0
        	//一 系统菜单
        	HMENU hSystemMenu=GetSystemMenu(hWnd, 0);//获取系统菜单句柄
        	//删除系统菜单项:系统菜单有七项,其中分隔符也算菜单项
        	for (int i = 0; i < 6; i++) {
        		DeleteMenu(hSystemMenu, 0, MF_BYPOSITION);//按照索引的方式删除,0表示当前状况的第一个,是变化的
        		//DeleteMenu(hSystemMenu, 0, MF_BYCOMMAND);//按照下标的方式删除,0表示初期情况下菜单栏的第一个(即分隔符),是固定的。
        
        	}
        	//追加系统菜单项:追加就一定在最后追加
        	AppendMenu(hSystemMenu, MF_SEPARATOR, 1111, NULL);//第二个参数决定菜单项的样式:分隔符(MF_SEPARATOR)还是字符串,如果第二个参数选分隔符,那么第三个参数就是分隔符的id
        	AppendMenu(hSystemMenu, MFT_STRING, 1112, L"(ง •_•)ง(M)");//第二个参数如果是字符串,则最后一个参数为字符串的内容。
        	//这里只能决定菜单的样子,而真正地处理才是关键。
        	/*真正的处理在消息处理函数中,系统菜单的消息由WM_COMANND消息管理*/
        #endif
        	//二、顶层菜单
        	HMENU hTopMenu = CreateMenu();//创建顶层菜单,返回顶层菜单的句柄
        	//创建弹出式菜单
        	HMENU hChinese = CreatePopupMenu();
        	HMENU hJapan = CreatePopupMenu();
        	HMENU hAmerican = CreatePopupMenu();
        	HMENU hSearch = CreatePopupMenu();
        	//将弹出式菜单添加到顶层菜单中
        	AppendMenu(hTopMenu,MF_POPUP,(UINT)hChinese,L"国产");//第三个参数需要弹出式菜单的id,我们将句柄强制转化成id类型
        	AppendMenu(hTopMenu, MF_POPUP, (UINT)hJapan,L"日本");
        	AppendMenu(hTopMenu, MF_POPUP, (UINT)hAmerican,L"欧美");
        	AppendMenu(hJapan, MF_POPUP, (UINT)hSearch,L"搜索");
        	//添加菜单项到弹出式菜单中
        	//添加到国产中
        	AppendMenu(hChinese, MF_STRING,2511, L"土肥圆矮穷挫");//第三个参数为你设置的这个菜单项的id
        	AppendMenu(hChinese, MF_STRING, 2512, L"艾栗栗");
        	AppendMenu(hChinese, MF_STRING, 2513, L"萌琪琪");
        	AppendMenu(hChinese, MF_STRING, 2514, L"张柏芝艳照门");
        	//添加到日本中
        	AppendMenu(hJapan, MF_STRING, 2521, L"波多野结衣");//第三个参数为你设置的这个菜单项的id
        	AppendMenu(hJapan, MF_STRING, 2522, L"泷泽萝拉");
        	AppendMenu(hJapan, MF_STRING, 2523, L"桃谷绘里香");
        	AppendMenu(hJapan, MF_STRING, 2524, L"桃乃木香奈");
        	AppendMenu(hJapan, MF_STRING, 2524, L"其他");
        	AppendMenu(hJapan, MF_STRING, 2525, L"选中泷泽萝拉");
        
        	//添加到欧美中
        	AppendMenu(hAmerican, MF_STRING, 2531, L"安洁莉卡");
        	//添加菜单项到搜索中
        	AppendMenu(hSearch, MF_STRING, 2541, L"搜索番号");
        	AppendMenu(hSearch, MF_STRING, 2541, L"搜索女优");
        	AppendMenu(hSearch, MF_STRING, 2541, L"搜索男优");
        	//显示顶层菜单
        	SetMenu(hWnd, hTopMenu);
        	//获取菜单项句柄,现在只有我自己设置的菜单项的id
        	HMENU hTemp = GetSubMenu(hJapan, 0);//得到波多野结衣菜单项的句柄
            //设置菜单项
        	EnableMenuItem(hJapan, 2521,MF_GRAYED);//第一个参数为菜单项所在弹出式菜单的句柄,第二参数该菜单项的id,设置菜单项“波多野结衣”为灰色
        	//三、创建右键菜单
        	hRight = CreatePopupMenu();
        	AppendMenu(hRight, MF_STRING, 3001, L"打开男人团");
        	AppendMenu(hRight, MF_STRING, 3002, L"打开福利档");
        	AppendMenu(hRight, MF_STRING, 3003, L"打开torrentkitty");
        
        
        
        }
        LRESULT CALLBACK WndProc(HWND hWnd,//窗口句柄  
        //CALLBACK表示是一个回调函数,LRESULT是函数返回值的类型,可以通过查看wc.lpfnWndProc的定义查看 
        UINT code,//消息  msg.message
        WPARAM wParam,//消息附加信息 
        LPARAM lParam//消息附加信息 
        ) {
        	HMENU hGet;
        	RECT rect;
        
        	//用switch case 来判断是什么消息 
        	switch (code) {
        	case WM_CONTEXTMENU:
        		GetWindowRect(hWnd, &rect);//获取当前窗口客户区的矩形,传参给rect
        		TrackPopupMenu(hRight, TPM_RIGHTBUTTON, LOWORD(lParam), HIWORD(lParam), 0, hWnd, &rect);//右键点击时显示菜单
        		break;
        #if 0
        	case WM_RBUTTONUP://当单击右键并弹起时,会收到此消息
        		//TrackPopupMenu()
        		GetWindowRect(hWnd, &rect);//获取当前窗口客户区的矩形,传参给rect
        		TrackPopupMenu(hRight, TPM_CENTERALIGN, rect.left+LOWORD(lParam),rect.top+HIWORD(lParam), 0, hWnd, &rect);//右键点击时显示菜单
        		break;//用这种方式右键菜单弹出的位置有点问题,因为WM_RBUTTONUP的lParam中存储的是相对于桌面的xy坐标,需要用当前窗口即rect.left+LOWOR(lParam)转化成相对于窗口的。
        #endif
        		break;
        	case WM_SYSCOMMAND://点击系统菜单项就会产生WM_SYSCOMMAND消息
        		switch (wParam) {//不同的系统菜单项会产生不同的WM_SYSCOMMAND消息,这些消息的wParam中保存的菜单项id号不同
        		case 1112://之前我们自己追加的菜单项id号为1112
        			MessageBox(hWnd, L"(ง •_•)ง", L"系统菜单项", NULL);
        			break;
        		default:
        			break;
        		}
        
        		break;
        	case WM_KEYDOWN:
        
        		break;
        	case WM_COMMAND://当点击菜单项时会发送WM_COMMAND消息,由于不同的菜单项我们设置了不同的id,所以可以根据菜单项的id来区分
        		switch (wParam) {// 点击不同的菜单项,WM_COMMAND的附加消息wParam中存储的id号不同
        		case 2522:
        			MessageBox(hWnd, L"泷泽萝拉的作品目前还没有", L"抱歉", MB_OK);
        			break;
        		//点击 桃乃木香奈 2524 菜单项 设置 波多野结衣菜单项 2521 可选中(由灰色变成黑色)
        		//点击 波多野结衣 2521 菜单项 设置 桃谷绘里香 2523 菜单项选中
        		case 2524:
        			hGet =GetSubMenu(GetMenu(hWnd),1);//GetMenu拿到的是窗口句柄为hWnd的窗口的顶层菜单的菜单句柄;以之作为参数去拿顶层菜单的弹出式菜单
        			EnableMenuItem(hGet, 2521, MF_ENABLED);//设置波多野结衣菜单项为黑色
        			break;
        		case 2521:
        			hGet = GetSubMenu(GetMenu(hWnd), 1);
        			//通过id号来选中桃谷绘里香菜单项
        			//CheckMenuItem(hGet, 2523, MF_CHECKED);//设置桃谷绘里香被选中
        			//通过相对位置来选中桃谷绘里香 菜单项
        			CheckMenuItem(hGet, 3, MF_CHECKED | MF_BYPOSITION);
        			break;
        		case 2525:
        			hGet = GetSubMenu(GetMenu(hWnd), 1);
        			switch (flag) {
        			case 0:
        				CheckMenuItem(hGet, 2522, MF_CHECKED);
        				flag = 1;
        				break;
        			case 1:
        				CheckMenuItem(hGet, 2522, MF_UNCHECKED);
        				flag = 0;
        				break;
        			}
        			break;
        
        
        		}
        		break;
        
        
        	case WM_MOUSEMOVE:
        		break;
        
        	case WM_CREATE://代表窗口创建消息 
        		OnCreate(hWnd, wParam, lParam);
        	
        		break;
        	case WM_PAINT://绘图消息
        		break;
        
        	case WM_DESTROY:
        		PostQuitMessage(0);//PostQuitMessage函数发送一个WM_QUIT消息到线程消息队列并且立即返回
        		break;
        	default:
        		return DefWindowProc(hWnd, code, wParam, lParam);//意味着开始下一次消息循环 
        	}
        	return DefWindowProc(hWnd, code, wParam, lParam);//意味着开始下一次消息循环 
        }
        
        
        int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hParentInstance, LPSTR lpCmd, int len) {
        	g_hInstance = hInstance;
        
        
        	//1.写主函数
        	//2.在主函数中注册窗口类  WNDCLASS WNDCLASSEX(64位扩展的) 
        	WNDCLASSEX wc;//wc是一个窗口类 类型的 结构体,它里面有很多成员变量,一个一个给它们初始化就可以了
        	wc.cbSize = sizeof(WNDCLASSEX);//窗口类大小 
        	wc.cbClsExtra = NULL;//窗口类附加信息 即 对窗口类的说明 等于NULL表示没有附加信息 
        	wc.cbWndExtra = NULL;//窗口附加信息 即对窗口的说明 
        	wc.lpszClassName = L"番号搜索大法";//窗口类名,主要是为了标志版权 用spy++工具可以查看类名 
        	//wc.hbrBackground=NULL;//背景 设置背景颜色
        	wc.hbrBackground = (HBRUSH)GetStockObject(3);//百度查,记不住 
        	wc.hCursor = NULL;
        																	//wc.hIcon = NULL;//窗口的图标(任务栏) 用loadicon函数来加载图标:加载一个图标资源,并且返回这个图标资源的句柄。 
        	wc.hIcon = NULL;
        	//两种方式loadIcon和(HICON)LoadImage(hInstance,MAKEINTRESOURCE(IDI_ICON2),IMAGE_ICON,32,32,LR_LOADTANSPARENT);
        	//加载方式:LR_LOADTANSPARENT资源方式加载,文件方式加载LOADFROMFILE
        
        	wc.hIconSm = NULL;//小图标
        	wc.hInstance = hInstance;//当前应用程序的实例句柄
        	wc.lpfnWndProc = WndProc; //消息处理函数=你自己定义的消息处理函数的名字 
        	wc.lpszMenuName = NULL; //菜单
        	wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格=水平/垂直滚动条
        	RegisterClassEx(&wc); //正式注册窗口类,只要把结构体wc的地址传入即可。 
        
        
        	//3.创建窗口 CreateWindow  //HWND 窗口句柄类型 Handle Window 
        	HWND hWnd = CreateWindowEx( //因为创建窗口函数会返回创建的窗口的句柄,所以首先定义好窗口句柄类型的变量。 
        		NULL,//窗口的附加风格 
        		wc.lpszClassName, //窗口类名 
        		L"番号搜索大法",//窗口名 
        		WS_OVERLAPPEDWINDOW,//窗口的风格 
        		1000, 100,//窗口出现的位置 (x,y)
        		600, 600,//窗口的宽高 
        		NULL,//父窗口实例句柄 
        		NULL,//窗口的菜单的句柄 
        		hInstance,//窗口的实例句柄(当前应用程序实例句柄 
        		NULL);//附加信息 消息是个结构体,消息有两个附加信息:lParam wParam 
        
        
        		 /*如果创建窗口失败,则CreateWindow的返回值为NULL即0;
        		  *如果创建窗口成功,则CreateWindow的返回值为所创建窗口的句柄
        		  */
        		  /*
        		 if(NULL==hWnd){
        			MessageBox(NULL,"创建窗口失败","警告",MB_OK);
        			return -1;
        		 }
        		 else{
        			MessageBox(NULL,"创建窗口成功","恭喜",MB_OK);
        		 }
        		*/
        
        		//4.显示刷新窗口 ShowWindow updateWindow
        	ShowWindow(hWnd, 5);//传入窗口的句柄即可。 
        	UpdateWindow(hWnd); //传入窗口的句柄即可。 
        	AllocConsole();//得到命令行窗口使用权限
        	g_hConsole = GetStdHandle(STD_OUTPUT_HANDLE);//用函数得到命令行窗口句柄,赋值给全局变量g_hConsole
        
        	//5.定义窗口的消息处理函数
        
        	//消息循环是一个死循环,永远不会结束,除非。。。你写一个语句break 
        	while (1) {
        		//获取消息 
        		//GetMessage(&msg, NULL, NULL, NULL);//GetMessage函数是一个阻塞函数,如果接收一个消息所用的时间过长,在此期间内,如果有另一个消息被发送,就会接受不到这个消息
        		if (PeekMessage(&msg, NULL, NULL, NULL, NULL))//最后一个参数表示是否删除消息
        		/*PeekMessage的工作原理:非阻塞方式接受消息,主要查看是否有消息,不会将消息存入MSG结构体中,GetMessage函数负责将消息存入MSG结构体中。
        		Peekmessage会检查消息队列,如果消息队列中有消息,函数就会查看最后一个参数,
        		如果最后一个参数为false或者NULL,直接返回1
        		如果最后一个参数为true,从消息队列中删除消息,然后返回1
        		如果消息队列中没有消息,直接返回0
        
        		*/ {
        			if (0 == GetMessage(&msg, NULL, NULL, NULL)) break;
        			/*GetMessage工作原理:
        			GetMessage从消息队列中获取一个消息存放到MSG结构体中。
        			如果消息队列中有消息,把消息存入MSG,删除当前程序消息队列中的消息,返回非0
        			直到遇到WM_QUIT消息才返回0.注意:关闭窗口不会发送WM_QUIT消息,只会发送WM_DESTROY消息,只有在消息处理函数中定义当收到WM_DESTROY时,向消息队列中添加WM_QUIT消息,
        			才能通过if(0 == GetMessage(&msg, NULL, NULL, NULL)) break;退出循环。
        			如果当前程序消息队列中没有消息,就去系统消息队列中看有没有消息。如果系统消息队列
        			里面有消息,就把系统消息队列中的消息放入当前程序消息队列。如果系统消息队列中没有消息,就
        			检查窗口是否需要重新绘制。如果需要重新绘制,操作系统发送WM_PAINT消息,如果不需要重新绘制
        			查看是否有定时器,如果有定时器,处理定时器消息,如果没有定时器,优化资源,处理内存,继续等待。
        			消息循环处理消息的次数可能小于消息处理函数处理消息的次数,因为其他应用程序的消息也可能发送给消息处理函数处理。
        
        
        			*/
        			/*
        			if (msg.message == WM_QUIT) { //WM_QUITE消息表示整个窗口退出
        				break;
        			}
        			*/
        
        			//翻译消息 
        			TranslateMessage(&msg);//翻译消息
        			/*消息的翻译主要针对键盘消息,键盘消息只有两个:
        			WM_TDOWN
        			WM_TUP
        			if(msg.message==WM_KEY 按键消息){
        			   if(是否可见字符){//可见字符即代表字符有回显,例如F1F2..PgUp等不是可见字符。
        			   //如果是可见字符,代表应该告诉应用程序,用户按键是用来编辑,发送的是一个字符,否则,就认为用户按键是发送一个指令。
        			   //如果用户发送的是一个字符,就需要翻译一下
        				 if(Caps Lock是否按下){
        					PostMessage(大写字母消息);//发送大写字母消息
        				 }else{
        				   PostMessage(小写字母消息);//发送小写字母消息
        				 }
        
        			   }
        			 }
        			 return;
        			*/
        			DispatchMessage(&msg);//派发消息,群发消息,给当前所有的应用程序都发送。而PostMessage表示只对当前应用程序的消息处理函数发送消息。
        
        
        		}
        
        	}
        	//6.消息循环    循环 接受消息 翻译消息 派发消息
        
        	//点击动作 操作系统产生消息 发给窗口应用程序,应用程序里面的“消息循环”接收消息,调用对应的消息处理函数,产生对应的响应动作。 
        
        	return 0;
        
        }
        

         

      2. WINAPI
        TrackPopupMenu(
            HMENU hMenu,//要显示的菜单句柄
            UINT uFlags, //方式(弹出菜单位于光标的右下方,还是右上方) 只要是方式就有对应的宏,这些宏的前缀是TPM_
            int x, int y, //显示的坐标
            int nReserved, //保留值,必须为0
            HWND hWnd,//窗口句柄
            CONST RECT *prcRect);//当前窗口应用程序的矩形区域

      3. 右键消息WM_RBUTTONUP触发:

Appendmenu的参数uflags

uFlags [in]

Type: UINT

Controls the appearance and behavior of the new menu item. This parameter can be a combination of the following values.

ValueMeaning

MF_BITMAP

0x00000004L

Uses a bitmap as the menu item. The lpNewItem parameter contains a handle to the bitmap.

MF_CHECKED

0x00000008L

Places a check mark next to the menu item. If the application provides check-mark bitmaps (see SetMenuItemBitmaps, this flag displays the check-mark bitmap next to the menu item.

MF_DISABLED

0x00000002L

Disables the menu item so that it cannot be selected, but the flag does not gray it.

MF_ENABLED

0x00000000L

Enables the menu item so that it can be selected, and restores it from its grayed state.

MF_GRAYED

0x00000001L

Disables the menu item and grays it so that it cannot be selected.

MF_MENUBARBREAK

0x00000020L

Functions the same as the MF_MENUBREAK flag for a menu bar. For a drop-down menu, submenu, or shortcut menu, the new column is separated from the old column by a vertical line.

MF_MENUBREAK

0x00000040L

Places the item on a new line (for a menu bar) or in a new column (for a drop-down menu, submenu, or shortcut menu) without separating columns.

MF_OWNERDRAW

0x00000100L

Specifies that the item is an owner-drawn item. Before the menu is displayed for the first time, the window that owns the menu receives a WM_MEASUREITEM message to retrieve the width and height of the menu item. The WM_DRAWITEM message is then sent to the window procedure of the owner window whenever the appearance of the menu item must be updated.

MF_POPUP

0x00000010L

Specifies that the menu item opens a drop-down menu or submenu. The uIDNewItem parameter specifies a handle to the drop-down menu or submenu. This flag is used to add a menu name to a menu bar, or a menu item that opens a submenu to a drop-down menu, submenu, or shortcut menu.

MF_SEPARATOR

0x00000800L

Draws a horizontal dividing line. This flag is used only in a drop-down menu, submenu, or shortcut menu. The line cannot be grayed, disabled, or highlighted. The lpNewItem and uIDNewItem parameters are ignored.

MF_STRING

0x00000000L

Specifies that the menu item is a text string; the lpNewItem parameter is a pointer to the string.

MF_UNCHECKED

0x00000000L

Does not place a check mark next to the item (default). If the application supplies check-mark bitmaps (see SetMenuItemBitmaps), this flag displays the clear bitmap next to the menu item.

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值