基于贴图的界面中,为了实现界面的统一,一种方法就是所有界面类派上自一个贴图的基类,而基类中一般是进行最基本的贴图,派生类中多数会进行自己的其他绘制,这时如果不进行特殊处理必然会出现闪烁,因为基类和派生类不是一起绘制的,这里介绍一种方案避免闪烁,具体实现参看代码:
下面是基类,只是象征性的绘制了下:
#include <atlgdi.h> #include <atlmisc.h> template <class T> class ATL_NO_VTABLE CFlickFreeBaseDlg : public CDialogImpl<T> { BEGIN_MSG_MAP_EX(CFlickFreeBaseDlg) MSG_WM_PAINT(OnPaint) MSG_WM_ERASEBKGND(OnEraseBkgnd) END_MSG_MAP() public: CFlickFreeBaseDlg():m_pMemDC(NULL) { } ~CFlickFreeBaseDlg() { if (m_pMemDC) { delete m_pMemDC; m_pMemDC=NULL; } } protected: void OnPaint(CDCHandle dc) { GetClientRect(&m_rcClient); CPaintDC dcPaint(m_hWnd); if (NULL==m_pMemDC) { m_pMemDC=new CMemoryDC(dcPaint,m_rcClient); } //Do Base Paint m_pMemDC->FillSolidRect(m_rcClient,RGB(0,100,255)); m_pMemDC->DrawText(_T("Draw In Base"),-1,CRect(0,0,80,20),DT_SINGLELINE|DT_VCENTER); static_cast<T*>(this)->DerivingDraw(); delete m_pMemDC; m_pMemDC=NULL; } BOOL OnEraseBkgnd(CDCHandle dc) { return TRUE; } protected: CRect m_rcClient; CMemoryDC *m_pMemDC; };
下面是派生类代码:
#include “FlickFreeBase.h”
class CMainDlg : public CFlickFreeBaseDlg<CMainDlg>, public CUpdateUI<CMainDlg>,
public CMessageFilter, public CIdleHandler
{
public:
enum { IDD = IDD_MAINDLG };
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
return CWindow::IsDialogMessage(pMsg);
}
virtual BOOL OnIdle()
{
return FALSE;
}
BEGIN_UPDATE_UI_MAP(CMainDlg)
END_UPDATE_UI_MAP()
BEGIN_MSG_MAP(CMainDlg)
CHAIN_MSG_MAP(CFlickFreeBaseDlg<CMainDlg>)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
END_MSG_MAP()
// Handler prototypes (uncomment arguments if needed):
//LRESULT MessageHandler(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
//LRESULT CommandHandler(WORD /wNotifyCode/, WORD /wID/, HWND /hWndCtl/, BOOL& /bHandled/)
//LRESULT NotifyHandler(int /idCtrl/, LPNMHDR /pnmh/, BOOL& /bHandled/)
LRESULT OnInitDialog(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
{
// center the dialog on the screen
CenterWindow();
// set icons
HICON hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);
SetIcon(hIcon, TRUE);
HICON hIconSmall = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MAINFRAME),
IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR);
SetIcon(hIconSmall, FALSE);
// register object for message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->AddMessageFilter(this);
pLoop->AddIdleHandler(this);
UIAddChildWindowContainer(m_hWnd);
return TRUE;
}
LRESULT OnDestroy(UINT /uMsg/, WPARAM /wParam/, LPARAM /lParam/, BOOL& /bHandled/)
{
// unregister message filtering and idle updates
CMessageLoop* pLoop = _Module.GetMessageLoop();
ATLASSERT(pLoop != NULL);
pLoop->RemoveMessageFilter(this);
pLoop->RemoveIdleHandler(this);
return 0;
}
LRESULT OnAppAbout(WORD /wNotifyCode/, WORD /wID/, HWND /hWndCtl/, BOOL& /bHandled/)
{
CAboutDlg dlg;
dlg.DoModal();
return 0;
}
LRESULT OnOK(WORD /wNotifyCode/, WORD wID, HWND /hWndCtl/, BOOL& /bHandled/)
{
// TODO: Add validation code
CloseDialog(wID);
return 0;
}
LRESULT OnCancel(WORD /wNotifyCode/, WORD wID, HWND /hWndCtl/, BOOL& /bHandled/)
{
CloseDialog(wID);
return 0;
}
void CloseDialog(int nVal)
{
DestroyWindow();
::PostQuitMessage(nVal);
}
void DerivingDraw()
{
m_pMemDC->FillSolidRect(CRect(100,50,400,300),RGB(119,173,2));
m_pMemDC->DrawText(_T(“Draw In Deriving”),-1,CRect(100,50,400,300),DT_SINGLELINE|DT_VCENTER);
}
};