⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 subwnds.h

📁 实时监控
💻 H
字号:
/*!	本文件中的类封装了视频子窗口的若干操作
 *	\mainpage 视频子窗口功能
 *	\author nodman (nodman@163.com)
 *	\date	2003-6-11
 */
#ifndef _SUBWNDS_H
#define _SUBWNDS_H

#include "utils.h"
#include "vector"
#include "rect.h"

/// 当视频子窗口被鼠标点击时触发该消息
/// WPARAM: 窗口指针
/// LPARAM: 鼠标点击类型
#define WM_VIDEO_WND_INVOKED	WM_USER + 32777

#define WM_VIDEO_ALARM_SHOW 	WM_USER + 32778

#define WM_SHOW_MENU			WM_USER + 32779

#define WM_MENU_CLOSE			WM_USER + 32780

#define WM_USER_MENU			WM_USER + 32781

/// 子窗口类.
/// @see basic_wnd
class video_wnd: public basic_wnd<CStatic>
{
	typedef basic_wnd<CStatic> baseclass;
	CFont ft;		// window text font
protected:
	CString title;	// window title
	int i;	///< 本窗口序号, i>=0. 如果i==-1, 说明本窗口没有初始化.
	
	/// 重载CWnd::PreTranslateMessage()
	virtual BOOL PreTranslateMessage(MSG* pMsg)
	{
		WPARAM w = 0;
		LPARAM l = 0;
		switch( pMsg->message )
		{
		case WM_LBUTTONDOWN:
		case WM_LBUTTONDBLCLK:
		case WM_RBUTTONDOWN:
		case WM_RBUTTONDBLCLK:
			w = (WPARAM)this;
			l = (LPARAM)pMsg->message;
			if( GetParent() )
				if( GetParent()->SendMessage(WM_VIDEO_WND_INVOKED, w, l) )
					return TRUE;
			break;
//			return TRUE;
/*
		case WM_PAINT:
			CPaintDC dc(this);
			client_rect rc(this);
#ifdef _DEBUG
			dc.FillRect(rc, &CBrush(RGB(0,0,0)));
			dc.SetBkMode(TRANSPARENT);
			dc.SetTextColor(RGB(255,255,255));
			CFont *old = dc.SelectObject(&ft);
			dc.TextOut(10,10,title);
			dc.SelectObject(old);
#endif
			// 在窗口边缘画白色方框
			dc.FrameRect(rc, &CBrush(framecl));
			return TRUE;
*/
		}
		return basic_wnd<CStatic>::PreTranslateMessage(pMsg);
	}

public:
	/// 构造函数.
	video_wnd():i(-1){ft.CreatePointFont(90,_T("Arial"), NULL);}

	/// 析构函数, 自动销毁窗口.
	virtual ~video_wnd()
	{
		destroy();
	}
	/// @name 初始化 与 销毁.
	//@{
	/// 初始化本窗口.
	/// @param parent 父窗口.
	/// @param style 窗口风格, 默认值为黑色矩形.
	/// @return true 成功, false 失败.
	/// @see is_window()
	virtual bool create(int index, CWnd* parent, const CRect& rc = CRect(0,0,0,0), 
		DWORD style = SS_GRAYRECT | WS_CHILD | SS_NOTIFY)
	{
		// already created
		if( is_window(this) )
			return true;
		i = index;
		if( !Create(_T(""), style, rc, parent ) )
			return false;
		title.Format(_T("Ch%02d"), index+1);
//		ModifyStyleEx(0, WS_EX_STATICEDGE, 0);
		return true;
	}

	/// 销毁本窗口.
	/// @see is_window()
	void destroy()
	{
		if( !is_window(this) )
			return;

		DestroyWindow();
		i = -1;
	}
	//@}

	/// 取得本窗口序号.
	/// @return 本窗口序号.
	int index() const {return i;}
};

/// 子窗口管理基类.
class sub_wnds_mgr
{
protected:
	typedef std::vector<video_wnd*> sub_wnd_list;
	/// @see sub_wnd_list
	sub_wnd_list lst;	///< 子窗口列表.
	int cnt;			///< 子窗口个数.

