MFC/VC++中怎样设置位图按钮并且位图不会覆盖文字——–位图按钮
1:第一次嘗試
設置??? IDC_BUTTON3按鈕風格的bitmap為true
在OnInitialDilog中:
CButton* cbpTest = NULL;
?? ?HINSTANCE hInstance=AfxGetResourceHandle();
HBITMAP?? ?m_hBmp4=(HBITMAP)LoadImage(hInstance, MAKEINTRESOURCE(IDB_BITMAP1), IMAGE_BITMAP, 0, 0, 0);
?? ?cbpTest = (CButton*)GetDlgItem(IDC_BUTTON3);
?::PostMessage(cbpTest->GetSafeHwnd(), BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)m_hBmp4);
覆蓋掉了文字,并且也有閃屏
2:第二次嘗試:https://wenku.baidu.com/view/95f2be7a1711cc7931b716e2.html
2.1建立基于對話框的MFC,并且將 IDC_BUTTON3按鈕風格的ower-draw打鉤:
2.2 聲明CBitamapButton m_btnBMP;
2.3 在對話框類CtestDlg的構造函數中m_btnBMP.loadbitmaps(IDB_BITMAP1,IDB_BITMAP2,IDB_BITMAP3,IDB_BITMAP4);
2.4 然后在OnInitialDilog中:m_btnBMP.SubClassDlgItem(IDC_BUTTON3,this);m_btnBMP.SizeToContent();
缺點:覆蓋掉了文字,并且也有閃屏
?
?
位圖按鈕
由于MFC提供的按鈕外觀不是很漂亮(其實是很丑),所以使用按鈕的時候往往要自己重新繪制,最多的就是添加自己的漂亮圖片。
1.CButton中提供了SetBitmap函數,可以給按鈕設置位圖,使用方法如下:
CButton button;
button.Create(_T("My button"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON, CRect(10,10,100,30),this, 1);
CBitmap bmp;
bmp.LoadBitmap(IDB_BMP);
button.SetBitmap(bmp);
優點:使用方法簡單
缺點:位圖單一,不能顯示區分按鈕各種狀態,有閃屏情況
2.使用MS做好的CBitmapButton類:
CBitmapButton是MS封裝好的位圖按鈕類,從CButton類繼承而來,提供兩種使用方法,但使用前要創建一個CButton對象與其關聯,另外,CBitmapButton類必須具有BS_OWNERDRAW屬性:
<1> 使用LoadBitmaps方法:
CBitmapButton bmpButton;
bmpButton.Create(NULL, WS_CHILD | WS_VISIBLE | BS_OWNERDRAW, CRect(10, 10, 100, 100), this, BTN_ID);
bmpButton.LoadBitmaps(IDB_UP, IDB_DOWN, IDB_FOCUS, IDB_DISABLE);
<2>使用AutoLoad方法:
創建一個按鈕資源ID為IDC_MYBUTTON并且具有BS_OWNERDRAW屬性,設定Caption為:MYBUTTON,插入四張資源位圖ID為"MYBUTTONU","MYBUTTOND","MYBUTTONF","MYBUTTONX",分別表示按鈕的”彈起“,”按下“,”焦點“,”禁用“狀態。最后調用AutoLoad函數就可以自動加載了:
CBitmapButton bmpButton;
bmpButton.AutoLoad(IDC_MYBUTTON, this);
以上兩種用法
優點:使用簡單,很好的用位圖表示了按鈕的各種狀態,豐富了按鈕的外觀
缺點:有閃屏情況
MS真讓人受傷啊,提供了位圖按鈕的使用,但就是不能用,都有閃屏。所以只有自己重新繪制了:
3.添加自定義類,從CButton繼承,在類向導中添加虛函數DrawItem,然后重畫:
??? //從lpDrawItemStruct獲取控件的相關信息
??? CRect rect = lpDrawItemStruct->rcItem;
??? CDC *pDC=CDC::FromHandle(lpDrawItemStruct->hDC);
??? int nSaveDC=pDC->SaveDC();
??? UINT state = lpDrawItemStruct->itemState;
??? if(state & ODS_SELECTED)
??? {
??? ?? // 畫按鈕按下狀態的時候需要顯示的位圖
??? ??? DrawBmpState(pDC, m_bmpResDown);
??? }
??? else
??? {
??? ?? // 畫按鈕其他狀態的時候需要顯示的位圖
??? ??? DrawBmpState(pDC, m_bmpResUp);
??? }
????
??? // 恢復DC
??? pDC->RestoreDC(nSaveDC);
注:DrawBmpState用來畫按鈕的各種狀態,采用雙緩沖技術,在PC上測試運行正常,但是在手持設備運行有閃屏情況。閃屏發生在按其他按鈕的時候,由于這個按鈕要丟失焦點,狀態轉換太快,處理器速度跟不上的原因。(這只是我的個人猜測,高人知道的請賜教)。或者是其他的原因。總之閃屏就像一個甩不掉的魔鬼一樣如影隨形,最后只能自己重畫了。
4.在OnPaint中徹底重畫,定制自己的位圖按鈕:
添加CBmpButton類繼承自CButton:
添加BOOL m_bDown;初始化為FALSE,用來標識按鈕的按下狀態,當按鈕按下是置為TRUE,否則為FALSE,主要是為了避免當鼠標在其他地方按下后,然后在按鈕上釋放造成的按鈕重繪。
添加WM_PAINT消息重繪:
??? CPaintDC dc(this); // device context for painting
??? if(m_bDown)
??? {
??? ??? DrawBmpState(&dc, m_bmpResDown);
??? }
??? else
??? {
??? ??? DrawBmpState(&dc, m_bmpResUp);
??? }
DrawBmpState函數用來畫按鈕各個狀態的位圖,采用雙緩沖技術避免了按鈕重繪時的閃屏,這里只列出了兩種:彈起和按下:
VOID CBmpButton::DrawBmpState(CDC *pDC, HBITMAP hBitmap)
{
??? CRect rect;
??? //GetWindowRect(&rect);
??? GetClientRect(&rect);
????
??? CDC MemDC,mdc;
??? mdc.CreateCompatibleDC(NULL);
??? MemDC.CreateCompatibleDC(NULL);
????
??? CBitmap MemBitmap;
??? MemBitmap.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());
????
??? MemDC.SelectObject(&MemBitmap);
??? MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(0,0,0));
????
??? //b1.LoadBitmap(bmpID);
??? //pb1 = CBitmap::FromHandle(hBitmap);
??? mdc.SelectObject(hBitmap);
??? MemDC.BitBlt(0,0,rect.Width(),rect.Height(),&mdc,0,0,SRCCOPY);
????
??? pDC->BitBlt(0,0,rect.Width(),rect.Height(),&MemDC,0,0,SRCCOPY);
??? //繪圖完成后的清理
??? MemBitmap.DeleteObject();
??? MemDC.DeleteDC();
}
添加WM_LBUTTONDOWN事件:
??? m_bDown = TRUE;
??? InvalidateRect(NULL);
添加WM_LBUTTONUP事件:
??? if(m_bDown)
??? {
??? ??? m_bDown = FALSE;
??? ??? InvalidateRect(NULL);
??? }
這樣就避免了重繪按鈕的閃屏,希望閃屏以后不要再來!
總結
以上是生活随笔為你收集整理的MFC/VC++中怎样设置位图按钮并且位图不会覆盖文字——–位图按钮的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网站程序员的程序员成长之路大概分几个阶段
- 下一篇: VC的MFC中重绘函数的使用总结(整理)