26
2014
07

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




版权声明:
作者:真爱无限 出处:http://www.pukuimin.top 本文为博主原创文章版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接.
« 上一篇下一篇 »

相关文章:

评论列表:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。