多个子对话框之间切换时的屏幕闪烁问题,求解

liuwanwei 2007-07-07 11:39:46
基本信息:
1,基于对话框的程序,包括一个主对话框,n个子对话框,所有子对话框的位置相同,都在父对话框中央;
2,用户点击主对话框上不同按钮时,在各个子对话框之间进行切换;
3,子对话框动态创建(Create),并使用SetWindowPos()函数显示;
4,主对话框和子对话框都有背景图,背景的重绘用双缓冲,在OnPaint()中完成;
4,主对话框的ClipChild属性已经设为True;

问题:
点击按钮,实现对话框切换的时候,新对话框在显示之前总是会闪一下,然后才蹦出来。

这些天在google上查了很久,也找到过类似的问题的解答,但依照各种方法总是不能解决问题。

谢谢关注,请有识者施举手之劳:)
...全文
983 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyg_zy 2007-07-15
  • 打赏
  • 举报
回复

CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
m_MemDC.Rectangle(rcClient);
改为:
CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);

/**
* 这里选一空Brush试试,这句话编译可能有错,自己改改
*/
m_MemDC.SelectObject( m_MemDC.GetStockObject( NULL_BRSHU) );

m_MemDC.Rectangle(rcClient);
happy_today 2007-07-14
  • 打赏
  • 举报
回复
嗯,我也有类似问题,情况跟lz差不多
我的也是主对话框和几个子对话框,但是我的主对话框上只有一张背景图片,外加几个按钮,按钮是要自绘的。我的情况是子对话框里操作比较多的话,主对话框就会闪烁。不闪烁的时候也比较多。
其实是因为主对话框重画背景的时候,先用原背景色擦了一次,再画,有的时候速度不够快,就能看到原背景色,造成闪烁。

楼主,你试试把主对话框的clip children属性去掉。我这边去掉效果还好一点。
但是没有根本性解决。
向立天 2007-07-14
  • 打赏
  • 举报
回复
楼主为什么一直回避OnEraseBkgnd的问题,
这个消息你是怎么处理的。
liuwanwei 2007-07-10
  • 打赏
  • 举报
回复
怎样使用双缓冲在一个对话框上绘制多幅背景图片呢?
不知道我用的方法是否正确
ggglivw 2007-07-10
  • 打赏
  • 举报
回复
在OnEraseBkgnd里直接返回TRUE,onpaint里面使用双缓冲应该不会出现闪烁才对
lyg_zy 2007-07-10
  • 打赏
  • 举报
回复
疑问中,楼主解决后通报一声解决办法。
liuwanwei 2007-07-09
  • 打赏
  • 举报
回复
贴出代码:

void CTestDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

// 使图标在工作矩形中居中
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;

// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
//CDialog::OnPaint(); 我注释掉的,不知会有什么效果
CPaintDC dc(this);
CRect rcClient;
GetClientRect(&rcClient);

// 内存画图,在内存中画背景图
CDC m_MemDC;
m_MemDC.CreateCompatibleDC(&dc);

CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
m_MemDC.Rectangle(rcClient);

// 帖三幅背景图片
::MyDrawRangeImage(&m_bmp_start_full, &m_MemDC, CRect(0, rcClient.Height() - m_bmp_start_full_size.cy, rcClient.Width(), rcClient.Height()));
::MyDrawRangeImage(&m_bmp_path_full, &m_MemDC, CRect(0, 0, rcClient.Width(), m_bmp_path_full_size.cy));
::MyDrawRangeImage(&m_bmp_home_bg, &m_MemDC, CRect(0, m_bmp_path_full_size.cy, rcClient.Width(), rcClient.Height() - m_bmp_path_full_size.cy - m_bmp_start_full_size.cy));

// 将内存中的图画到显示器上
dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &m_MemDC, 0, 0, SRCCOPY);

btScreen.DeleteObject();
m_MemDC.DeleteDC();
}
}

BOOL CTestDlg::OnEraseBkgnd(CDC * pDC)
{
return TRUE;
}

// 在内存中绘制一副背景图片
void MyDrawRangeImage(CBitmap *pBitmap, CDC *pDC, CRect rc)
{
CDC MemDC;
BITMAP bm;
pBitmap->GetBitmap(&bm);

int li_Width = bm.bmWidth;
int li_Height = bm.bmHeight;

MemDC.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = MemDC.SelectObject(pBitmap);

pDC->BitBlt(rc.left, rc.top, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBitmap);
MemDC.DeleteDC();
}


// 进行子对话框切换的代码
void CTestDlg::ShowDialog(UINT dlg_id)
{
......


// 寻找当前正在显示的子对话框,和将要显示的子对话框
while(pTemp)
{
if(pTemp->is_show)
{
cur_show = pTemp;
}

if(pTemp->dlg_id == nPos)
{
to_be_show = pTemp;
}

pTemp=pTemp->Next;
}

// 隐藏当前显示的子对话框
if(cur_show)
{
cur_show->pDialog->ShowWindow(SW_HIDE);
cur_show->is_show = FALSE;
}
// 显示新子对话框
if(to_be_show)
{
to_be_show->pDialog->ShowWindow(SW_SHOW);
to_be_show->is_show = TRUE;
}
......
}
liuwanwei 2007-07-09
  • 打赏
  • 举报
