老问题:MFC 大量MoveWindow移动控件导致界面闪烁的问题

marslycan 2019-02-26 09:58:28
封装了一个窗口类class CDynamicFilterSettingFrame : public CWnd{};
主要功能如下图,每次点击+-按钮对应的增加删除一组按钮,考虑到插入的操作,因此在刷新时有大量的MoveWidow来改变控件位置

实际操作时,发现会有界面闪烁现象产生,以前做绘图我知道通过双缓冲来解决绘图闪烁,但是这个动态创建控件....Emmm...抓狂完全没方向...目前我是通过设置SetRedraw()(用这个方式减缓了闪烁现象,但是还是有):

BOOL CDynamicFilterSettingFrame::OnEraseBkgnd(CDC* pDC)
{
// TODO: Add your message handler code here and/or call default
return TRUE;
//return CWnd::OnEraseBkgnd(pDC);
}
void CDynamicFilterSettingFrame::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
// Do not call CWnd::OnPaint() for painting messages
dc.SetBkMode(TRANSPARENT); //设置背景透明
dc.FillSolidRect(0, 0, m_nViewWidth, m_nViewHeight, RGB(240, 240, 240));
}
void CDynamicFilterSettingFrame::CreateDynamicCtrl()
{
SetRedraw(FALSE);

//LockWindowUpdate();
CreateAddButton();
CreateReduceButton();

CreateLeftBraceRadiobutton();
CreateRightBraceRadiobutton();

CreateLeftBraceStatic(); // 左括号静态文本
CreateRightBraceStatic(); // 右括号静态文本
CreateColNameCombox(); // 字段选择Combox
CreateOperatorCombox(); // 运算符选择Combox
CreateValueAEdit(); // 值A 编辑框
CreateValueBEdit(); // 值A 编辑框
CreateLogicalConnectorCombox(); // 逻辑连接符选择Combox


UpdateVScroll();
SetRedraw(TRUE);
//
// CRect rect;
// GetClientRect(&rect);
this->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}

完全混乱的逻辑。。。求大神指点方向
...全文
1115 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
marslycan 2019-02-26
  • 打赏
  • 举报
回复
引用 3 楼 schlafenhamster 的回复:
大量移动前 对话框 先 LockWindowUpdate, 以后 Unlock
我用的是SetRedraw()这对函数,参照帖子https://www.topomel.com/archives/972.html
zgl7903 2019-02-26
  • 打赏
  • 举报
回复
Create 之前将坐标算好, 这样就不需要移动了,
或者先不要 WS_VISIBLE, 移动完了再ShowWindow

schlafenhamster 2019-02-26
  • 打赏
  • 举报
回复 1
大量移动前 对话框 先 LockWindowUpdate, 以后 Unlock
marslycan 2019-02-26
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903 的回复:
MoveWindow 最后一个参数 BOOL bRepaint 默认是 TRUE ,就是移动后重绘,
可以把这个参数设置为FALSE, 全部移动完成后调用一次 Invalidate
非常感谢指导,以前都没注意过这个参数;但是加上Flase还是有点闪烁,是否是因为我的Create控件导致的呢?
void CDynamicFilterSettingFrame::CreateRightBraceStatic()
{
CRect BaseRect;
m_BaseStaticPtr[3]->GetWindowRect(BaseRect);
ScreenToClient(&BaseRect);

int nLeft = BaseRect.left + VALUE_EDIT_WIDTH/* + BASE_DISTANCE_X*/;
int nTop = BaseRect.top + (BASE_HEIGHT + BASE_DISTANCE_Y) * (m_nNewAddRowIdx + 1)/* - m_iCurrentScrollPos*/;
int nRight = nLeft + BRACE_STATIC_WIDTH;
int nBottom = nTop + BASE_HEIGHT;

DWORD bn_dwStyle = WS_CHILD | WS_VISIBLE | SS_RIGHT| SS_CENTERIMAGE;
CStatic *pstatic = new CStatic;
pstatic->Create(_T(""), bn_dwStyle, CRect(nLeft, nTop, nRight, nBottom), this, IDC_STATIC_DYNAMIC_RIGHT_BRACE_BEGIN + m_vecUsedBaseID[m_nNewAddRowIdx]);//Button的创建语句
pstatic->SetFont(&m_fontbase);
// 保存控件指针
m_RightBraceStaticPtr.insert(m_RightBraceStaticPtr.begin() + m_nNewAddRowIdx, pstatic);

// 更新控件坐标
if (m_nNewAddRowIdx < m_vecUsedBaseID.size() - 1)
{
int nOffSetY = BASE_HEIGHT + BASE_DISTANCE_Y;

for (int i = m_nNewAddRowIdx + 1; i < m_vecUsedBaseID.size(); i++)
{
// 先获取旧的位置,然后直接整体平移一层
m_RightBraceStaticPtr[i]->GetWindowRect(BaseRect);
ScreenToClient(&BaseRect);

m_RightBraceStaticPtr[i]->MoveWindow(BaseRect.left, BaseRect.top + nOffSetY, BaseRect.Width(), BASE_HEIGHT, FALSE);
}
}
}
zgl7903 2019-02-26
  • 打赏
  • 举报
回复
MoveWindow 最后一个参数 BOOL bRepaint 默认是 TRUE ,就是移动后重绘,
可以把这个参数设置为FALSE, 全部移动完成后调用一次 Invalidate

marslycan 2019-02-26
  • 打赏
  • 举报
回复
引用 7 楼 sichuanwww 的回复:
marslycan 2019-02-26
  • 打赏
  • 举报
回复
引用 4 楼 zgl7903 的回复:
Create 之前将坐标算好, 这样就不需要移动了,
或者先不要 WS_VISIBLE, 移动完了再ShowWindow
还是不行 我在研究一下是不是因为我的滚动条刷新的问题

15,977

社区成员

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

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