情况是这样的:
我首先拦截了窗口的WM_PAINT消息,然后在该消息内对窗口的背景进行了绘制,我的绘制是这样的:
DrawBK(...);//背景绘制函数
InvalidateRect(NULL,true);
上面代码能够实现窗口背景的绘制,但是当拖大或是缩小窗口时,窗口上的其它子控件就闪烁的特别厉害。
这样肯定不行,我便把InvalidateRect(NULL,true);函数去掉,直接用DrawBk函数,可是发现当窗口
重绘时,窗口上的控件都被背景覆盖了,显示不出来!
于是,我便给窗口增加了WS_CLIPCHILDREN,再使用
DrawBK(...);//背景绘制函数
InvalidateRect(NULL,true);
进行绘制,这时发现,在窗口变量或缩小时大部分子控件没有闪烁了,但是也有一些控件发生了闪烁!我想问一下朋友们,对于我们自绘窗口时,怎么样消除窗口上其它子控件的闪烁问题呢?都有那些好的方法!大家的在这方面又如何处理的呢?
我首先拦截了窗口的WM_PAINT消息,然后在该消息内对窗口的背景进行了绘制,我的绘制是这样的:
DrawBK(...);//背景绘制函数
InvalidateRect(NULL,true);
上面代码能够实现窗口背景的绘制,但是当拖大或是缩小窗口时,窗口上的其它子控件就闪烁的特别厉害。
这样肯定不行,我便把InvalidateRect(NULL,true);函数去掉,直接用DrawBk函数,可是发现当窗口
重绘时,窗口上的控件都被背景覆盖了,显示不出来!
于是,我便给窗口增加了WS_CLIPCHILDREN,再使用
DrawBK(...);//背景绘制函数
InvalidateRect(NULL,true);
进行绘制,这时发现,在窗口变量或缩小时大部分子控件没有闪烁了,但是也有一些控件发生了闪烁!我想问一下朋友们,对于我们自绘窗口时,怎么样消除窗口上其它子控件的闪烁问题呢?都有那些好的方法!大家的在这方面又如何处理的呢?
InvalidateRect(NULL,true); 这个会死循环的。InvalidateRect后,系统会自己再发Paint消息。
不会的!这两个语句不是放在WM_PINT消息对应该的消息映射函数中!是在我自己设计的绘制事件中!
CWnd::OnEraseBkgnd
如果我们能找到这个函数的实现机制那就好了!不知道大家没有没有研究过该函数!谁有这个函数的原代码没有?
HBITMAP hbmBk = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BK));
case WM_PAINT:
{
//绘制背景
BITMAP bminfo;
GetObject(hbmBk, sizeof(bminfo), &bminfo);
PAINTSTRUCT ps;
HDC dc = BeginPaint(hwnd, &ps);
HDC memdc = CreateCompatibleDC(dc);
SelectObject(memdc, hbmBk);
BitBlt(dc,0,0,bminfo.bmWidth,bminfo.bmHeight,memdc,0,0,SRCCOPY);
DeleteDC(memdc);
EndPaint(hwnd, &ps);
return TRUE;
}
//没有发现将子控件覆盖的情况,没有使用双缓冲,因为图比较小闪烁不明显子控件则是在DrawItem里面完成 case WM_DRAWITEM:
{
LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) lParam; BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED); HWND btnHwnd = GetDlgItem(hwnd,IDC_BUTTON1); if (bIsPressed)
{
::kbtn32.SyncDown(btnHwnd,hwnd);
}
else
{
::kbtn32.SyncNomal(btnHwnd,hwnd);
}
}
return TRUE;没有使用RedrawWindow 这类重绘
非常感谢你的建议,你的这个方法我到没有试过!你把窗口上的子控件绘制从WM_DRAWITEM内拦截,这个我到没这样试过,而我是直接用InvalidateRect来使子窗获得重绘!你的方法值得借鉴。还有你说 你的case WM_PAINT内的绘制没有覆盖子控件那是因为你取得的DC是CPaintDC,而我取得的是窗口DC:GetWindowsDC,所以你的绘制才没有被覆盖,如果你也是窗口DC我想应该也会覆盖掉子控件的!
语法objectname.SetRedraw(boolean)
参数objectname 要修改重绘属性的控件或对象名objectname 可以是子数据窗口
但不能是菜单
boolean boolean 型值指定修改控件或对象的属性后PowerBuilder 是否自动重
绘控件或对象有效取值为
TRUE 每次修改属性后自动重绘该对象或控件
FALSE 修改属性后不自动重绘该对象或控件
将控件setredraw(false)就不闪了
父窗口创建时要加上WS_CLIPCHILDREN
MFC窗口默认情况下,不管有没有这个属性,窗口在重绘时,其子控件都不会有闪烁!其背景的绘制是采用了CWnd::OnEraseBkgnd 这个函数!我想最好的消除背景重绘时如何消除子控件的闪烁还是要知道CWnd::OnEraseBkgnd 函数的实现机制是怎么样的!
一般的做法是这么做的:
BOOL OnEraseBkgnd(CDC * pDC)
{
CRect rect;
GetClientRect(&rect);
pDC->FillRect(m_bkBrush, &rect);
....
}
现在这直接这么做:
BOOL OnEraseBkgnd(CDC * pDC)
{
return TRUE;
} void OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(&rect);
dc.FillRect(m_bkBrush, &rect);
......
}
这个属性一开始我就说有加过!但并不是加了这个属性所有子控件就都不闪烁了!如:Slider,Tab Control就照闪不误!