	/// 构造函数.
	/// @param count 子窗口的个数.
	sub_wnds_mgr(int count):cnt(count){}

public:
	/// 子窗口参数.
	struct sub_wnd_param
	{
		CRect rc;	///< 子窗口容器区域
		int hm;	///< 子窗口之间水平方向间距.
		int vm;	///< 子窗口之间垂直方向间距.
	};

	/// 查询子窗口个数.
	/// @return 子窗口个数.
	int sub_wnds_count() const {return cnt;}

	/// 刷新所有子窗口.
	/// @param swp 子窗口参数.
	/// @see sub_wnd_param.
	/// @see calc_rect().
	void update(const sub_wnd_param& swp)
	{
		for( int i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			ref->MoveWindow(calc_rect(i, swp));
		}
		for( i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			ref->show();
		}
	}

	/// 显示窗口.
	void show(int index)
	{
		lst[index]->show();
	}

	/// 隐藏窗口.
	void hide(int index)
	{
		lst[index]->hide();
	}

	/// 显示所有.
	void show_all()
	{
		for( int i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			ref->show();
		}
	}

	/// 隐藏所有.
	void hide_all()
	{
		for( int i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			ref->hide();
		}
	}

/*
	void show_all_except(const video_wnd* vm)
	{
		for( int i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			if( ref != vm )
				ref->show();
		}
	}

	void hide_all_except(const video_wnd* vm)
	{
		for( int i=0; i<cnt; i++ )
		{
			video_wnd*& ref = lst[i];
			if( ref != vm )
				ref->hide();
		}
	}
*/

	/// 往队列中加入一个窗口.
	/// 注意顺序, 第一个加入的窗口为1号窗口, 依此类推.
	void add(video_wnd* wnd)
	{
		lst.push_back(wnd);
	}
	void add(video_wnd& wnd){add(&wnd);}

	/// 清除窗口列表.
	void clear()
	{
		lst.clear();
	}

	/// 查询某路窗口对象.
	video_wnd* operator[](int index)
	{
		if( index >= lst.size() )
			return NULL;
		return lst[index];
	}

	/// 根据窗口序号计算子窗口位置和大小.
	/// 该功能必须由派生类实现, 以供create()使用.
	/// @param index 子窗口的序号.
	/// @param swp 子窗口参数.
	/// @return 该子窗口的位置(CRect).
	/// @see sub_wnd_param.
	virtual CRect calc_rect(int index, const sub_wnd_param& swp){return CRect(0,0,0,0);}
};

/// 规则视频子窗口基类.
/// 本类要用到其派生类中的枚举类型: count, cols, rows.
template<typename T>
class video_square: public sub_wnds_mgr
{
public:
	/// 构造函数, 为基类确定子窗口个数.
	video_square(): sub_wnds_mgr(T::count){}

	/// 计算某个子窗口位置.
	/// @param index 子窗口序号.
	/// @param swp 子窗口参数.
	/// @return 子窗口位置.
	/// @see sub_wnds_mgr::sub_wnd_param
	virtual CRect calc_rect(int index, const sub_wnd_param& swp)
	{
		// w = sub_w*2 + hm*3;
		// h = sub_h*2 + vm*3;
		// =>
		// sub_w = (w-hm*3)/2;
		// sub_h = (h-vm*3)/2;
		int sub_w = 0, sub_h = 0;
		CRect ret(0,0,0,0);
		
		// for convenience :)
		const CRect& rc = swp.rc;
		const int& hm = swp.hm;
		const int& vm = swp.vm;
		
		sub_w = (swp.rc.Width() - hm*(T::cols+1))/T::cols;
		sub_h = (swp.rc.Height() - vm*(T::rows+1))/T::rows;
		
		int h_factor = index % T::cols;	// horizontal video wnds
		int v_factor = index / T::cols;	// vertical video wnds

		ret.left = swp.rc.left + hm*(h_factor+1) + sub_w*h_factor;
		ret.top = swp.rc.top + vm*(v_factor+1) + sub_h*v_factor;
		ret.right = ret.left + sub_w;
		ret.bottom = ret.top + sub_h;
		
		return ret;
	}
};

/// 4路子窗口.
/// @see video_square
class video_4ch: public video_square<video_4ch>
{
public:
	enum {count=4, cols=2, rows=2};	///< 子窗口个数.
};

