Hướng dn thc hành Lp trình C trên Windows
1
S DNG K THUT DEVICE CONTEXT O
1 Mc đích
S dng k thut MemDC.
Thao tác trên nh bitmap.
2 K thut MemDC
2.1 Ý tưởng chính:
Nếu thc hin nhiu thao tác v trc tiếp trên device context ca màn hình thì
s b tình trng màn hình b “git”.
Khi s dng k thut MemDC có th hn chế được hin tượng “git” màn hình:
Trước tiên cn to ra 1 device context o trong b nh tương thích vi device
context tht s cn x.
Sau đó, tt c mi thao tác v s được thc hin trên dc o này thay vì thc hin
trc tiếp trên dc tht.
Cui cùng chép ni dung ca dc o vào dc tht. Xem như ch thao tác trc tiếp
trên device context tht.
2.2 Khai báo biến
Khai báo b sung biến thành phn trong lp CxxxView (trong file xxxView.h):
CDC m_MemDC;
CBitmap m_MemBitmap, *m_pOldBitmap;
2.3 Các hàm x
2.3.1 To MemDC
Cn phi to ra memdc trước khi s dng.
To hàm OnCreate ng vi s kin WM_CREATE ca lp CxxxView
int CxxxView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
// Ly dc ca màn hình
CClientDC dc(this);
// Ly kích thước màn hình.
int MaxX = ::GetSystemMetrics(SM_CXSCREEN);
int MaxY = ::GetSystemMetrics(SM_CYSCREEN);
// To ra m_MemDC tương thích vi dc ca màn hình
m_MemDC.CreateCompatibleDC(&dc);
Hướng dn thc hành Lp trình C trên Windows
2
// To ra 1 đối tượng CBitmap (kích thước MaxX × MaxY)
// tương thích vi dc màn hình
m_MemBitmap.CreateCompatibleBitmap(&dc, MaxX, MaxY);
// Đưa đối tượng bitmap m_MemBitmap vào m_MemDC
m_pOldBitmap = m_MemDC.SelectObject(&m_MemBitmap);
return 0;
}
2.3.2 Hy MemDC
Cn hy MemDC sau khi s dng xong.
Trong hàm destructor ca lp CxxxView, b sung các hàm hy đối tượng MemDC và
MemBitmap
CxxxView::~CxxxView()
{
m_MemDC.DeleteDC();
m_MemBitmap.DeleteObject();
m_Objects.RemoveAll();
}
2.3.3 S dng MemDC
Có th viết code trong hàm OnDraw để s dng MemDC như sau :
void CxxxView::OnDraw(CDC* pDC)
{
CVD4Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(rect);
m_MemDC.FillSolidRect(rect, RGB(59, 112, 168));
int i, n=m_Objects.GetSize();
for (i=0; i<n; i++)
((CEllipse*)m_Objects[i])->Draw(&m_MemDC);//V lên memDC
pDC->BitBlt(0, 0, rect.Width(), rect.Height(),
&m_MemDC, 0, 0, SRCCOPY);
}
Build và thc hin th chương trình
Vn còn hin tượng “git” màn hình
Lý do: mi khi cn v li ca s ca View, s kin WM_ERASEBKGND s
được t động phát sinh đểu cu xóa toàn b nn ca View bng cách tô màu
trng vào vùng client ca View. Khi đã s dng MemDC thì vic tô màu nn có
th thc hin bng lnh FillSolidRect trong đọan code trên đây. Như vy,
thao tác tô màu nn vùng client ca View trong s kin xóa nn WM_ERASEBKGND
là hoàn toàn không cn thiết và s gây ra hin tượng “git” màn hình.
Hướng dn thc hành Lp trình C trên Windows
3
Gii pháp: override hàm x lý s kin WM_ERASEBKGND ca CxxxView: Vào
Class Wizard để to ra hàm OnEraseBkgnd tương ng vi s kin
WM_ERASEBKGND ca CxxxView.
BOOL CxxxView::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
// return CView::OnEraseBkgnd(pDC);
}
Build và thc hin chương trình để xem th hiu qu ca vic s dng memdc.
2.3.4 Hàm BitBlt
Hàm BitBlt ca lp CDC có tác dng chép ni dung bitmap t device context ngun
sang device context đích.
BOOL BitBlt(int x, int y, int nWidth, int nHeight,
CDC* pSrcDC, int xSrc, int ySrc,
DWORD dwRop );
vi
x, y Góc trái trên ca vùng device context đích
nWidth, nHeight Kích thước vùng device context đích
pSrcDC Con tr đến device context ngun
xSrc, yScr Góc trái trên ca vùng nh được chép trong device context ngun
dwRop Chế độ chép nh
nWidth
nHeight
DC nguoàn
(xSrc, ySrc)
nWidth
nHeight
DC ñích
(x, y)
BitBlt
3 Thao tác trên nh bitmap
3.1 To nh bitmap trong Resource
Trong ca s Resource View, chn chc năng Insert (hay dùng chc năng
Resource trong menu Insert), sau đó chn loi resource là bitmap. Trong phn Bitmap
ca Resource View s xut hin thêm 1 bitmap (ví d có ID là IDB_BITMAP1)
Hướng dn thc hành Lp trình C trên Windows
4
Lưu ý: nh bitmap to trong resource theo cách này có thnh nh phân (2
màu), nh 16 màu hay 256 màu. Không th to ra nh true color (ví d nh 24bit)
trong resource bng cách này.
3.2 Import nh bitmap vào Resource
Có th import nh bitmap có sn vào resource theo cách sau:
Vào Resource View, chn chc năng Import.
Trong hp thoi Import Resource, nhp vào ô File name *.bmp
Chn file bitmap đã lưu sn trên đĩa để import vào resource.
Lưu ý: nếu nh bitmap nhiu hơn 256 màu (tc là nh true color, ví d như nh
24 bit) thì không th xem hay sa đổi trong Resource View ca Visual C++. Tuy
nhiên, tt c nh bitmap này đều có th s dng bình thường như các nh bitmap có ít
hơn hay bng 256 màu.
3.3 Load nh bitmap t Resource
Mi thao tác trên nh bitmap trong resource được thc hin thông qua lp
CBitmap.
S dng hàm LoadBitmap ca lp CBitmap để load nh bitmap trong resource.
Sau khi s dng xong thì cn hy đối tượng bitmap bng hàm DeleteObject.
Ví d:
CBitmap Pic;
Pic.LoadBitmap(IDB_BITMAP1);
… … …
Pic.DeleteObject();
3.4 Load nh bitmap t tp tin
S dng hàm LoadImage để load bitmap t tp tin :
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
Mt ví d m tp tin (m tp tin Bitmap vi tên là m_strFileName)
bmRead = (HBITMAP) LoadImage(NULL, m_strFileName,
IMAGE_BITMAP, 0,0 , LR_LOADFROMFILE);
Hướng dn thc hành Lp trình C trên Windows
5
3.5 Hin th CBitmap trên device context (DC)
Xây dng hàm PutBitmap để hin th pBitmap lên pDC ti v trí góc trái trên là
TopLeft và chế độ chép nh là dwRop (mc định là SRCCOPY)
void PutBitmap(CDC* pDC, CBitmap* pBitmap,
CPoint TopLeft, DWORD dwRop = SRCCOPY )
{
BITMAP bm;
CDC TempDC;
TempDC.CreateCompatibleDC(pDC);
TempDC.SelectObject(pBitmap);
pBitmap->GetBitmap(&bm);
pDC->BitBlt(TopLeft.x, TopLeft.y, bm.bmWidth, bm.bmHeight,
&TempDC, 0, 0, dwRop);
TempDC.DeleteDC();
}
Gii thích: cu trúc BITMAP đưc s dng để ly các thông s ca 1 đối tượng
CBitmap, chng hn như kích thước, s bit màu/ pixel…
3.6 Ví d:
To ra 1 bitmap trong resource view (ví d: IDB_BITMAP1).
Xây dng hàm PutBitmap như đã trình bày trên
Xây dng tiếp hàm OnDraw như sau:
void CxxxView::OnDraw(CDC* pDC)
{
CVD4Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CRect rect;
GetClientRect(rect);//Ly ca s vùng client
m_MemDC.FillSolidRect(rect, RGB(59, 112, 168));
CBitmap Pic;
Pic.LoadBitmap(IDB_BITMAP1);
PutBitmap(&m_MemDC, &Pic, CPoint(0, 0), SRCCOPY);
Pic.DeleteObject();
int i, n=m_Objects.GetSize();
for (i=0; i<n; i++)
((CEllipse*)m_Objects[i])->Draw(&m_MemDC);
pDC->BitBlt(0, 0, rect.Width(), rect.Height(),
&m_MemDC, 0, 0, SRCCOPY);
}