用弹出菜单模拟窗口的菜单

在加了Skin的不规则区域窗口,窗口菜单很难固定在原来的位置,无法用原来的方式实现。这里提供了一种用弹出菜单模拟窗口菜单的方法。

        首先在窗口的任意一个区域画出菜单的效果,这个区域我们称为菜单区,我们把每个菜单项在窗口中的位置保存下来

        CRect m_rcMenu[3];

       程序主要要处理三个消息: WM_LBUTTONDOWN、WM_MOUSEMOVE、WM_ENTERIDLE

       BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
              //{{AFX_MSG_MAP(CMyDlg)
                    ON_WM_LBUTTONDOWN( )
                    ON_WM_MOUSEMOVE()
                    ON_WM_ENTERIDLE()
              //}}AFX_MSG_MAP
       END_MESSAGE_MAP()

        当鼠标在菜单区内按下的时候,开始用弹出菜单模拟窗口菜单。

        void CMyDlg::OnLButtonDown(UINT nFlags, CPoint ptStart)
        {
              for (i=0 ;i<3; i++)
              {
                     if (PtInRect(m_rcMenu[i], point))
                     {
        
                            if (!PtInRect(m_rcMenu[m_iMenuIndex], point))
                            {
                                   InvalidateRect(&m_rcMenu[m_iMenuIndex], TRUE);
                                   UpdateWindow();
                           }

                           //这个是菜单索引,用它来标示显示那个菜单
                           m_iMenuIndex = i;
                          m_bShowMenu = TRUE;


                          //菜单显示,如果m_bMenuContinue为TRUE, 不断显示新的菜单,旧的在WM_ENTERIDLE中清除,之所以做这样的处理,是因为窗口菜单要求当菜单弹出时,随着鼠标在菜单区的移动,菜单变更为相应的子菜单


                         do
                         {

                                   //画菜单的按下效果
                                    CDC* pDC = GetDC();
                                    pDC->Draw3dRect(&m_rcMenu[m_iMenuIndex], RGB(100, 100, 100), RGB(160, 160, 160));
                                    ReleaseDC(pDC);
                                    m_bMenuContinue = FALSE;
                                    ShowMenu();
                          } while(m_bMenuContinue);  
                          InvalidateRect(&m_rcMenu[m_iMenuIndex], TRUE);
                          UpdateWindow();
                           m_bShowMenu = FALSE;
                           CWnd::OnLButtonDown(nFlags, point);
                           return;
                    }
               }
               if ( i== 3)
                      m_iMenuIndex = -1;
               CDialog::OnLButtonDown(nFlags, point);

           }

           然后在OnMouseMove里更新菜单索引

           void CMyDlg::OnMouseMove(UINT nFlags, CPoint point)
           {
                   // TODO: Add your message handler code here and/or call default
 
                   //把原来的菜单按下效果清除掉
                   if (m_iMenuIndex != -1)
                   {
                             if (!PtInRect(m_rcMenu[m_iMenuIndex], point))
                                       InvalidateRect(&m_rcMenu[m_iMenuIndex], TRUE);

                   }

                  UpdateWindow();

                   m_iMenuIndex = -1;
                   for (i=0 ;i<3; i++)
                   {
                            if (PtInRect(m_rcMenu[i], point))
                            {
                                   //确定当前菜单索引
                                  m_iMenuIndex = i;
                                  //画菜单的抬起效果
                                  CDC* pDC = GetDC();
                                  pDC->Draw3dRect(&m_rcMenu[i], RGB(160, 160, 160), RGB(100, 100, 100));
                                  ReleaseDC(pDC);
                                  break;
                              }
                    }

                    CDialog::OnMouseMove(nFlags, point);
            }

           在OnEnterIdle将菜单取消并重新显示

           void CGameBoxShell::OnEnterIdle(UINT nWhy, CWnd* pWho)
          {
                  CWnd::OnEnterIdle(nWhy, pWho);
 
                  // TODO: Add your message handler code here
                  if (nWhy == MSGF_MENU)
                  {

                        if (!m_bShowMenu)
                                return;
                         CPoint point;
                         GetCursorPos(&point);
                         ScreenToClient(&point);
 
                         for (int i=0 ;i<3; i++)
                         {
                                   if (PtInRect(m_rcMenu[i], point))
                                   {
                                             if (m_iMenuIndex != i)
                                             {
                                                      if (m_iMenuIndex != -1)
                                                      {
                                                                if (!PtInRect(m_rcMenu[m_iMenuIndex], point))
                                                                {
                                                                       InvalidateRect(&m_rcMenu[m_iMenuIndex], TRUE);
                                                                       UpdateWindow();
                                                                }
                                                      }
                                                      m_iMenuIndex = i;
                                                      m_bMenuContinue = TRUE;
                                                      SendMessage(WM_CANCELMODE);
                                               }
                                               break;
                                     }
                           }

                 }
         }

         最后,把显示菜单的代码补充完整
          void CMyDlg::ShowMenu()
         {
                     if (m_PopupMenu.GetSafeHmenu())
                               m_PopupMenu.DestroyMenu();
                     m_PopupMenu.LoadMenu(IDR_POPUP);
                     CMenu* pSub = m_PopupMenu.GetSubMenu(m_iMenuIndex);
                     CPoint pt(m_rcMenu[m_iMenuIndex].left, m_rcMenu[m_iMenuIndex].bottom+2);
                    ClientToScreen(&pt);
                     TrackPopupMenu(pSub->GetSafeHmenu(), TPM_LEFTALIGN |
                                    TPM_LEFTBUTTON, pt.x, pt.y, NULL, m_hWnd, NULL);
      }
      这样,我们就可以完用弹出菜单来模拟窗口的菜单,你可以在你的不规则窗口上的任何位置实现出菜单的效果。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值