#ifndef  _TEST_H_
#define  _TEST_H_class CTestApp:public CWinApp
{
public:
virtual BOOL InitInstance( );
};class CTestFrame:public CFrameWnd
{
public:
CTestFrame();
virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName);
protected:
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
private:
bool bSetDc;//dc need set?
int m_iSetID;//dc saved id.

};
#endif
#include <afxwin.h>
#include "test.h"CTestApp TheApp;
BOOL CTestApp::InitInstance()
{
CTestFrame *pFrame=new CTestFrame();
pFrame->Create(NULL,_T("Test"));
m_pMainWnd=pFrame;
m_pMainWnd->ShowWindow(SW_NORMAL);
m_pMainWnd->UpdateWindow();
return TRUE;
}CTestFrame::CTestFrame()
{
bSetDc=1;//need set first
}BOOL CTestFrame::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName)
{
return CFrameWnd::Create( lpszClassName, lpszWindowName);
}BEGIN_MESSAGE_MAP(CTestFrame,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP()void CTestFrame::OnPaint()
{
PAINTSTRUCT ps;
HDC hdc;
RECT rc;
char buf[256];
memset(buf,0,256);
::GetClientRect(this->GetSafeHwnd(),&rc);
hdc=::BeginPaint(this->GetSafeHwnd(),&ps);
if(bSetDc==1)
{
SetBkMode(hdc,TRANSPARENT);
SetTextColor(hdc,RGB(255,0,0));//red
m_nSavedDc=::SaveDC(hdc);
bSetDc=0;
}
else
{
::RestoreDC(hdc,m_nSavedDc);//it doesn't work,how to make it work well?
}
DrawText(hdc,_T("Text"),wcslen(_T("Text")),&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
//the second time it draw  default(black )why not red?
::EndPaint(this->GetSafeHwnd(),&ps);
}

解决方案 »

  1.   

    就是要实现我第一次响应paint以后   把dc的设置保存下来  下次再次响应的时候  把这个dc恢复 而不去重新设置 就可以直接画了
      

  2.   

    那你把
    else
    {
        ::RestoreDC(hdc,m_nSavedDc);//it doesn't work,how to make it work well?
    }
    改成
    else
    {
        ::RestoreDC(hdc,m_nSavedDc);//it doesn't work,how to make it work well?
        bSetDc=1;
    }
      

  3.   

    这个应该跟作用域有关, 因为是保存在函数栈里面, 下次再进入函数的时候又是一个新的栈了.. 所以无法恢复上一次函数调用时的DC, 除非把函数定义为static??(没试验过).. 不过如果是在一次函数调用里面save跟restore是成功的...
      

  4.   

    好像是保存在设备上下文的栈里面了,所以你的程序应当保证这个栈不消失:
    1:HDC hdc; 修改为:static HDC hdc
    2: hdc=::BeginPaint(this->GetSafeHwnd(),&ps); 这一句放到if(bSetDc==1)里面
    3:::EndPaint(this->GetSafeHwnd(),&ps); 这句删掉
      

  5.   

    在MFC工程编程要按照MFC的规则,你的::BeginPaint(this->GetSafeHwnd(),&ps);
    与 ::EndPaint(this->GetSafeHwnd(),&ps);无需使用,因为MFC在调用OnPaint前后自动调用了这两句话.不要定义 PAINTSTRUCT ps; HDC hdc;这是MFC内部使用的对象.
    在你的类中定义了成员变量 m_iSetID,而OnPaint方法中使用的却是m_nSavedDc.你应该把m_nSavedDc定义成类的成员变量,或函数OnPaint的静态变量.这样调用RestoreDC方法时,才能使用之前保存的状态.
      

  6.   

    to paerxiushi:
    m_iSetID 和 m_nSavedDc本来应该是一个变量 是发的时候写错了
    至于 BeginPaint 和EndPaint 是必须要的  看一下msdn你们就知道了 如果系统对ON_WM_PAINT响应的时候 系统会检测这2个函数 如果检测不到 系统将 不会把这个消息从消息队列中移除  这样将导致系统死循环 如果不想用这2个函数也可以 但是必须用MFC的CPaintDC 这个类先声明一个对象  CPaintDC dc(this);这个对象在 构造函数的时候会调用 BeginPaint() 析构的时候 会调用 EndPaint()我写的这个工程原本只是为了加深 对MFC框架的深入理解  所以整个工程没有用到 AppWizard.
      

  7.   

    我查了一下msdn:
    SaveDC:Saves the current state of the device context by copying state information (such as clipping region, selected objects, and mapping mode) to a context stack maintained by Windows.注意那个clipping region,我估计这是问题的关键,因为上次的失效区域基本上不可能与这次相同。可以这样测试一下:在BeginPaint之前先Invalidate(FALSE),使所有区域都失效,看看这样绘出来是不是就正常了,如果是的话再另作打算。
      

  8.   

    你能确定MFC在你创建CFrameWnd窗体时,将它的窗体类风格设置成CS_OWNDC吗?