21 个解决方案
#1
这和你的绘图时机,绘图区域大小等都有关系,你这么说很难说怎样才能不闪烁。但我的方法是,在WM_PAIT消息里,获取需重绘区域的大小,然后在我的缓冲将像素数据拷贝到目标DC中,没有出现你说闪烁现像。
#2
你可以试下把擦除背景的函数修改下,
让它直接return FALSE就会好。
因为擦除背景函数会在重绘时默认把dc至为白色
让它直接return FALSE就会好。
因为擦除背景函数会在重绘时默认把dc至为白色
#3
你说的是这个意思吧
一下是一些背景图片的摆放。。
void CxxxDlg::OnPaint()
{
if (IsIconic())
{
...
}
else
{
CPaintDC dc(this);
dc.SetStretchBltMode(COLORONCOLOR);
CBitmap bitmap;
CBitmap* pOldBitmap;
CDC MemDC;
RECT rect;
BITMAP bmp;
GetClientRect(&rect);
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_SPEED);
pOldBitmap=MemDC.SelectObject(&bitmap);
bitmap.GetBitmap(&bmp);
dc.StretchBlt(131,0,rect.right-121-131,57,&MemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
MemDC.SelectObject(pOldBitmap);
bitmap.DeleteObject();
MemDC.DeleteDC();
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_xxx);
...
MemDC.DeleteDC();
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_xxx);
...
MemDC.DeleteDC();
}
一下一是一些按钮(继承CBtton类)的摆放
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
...
}
#4
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
是这个意思吧,我以前已经这么做了,这么做确实会好些但还是有,怎么办?
#5
漏了响应WM_ERASEBKGND消息吧.
#6
return TRUE..
#7
放按钮的父窗口再加一个WS_CLIPCHILDREN 属性
#8
绘制时用双DC,然后再BitBlt内存DC到窗口DC上,OnEraseBkgnd返回True,不然系统帮你重绘背景
#9
------
补充下,确实是return true, 但是记得要层层传递呀, 有一个父(或以上的)窗口没处理这个就,没什么效果的。
#10
在Windows 下,窗口重绘时,会首先会窗口背景色,然后是onPaint事件绘制窗口内容.我看了一下你的贴出的代码,里面的操作太多,这样的话当窗口重绘时,先画完背景,然后好长时间后在画图像当然会闪烁(即使不响应背景重绘事件也不行,这样会在屏幕上留下图像的碎片),解决方法是把你的所有要载入的图片,全部载入到全局的DC中,这样在OnPaint中需要 StretchBlt()这个方法就行了,应该会解决这个问题。还有重绘时,你要调用 GetUpdateRect 函数,来获取一个更新区域,有时你的窗体并不需要全部重画,这样可以加快绘制速度。
#11
层层传递是每个窗体都相应OnEraseBkgnd方法的意思吧,这么做了没什么改进啊
#12
有道理,那么怎么载入到全局的调查中那,能说的详细点?谢谢
#13
很简单,将你的图片在程序初始代是就载入,然后建立几个全局的CDC类型变量,将图片载入这些DC就行了.
#14
1 , 父窗口加WS_CLIPCHILDREN ,
2 ,
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
GetDlgItem(IDC_BUTTONXX)->Invalidate(FALSE);
...
}
2 ,
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
GetDlgItem(IDC_BUTTONXX)->Invalidate(FALSE);
...
}
#15
用双缓冲画图能够将图像画图一次性画好,但是应该还是不能解决你的问题,
你的问题似乎是重绘的时候把子窗口那部分图也重绘了
你可以在擦除背景函数做这样处理
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
//假设一个button,
CRect rect;
GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);
ScreenToClient(&rect);
pDC->ExcludeClipRect (&rect);//该函数可以使这部分区域不被画,你可以再试试看下
CDialog::OnEraseBkgnd(pDC);
}
最后建议你使用双缓冲画图,这样一次性画完
你的问题似乎是重绘的时候把子窗口那部分图也重绘了
你可以在擦除背景函数做这样处理
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
//假设一个button,
CRect rect;
GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);
ScreenToClient(&rect);
pDC->ExcludeClipRect (&rect);//该函数可以使这部分区域不被画,你可以再试试看下
CDialog::OnEraseBkgnd(pDC);
}
最后建议你使用双缓冲画图,这样一次性画完
#16
定义一个成员变量 CBrush m_brush;
在OnInitDialog初始化,在OnCtlColor返回就可以了
在OnInitDialog初始化,在OnCtlColor返回就可以了
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CBitmap bmp;
bmp.加载你的背景图片
m_brush.CreatePatternBrush(&bmp);
}
HBRUSH Cldlg1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return (HBRUSH )(m_brush);
}
#17
定义一个成员变量 CBrush m_brush;
在OnInitDialog初始化,在OnCtlColor返回就可以了
在OnInitDialog初始化,在OnCtlColor返回就可以了
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CBitmap bmp;
bmp.加载你的背景图片
m_brush.CreatePatternBrush(&bmp);
}
HBRUSH Cldlg1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return (HBRUSH )(m_brush);
}
#18
不好意思,网络太慢,不小心发了两次
#19
把窗口重绘的代码放在OnPaint里面,而不是什么时候想绘就绘。另外在项目的代码中找找InvalidateRect这个函数, 把擦除背景(是最后一个参数)设为FALSE.
#20
我把上面代码放在onpaint函数里了,问题解决了,嘎嘎
ExcludeClipRect 这个函数很好很强大,灵活使用可以解决很多刷新闪烁问题,还有个问题就是为什么指定区域不刷新了,我拖拽窗口时候那些区域并没有出现问题(按钮也移到那个位置了)?当然不出问题正是我想要的,我只是不明白为什么,给我讲讲呗,谢谢!
#21
#1
这和你的绘图时机,绘图区域大小等都有关系,你这么说很难说怎样才能不闪烁。但我的方法是,在WM_PAIT消息里,获取需重绘区域的大小,然后在我的缓冲将像素数据拷贝到目标DC中,没有出现你说闪烁现像。
#2
你可以试下把擦除背景的函数修改下,
让它直接return FALSE就会好。
因为擦除背景函数会在重绘时默认把dc至为白色
让它直接return FALSE就会好。
因为擦除背景函数会在重绘时默认把dc至为白色
#3
你说的是这个意思吧
一下是一些背景图片的摆放。。
void CxxxDlg::OnPaint()
{
if (IsIconic())
{
...
}
else
{
CPaintDC dc(this);
dc.SetStretchBltMode(COLORONCOLOR);
CBitmap bitmap;
CBitmap* pOldBitmap;
CDC MemDC;
RECT rect;
BITMAP bmp;
GetClientRect(&rect);
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_SPEED);
pOldBitmap=MemDC.SelectObject(&bitmap);
bitmap.GetBitmap(&bmp);
dc.StretchBlt(131,0,rect.right-121-131,57,&MemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
MemDC.SelectObject(pOldBitmap);
bitmap.DeleteObject();
MemDC.DeleteDC();
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_xxx);
...
MemDC.DeleteDC();
MemDC.CreateCompatibleDC(&dc);
bitmap.LoadBitmap(IDB_xxx);
...
MemDC.DeleteDC();
}
一下一是一些按钮(继承CBtton类)的摆放
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
...
}
#4
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
return FALSE;
}
是这个意思吧,我以前已经这么做了,这么做确实会好些但还是有,怎么办?
#5
漏了响应WM_ERASEBKGND消息吧.
#6
return TRUE..
#7
放按钮的父窗口再加一个WS_CLIPCHILDREN 属性
#8
绘制时用双DC,然后再BitBlt内存DC到窗口DC上,OnEraseBkgnd返回True,不然系统帮你重绘背景
#9
------
补充下,确实是return true, 但是记得要层层传递呀, 有一个父(或以上的)窗口没处理这个就,没什么效果的。
#10
在Windows 下,窗口重绘时,会首先会窗口背景色,然后是onPaint事件绘制窗口内容.我看了一下你的贴出的代码,里面的操作太多,这样的话当窗口重绘时,先画完背景,然后好长时间后在画图像当然会闪烁(即使不响应背景重绘事件也不行,这样会在屏幕上留下图像的碎片),解决方法是把你的所有要载入的图片,全部载入到全局的DC中,这样在OnPaint中需要 StretchBlt()这个方法就行了,应该会解决这个问题。还有重绘时,你要调用 GetUpdateRect 函数,来获取一个更新区域,有时你的窗体并不需要全部重画,这样可以加快绘制速度。
#11
层层传递是每个窗体都相应OnEraseBkgnd方法的意思吧,这么做了没什么改进啊
#12
有道理,那么怎么载入到全局的调查中那,能说的详细点?谢谢
#13
很简单,将你的图片在程序初始代是就载入,然后建立几个全局的CDC类型变量,将图片载入这些DC就行了.
#14
1 , 父窗口加WS_CLIPCHILDREN ,
2 ,
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
GetDlgItem(IDC_BUTTONXX)->Invalidate(FALSE);
...
}
2 ,
void CPlayerDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
...
rc_save = CPoint(80,4) + CRect(0,0,39,50);
GetDlgItem(IDC_BUTTONXX)->MoveWindow(&rc_save);
GetDlgItem(IDC_BUTTONXX)->Invalidate(FALSE);
...
}
#15
用双缓冲画图能够将图像画图一次性画好,但是应该还是不能解决你的问题,
你的问题似乎是重绘的时候把子窗口那部分图也重绘了
你可以在擦除背景函数做这样处理
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
//假设一个button,
CRect rect;
GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);
ScreenToClient(&rect);
pDC->ExcludeClipRect (&rect);//该函数可以使这部分区域不被画,你可以再试试看下
CDialog::OnEraseBkgnd(pDC);
}
最后建议你使用双缓冲画图,这样一次性画完
你的问题似乎是重绘的时候把子窗口那部分图也重绘了
你可以在擦除背景函数做这样处理
BOOL CPlayerDlg::OnEraseBkgnd(CDC* pDC)
{
//假设一个button,
CRect rect;
GetDlgItem(IDC_BUTTON1)->GetWindowRect(&rect);
ScreenToClient(&rect);
pDC->ExcludeClipRect (&rect);//该函数可以使这部分区域不被画,你可以再试试看下
CDialog::OnEraseBkgnd(pDC);
}
最后建议你使用双缓冲画图,这样一次性画完
#16
定义一个成员变量 CBrush m_brush;
在OnInitDialog初始化,在OnCtlColor返回就可以了
在OnInitDialog初始化,在OnCtlColor返回就可以了
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CBitmap bmp;
bmp.加载你的背景图片
m_brush.CreatePatternBrush(&bmp);
}
HBRUSH Cldlg1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return (HBRUSH )(m_brush);
}
#17
定义一个成员变量 CBrush m_brush;
在OnInitDialog初始化,在OnCtlColor返回就可以了
在OnInitDialog初始化,在OnCtlColor返回就可以了
BOOL CMyDlg::OnInitDialog()
{
CDialog::OnInitDialog();
CBitmap bmp;
bmp.加载你的背景图片
m_brush.CreatePatternBrush(&bmp);
}
HBRUSH Cldlg1Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: 在此更改 DC 的任何属性
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return (HBRUSH )(m_brush);
}
#18
不好意思,网络太慢,不小心发了两次
#19
把窗口重绘的代码放在OnPaint里面,而不是什么时候想绘就绘。另外在项目的代码中找找InvalidateRect这个函数, 把擦除背景(是最后一个参数)设为FALSE.
#20
我把上面代码放在onpaint函数里了,问题解决了,嘎嘎
ExcludeClipRect 这个函数很好很强大,灵活使用可以解决很多刷新闪烁问题,还有个问题就是为什么指定区域不刷新了,我拖拽窗口时候那些区域并没有出现问题(按钮也移到那个位置了)?当然不出问题正是我想要的,我只是不明白为什么,给我讲讲呗,谢谢!