另一种界面闪烁解决方案

      基于贴图的界面中,为了实现界面的统一,一种方法就是所有界面类派上自一个贴图的基类,而基类中一般是进行最基本的贴图,派生类中多数会进行自己的其他绘制,这时如果不进行特殊处理必然会出现闪烁,因为基类和派生类不是一起绘制的,这里介绍一种方案避免闪烁,具体实现参看代码:

下面是基类,只是象征性的绘制了下:

#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);
}
};