回复
没有用,所有的子对话框在创建的时候都隐藏了,以后需要显示哪个就Show哪个。
还有一点我忘了说明,我在子对话框OnShowWindow里面做了些工作,
每当显示一个子对话框的时候,在对话框内动态创建一些按钮,
刚才我将动态创建按钮的语句注释掉,仍然发现对话框闪烁,可见这问题不在这里。

我又仔细测试了一下,点击主对话框上的按钮,重复显示同一个子对话框的时候也会闪烁;
但假如将子对话框的背景图去掉,那看起来就不闪了。

我也觉得问题出在绘制背景的时候,但上面的代码看起来也没什么问题,很是奇怪,再帖一个子对话框的OnPaint
void CSubDlg1::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialog::OnPaint()
CRect rcClient;
GetClientRect(&rcClient);

// 内存画图,在内存中画背景图
CDC m_MemDC;
m_MemDC.CreateCompatibleDC(&dc);

CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
m_MemDC.Rectangle(rcClient);

if(m_img_load_ok)
{
MyDrawRangeImage(&m_bmp_hdr, &m_MemDC, CRect(0, 0, rcClient.Width(), m_bmp_hdr_size.cy));
MyDrawRangeImage(&m_bmp_bg, &m_MemDC, CRect(0, m_bmp_hdr_size.cy, rcClient.Width(), rcClient.Height()));
}

// 将内存中的图画到显示器上
dc.BitBlt(rcClient.left, rcClient.top, rcClient.Width(), rcClient.Height(), &m_MemDC, 0, 0, SRCCOPY);

btScreen.DeleteObject();
m_MemDC.DeleteDC();
}
lyg_zy 2007-07-09
  • 打赏
  • 举报
回复
已阅。显示隐藏对话框的策略改为以下试试:
1:先隐藏所有的子对话框
2:显示你要显示的子对话框
liuwanwei 2007-07-09
  • 打赏
  • 举报
回复
我觉得问题有可能出在OnPaint函数的这几句:
CBitmap btScreen;
btScreen.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
m_MemDC.SelectObject(&btScreen);
m_MemDC.Rectangle(rcClient);

因为通过将这几句注释掉后,对话框的背景色为空,而这个“空”的颜色好像就是闪烁时候出现的颜色。

不知道怀疑的对不对,我继续做实验,希望有人能看到,给个建议:)

liuwanwei 2007-07-09
  • 打赏
  • 举报
回复
To ggglivw:

我并没有处理OnSize,我的所有对话框大小都是固定的。
LockWindowUpdate()和UnlockWindowUpdate()我都试过,就是在主对话框显示子对话框的时候,可惜没有效果。

To Prince_vegeta:

恩,假如我把背景去掉的话,也不闪了
ggglivw 2007-07-09
  • 打赏
  • 举报
回复
在OnEraseBkgnd里直接返回TRUE。

你在onsize的时候先
LockWindowUpdate();

完了再
UnlockWindowUpdate();
Invalidate(TRUE);
Prince_vegeta 2007-07-09
  • 打赏
  • 举报
回复
就是像你说的那样创建,我就是这么做的。
可能我的程序中没有像你那样有绘图操作吧.
Prince_vegeta 2007-07-08
  • 打赏
  • 举报
回复
用非模对话框,然后ShowWindow,我实现过.无闪烁,
liuwanwei 2007-07-08
  • 打赏
  • 举报
回复
涛声依旧,还是闪烁
小麻侬 2007-07-08
  • 打赏
  • 举报
回复
将主对话框的样式选为重叠试一下
liuwanwei 2007-07-08
  • 打赏
  • 举报
回复
To LS 两位:
一开始我就是使用静态创建,通过ShowWindow(SW_HIDE),ShowWindow(SW_SHOW)来隐藏和显示子对话框,同样有闪烁,所以我参考了其他人的建议,才改为SetWindowPos()来实现,结果发现一样的闪。

这个帖子中的问题跟我的类似:
http://topic.csdn.net/t/20050705/15/4124317.html
但我照着答题者的意见做,却收不到效果

youngwolf 2007-07-08
  • 打赏
  • 举报
回复
要防止主对话框刷背景,在OnEraseBkgnd里直接返回TRUE。
wfenj 2007-07-08
  • 打赏
  • 举报
回复
我也觉得是绘制对话矿的问题,跟SHOWWINDOW没关系吧
lyg_zy 2007-07-08
  • 打赏
  • 举报
回复
如果依然有闪烁,那我估计还是你本身对话框的绘制代码有问题。而不是ShowWindow()这种方式有什么问题。
加载更多回复(3)

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