/// 单路.
/// @see video_square
class video_1ch: public video_square<video_1ch>
{
public:
	enum {count=1, cols=1, rows=1};
};

/// 9路.
/// @see video_square
class video_9ch: public video_square<video_9ch>
{
public:
	enum {count=9, cols=3, rows=3};
};

/// 16路.
/// @see video_square
class video_16ch: public video_square<video_16ch>
{
public:
	enum {count=16, cols=4, rows=4};
};

/// 32路.
/// @see video_square
class video_25ch: public video_square<video_25ch>
{
public:
	enum {count=25, cols=5, rows=5};
};

/// 12路.
/// @see video_square
class video_12ch: public video_square<video_12ch>
{
public:
	enum {count=12, cols=3, rows=4};
};

/// 6路.
/// 本类描述的子窗口序列是不规则的.
class video_6ch: public sub_wnds_mgr
{
public:
	enum {count=6, cols=0, rows=0};		///< 特殊窗口.
	video_6ch(): sub_wnds_mgr(count){}

	/// 指定放大窗口.
	/// 该函数将要放大的窗口放到队列的第一个.
	/// @param zoom 放大的窗口.
	/// @param w 放大窗口的宽度.
	/// @param h 放大窗口的高度.
	void set_zoom(video_wnd* zoom)
	{
		// if the one is already the first one
		// OK, return
		if( zoom == lst[0] )
			return;

		std::vector<video_wnd*> tmp;
		
		// find the one
		for( int i=0; i<lst.size(); i++ )
		{
			if( zoom == lst[i] )
				tmp.push_back(lst[i]);
		}
		if( tmp.empty() )	// specified item not found in the list
			return;

		// add the remaining items to tail
		for( i=0; i<lst.size(); i++ )
		{
			if( zoom != lst[i] )
				tmp.push_back(lst[i]);
		}

		// save the result
		lst.swap(tmp);
	}

	/*
	 *	|-----------| |----|
	 *	|		    | | 01 |
	 *	|		    | |----|
	 *	|	  z     |
	 *	|		    | |----|
	 *	|		    | | 02 |
	 *	|-----------| |----|
	 *
	 *	|----| |----| |----|
	 *	| 03 | | 04 | | 05 |
	 *	|----| |----| |----|
	 */
	/// 计算窗口位置.
	/// @see video_square::calc_rect()
	virtual CRect calc_rect(int index, const sub_wnd_param& swp)
	{
		CRect ret(0,0,0,0);
		int sub_w = 0, sub_h = 0;

		// for convenience :)
		const CRect& rc = swp.rc;
		const int& hm = swp.hm;
		const int& vm = swp.vm;
		

		// 宽度高度按照3x3方法计算
		sub_w = (swp.rc.Width() - hm*(3+1))/3;
		sub_h = (swp.rc.Height() - vm*(3+1))/3;

		// 如果是放大窗口
		if( index == 0 )
		{
			ret.left = swp.rc.left + hm;
			ret.top = swp.rc.top + vm;
			ret.right = ret.left + sub_w*2+hm;
			ret.bottom = ret.top + sub_h*2+vm;
			return ret;
		}


		/*  this:
		 * -------
		 *  0   1
		 *	    2
		 *  3 4 5
		 *
		 * +++++++
		 *
		 *	 3x3
		 * -------
		 *	0 1 2
		 *	3 4 5
		 *	6 7 8
		 */
		// 用对应法则, 建立一张表格, 按照3x3的算法计算
		//				1  2  3  4  5		// 6路的窗口序列
		int table[5] = {2, 5, 6, 7, 8};		// 对应的3x3窗口序列号

		int h_factor = table[index-1] % 3;	// horizontal video wnds
		int v_factor = table[index-1] / 3;	// vertical video wnds
		
		ret.left = swp.rc.left + hm*(h_factor+1) + sub_w*h_factor;
		ret.top = swp.rc.top + vm*(v_factor+1) + sub_h*v_factor;
		ret.right = ret.left + sub_w;
		ret.bottom = ret.top + sub_h;
		
		return ret;
	}
};
#endif	// _SUBWNDS_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -