关于多画面窗口切换的刷新重绘问题

这段时间一直在开发电视转发和文件播放的服务器软件,基于PC端的。

之前在做多画面切换的时候,发现存在一个BUG,当多画面窗口切换的时候,存在窗口画面留有影子的问题,留有之前窗口的边框,看上去像重叠一样的问题,但当我点击全屏操作以后,画面重叠就消除了,一切恢复正常。

例如当我点击画面切换的时候,从9画面切换到12画面的时候,出现了下面的这种情况:

这种情况,看上去像是画面没刷新一样,就是说从9画面切到12画面的时候,画面没刷新。

下面就来看看我的画面关键代码:

在窗口切换的时候,我们需要先将窗口隐藏,然后再把窗口SHOW出来。

关键代码1:

///
//将各个多画面窗口复位到初始化状态
void CWndFilePlayVideoView::ResetFilePlayMonitorSta(int nWin)
{

for(int i=0;i<MULFILE_MONITOR_PLAYS;i++)
{
m_MulFilePlayDisplay[i].ShowWindow(SW_HIDE);
m_MulFilePlayDisplay[i].m_left = 0;
m_MulFilePlayDisplay[i].m_top = 0;
m_MulFilePlayDisplay[i].m_width = 0;
m_MulFilePlayDisplay[i].m_height = 0;

m_MulFilePlayDisplay[i].m_ischange = false;
}
TRACE("\nCWndFilePlayVideoView::ResetFilePlayMonitorSta 复位子播放窗口.\n");
}

关键代码2:

/
//对多窗口多画面播放的视频进行窗口重新布局
//
void CWndFilePlayVideoView::RestorFilePlayMonitorLayout(int nWin)
{
int i=0;
int iSingleWidth;//单个界面
int iSingleHeight;

int tempCurPlayNum=m_iCurFilePlayMonitorNum;//
//int tempNextPlayNum=m_iNextFilePlayMonitorNum;
int iRowPlayNum=0;//行
int iColumnPlayNum=0;//列
if(tempCurPlayNum==12)//12画面
{
iRowPlayNum=3;//
iColumnPlayNum=4;//
//计算单个窗口的大小
//iSingleWidth=m_rectFilePlayVideoView.Width()/iColumnPlayNum;
//iSingleHeight=m_rectFilePlayVideoView.Height()/iRowPlayNum;
iSingleWidth=(m_rectFilePlayVideoView.Width()-(iColumnPlayNum+1)*MULFILE_PlAYS_WIDTH_INTERVAL)/iColumnPlayNum;
iSingleHeight=(m_rectFilePlayVideoView.Height()-(iRowPlayNum+1)*MULFILE_PlAYS_HEIGHT_INTERVAL)/iRowPlayNum;

for(i=0;i<tempCurPlayNum;i++)//留两个像素点做间距
{
//m_MulFilePlayDisplay[i].m_left = m_rectFilePlayVideoView.left+(i%iColumnPlayNum) * iSingleWidth;
//m_MulFilePlayDisplay[i].m_top = m_rectFilePlayVideoView.top+(i/iColumnPlayNum) * iSingleHeight;
m_MulFilePlayDisplay[i].m_left = m_rectFilePlayVideoView.left+(i%iColumnPlayNum) * iSingleWidth+(i%iColumnPlayNum+1)*MULFILE_PlAYS_WIDTH_INTERVAL;
m_MulFilePlayDisplay[i].m_top = m_rectFilePlayVideoView.top+(i/iColumnPlayNum) * iSingleHeight+(i/iColumnPlayNum+1)*MULFILE_PlAYS_HEIGHT_INTERVAL;

m_MulFilePlayDisplay[i].m_width=iSingleWidth;
m_MulFilePlayDisplay[i].m_height=iSingleHeight;
m_MulFilePlayDisplay[i].m_ischange=true;//
}
}else{//1-4-9-16画面
iRowPlayNum=iColumnPlayNum=(int)sqrt((double)tempCurPlayNum);;//
//计算单个窗口的大小
//iSingleWidth=m_rectFilePlayVideoView.Width()/iColumnPlayNum;
//iSingleHeight=m_rectFilePlayVideoView.Height()/iRowPlayNum;
iSingleWidth=(m_rectFilePlayVideoView.Width()-(iColumnPlayNum+1)*MULFILE_PlAYS_WIDTH_INTERVAL)/iColumnPlayNum;
iSingleHeight=(m_rectFilePlayVideoView.Height()-(iRowPlayNum+1)*MULFILE_PlAYS_HEIGHT_INTERVAL)/iRowPlayNum;

for(i=0;i<tempCurPlayNum;i++)//留两个像素点做间距
{
//m_MulFilePlayDisplay[i].m_left = m_rectFilePlayVideoView.left+(i%iRowPlayNum) * iSingleWidth+2;
//m_MulFilePlayDisplay[i].m_top = m_rectFilePlayVideoView.top+(i/iRowPlayNum) * iSingleHeight+2;
m_MulFilePlayDisplay[i].m_left = m_rectFilePlayVideoView.left+(i%iColumnPlayNum) * iSingleWidth+(i%iColumnPlayNum+1)*MULFILE_PlAYS_WIDTH_INTERVAL;
m_MulFilePlayDisplay[i].m_top = m_rectFilePlayVideoView.top+(i/iColumnPlayNum) * iSingleHeight+(i/iColumnPlayNum+1)*MULFILE_PlAYS_HEIGHT_INTERVAL;

m_MulFilePlayDisplay[i].m_width=iSingleWidth;
m_MulFilePlayDisplay[i].m_height=iSingleHeight;
m_MulFilePlayDisplay[i].m_ischange=true;//
}
}

/开始调整位置/
for(i=0;i<MULFILE_MONITOR_PLAYS;i++)
{
if(m_MulFilePlayDisplay[i].m_ischange)
{
m_MulFilePlayDisplay[i].RestorPosition();//调整
m_MulFilePlayDisplay[i].ShowWindow(SW_SHOW);
TRACE("\nCWndFilePlayVideoView::RestorFilePlayMonitorLayout 开始调整%d窗口.\n",i);
}else{

}
}
m_iCurFilePlayMonitorNum=tempCurPlayNum;
}

关键代码3:


//重定义显示窗口位置
void CWndMulFilePlayDisp::RestorPosition()
{
MoveWindow(m_left, m_top, m_width, m_height, TRUE);
}

 

所以在窗口切换的时候,我们的代码调用顺序是:

m_iCurFilePlayMonitorNum=1;//这里切换到哪个画面,这里就赋值为x
ResetFilePlayMonitorSta(0);
RestorFilePlayMonitorLayout(0);

 ====================================

为什么会出现之前的情况?于是按照自己的判断,画面没刷新的思路,我在画面切换的函数完成以后,调用一次RedrawWindow();立即进行一次画面的刷新。

但加了以后,在多次切换以后,问题还是没有解决。

我左右想想,也不知道哪里出了问题,根据程序也发现已经进入了dopaint函数,完成了重绘刷新,但为什么还是出现这种看上去没刷新的问题?

后面想了好久,感觉难道是因为我们刷新的是父窗口??因为我们这里画面切换都是在父窗口的函数中进行的。

按照这个思路,我尝试了下在播放的各个子窗口中进行窗口刷新。

所以最后在子窗口类里面添加onsize和onpaint函数,代码很简单:

//wm_size消息处理

void CWndMulFilePlayDisp::OnSize(UINT nType,int cx,int cy)

{

  TRACE("\n CWndMulFilePlayDisp::Onsize.\n");

  CSkinStatic::Onsize(nType,cx,cy);

  RedrawWindow();//更新界面

}

//重绘消息响应函数

void CWndMulFilePlayDisp::OnPaint()

{

CPaintDC dc(this);

CRect rcClip, rcClient;
dc.GetClipBox( &rcClip );
GetClientRect(&rcClient);

// Create a compatible memory DC
CDC memDC;
memDC.CreateCompatibleDC( &dc );

// Select a compatible bitmap into the memory DC
CBitmap bitmap, bmpImage;
bitmap.CreateCompatibleBitmap( &dc, rcClient.Width(), rcClient.Height() );
memDC.SelectObject( &bitmap );


// First let the control do its default drawing.
//CWnd::DefWindowProc( WM_PAINT, (WPARAM)memDC.m_hDC, 0 );

/*********************add by lhp******************************/
DrawTreeItem(&memDC,rcClient,rcClip);
dc.BitBlt( rcClip.left, rcClip.top, rcClip.Width(),
rcClip.Height(), &memDC,
rcClip.left, rcClip.top, SRCCOPY );
// 删除资源
memDC.DeleteDC();
bitmap.DeleteObject();

}

添加了上述的代码以后,进行调试,发现问题解决了。

 

 

 

 

转载于:https://www.cnblogs.com/lihaiping/p/mulfilepalydisp.html

### 回答1: Ctabctrl是一个MFC框架下的控件,通常用于显示多个tab页,每一个tab页显示不同的内容。在实际开发中,由于多个tab页之间的内容不同,可能出现一些需要重新绘制的情况。这时,我们就可以通过重新绘制ctabctrl来达到我们想要的效果。 在使用ctabctrl控件时,我们首先需要选择一个合适的绘制方式,并为tabctrl控件进行预处理。当我们需要对控件进行重绘时,可以先使用WM_SETREDRAW消息,将控件设置为不进行重绘状态,此时修改控件的属性并不对界面上显示的内容产生影响。当需要恢复控件的重绘状态时,可以使用WM_SETREDRAW消息,将控件设置为可以重绘状态。 在进行重绘时,我们通常需要先擦除控件内容,并重新绘制。在绘制时,我们可以使用MFC框架下提供的CDC类和其他相关类,来进行绘制。在绘制时,需要考虑到控件的不同状态和不同信息,以达到最佳的绘制效果。最后,如果需要控制重绘的时间和频率,可以在控件初始化时设置相关的定时器和消息处理函数,来控制重绘的方式和间隔时间。 总之,ctabctrl控件的重绘是一个比较重要的开发问题,需要在具体使用时仔细研究,理解控件的特性和绘制方式,以达到理想的效果。 ### 回答2: ctabctrl 是一个MFC控件,在Windows窗口界面下使用极为广泛,主要功能是用于设置和维护多个选项卡,方便用户在多个选项间便捷切换。在使用 ctabctrl 的过程中,如果发现选项卡显示不正确,可能需要进行重绘操作。 CTabCtrl 重绘操作通常需要在如下三种情况下进行: 一、 当选项卡背景色与其他控件或窗口颜色不一致时,需要进行重绘操作,使得选项卡的背景色与其他控件或窗口颜色相统一,使得整个界面更加和谐。 二、 当选项卡中的文本或图标发生变化,或者选项卡的排列顺序发生改变时,需要进行重绘操作,使得选项卡显示的内容与实际操作结果保持一致。 三、 当选项卡中的控件需要刷新时,需要进行重绘操作,以便及时更新选项卡内的控件,保证用户操作的实时性。 CTabCtrl 重绘操作通常采用 Invalidate() 函数来触发,常见的调用方式有两种: 一、 在选项卡的 OnPaint() 函数中进行调用,并将需要刷新的区域作为参数传入。例如: void CMyTabCtrl::OnPaint() { CPaintDC dc(this); // 需要进行重绘的选项卡区域 CRect rect; GetClientRect(&rect); rect.DeflateRect(1,1); // 缩小矩形区域,保证视觉效果 m_myTabCtrl.InvalidateRect(&rect); } 二、 在选项卡的其他操作函数中(例如 OnSelChange())调用 Invalidate() 函数,以保证操作结果及时显示。 总之,CTabCtrl 重绘操作是 Windows 界面编程中的一个重要内容,需要程序员在开发中充分理解掌握其使用方法,以便打造更加完美的用户界面体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值