模态对话框中有自绘的CListBox、CButton控件,对话框窗体也是自绘的,控件在不移动的情况下不闪烁,在移动的时候,不停闪烁,行了很久都没有解决的办法,请各位给点意见,谢谢了LRESULT CKwMusicDlg::DefWindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
LRESULT lrst=CDialog::DefWindowProc(message, wParam, lParam);
if (!::IsWindow(m_hWnd))
return lrst;
if (message==WM_MOVE||message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY)
{
//自绘窗体
CDC* pWinDC = GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
if (message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE)
{
//处理控件的消息
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
m_wndSplitter1.InvalidateRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
m_PlayList.InvalidateRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
m_Bvolume.InvalidateRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
m_ProcessBar.InvalidateRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
m_Logon.InvalidateRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
m_GetScore.InvalidateRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
m_LogonAndScore.InvalidateRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
m_SLogon.InvalidateRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
m_Singn.InvalidateRect(rect);
}
//分隔条消息处理
if (message == WM_NOTIFY)
{
if (wParam == IDC_SPLITER)
{
SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
DoResize(pHdr->delta);
}
} return lrst;
}
{
LRESULT lrst=CDialog::DefWindowProc(message, wParam, lParam);
if (!::IsWindow(m_hWnd))
return lrst;
if (message==WM_MOVE||message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY)
{
//自绘窗体
CDC* pWinDC = GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
if (message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE)
{
//处理控件的消息
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
m_wndSplitter1.InvalidateRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
m_PlayList.InvalidateRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
m_Bvolume.InvalidateRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
m_ProcessBar.InvalidateRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
m_Logon.InvalidateRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
m_GetScore.InvalidateRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
m_LogonAndScore.InvalidateRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
m_SLogon.InvalidateRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
m_Singn.InvalidateRect(rect);
}
//分隔条消息处理
if (message == WM_NOTIFY)
{
if (wParam == IDC_SPLITER)
{
SPC_NMHDR* pHdr = (SPC_NMHDR*) lParam;
DoResize(pHdr->delta);
}
} return lrst;
}
{
return TRUE;
}
贴图不闪啊,只是控件在移动窗体时不停的闪烁
if (message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE)
{
//处理控件的消息
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
m_wndSplitter1.InvalidateRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
m_PlayList.InvalidateRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
m_Bvolume.InvalidateRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
m_ProcessBar.InvalidateRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
m_Logon.InvalidateRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
m_GetScore.InvalidateRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
m_LogonAndScore.InvalidateRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
m_SLogon.InvalidateRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
m_Singn.InvalidateRect(rect);
}
感觉问题关键在上一部分,但是也不知道怎么解决?给点思路...
{
}
把这个if块整个删掉。绘制非客户区时不要动客户区。
{
//处理控件的消息
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
m_wndSplitter1.InvalidateRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
m_PlayList.InvalidateRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
m_Bvolume.InvalidateRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
m_ProcessBar.InvalidateRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
m_Logon.InvalidateRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
m_GetScore.InvalidateRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
m_LogonAndScore.InvalidateRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
m_SLogon.InvalidateRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
m_Singn.InvalidateRect(rect);
}
楼主自己也知道问题在这。 那我就给你分析下吧当对话框移动的时候会重绘窗体,也就是message==WM_PAINT,这个时候你在以上的代码中,都把控件给刷新了一遍。 试想,对话框移动,会触发N个WM_PAINT消息,你的控件不闪烁才怪了。 就算是用了双缓冲也会出现闪烁了。楼主刷新控件的代码明显不应该放到以上的代码中。
void CKwMusicDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (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();
}
}
//双缓冲时已经用上了
BOOL CKwMusicDlg::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}移动窗体时系统处理WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY重画窗体
覆盖控件造成的,如果不重绘控件的话,控件就显示不了啊,可是重绘又产生控件的闪烁,该怎么处理呢?
谢谢楼上的朋友们!!!
if (message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE)
{
//处理控件的消息
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
m_wndSplitter1.InvalidateRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
m_PlayList.InvalidateRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
m_Bvolume.InvalidateRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
m_ProcessBar.InvalidateRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
m_Logon.InvalidateRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
m_GetScore.InvalidateRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
m_LogonAndScore.InvalidateRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
m_SLogon.InvalidateRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
m_Singn.InvalidateRect(rect);
}这里的控件都是子类化的,他们的刷新应该不会造成主窗体的刷新啊
if (message==WM_MOVE||message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY)
{
//自绘窗体
CDC* pWinDC = GetWindowDC();
if (pWinDC)
DrawTitleBar(pWinDC);
ReleaseDC(pWinDC);
}
自绘只是画了个Titlebar而已,不至于把客户区都覆盖了吧,用不着把控件都刷一遍.窗口类型有WS_CLIPCHILDREN吗?加上试试。如果不行的话,教你个办法,把控件区域排除掉再画:
if (message==WM_MOVE||message==WM_PAINT||message==WM_NCPAINT||message==WM_NCACTIVATE ||message == WM_NOTIFY)
{
//自绘窗体
CDC* pWinDC = GetWindowDC();
if (pWinDC)
{
CRect rect;
::GetClientRect(m_wndSplitter1.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_PlayList.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_Bvolume.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_ProcessBar.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_Logon.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_GetScore.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_LogonAndScore.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_SLogon.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect);
::GetClientRect(m_Singn.m_hWnd,&rect);
pWinDC.ExcludeClipRect(rect); DrawTitleBar(pWinDC);
}
ReleaseDC(pWinDC);
}下面的那一堆刷控件的代码就不要了。
14楼的代码值得一试。InvalidateRect 是造成闪烁的主凶,不管是刷新控件还是对话框。而且,你是利用点击鼠标拖动的时候去判断是否进行重绘的,
只要鼠标有消息,重绘就会不断进行下去。
一般要重载窗口处理消息,最好在WindowProc内实现,尽量别在DefWindowProc中处理。
1. 画窗口或控件时, 在WM_PAINT中尽量用双缓存
2. 把父窗口的窗口Style设置成WS_CLIPCHILDREN. [ ModifyStyle( 0, WS_CLIPCHILDREN ); ]
3. 楚用WM_ERASEBKGND消息.注意以上3点基本不会有控件闪动的问题了~~
1. 把所有父窗口的属性加上WS_CLIPCHILDREN和WS_CLIPSIBLINGS属性
2.所有的子窗口的WM_ERASEBKGND消息直接返回TRUE.
3.子窗口所有内容,都在WM_PAINT消息中,使用双缓存绘制.
闪烁只是背景在画完控件后才刷上 导致闪烁...
不过还有更高级闪烁 不是28楼的方法能搞定的...
还有很多要注意的 移动和改变大小 用defwindow什么什么的 忘了
我最近遇到 各种防闪烁技术都没用的闪烁.... 虽然轻微的 但是很影响效果
都快被搞疯了...
哎 如果你的不是透明png图片自绘的按钮 那么这个方法够你用的了