- void CDDDDlg::OnPaint()
- {
- if (IsIconic())
- {
- CPaintDC dc(this); // device context for painting
- SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
- // Center icon in client rectangle
- int cxIcon = GetSystemMetrics(SM_CXICON);
- int cyIcon = GetSystemMetrics(SM_CYICON);
- CRect rect;
- GetClientRect(&rect);
- int x = (rect.Width() - cxIcon + 1) / 2;
- int y = (rect.Height() - cyIcon + 1) / 2;
- // Draw the icon
- dc.DrawIcon(x, y, m_hIcon);
- }
- else
- {
- //CDialog::OnPaint();
- }
- }
則執行后界面沒有問題,如下圖:
但是,如果將此界面隱藏后再顯示,則上面的控件都不能顯示了,如下圖:
跟蹤程序會發現,第一次生成界面時候,進入過OnCtlColor函數(TRACE("OnCtlColor\n");語句輸出),
當隱藏界面再顯示后,就再也沒進過OnCtlColor函數。當然看不見原先界面的控件了,因為根本沒有重繪出來。原因見下篇
A:在OnPaint中注釋此句CDialog::OnPaint();為什么會不停地調用OnPaint函數呢(不斷執行TRACE("OnPaint\n");語句)?
Q:如果自己的OnPaint代碼什么也沒做的話(至少沒有聲明過CPaintDC類型的變量),還必須調用一下CDialog::OnPaint,否則BeginPaint和EndPaint就沒有辦法被調用了。
總之,在響應WM_PAINT消息的時候,必須調用一遍BeginPaint和EndPaint。調用的方法有三種:
1、聲明一個CPaintDC類型的變量(即使你什么也不畫),CPaintDC的構造函數就是調用BeginPaint,析構函數就是調用EndPaint。
2、調用基類的OnPaint(實際上就是調用API的DefWindowProc,它會自動調用BeginPaint和EndPaint)。
3、自己直接調用BeginPaint和EndPaint。
上述三種方法,必須選擇其一,而且也只能選擇其一(因為在一個WM_PAINT消息內不能調用兩次BeginPaint和EndPaint)。
正如我猜想的,因為你調用了CDialog::OnPaint();
你把這句注釋掉就可以了。
所以說凡事總有因果,CDialog::OnPaint()調用默認的窗口過程來繪制,也會調用BeginPaint/EndPaint()。而這兩個函數的作用,是獲取DC、剪裁區域和從消息隊列中移走WM_PAINT消息(因此,如果不用上述三種方法的一種調用一遍BeginPaint和EndPaint的話,WM_PAINT消息就不會從消息隊列里面移走,系統就會不停的發送WM_PAINT,這就是問題中所提到的不停的調用OnPaint函數的原因了)。這兩個函數,必須在WM_PAINT消息中調用,而且只能調用一次!
相關帖子:
http://topic.csdn.net/u/20100801/11/40897468-807e-445a-a817-ede00dfd406e.html
http://topic.csdn.net/u/20080620/15/1D8E30FD-584A-4551-B93A-DA97D5F6423C.html#r_50392023