我正在尝试调用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()函数。但是我发现了另一个问题:为什么当我使用StretchBltInvalidate()重绘(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而就。当我开始学习时,我会阅读书籍和进行大量搜索。您只是无法猜测基础架构的工作方式。希望这可以帮助...

10-07 15:34