CButton控制元件:MFC如何給按鈕新增圖片,顯示三種狀態,分別是點選、盤旋、初始狀態(不點選也不盤旋狀態)。
阿新 • • 發佈:2019-02-12
// PicButton.cpp : 實現檔案
//
#include "stdafx.h"
#include "MFCApplication5.h"
#include "PicButton.h"
// CPicButton
IMPLEMENT_DYNAMIC(CPicButton, CButton)
CPicButton::CPicButton()
{
m_bOver/*(滑鼠位於按鈕之上)*/ = FALSE;
m_bSelected/*(按鈕被按下)*/ = FALSE;
m_bTracking/*(在滑鼠按下釋放)*/ = FALSE;
m_bFocus /*按鈕為當前焦點*/ = FALSE;
}
CPicButton::~CPicButton()
{
}
BEGIN_MESSAGE_MAP(CPicButton, CButton)
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
ON_WM_MOUSEHOVER()
END_MESSAGE_MAP()
// CPicButton 訊息處理程式
void CPicButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);//cbSize 定義TRACKMOUSEEVENT結構體的大小;
tme.hwndTrack = m_hWnd;//hwndTrack 待跟蹤視窗的控制代碼
tme.dwFlags = TME_LEAVE | TME_HOVER;//服務請求,滑鼠移動位置,離開和盤旋按鈕的事件消耗時間,也就是改變狀態的失效和生效性
tme.dwHoverTime = 100;//游標在按鈕上,改變狀態的時間,以1毫秒為單位
m_bTracking = _TrackMouseEvent(&tme);
} CButton::OnMouseMove(nFlags, point);
}
//手動新增的是
LRESULT CControlButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bOver = FALSE; // 滑鼠沒位於按鈕之上
m_bTracking = FALSE; //滑鼠離開按鈕
InvalidateRect(NULL, FALSE); //讓按鈕重畫
return 0;//注意要返回值。
}
void CPicButton::OnMouseLeave()
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
m_bOver = FALSE; // 滑鼠沒有位於按鈕之上
m_bTracking = FALSE; //滑鼠離開按鈕
InvalidateRect(NULL, FALSE); //讓按鈕重畫
CButton::OnMouseLeave();
}
//手動新增的是
LRESULT CControlButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
m_bOver = TRUE; //滑鼠盤旋在按鈕上空
InvalidateRect(NULL); //重畫!
return 0;
}
void CPicButton::OnMouseHover(UINT nFlags, CPoint point)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
m_bOver = TRUE; //滑鼠盤旋在按鈕上空
InvalidateRect(NULL); //重畫!
CButton::OnMouseHover(nFlags, point);
}
void CPicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
int nSaveDC = pDC->SaveDC();
UINT state = lpDrawItemStruct->itemState;
//根據按鈕的狀態貼圖
//(以下貼按鈕狀態圖,分以下幾種情況來貼,,,和我們平常貼背景圖片一樣的做法)
//滑鼠停留按鈕的狀態
if (m_bOver)
{
//(以下按鈕貼圖,,可以用我們自己以前貼背景圖的方法去做)
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_OverBitmap);//載入停留狀態
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
else
{
//初始狀態
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_NormalBitmap);//載入最初狀態
BITMAP bmp;
m_NormalBitmap.GetObject(sizeof(bmp), &bmp);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
//按鈕被按下(選中)
if (state & ODS_SELECTED)
{
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_PressedBitmap);
BITMAP bmp;
//pOldBmp->GetBitmap(&bmp);
m_PressedBitmap.GetObject(sizeof(bmp), &bmp);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
// TODO: 新增您的程式碼以繪製指定項
}
//按鈕圖片的ID載入函式,在下面步驟的主對話方塊那裡會被呼叫
void CPicButton::SetBitmapId(int nOver, int nNormal, int nPressed, int nFocus)
{
m_NormalBitmap.LoadBitmap(nNormal);
m_PressedBitmap.LoadBitmap(nPressed);
m_FocusBitmap.LoadBitmap(nFocus);
m_OverBitmap.LoadBitmap(nOver);
}
6.
在資源檢視,引入Bitmap六張圖片:
“確定”按鈕的3張圖片,我這裡設定他們的ID是IDB_ok(初始狀態),IDB_ok2(盤旋狀態),IDB_ok2(按下狀態)。
“取消”按鈕的3張圖片,我這裡設定他們的ID是IDB_cancel1(初始狀態),IDB_okcancel2(盤旋狀態),IDB_cancel3(按下狀態)。
7.
在主對話方塊MFCApplication5Dlg,在建立類嚮導為兩個按鈕新增成員變數,我這裡把“確定”按鈕的變數設定為m_ok,把“取消”按鈕設定為m_cancel。
在MFCApplication5Dlg.h,新增#include "PicButton.h"這行程式碼,然後再把之前新新增的按鈕成員變數的類名改掉,CButton改成CPicButton.
例如:
public:
CPicButton m_cancel;
CPicButton m_ok;
8.
在MFCApplication5Dlg.cpp中的OnInitDialog()中新增以下程式碼:
BOOL CMFCApplication5Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關於...”選單項新增到系統選單中。
......
......
SetIcon(m_hIcon, TRUE); // 設定大圖示
SetIcon(m_hIcon, FALSE); // 設定小圖示
// TODO: 在此新增額外的初始化程式碼
-------------------------按鈕自繪新增的程式碼-----------------------------------------
m_ok.SetBitmapId(IDB_ok2, IDB_ok, IDB_ok3, IDB_ok);
m_cancel.SetBitmapId(IDB_cancel2, IDB_cancel1, IDB_cancel3, IDB_cancel1);
-------------------------------------------------------------------------------------
return TRUE; // 除非將焦點設定到控制元件,否則返回 TRUE
}
做完以上步驟之後,執行程式,如下圖效果:
//
#include "stdafx.h"
#include "MFCApplication5.h"
#include "PicButton.h"
// CPicButton
IMPLEMENT_DYNAMIC(CPicButton, CButton)
CPicButton::CPicButton()
{
m_bOver/*(滑鼠位於按鈕之上)*/ = FALSE;
m_bSelected/*(按鈕被按下)*/ = FALSE;
m_bTracking/*(在滑鼠按下釋放)*/ = FALSE;
m_bFocus /*按鈕為當前焦點*/ = FALSE;
}
CPicButton::~CPicButton()
{
}
BEGIN_MESSAGE_MAP(CPicButton, CButton)
ON_WM_MOUSEMOVE()
ON_WM_MOUSELEAVE()
ON_WM_MOUSEHOVER()
END_MESSAGE_MAP()
// CPicButton 訊息處理程式
void CPicButton::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
if (!m_bTracking)
{
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);//cbSize 定義TRACKMOUSEEVENT結構體的大小;
tme.hwndTrack = m_hWnd;//hwndTrack 待跟蹤視窗的控制代碼
tme.dwFlags = TME_LEAVE | TME_HOVER;//服務請求,滑鼠移動位置,離開和盤旋按鈕的事件消耗時間,也就是改變狀態的失效和生效性
tme.dwHoverTime = 100;//游標在按鈕上,改變狀態的時間,以1毫秒為單位
m_bTracking = _TrackMouseEvent(&tme);
} CButton::OnMouseMove(nFlags, point);
}
//手動新增的是
LRESULT CControlButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
m_bOver = FALSE; // 滑鼠沒位於按鈕之上
m_bTracking = FALSE; //滑鼠離開按鈕
InvalidateRect(NULL, FALSE); //讓按鈕重畫
return 0;//注意要返回值。
}
void CPicButton::OnMouseLeave()
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
m_bOver = FALSE; // 滑鼠沒有位於按鈕之上
m_bTracking = FALSE; //滑鼠離開按鈕
InvalidateRect(NULL, FALSE); //讓按鈕重畫
CButton::OnMouseLeave();
}
//手動新增的是
LRESULT CControlButton::OnMouseHover(WPARAM wParam, LPARAM lParam)
{
m_bOver = TRUE; //滑鼠盤旋在按鈕上空
InvalidateRect(NULL); //重畫!
return 0;
}
void CPicButton::OnMouseHover(UINT nFlags, CPoint point)
{
// TODO: 在此新增訊息處理程式程式碼和/或呼叫預設值
m_bOver = TRUE; //滑鼠盤旋在按鈕上空
InvalidateRect(NULL); //重畫!
CButton::OnMouseHover(nFlags, point);
}
void CPicButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CRect rect = lpDrawItemStruct->rcItem;
CDC *pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
int nSaveDC = pDC->SaveDC();
UINT state = lpDrawItemStruct->itemState;
//根據按鈕的狀態貼圖
//(以下貼按鈕狀態圖,分以下幾種情況來貼,,,和我們平常貼背景圖片一樣的做法)
//滑鼠停留按鈕的狀態
if (m_bOver)
{
//(以下按鈕貼圖,,可以用我們自己以前貼背景圖的方法去做)
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_OverBitmap);//載入停留狀態
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
else
{
//初始狀態
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_NormalBitmap);//載入最初狀態
BITMAP bmp;
m_NormalBitmap.GetObject(sizeof(bmp), &bmp);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
//按鈕被按下(選中)
if (state & ODS_SELECTED)
{
CDC MemDC;
MemDC.CreateCompatibleDC(pDC);
CBitmap *pOldBmp;
pOldBmp = MemDC.SelectObject(&m_PressedBitmap);
BITMAP bmp;
//pOldBmp->GetBitmap(&bmp);
m_PressedBitmap.GetObject(sizeof(bmp), &bmp);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &MemDC, 0, 0, SRCCOPY);
}
// TODO: 新增您的程式碼以繪製指定項
}
//按鈕圖片的ID載入函式,在下面步驟的主對話方塊那裡會被呼叫
void CPicButton::SetBitmapId(int nOver, int nNormal, int nPressed, int nFocus)
{
m_NormalBitmap.LoadBitmap(nNormal);
m_PressedBitmap.LoadBitmap(nPressed);
m_FocusBitmap.LoadBitmap(nFocus);
m_OverBitmap.LoadBitmap(nOver);
}
6.
在資源檢視,引入Bitmap六張圖片:
“確定”按鈕的3張圖片,我這裡設定他們的ID是IDB_ok(初始狀態),IDB_ok2(盤旋狀態),IDB_ok2(按下狀態)。
“取消”按鈕的3張圖片,我這裡設定他們的ID是IDB_cancel1(初始狀態),IDB_okcancel2(盤旋狀態),IDB_cancel3(按下狀態)。
7.
在主對話方塊MFCApplication5Dlg,在建立類嚮導為兩個按鈕新增成員變數,我這裡把“確定”按鈕的變數設定為m_ok,把“取消”按鈕設定為m_cancel。
在MFCApplication5Dlg.h,新增#include "PicButton.h"這行程式碼,然後再把之前新新增的按鈕成員變數的類名改掉,CButton改成CPicButton.
例如:
public:
CPicButton m_cancel;
CPicButton m_ok;
8.
在MFCApplication5Dlg.cpp中的OnInitDialog()中新增以下程式碼:
BOOL CMFCApplication5Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關於...”選單項新增到系統選單中。
......
......
SetIcon(m_hIcon, TRUE); // 設定大圖示
SetIcon(m_hIcon, FALSE); // 設定小圖示
// TODO: 在此新增額外的初始化程式碼
-------------------------按鈕自繪新增的程式碼-----------------------------------------
m_ok.SetBitmapId(IDB_ok2, IDB_ok, IDB_ok3, IDB_ok);
m_cancel.SetBitmapId(IDB_cancel2, IDB_cancel1, IDB_cancel3, IDB_cancel1);
-------------------------------------------------------------------------------------
return TRUE; // 除非將焦點設定到控制元件,否則返回 TRUE
}
做完以上步驟之後,執行程式,如下圖效果: