實現自繪菜單

來源:互聯網
上載者:User

為了實現菜單的自繪,花了我幾個小時,其實真正解決後又發現很簡單。實現菜單的自繪只需要三個步驟:

第一步:將所有功能表項目設定為MF_OWNERDRAW,即自繪模式

第二步:在WM_MEASUREITEM訊息中設定功能表項目的大小

第三步:在WM_DRAWITEM訊息中進行功能表項目的繪製

問題首先出現在了第一步,我要繪製的是一個操作功能表,即右鍵菜單,要將功能表項目設定為MF_OWNERDRAW,需要用到ModifyMenu函數,起始由於ModifyMenu函數的參數設定錯誤,導致程式怎麼也響應不了WM_MEASUREITEM和WM_DRAWITEM訊息,所以建議在使用ModifyMenu時對傳回值進行檢查。

void CMainWindow::OnRButtonDown(UINT nFlags, CPoint point) {     ClientToScreen(&point);     CMenu Menu;     Menu.LoadMenuW(IDR_MENU2);     CMenu *pMenu = Menu.GetSubMenu(0);     CString strText;     for (int i = 0; i < pMenu->GetMenuItemCount(); i++)     {         BOOL bModi = pMenu->ModifyMenuW(ID_123_456 + i, MF_BYCOMMAND|MF_OWNERDRAW, ID_123_456 + i);         if (!bModi)        {               TRACK("ModifyMenu fail!");        }         pMenu->GetMenuStringW(i, strText, MF_BYPOSITION);     }     pMenu->TrackPopupMenu(TPM_LEFTBUTTON|TPM_LEFTALIGN,         point.x,         point.y,         this); }

第一步的問題解決後,接在在第二步的WM_MEASUREITEM訊息中設定功能表項目的大小:

void CMainWindow::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpmis) {     //lpmis->itemWidth = ::GetSystemMetrics(SM_CYMENU) * 4;     lpmis->itemWidth = 150;     lpmis->itemHeight = ::GetSystemMetrics(SM_CYMENU); }  在WM_MEASUREITEM訊息中設定的功能表項目大小會傳入WM_DRAWITEM訊息中,然後再在WM_DRAWITEM訊息中根據功能表項目的大小來進行重繪。

到第三步也遇到了幾個問題,由於最初對WM_DRAWITEM訊息中的LPDRAWITEMSTRUCT結構體不瞭解,以致寫出的程式不管在什麼時候都會作同一個繪製操作,先來看看WM_DRAWITEM訊息的聲明:

afx_msg void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis);

在這個訊息中有兩個參數,在自繪菜單時,兩個參數都要用到。其中nIDCtl,書上說是所屬控制項的ID,不太明白是什麼意思,在MSDN看到,對於菜單發出的WM_DRAWITEM訊息,nIDCtl為0。再說LPDRAWITEMSTRUCT結構體,該結構體中包含了菜單複選狀態、選中狀態以及功能表項目的大小等資訊。

下面是OnDrawItem訊息的實現代碼:

void CMainWindow::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpdis) {     CBrush *brush = new CBrush;     CPen *pen = new CPen;     CString strText;     CDC *pDC = CDC::FromHandle(lpdis->hDC); //擷取功能表項目的裝置控制代碼     //功能表項目是否為選中狀態     if ((lpdis->itemState & ODS_SELECTED))     {         //在功能表項目上自繪矩形框的背景顏色         brush->CreateSolidBrush(RGB(182, 189,210));         //在功能表項目自繪矩形的邊框顏色         pen->CreatePen(PS_SOLID, 1, RGB(10,36,106));         //設定功能表項目的文字背景顏色         pDC->SetBkColor(RGB(182,189,210));     }     else     {         brush->CreateSolidBrush(GetSysColor(COLOR_MENU));         pen->CreatePen(PS_SOLID, 0, GetSysColor(COLOR_MENU));         pDC->SetBkColor(GetSysColor(COLOR_MENU));     }     pDC->SelectObject(pen);     pDC->SelectObject(brush);     //在當前功能表項目上畫一個矩形框     pDC->Rectangle(lpdis->rcItem.left,         lpdis->rcItem.top,         lpdis->rcItem.right,         lpdis->rcItem.bottom);     /*--------------------------------------*/     //擷取當前訊息所在功能表項目的文本     CMenu menu;     menu.Attach((HMENU)lpdis->hwndItem);     menu.GetMenuStringW(lpdis->itemID, strText,MF_BYCOMMAND);     /*--------------------------------------*/     //如果為菜單發出的DrawItem訊息     if (nIDCtl == 0)     {         //在功能表項目上輸出菜單文本         pDC->TextOutW(lpdis->rcItem.left + 20, lpdis->rcItem.top + 4, strText.GetBuffer(0), strText.GetLength());     }     menu.Detach();     delete brush;     delete pen; }

 

參考資料:http://www.vckbase.com/document/viewdoc/?id=1583

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.