實現功能:
1、在對話方塊上的一塊地區繪製彩色線條。
2、視窗被覆蓋後恢複時,映像自動重繪。
3、改變按鈕顏色。
操作:
根據嚮導建立一個對話方塊程式。在資源中添加一個靜態文字框,其ID為IDC_STATIC。
在DialogXXXDlg.h 中加入如下內容
CBrush m_brush;//用於自訂色彩
CDC m_memDC;//螢幕DC相容的記憶體DC
CBitmap m_Bmp;//位元影像
CWnd* m_pDrawWnd;//用於儲存靜態文字框的對象指標
//
// 初始化和雙緩衝相關的資料
void InitialDBB();
//雙緩衝記憶體上繪圖
void DrawOnMem();
//在靜態地區畫圖
void DrawOnStaticArea();
//更改顏色的訊息響應函數
afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor);
在DialogXXXDlg.cpp 中加入如下內容
1、添加訊息映射
ON_WM_CTLCOLOR()
2、OnInitDialog()中添加初始化代碼
// TODO: 在此添加額外的初始化代碼
m_brush.CreateSolidBrush(RGB(255,0,0));//初始化畫刷
m_pDrawWnd = GetDlgItem(IDC_STATIC);//獲得靜態視窗對象指標
InitialDBB();// 初始化雙緩衝相關的資料
3、重寫函數OnCtlColor()
//改變按鈕顏色
HBRUSH CDialogDrawDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor)
{
HBRUSH hbr=CDialog::OnCtlColor(pDC,pWnd,nCtlColor);
//
if(pWnd->GetDlgCtrlID()==IDOK || pWnd->GetDlgCtrlID()==IDCANCEL)
{
pDC->SetTextColor(RGB(255,0,0));//設定文本顏色
pDC->SetBkMode(TRANSPARENT);//文字背景設為透明
pDC->SetBkColor(RGB(255,0,0));//設定背景色
return m_brush;
}
//
return hbr;//m_brush;///hbr
}
4、添加標頭檔中聲明的函數的定義代碼
// 初始化和雙緩衝相關的要素
void CDialogDrawDlg::InitialDBB()
{
CRect rt;
m_pDrawWnd->GetClientRect(&rt);
CDC* sDC = m_pDrawWnd->GetDC();
// 為螢幕DC建立相容的記憶體DC
if(!m_memDC.CreateCompatibleDC(sDC))//
{
::PostQuitMessage(0);
}
// 建立位元影像,不能是m_memDC,否則無顏色
m_Bmp.CreateCompatibleBitmap(sDC, rt.Width(), rt.Height());//m_memDC
// 相當於選擇畫布,m_pDrawWnd->
::SelectObject(m_memDC.GetSafeHdc(), m_Bmp);
m_pDrawWnd->ReleaseDC(sDC);
}
//雙緩衝記憶體上繪圖
void CDialogDrawDlg::DrawOnMem()
{
CRect rect;
m_pDrawWnd->GetClientRect(&rect);
//COLORREF crl = GetSysColor(COLOR_3DFACE);
//m_memDC.FillSolidRect(rect, crl);
//m_memDC.FillSolidRect(&rect, 0x00FFFFFF);// 白色填充, 注意,這次是畫在記憶體裝置環境上
CPen pen(PS_SOLID,1,RGB(255,0,0));
m_memDC.SelectObject(&pen);
//畫圖部分
m_memDC.MoveTo(rect.right,rect.bottom);
m_memDC.LineTo(rect.left,rect.top);
}
//
//在靜態地區畫圖
void CDialogDrawDlg::DrawOnStaticArea()
{
CWnd* pWnd = GetDlgItem(IDC_STATIC);//獲得靜態文字框的視窗對象
CRect rect;
pWnd->GetClientRect(&rect);
//
CDC* pDC = pWnd->GetDC();//
//
DrawOnMem();
// 一次性的將記憶體裝置環境上繪製完畢的圖形"貼"到螢幕上
pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_memDC, 0, 0, SRCCOPY);
pWnd->ReleaseDC(pDC);//
//
}
5、OnPaint()函數中添加繪圖代碼(紅色部分為新增內容)
void CDialogDrawDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用於繪製的裝置上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 使表徵圖在工作區矩形中置中
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// 繪製表徵圖
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
//重繪映像地區
PAINTSTRUCT ps;
CRect rt;
m_pDrawWnd->GetClientRect(&rt);
CDC* pDC=m_pDrawWnd->BeginPaint(&ps);
DrawOnMem();
pDC->BitBlt(0, 0, rt.Width(), rt.Height(), &m_memDC, 0, 0, SRCCOPY);
m_pDrawWnd->EndPaint(&ps);
}
}
這裡需要用BeginPaint() 和 EndPaint()函數獲得DC。原因是主表單在處理WM_PAINT訊息的時候也需要繪製發送訊息給各個控制項有機會繪製自己;如果不用BeginPaint() 和 EndPaint()函數獲得控制項DC,該控制項的訊息佇列中的WM_PAINT訊息就不會被刪除,控制項就還會調用其自身的OnPaint()函數重繪控制項,從而我們繪製的映像會被覆蓋。
說明:這裡的DrawOnStaticArea()沒有用到。這是用作擴充時在該地區繪圖的,寫在這裡是方便日後擴充。如果這樣的話,OnPaint()中就不需要DrawOnMem();這句,直接將前面繪好的圖貼上來就是。