我试图调用OnEraseBkgnd()
在另一个函数中重新绘制窗口。如何调用OnEraseBkgnd()重新绘制另一个函数中的窗口? (MFC)
例如,像下面的代码:
...
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()
执行重绘窗口。我搜索了互联网,它总是说使用Invalidate();
或RedrawWindow();
重新绘制它,它也会调用OnEraseBkgnd()
函数。问题是:我应该如何使用Invalidate();
或RedrawWindow();
?我应该在哪里放置这些功能?
我已经把这两个功能放在任何地方,但它仍然不起作用。
编辑:
我已经修改了它。虽然现在Invalidate()
和UpdateWindow()
都能成功调用OnEraseBkgnd()
函数。但我发现另一个问题:为什么StretchBlt
没有工作,当我用Invalidate()
或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;
}
...
http://stackoverflow.com/questions/2183649/what-is-invalidate-update-methods-do-in-vc – Ripi2
直到'OnInitDialog'返回对话框才可见。你可以在'OnInitDialog'中做的事情是创建一个5毫秒的定时器SetTimer(1,5,0),添加'ON_WM_TIMER'到消息映射,然后在'OnTimer(UINT_PTR)'调用'Invalidate()'。在'OnPaint'中,不在'OnEraseBkgnd'中绘画 –
在你的第二次编辑中,一切都是正确的,除了在Frame-> Invalidate后Windows消息被阻塞之后,它不更新窗口,因为系统仍然是处理另一个消息('WM_INITDIALOG')。你可以在它之后调用'UpdateWindow',希望说服Windows来处理这个消息,但是它仍然没有做到。唯一的选择是在(使用'PeekMessage')之间插入一个消息循环来处理消息队列中的当前消息,但是你必须小心。或者使用'WM_TIMER'执行此操作[ –