简单实现菜单自绘

简单对下面3 个消息处理 就可实现菜单自绘, 其他控件类似;

 

 

 //WM_DRAWITEM:绘制菜单的样式
//WM_MEASUREITEM:指定要绘制菜单的大小
//WM_INITMENU:把框架菜单全部改成带MF_OWNERDRAW标志

void CTestRgnDlg::OnInitMenu(CMenu* pMenu)
{
 //CDialog::OnInitMenu(pMenu);

 CMenu *pSubMenu;
 UINT nCount,nSubCount,nID;
 CString strText;
 nCount=pMenu->GetMenuItemCount();
 
 for(UINT i=0;i<nCount;i++)
 {
  pSubMenu =pMenu->GetSubMenu(i);
  nSubCount=pSubMenu->GetMenuItemCount();
  for(UINT j=0;j<nSubCount;j++)
  {
   nID=pSubMenu->GetMenuItemID(j);
   // 将框架菜单所有菜单都添加MF_OWNERDRAW标志
   pSubMenu->ModifyMenu(j,MF_BYPOSITION|MF_OWNERDRAW,nID);
   pSubMenu->GetMenuString(j,strText,MF_BYPOSITION);
  }
 }

 // TODO: 在此处添加消息处理程序代码
}

 

 

void CTestRgnDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
 LPDRAWITEMSTRUCT& lpD=lpDrawItemStruct; //起个别名,好用一点

 //判断是不是菜单自绘,因为按钮也可以自绘
 if(nIDCtl==0)
 {
  CDC* pDC=CDC::FromHandle(lpD->hDC); //得到菜单的设备指针,用来绘制菜单
  pDC->SetBkMode(TRANSPARENT);

  CMenu menu;
  menu.Attach((HMENU)lpD->hwndItem); //得到框架菜单对象
  CRect AllRgn(lpD->rcItem);   //得到当前绘制的菜单选项项大小
  CRect FrontRgn(AllRgn.left,AllRgn.top,20,AllRgn.bottom);
  CBrush brushAll(RGB( 250,250,250 )); //初始化画刷
  CBrush brushFront(RGB( 230,230,230 ));
  CBrush brushSel(RGB(148,170,214 ));
  CString strText;
  menu.GetMenuString(lpD->itemID,strText,MF_BYCOMMAND);//得到当前绘制的菜单选项文本                
  if(lpD->itemID!=ID_SEPARATOR) //菜单和分隔栏分别绘制
  {
   if(lpD->itemAction & ODA_SELECT) //菜单选中时的样式
   {
    pDC->FillRect(AllRgn,&brushSel);//绘制
    if(lpD->itemState &ODS_GRAYED)
     //设定文本颜色(在最后才绘制出来)
     pDC->SetTextColor(RGB(194,194,194));
    else if(lpD->itemState & ODS_SELECTED)
     pDC->SetTextColor(RGB(250,250,250));
   }

   //菜单非选中时的样式
   if(!((lpD->itemAction & ODA_SELECT) && (lpD->itemState & ODS_SELECTED)))
   {
    pDC->FillRect(AllRgn,&brushAll);//绘制
    pDC->FillRect(FrontRgn,&brushFront);
    if(lpD->itemState & ODS_GRAYED)
     pDC->SetTextColor(RGB(194,194,194 ));
    else
     pDC->SetTextColor(RGB(66,110,180 ));
   }
  }
  else
   pDC->FillRect(AllRgn,&brushFront);//绘制分隔栏

  pDC->TextOut(AllRgn.left+30,AllRgn.top+5,strText);//打印出字体

  menu.Detach();//分隔菜单句柄和对象(必要!)
 }

 //CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
}

 

 

void CTestRgnDlg::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
 // TODO: 在此添加消息处理程序代码和/或调用默认值
 LPMEASUREITEMSTRUCT& lpM=lpMeasureItemStruct; //起个别名,好用一点

 if(lpM->CtlType==ODT_MENU)
 { //判断是不是菜单要自绘
  if(lpM->itemID!=ID_SEPARATOR)//分别设定普通菜单和分隔栏的大小  
  {
   lpM->itemHeight=20;//普通菜单大小 
   lpM->itemWidth=150;
  }
  else
  {
   lpM->itemHeight=1;//分隔栏大小
   lpM->itemWidth=150;
  }
 }
}

在OpenGL中实现右键菜单切换的简单绘图程序通常涉及到鼠标事件处理、渲染循环和菜单管理。下面是一个简化的示例,它使用了GLFW库(一个跨平台的窗口系统库)来处理输入和OpenGL用于图形渲染: ```c++ #include <GLFW/glfw3.h> #include <vector> // 假设我们有一个简单菜单结构 enum MenuOption { OPTION_DRAW_SQUARE, OPTION_DRAW_CIRCLE, NUM_OPTIONS }; struct MenuItem { std::string label; int option; }; class MenuManager { public: void showMenu(GLFWwindow* window); private: std::vector<MenuItem> menuItems = {{"Draw Square", OPTION_DRAW_SQUARE}, {"Draw Circle", OPTION_DRAW_CIRCLE}}; }; void handleMouseClick(GLFWwindow* window, double x, double y) { if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT)) { MenuManager().showMenu(window); } } void drawSquare() { // 绘制方块的代码... } void drawCircle() { // 绘制圆的代码... } void render(GLFWwindow* window) { // 渲染代码... if (menuIsShowing) { // 如果菜单正在显示 for (const auto& item : menuItems) { // 画出菜单项并更新其状态... } } else { if (currentOption == OPTION_DRAW_SQUARE) { drawSquare(); } else if (currentOption == OPTION_DRAW_CIRCLE) { drawCircle(); } } } int main() { GLFWwindow* window = createWindow(); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); // 处理事件 render(window); } glfwTerminate(); return 0; } void MenuManager::showMenu(GLFWwindow* window) { menuIsShowing = true; currentOption = menuItems[currentMenuIndex].option; // 更新屏幕上的菜单... } // 其他窗口初始化和关闭函数... ``` 在这个示例中,当用户点击右键时,`handleMouseClick`函数会触发`MenuManager`的菜单显示功能。`render`函数根据当前选中的菜单选项执行相应的绘制操作。这只是一个基础框架,实际的代码可能需要更复杂的事件处理和用户交互设计。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blue_Dream_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值