视频监控UI设计

1.将static控件的notify属性设置为true,才能响应鼠标点击事件(STN_CLICKED)。

2.将多个static控件的单击事件响应到同一个函数:
  只需在对应的.cpp文件里,将

  ON_STN_CLICKED(IDC_STATIC_x,&CMSVideoMonitorView::OnStnClickedStatic0)复制,将多个控件ID与同一个处理函数对应起来即可。

代码:

BEGIN_MESSAGE_MAP(CMSVideoMonitorView, CFormView)
	//用该宏将所有所有分屏消息的响应函数设置为同一个
	ON_COMMAND_RANGE(32860,32869,&CMSVideoMonitorView::OnArrangeScreen)
	ON_WM_SIZE()
	ON_STN_CLICKED(IDC_STATIC_0, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_1, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_2, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_3, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_4, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_5, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_6, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_7, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_8, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_9, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_10, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_11, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_12, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_13, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_14, &CMSVideoMonitorView::OnStnClickedStatic0)
	ON_STN_CLICKED(IDC_STATIC_15, &CMSVideoMonitorView::OnStnClickedStatic0)
END_MESSAGE_MAP()

  分析:在单击绘制边框的功能里,不需要知道具体的控件ID,所以这样做可以。参数里也没有控件ID的信息。(这个功能是根据鼠标所在点,判断所在的窗口,为这个窗口绘制边框。没有用到static控件ID。)
3.绘制功能的实现定义了两个函数,源码如下:

绘制:

// 为当前点击的控件绘制边框
int CMSVideoMonitorView::DrawCurrentBound(void)
{
	//Step 1: 得到绘图点
	CPoint Point;
	GetCursorPos(&Point);//得到鼠标的位置
	HWND hWnd = ::WindowFromPoint(Point);//得到该点所在的窗口句柄
	CRect rectCurrentWnd;//当前窗口的矩形
	::GetWindowRect(hWnd,rectCurrentWnd);
	ScreenToClient(rectCurrentWnd);

	pointsForDraw[0] = CPoint(rectCurrentWnd.left-3,rectCurrentWnd.top-3); 
	pointsForDraw[1] = CPoint(rectCurrentWnd.right+3,rectCurrentWnd.top-3); 
	pointsForDraw[2] = CPoint(rectCurrentWnd.right+3,rectCurrentWnd.bottom+3); 
	pointsForDraw[3] = CPoint(rectCurrentWnd.left-3,rectCurrentWnd.bottom+3); 
	pointsForDraw[4] = CPoint(rectCurrentWnd.left-3,rectCurrentWnd.top-3); 

	//Step 2:准备DC、画笔并设定模式
	CClientDC clientDC(this);
	PrevClientDC = ::GetDC(this->m_hWnd);   //保存上一次的DC
	SetROP2(clientDC,R2_NOTXORPEN);
	HPEN hPenOld = (HPEN)SelectObject(clientDC,hPenDrawBound);//保存DC原来的画笔

	//Step 3:作画
	::Polyline(clientDC,pointsForDraw,5);//作画

	//Step 4:Be tidy
	::SelectObject(clientDC,hPenOld);
	::ReleaseDC(m_hWnd,clientDC);

	return 0;
}

擦除:

int CMSVideoMonitorView::ErasePrevBound(void)
 {
	if (pointsForDraw[0].x != NULL)//判断pointsForDraw[]数组是否有值
	{
		SetROP2(PrevClientDC,R2_NOTXORPEN);
		HPEN hPenOld = (HPEN)SelectObject(PrevClientDC,hPenDrawBound);//保存DC原来的画笔

		::Polyline(PrevClientDC,pointsForDraw,5);//作画

		::SelectObject(PrevClientDC,hPenOld);
		::ReleaseDC(m_hWnd,PrevClientDC);
	}
	return 0;
}

调用:

void CMSVideoMonitorView::OnStnClickedStatic0()
{
	// TODO: 在此添加控件通知处理程序代码
	ErasePrevBound();
	DrawCurrentBound();
}


4.这样做后会出现问题:窗口发生变化(最大化、向下还原)后,变化前被选中的控件再次被点击时,不能再绘制出红色边框。
    分析:擦除逻辑的控制有问题。

  先分析擦除的实现原理:将绘图模式设置为R2_NOTXORPEN。这样,在同一个地方,画一次,出现红色边框。画两次,变回原来的颜色。相当于“擦除”。

  所以,

  • 窗口变化(最大化、还原)时,导致视图重绘,因此第一次绘制的红色边框不见了。
  • 再次点击该控件,由响应函数代码可知,先进行“擦除”操作,再进行“绘制”操作。即,画一次,再画一次。
  • 窗口变化后因为原先画的边框不见了,画第一次时,本来的消除操作变成了绘制操作。显示出了边框。
  • 画第二次,将第一次画的边框擦除掉。因为这个过程非常快。肉眼看不见,所以出现了“点击后无反应”的现象。
  • 而点击别的边框时,先对问题控件画一次,“擦除”。这时变成了绘制操作。再将被点击的框架绘制。

    解决:在OnDraw()里加上绘制操作。
    代码:

void CMSVideoMonitorView::OnDraw(CDC* /*pDC*/)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pointsForDraw[0].x != NULL)//只有在已经点击过控件后,再进行绘制。
	{	
		DrawCurrentBound();
	}
 	
}



posted on 2011-08-23 17:49  LateStop  阅读(2329)  评论(2)    收藏  举报

导航