Files
FC1/Editor/Controls/MemDC.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

153 lines
4.8 KiB
C++

//MemDC.h
#if _MSC_VER > 1000
#pragma once
#pragma pack(push)
#pragma pack(1)
#endif // _MSC_VER > 1000
#ifndef MemDCh
#define MemDCh
/*
This is a slightly optimised version of the popular CMemDC class.
For the fastest redraw put a bitmap in your Dialog, Control or View header:
CBitmap Bitmap;
In the .cpp file:
#include "MemDC.h"
and then call the following just once:
Bitmap.CreateCompatibleBitmap(pDC, Rect.Width(), Rect.Height());
For a Modal dialog call the above in OnInitDlg otherwise in your classe's contstructor.
If you don't have pDC use GetDC() which returns the DC of the screen.
If you're using OnPaint() use the following two lines:
CPaintDC PaintDC(this); // device context for painting
CMemDC dc(PaintDC, &Bitmap);
Then draw everything to dc - and thats it!
You don't need the Bitmap: you can just create the CMemDC with:
void CMyDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) {
CPaintDC PaintDC(this); // device context for painting
CMemDC dc(PaintDC);
it'll be slower for complex animations, but fine for most Controls.
The same applies to OwnerDraw Buttons, create the MemDC object as follows:
void CMemDCTesterDlg::OnDrawItem(int nIDCtl, LPDRAWITEMSTRUCT lpDrawItemStruct) {
CMemDC dc(lpDrawItemStruct, &Bitmap);
Theres also a constructor for Views:
void CMyView::OnDraw(CDC* pDC) {
CMemDC dc(pDC, &Bitmap);
Remember the following tips:
if you're filling the background yourself:
Remember to either do it in OnEraseBkgnd or to not do it at all use:
BOOL CMyDlgOrControl::OnEraseBkgnd(CDC* pDC) {return TRUE;}
If you're filling it black or white use:
PatBlt(Rect.left, Rect.top, Rect.Width(), Rect.Height(), BLACKNESS);
or:
PatBlt(Rect.left, Rect.top, Rect.Width(), Rect.Height(), WHITENESS);
to fill with the current dialog background colour use:
dc.FillSolidRect(&Rect, GetSysColor(COLOR_3DFACE)); //Draw in dialogs background colour
To draw text using the same font as the dialog box use:
CGdiObject* OldFont=dc.SelectObject(GetParent()->GetFont());
then use dc.DrawText(...);
and finish with
dc.SelectObject(OldFont);
To draw using the system dialog font use:
CGdiObject* OldFont=dc.SelectStockObject(ANSI_VAR_FONT);
then use dc.DrawText(...);
and finish with
dc.SelectObject(&OldFont);
It is best to use a class to encapsulate the clean-up:
class CUseDialogFont {
CGdiObject* OldFont;
CDC* pDC;
public:
CUseDialogFont(CDC* _pDC) {pDC=_pDC; OldFont=pDC->SelectStockObject(ANSI_VAR_FONT);}
~CUseDialogFont() {pDC->SelectObject(&OldFont);}
};
Then in your code just use:
CUseDialogFont Font(&dc);
That way you can 'return' at any time safe in the knowledge that the original font will be selected.
*/
class CMemDC : public CDC {
public:
CMemDC(CPaintDC& dc, CBitmap* pBmp=NULL) : isMemDC(!dc.IsPrinting()) {
//if(dc.GetWindow()) (dc.GetWindow())->GetClientRect(&Rect);
//else
Rect = dc.m_ps.rcPaint;
Set(&dc, Paint, pBmp);
}
CMemDC(CDC* pDC, CBitmap* pBmp=NULL) {
isMemDC=!pDC->IsPrinting();
if(isMemDC) {
pDC->GetClipBox(&Rect); //For Views
pDC->LPtoDP(&Rect);
}
Set(pDC, Draw, pBmp);
}
CMemDC(LPDRAWITEMSTRUCT lpDrawItemStruct, CBitmap* pBmp=NULL) : isMemDC(true) {
Rect=lpDrawItemStruct->rcItem;
Set(CDC::FromHandle(lpDrawItemStruct->hDC), DrawItem, pBmp);
}
~CMemDC() { // Destructor copies the contents of the mem DC to the original DC
if(isMemDC) {
pDC->BitBlt(Rect.left, Rect.top, Rect.Width(), Rect.Height(), this, Rect.left, Rect.top, SRCCOPY);
SelectObject(OldBitmap);
}
}
CMemDC* operator->() {return this;} // Allow usage as a pointer
operator CMemDC*() {return this;} // Allow usage as a pointer
private:
enum dcType {Paint,Draw,DrawItem};
void Set(CDC* _pDC, dcType Type, CBitmap* pBmp=NULL) {
ASSERT_VALID(_pDC);
pDC=_pDC;
OldBitmap=NULL;
if(isMemDC) {
CreateCompatibleDC(pDC);
if(pBmp!=NULL) OldBitmap=SelectObject(pBmp); //User passed bitmap, use it
else { //Create our own bitmap
CRect rc;
pDC->GetWindow()->GetClientRect(rc);
Bitmap.CreateCompatibleBitmap(pDC, rc.Width(), rc.Height());
OldBitmap=SelectObject(&Bitmap);
}
if(Type==Draw) {
SetMapMode(pDC->GetMapMode());
pDC->DPtoLP(&Rect);
SetWindowOrg(Rect.left, Rect.top);
}
}else{ // Make a copy of the relevent parts of the current DC for printing
m_bPrinting=pDC->m_bPrinting;
m_hDC=pDC->m_hDC;
m_hAttribDC=pDC->m_hAttribDC;
}
}
CBitmap Bitmap; // Offscreen bitmap
CBitmap* OldBitmap; // bitmap originally found in CMemDC
CDC* pDC; // Saves CDC passed in constructor
CRect Rect; // Rectangle of drawing area.
bool isMemDC; // TRUE if CDC really is a Memory DC.
};
#if _MSC_VER >= 1000
#pragma pack(pop)
#endif // _MSC_VER >= 1000
#endif //ndef MemDCh