CDC(HDC)繪圖類:
五大GDI對象類:
CPen,CBrush,CFont,CBitmap,CRgn
23.1 LoadImage API
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
uType參數填寫以下三種:
IMAGE_BITMAP Loads a bitmap.
IMAGE_CURSOR Loads a cursor.
IMAGE_ICON Loads an icon
從HINSTANCE内部加載
void CTestImageDlg::OnBnClickedButton1()
{
static HICON hIcon = (HICON)::LoadImage(theApp.m_hInstance, (LPCTSTR)IDI_TEST, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
SetIcon(hIcon, FALSE);
//*.cur
}
m_hBitmap = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
m_hBitmap = ::LoadBitmap(theApp.m_hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
從檔案中直接加載
m_hBitmap = (HBITMAP)::LoadImage(NULL, _T("./ban.bmp"),
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
HICON hIcon = (HICON)::LoadImage(NULL, _T("DfIcon.ico"),
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE| LR_DEFAULTSIZE);
SetIcon(hIcon, TRUE);
SetIcon(hIcon, FALSE);
顯示
//CDC mdc;
//BITMAP bm;
//::GetObject(m_hBitmap, sizeof(bm), &bm);
//mdc.CreateCompatibleDC(&dc);
//mdc.SelectObject(m_hBitmap);
dc.BitBlt(10, 40, m_mdc.GetWidth(), mdc.GetHeight(), &m_mdc, 0, 0, SRCCOPY);
23.2 解決閃爍問題:
1、禁用非客戶區輸出,讓非客戶區
WM_NCPAINT
産生空輸出。
2、禁用客戶區背景輸出:
WM_ERASEBKGRAND
消息是
Invalidate(TRUE)
要調用的背景輸出。
3、調用Invalidate函數時,盡量使用
FALSE
。
4、當有多層次輸出時,使用雙緩沖技術,在記憶體中做好多次輸出的草稿。
23.3 CMemoryDC類
#ifndef __MEMDC_H__
#define __MEMDC_H__
//Author:www.baojy.com
class CMemoryDC :public CDC
{
CSize m_size;
public:
void BitTrans(
int nXDest, // 目标起點X
int nYDest, // 目标起點Y
int nWidthDest, // 目标寬度
int nHeightDest,// 目标高度
CDC* pDC, // 目标DC
int nXSrc, // 來源起點X
int nYSrc, // 來源起點Y
COLORREF crTrans// 透明色
)
{
CMemoryDC dcImage(nWidthDest, nHeightDest,pDC);//臨時DC
CBitmap bmpMask;
bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 建立單色掩碼位圖
CDC dcMask;//掩碼DC
dcMask.CreateCompatibleDC(pDC);
dcMask.SelectObject(bmpMask);
//将載入位圖的記憶體DC中的位圖,拷貝到臨時DC中
dcImage.BitBlt( 0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
// 設定臨時DC的透明色
dcImage.SetBkColor(crTrans);
//掩碼DC的透明區域為白色其它區域為黑色
dcMask.BitBlt(0, 0, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCCOPY);
//臨時DC透明區域為黑色,其它區域保持不變
dcImage.SetBkColor(RGB(0,0,0));
dcImage.SetTextColor(RGB(255,255,255));
dcImage.BitBlt( 0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
// 目标DC透明部分保持螢幕不變,其它部分變成黑色
pDC ->SetBkColor(RGB(255,255,255));
pDC ->SetTextColor(RGB(0,0,0));
pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
}
void StretchTrans(
int nXDest, // 目标起點X
int nYDest, // 目标起點Y
int nWidthDest, // 目标寬度
int nHeightDest, // 目标高度
CDC* pDC, // 目标DC
int nXSrc, // 來源起點X
int nYSrc, // 來源起點Y
int nWidthSrc, // 來源寬度
int nHeightSrc, // 來源高度
COLORREF crTrans // 透明色
)
{
CMemoryDC dcImage(nWidthDest, nHeightDest,pDC);//臨時DC
CBitmap bmpMask;
// 建立單色掩碼位圖
bmpMask.CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);
CDC dcMask;
dcMask.CreateCompatibleDC(pDC);
dcMask.SelectObject(bmpMask);
// 将載入位圖的記憶體DC中的位圖,拷貝到臨時DC中
if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, this, nXSrc, nYSrc, SRCCOPY);
else
dcImage.StretchBlt(0, 0, nWidthDest, nHeightDest,
this, nXSrc, nYSrc, nWidthSrc, nHeightSrc, SRCCOPY);
// 設定臨時DC的透明色
dcImage.SetBkColor( crTrans);
//掩碼DC的透明區域為白色其它區域為黑色
dcMask.BitBlt(0,0,nWidthDest, nHeightDest,&dcImage,0,0,SRCCOPY);
//臨時DC透明區域為黑色,其它區域保持不變
dcImage.SetBkColor(RGB(0,0,0));
dcImage.SetTextColor(RGB(255,255,255));
dcImage.BitBlt(0, 0, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
// 目标DC透明部分保持螢幕不變,其它部分變成黑色
pDC ->SetBkColor(RGB(255,255,255));
pDC ->SetTextColor(RGB(0,0,0));
pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcMask, 0, 0, SRCAND);
pDC ->BitBlt(nXDest, nYDest, nWidthDest, nHeightDest, &dcImage, 0, 0, SRCPAINT);
}
CMemoryDC()
{
m_size.cx = m_size.cy = 0;
}
//從資源中加載位圖
BOOL LoadBitmap(UINT nBitmapID,CDC* pDC=NULL)
{
CBitmap bitmap;
bitmap.LoadBitmap(nBitmapID);
BITMAP bm;
bitmap.GetBitmap(&bm);
m_size.cx = bm.bmWidth;
m_size.cy = bm.bmHeight;
CreateCompatibleDC(pDC);
SelectObject(bitmap);
return TRUE;
}
CMemoryDC(UINT nBitmapID,CDC* pDC=NULL)
{
LoadBitmap(nBitmapID,pDC);
}
//從.bmp檔案中加載位圖
BOOL LoadBitmap(LPCTSTR szBitmapFile,CDC* pDC=NULL)
{
HBITMAP hBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
szBitmapFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
BITMAP bm;
GetObject(hBitmap,sizeof(bm),&bm);
m_size.cx = bm.bmWidth;
m_size.cy = bm.bmHeight;
CreateCompatibleDC(pDC);
SelectObject(hBitmap);
return TRUE;
}
CMemoryDC(LPCTSTR szBitmapFile,CDC* pDC=NULL)
{
LoadBitmap(szBitmapFile,pDC);
}
//建立一張空白記憶體畫布
BOOL Create(int cx,int cy,CDC* pDC = NULL)
{
CreateCompatibleDC(pDC);
CBitmap bitmap;
if(pDC)
bitmap.CreateCompatibleBitmap(pDC,cx,cy);
else
bitmap.CreateCompatibleBitmap(&CClientDC(NULL),cx,cy);
m_size.cx = cx;
m_size.cy = cy;
SelectObject(bitmap);
return TRUE;
}
CMemoryDC(int cx,int cy,CDC* pDC = NULL)
{
Create(cx,cy,pDC);
}
//摧毀
BOOL DeleteDC()
{
if(!GetSafeHdc())
return TRUE;
CBitmap * pBitmap = GetCurrentBitmap();
pBitmap ->DeleteObject();
return CDC::DeleteDC();
}
~CMemoryDC()
{
DeleteDC();
}
inline int Width(){return m_size.cx;}
inline int Height(){return m_size.cy;}
};
#endif //__MEMDC_H__
23.4 采用CMemoryDC類實作圖檔旋轉
//1、加載資源位圖
//2、加載外部位圖
//3、建立空白位圖(黑色:指定高寬)
//4、顯示透明和伸縮透明圖檔
m_dcBack.LoadBitmap(IDB_BITMAP1); // 初始化
void CPageDlg::OnPaint()
{
CPaintDC dc(this); // 用于繪制的裝置上下文
CRect rect;
GetClientRect(rect);
CMemoryDC mdc(rect.Width(), rect.Height(),&dc);//緩沖DC:黑色
mdc.FillSolidRect(rect, GetSysColor(COLOR_3DFACE)); // 緩沖DC:灰色
mdc.StretchBlt(m_nLeft, 0, rect.Width() - m_nLeft * 2, rect.Height(),
&m_dcBack, 0, 0, rect.Width(), rect.Height(), SRCCOPY); // 繪圖輸出到緩沖DC中
dc.BitBlt(0, 0, rect.Width(),rect.Height(), &mdc, 0, 0, SRCCOPY);//一次性對界面(dc)輸出
}
23.5 采用CMemoryDC類實作蝴蝶動畫
#include "MemoryDC.h"
#pragma once
// CfsDlg 對話框
class CfsDlg : public CDialogEx
{
CMemoryDC m_dc;//緩沖
enum { PAGE_COUNT =7};
CMemoryDC m_dcBack;
CMemoryDC m_dcFly[PAGE_COUNT];
struct SData
{
CPoint pos;
CPoint dir;//5,5 -5,5 5,-5 -5,-5
int nIndex;
};
CArray<SData> m_arr;//動态數組
public:
CfsDlg(CWnd* pParent = NULL); // 标準構造函數
protected:
HICON m_hIcon;
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnNcPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnTimer(UINT_PTR nIDEvent);
};
BOOL CfsDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
srand(time(NULL));
m_dcBack.LoadBitmap(_T("./images/back.bmp"));
int cx = GetSystemMetrics(SM_CXSCREEN);
int cy = GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(NULL, 0, 0, cx, cy, 0);
m_dc.Create(cx, cy);
int i = -1;
CString str;
while (++i<_countof(m_dcFly))
{
str.Format(_T("./images/%03d.bmp"), i + 1);
m_dcFly[i].LoadBitmap(str);
}
SetTimer(1, 20, NULL);
SetIcon(m_hIcon, TRUE); // 設定大圖示
SetIcon(m_hIcon, FALSE); // 設定小圖示
return TRUE; // 除非将焦點設定到控件,否則傳回 TRUE
}
void CfsDlg::OnPaint()
{
CPaintDC dc(this); //界面dc
CRect rect;
GetClientRect(rect);
//dc.BitBlt(0, 0, m_dcBack.GetWidth(), m_dcBack.GetHeight(), &m_dcBack, 0, 0, SRCCOPY);
m_dc.StretchBlt(0, 0, rect.Width(), rect.Height(), &m_dcBack, 0, 0, m_dcBack.GetWidth(), m_dcBack.GetHeight(), SRCCOPY);
int i = 0,nSize = m_arr.GetSize();
while (i < nSize)
{
SData& d = m_arr[i];
m_dcFly[d.nIndex].BitTrans(d.pos.x,d.pos.y ,m_dcFly->GetWidth(),m_dcFly->GetHeight(),&m_dc,0,0,0);
if (++d.nIndex > 6)
d.nIndex = 0;
d.pos.Offset(d.dir);
GetClientRect(rect);
if (d.pos.x >= rect.right - m_dcFly->GetWidth() || d.pos.x <= 0)
d.dir.x *= -1;
if (d.pos.y >= rect.bottom - m_dcFly->GetHeight() || d.pos.y <= 0)
d.dir.y *= -1;
++i;
}
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &m_dc, 0, 0, SRCCOPY);
}
BOOL CfsDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
void CfsDlg::OnNcPaint()
{
}
void CfsDlg::OnLButtonDown(UINT nFlags, CPoint point)
{//無限增長的蝴蝶個數
SData data = { point,{5,5},0 };
if(rand()%2) //893253%2
data.dir.x *= -1;
if (rand() % 2) //547547%2
data.dir.y *= -1;
m_arr.Add(data);
CDialogEx::OnLButtonDown(nFlags, point);
}
void CfsDlg::OnTimer(UINT_PTR nIDEvent)
{
Invalidate(FALSE);
CDialogEx::OnTimer(nIDEvent);
}