我正在尝试调用OnEraseBkgnd()
在另一个函数中重新绘制窗口。
例如,如下代码:
...
CBitmap Background;
BITMAP bm;
CDC dcMemory;
int width, height;
...
BOOL CSplashDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CDC* dc;
Background.LoadBitmap(IDB_COVER); //Load Bitmap
Background.GetBitmap(&bm); //Load Bitmap into handle
width = 0;
height = 0;
while(width < 300)
{
width += 10;
height += 10;
OnEraseBkgnd(dc); //<--- Here I want to call OnEraseBkgnd()
Sleep(5); //Delay 5 millisecond
}
return TRUE;
}
BOOL CSplashDlg::OnEraseBkgnd(CDC* pDC)
{
///////////////////////////////////
Invalidate(); //I don't know where I should put this function
///////////////////////////////////
dcMemory.CreateCompatibleDC(pDC);
CBitmap *pOldbmp = dcMemory.SelectObject(&Background);
pDC->SetStretchBltMode(HALFTONE);
pDC->StretchBlt(0, 0, width, height, &dcMemory, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
return TRUE;
}
在上面的示例中,我想在
OnEraseBkgnd()
内部执行时调用OnInitDialog()
重绘窗口。我已经搜索了Internet,并且总是说使用Invalidate();
或RedrawWindow();
对其进行重新粉刷,它也将调用OnEraseBkgnd()
函数。问题是:我应该如何使用Invalidate();
或RedrawWindow();
?我应该把这些功能放在哪里?我已经将这两个函数放在任何地方,但仍然无法正常工作。
编辑:
我已经修改了。尽管现在
Invalidate()
和UpdateWindow()
成功调用了OnEraseBkgnd()
函数。但是我发现了另一个问题:为什么当我使用StretchBlt
或Invalidate()
重绘(repaint)油漆时UpdateWindow()
不能工作,但是FillSolidRect
可以工作吗?...
BOOL CMainDlg::OnInitDialog()
{
CSplashDlg Frame;
Frame.width = 0;
Frame.height = 0;
while(Frame.width <= 300)
{
Frame.width += 10;
Frame.height += 10;
Frame.Invalidate(); //<---Here I use both Invalidate() and UpdateWindow()
Frame.UpdateWindow(); //<---Here I use both Invalidate() and UpdateWindow()
Sleep(5); //Delay 5 millisecond
}
CDialog::OnInitDialog();
return TRUE;
}
BOOL CSplashDlg::OnInitDialog()
{
CDialog::OnInitDialog();
width = 0;
height = 0;
Background.LoadBitmap(IDB_COVER); //Load Bitmap
Background.GetBitmap(&bm); //Load Bitmap into handle
return TRUE;
}
BOOL CSplashDlg::OnEraseBkgnd(CDC* pDC)
{
dcMemory.CreateCompatibleDC(pDC);
CBitmap *pOldbmp = dcMemory.SelectObject(&Background);
///////////////////////////////////////////////////////////////
pDC->SetStretchBltMode(HALFTONE);
pDC->StretchBlt(0, 0, width, height, &dcMemory, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); //It doesn't work when using this one (StretchBlt)
///////////////////////////////////////////////////////////////
pDC->FillSolidRect(0, 0, width, height, RGB(255,0,0)); //But it works when using this one (FillSolidRect)
///////////////////////////////////////////////////////////////
return TRUE;
}
...
最佳答案
您永远不要给OnEraseBkgnd( )
和OnPaint( )
之类的名字打电话。当需要绘图时,MFC将调用这些。您的工作是处理绘制OnEraseBkgnd( )
的需要。Invalidate( )
使MFC更新绘图区域,然后它将调用OnEraseBkgnd( )
和OnPaint( )
。如果您在Invalidate( )
或OnPaint( )
中使用OnEraseBkgnd( )
,则该程序可能会挂起,因为这将导致无休止的重绘窗口循环。
您可以在Invalidate( )
中调用OnInitDialog( )
,但这可能是不必要的。
因此,请从OnEraseBkgnd( )
中取出Invalidate,不要在OnEraseBkgnd( )
中调用OnInitDialog( )
并从那里去。
你也必须ON_WM_PAINT( )ON_WM_ERASEBKGND( )
在您的消息映射中找到那些由MFC调用的对象。
注意:
我不相信重塑车轮。它大部分之前已经完成。我没有在项目中使用启动画面,但是如果要使用,我将从这里开始:Splash Screen C++ Class using MFC。
我没有下载并查看代码,但是有四颗星,所以它应该是一个不错的起点。 MFC并非一overnight而就。当我开始学习时,我会阅读书籍和进行大量搜索。您只是无法猜测基础架构的工作方式。希望这可以帮助...