2016-12-03 69 views
0

我试图调用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; 
} 

... 
+0

http://stackoverflow.com/questions/2183649/what-is-invalidate-update-methods-do-in-vc – Ripi2

+0

直到'OnInitDialog'返回对话框才可见。你可以在'OnInitDialog'中做的事情是创建一个5毫秒的定时器SetTimer(1,5,0),添加'ON_WM_TIMER'到消息映射,然后在'OnTimer(UINT_PTR)'调用'Invalidate()'。在'OnPaint'中,不在'OnEraseBkgnd'中绘画 –

+0

在你的第二次编辑中,一切都是正确的,除了在Frame-> Invalidate后Windows消息被阻塞之后,它不更新窗口,因为系统仍然是处理另一个消息('WM_INITDIALOG')。你可以在它之后调用'UpdateWindow',希望说服Windows来处理这个消息,但是它仍然没有做到。唯一的选择是在(使用'PeekMessage')之间插入一个消息循环来处理消息队列中的当前消息,但是你必须小心。或者使用'WM_TIMER'执行此操作[ –

回答

1

你不应该调用OnEraseBkgnd()OnPaint()喜欢。当需要绘图时MFC会调用这些。你的工作是处理需要吸取OnEraseBkgnd()

导致MFC更新绘图区域,然后它会调用OnEraseBkgnd()OnPaint()。如果在OnPaint()OnEraseBkgnd()该程序可能会挂起,因为它会导致无限循环重绘窗口。

您可以拨打电话 OnInitDialog()但它可能是不必要的。

因此,取出失效的OnEraseBkgnd(),不要拨打OnEraseBkgnd()OnInitDialog()并从那里去。

你还必须有

ON_WM_PAINT() ON_WM_ERASEBKGND()

在那些由MFC称为你的消息映射。

注意: 我不相信重新发明轮子。它主要是以前完成的。我的项目中没有使用启动画面,但如果我想要,我会从这里开始:Splash Screen C++ Class using MFC

我没有下载和审查代码,但与四颗星,它应该是一个很好的开始。 MFC不是一夜之间学习的。当我开始阅读书籍和大量的搜索学习。你无法猜测基础设施如何工作。希望这可以帮助...

+0

]我在'OnInitDialog()'中放入了'Invalidate()',并在消息映射中添加了'ON_WM_ERASEBKGND()',但它仍然不会重绘任何东西。 –

+0

@BananaCode调用'Invalidate'只是标记重绘窗口。要查看更改,需要在无效后调用'UpdateWindow',不要使无效并调用'RedrawWindow',或者在无效后运行消息循环。 – 1201ProgramAlarm

+0

我发现了另一个问题:当我使用'Invalidate()'或'UpdateWindow()'但是'FillSolidRect'工作时,为什么'StretchBlt'没有工作?该代码位于更新的内容中。 –