Parcourir la source

UB530视频采集卡主程序

Jeff il y a 5 ans
Parent
commit
da82b723fe
100 fichiers modifiés avec 22779 ajouts et 0 suppressions
  1. 3052 0
      VideoCapture/UI/BCMenu.cpp
  2. 366 0
      VideoCapture/UI/BCMenu.h
  3. 2559 0
      VideoCapture/UI/BtnST.cpp
  4. 321 0
      VideoCapture/UI/BtnST.h
  5. 161 0
      VideoCapture/UI/ComboTreeCtrl.cpp
  6. 59 0
      VideoCapture/UI/ComboTreeCtrl.h
  7. 36 0
      VideoCapture/UI/FontSize.cpp
  8. 25 0
      VideoCapture/UI/FontSize.h
  9. 1216 0
      VideoCapture/UI/PictureEx.cpp
  10. 305 0
      VideoCapture/UI/PictureEx.h
  11. 1364 0
      VideoCapture/UI/SubLabel.cpp
  12. 117 0
      VideoCapture/UI/SubLabel.h
  13. 244 0
      VideoCapture/UI/TreeComboBox.cpp
  14. 90 0
      VideoCapture/UI/TreeComboBox.h
  15. 260 0
      VideoCapture/UI/XColorStatic.cpp
  16. 65 0
      VideoCapture/UI/XColorStatic.h
  17. 333 0
      VideoCapture/VideoCapture/ClassView.cpp
  18. 64 0
      VideoCapture/VideoCapture/ClassView.h
  19. 74 0
      VideoCapture/VideoCapture/DlgIRControl.cpp
  20. 29 0
      VideoCapture/VideoCapture/DlgIRControl.h
  21. 267 0
      VideoCapture/VideoCapture/FileView.cpp
  22. 65 0
      VideoCapture/VideoCapture/FileView.h
  23. 522 0
      VideoCapture/VideoCapture/Global.cpp
  24. 46 0
      VideoCapture/VideoCapture/Global.h
  25. 187 0
      VideoCapture/VideoCapture/IRControlWnd.cpp
  26. 72 0
      VideoCapture/VideoCapture/IRControlWnd.h
  27. 633 0
      VideoCapture/VideoCapture/MainFrm.cpp
  28. 157 0
      VideoCapture/VideoCapture/MainFrm.h
  29. 338 0
      VideoCapture/VideoCapture/MemoryClient.cpp
  30. 41 0
      VideoCapture/VideoCapture/MemoryClient.h
  31. 139 0
      VideoCapture/VideoCapture/MemoryComm.cpp
  32. 30 0
      VideoCapture/VideoCapture/MemoryComm.h
  33. 134 0
      VideoCapture/VideoCapture/MemoryDef.h
  34. 210 0
      VideoCapture/VideoCapture/OutputWnd.cpp
  35. 69 0
      VideoCapture/VideoCapture/OutputWnd.h
  36. 283 0
      VideoCapture/VideoCapture/PropertiesWnd.cpp
  37. 72 0
      VideoCapture/VideoCapture/PropertiesWnd.h
  38. 2837 0
      VideoCapture/VideoCapture/QCAP.H
  39. BIN
      VideoCapture/VideoCapture/QCAP.X86.LIB
  40. 178 0
      VideoCapture/VideoCapture/Resource.h
  41. 1290 0
      VideoCapture/VideoCapture/SpreadSheet.cpp
  42. 78 0
      VideoCapture/VideoCapture/SpreadSheet.h
  43. 471 0
      VideoCapture/VideoCapture/TrayIcon.cpp
  44. 84 0
      VideoCapture/VideoCapture/TrayIcon.h
  45. 272 0
      VideoCapture/VideoCapture/VideoCapture.cpp
  46. 51 0
      VideoCapture/VideoCapture/VideoCapture.h
  47. BIN
      VideoCapture/VideoCapture/VideoCapture.rc
  48. 336 0
      VideoCapture/VideoCapture/VideoCapture.vcxproj
  49. 324 0
      VideoCapture/VideoCapture/VideoCapture.vcxproj.filters
  50. 148 0
      VideoCapture/VideoCapture/VideoCaptureDoc.cpp
  51. 58 0
      VideoCapture/VideoCapture/VideoCaptureDoc.h
  52. 1221 0
      VideoCapture/VideoCapture/VideoCaptureView.cpp
  53. 199 0
      VideoCapture/VideoCapture/VideoCaptureView.h
  54. 52 0
      VideoCapture/VideoCapture/ViewTree.cpp
  55. 33 0
      VideoCapture/VideoCapture/ViewTree.h
  56. 172 0
      VideoCapture/VideoCapture/calendarbar.cpp
  57. 46 0
      VideoCapture/VideoCapture/calendarbar.h
  58. 59 0
      VideoCapture/VideoCapture/framework.h
  59. BIN
      VideoCapture/VideoCapture/res/Toolbar.bmp
  60. BIN
      VideoCapture/VideoCapture/res/Toolbar256.bmp
  61. BIN
      VideoCapture/VideoCapture/res/VideoCapture.ico
  62. BIN
      VideoCapture/VideoCapture/res/VideoCapture.rc2
  63. BIN
      VideoCapture/VideoCapture/res/VideoCaptureDoc.ico
  64. BIN
      VideoCapture/VideoCapture/res/buttons.bmp
  65. BIN
      VideoCapture/VideoCapture/res/class_view.ico
  66. BIN
      VideoCapture/VideoCapture/res/class_view_hc.ico
  67. BIN
      VideoCapture/VideoCapture/res/classview.bmp
  68. BIN
      VideoCapture/VideoCapture/res/classview_hc.bmp
  69. BIN
      VideoCapture/VideoCapture/res/explorer.bmp
  70. BIN
      VideoCapture/VideoCapture/res/explorer_hc.bmp
  71. BIN
      VideoCapture/VideoCapture/res/file_view.ico
  72. BIN
      VideoCapture/VideoCapture/res/file_view_hc.ico
  73. BIN
      VideoCapture/VideoCapture/res/filelarge.bmp
  74. BIN
      VideoCapture/VideoCapture/res/filesmall.bmp
  75. BIN
      VideoCapture/VideoCapture/res/fileview.bmp
  76. BIN
      VideoCapture/VideoCapture/res/fileview_hc.bmp
  77. BIN
      VideoCapture/VideoCapture/res/info.bmp
  78. BIN
      VideoCapture/VideoCapture/res/main.bmp
  79. BIN
      VideoCapture/VideoCapture/res/menuimages.bmp
  80. BIN
      VideoCapture/VideoCapture/res/menuimages_hc.bmp
  81. BIN
      VideoCapture/VideoCapture/res/nav_large.bmp
  82. BIN
      VideoCapture/VideoCapture/res/nav_large_hc.bmp
  83. BIN
      VideoCapture/VideoCapture/res/output_wnd.ico
  84. BIN
      VideoCapture/VideoCapture/res/output_wnd_hc.ico
  85. BIN
      VideoCapture/VideoCapture/res/pages.bmp
  86. BIN
      VideoCapture/VideoCapture/res/pages_hc.bmp
  87. BIN
      VideoCapture/VideoCapture/res/pages_small.bmp
  88. BIN
      VideoCapture/VideoCapture/res/pages_small_hc.bmp
  89. BIN
      VideoCapture/VideoCapture/res/properties.bmp
  90. BIN
      VideoCapture/VideoCapture/res/properties_hc.bmp
  91. BIN
      VideoCapture/VideoCapture/res/properties_wnd.ico
  92. BIN
      VideoCapture/VideoCapture/res/properties_wnd_hc.ico
  93. 790 0
      VideoCapture/VideoCapture/res/ribbon.mfcribbon-ms
  94. BIN
      VideoCapture/VideoCapture/res/sort.bmp
  95. BIN
      VideoCapture/VideoCapture/res/sort_hc.bmp
  96. BIN
      VideoCapture/VideoCapture/res/writelarge.bmp
  97. BIN
      VideoCapture/VideoCapture/res/writesmall.bmp
  98. 5 0
      VideoCapture/VideoCapture/stdafx.cpp
  99. 51 0
      VideoCapture/VideoCapture/stdafx.h
  100. 19 0
      VideoCapture/VideoCapture/targetver.h

+ 3052 - 0
VideoCapture/UI/BCMenu.cpp

@@ -0,0 +1,3052 @@
+#include "stdafx.h"       // Standard windows header file
+#include "BCMenu.h"        // BCMenu class declaration
+#include <afxpriv.h>       //SK: makes A2W and other spiffy AFX macros work
+#include <VersionHelpers.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+#define BCMENU_GAP 1
+#ifndef OBM_CHECK
+#define OBM_CHECK 32760 // from winuser.h
+#endif
+
+#if _MFC_VER <0x400
+#error This code does not work on Versions of MFC prior to 4.0
+#endif
+
+static CPINFO CPInfo;
+// how the menu's are drawn in win9x/NT/2000
+UINT BCMenu::original_drawmode=BCMENU_DRAWMODE_ORIGINAL;
+BOOL BCMenu::original_select_disabled=TRUE;
+// how the menu's are drawn in winXP
+UINT BCMenu::xp_drawmode=BCMENU_DRAWMODE_XP;
+BOOL BCMenu::xp_select_disabled=FALSE;
+BOOL BCMenu::xp_draw_3D_bitmaps=TRUE;
+
+CImageList BCMenu::m_AllImages;
+CArray<int,int&> BCMenu::m_AllImagesID;
+
+enum Win32Type{
+	Win32s,
+	WinNT3,
+	Win95,
+	Win98,
+	WinME,
+	WinNT4,
+	Win2000,
+	WinXP
+};
+
+
+Win32Type IsShellType()
+{
+	Win32Type  ShellType;
+
+	if (IsWindowsXPOrGreater())
+	{
+		ShellType = WinXP;
+	}
+	else if (IsWindowsXPSP3OrGreater())
+	{
+		ShellType = WinXP;
+	}
+	else
+	{
+		ShellType = WinNT4;
+	}
+
+	return ShellType;
+}
+
+static Win32Type g_Shell=IsShellType();
+
+void BCMenuData::SetAnsiString(LPCSTR szAnsiString)
+{
+	USES_CONVERSION;
+	SetWideString(A2W(szAnsiString));  //SK:  see MFC Tech Note 059
+}
+
+CString BCMenuData::GetString(void)//returns the menu text in ANSI or UNICODE
+//depending on the MFC-Version we are using
+{
+	CString strText;
+	if (m_szMenuText)
+	{
+#ifdef UNICODE
+		strText = m_szMenuText;
+#else
+		USES_CONVERSION;
+		strText=W2A(m_szMenuText);     //SK:  see MFC Tech Note 059
+#endif    
+	}
+	return strText;
+}
+
+CTypedPtrArray<CPtrArray, HMENU> BCMenu::m_AllSubMenus;  // Stores list of all sub-menus
+
+IMPLEMENT_DYNAMIC( BCMenu, CMenu )
+
+/*
+===============================================================================
+BCMenu::BCMenu()
+BCMenu::~BCMenu()
+-----------------
+
+Constructor and Destructor.
+
+===============================================================================
+*/
+
+BCMenu::BCMenu()
+{
+	m_bDynIcons = FALSE;     // O.S. - no dynamic icons by default
+	disable_old_style=FALSE;
+	m_iconX = 16;            // Icon sizes default to 16 x 16
+	m_iconY = 15;            // ...
+	m_selectcheck = -1;
+	m_unselectcheck = -1;
+	checkmaps=NULL;
+	checkmapsshare=FALSE;
+	// set the color used for the transparent background in all bitmaps
+	m_bitmapBackground=RGB(192,192,192); //gray
+	m_bitmapBackgroundFlag=FALSE;
+	GetCPInfo(CP_ACP,&CPInfo);
+	m_loadmenu=FALSE;
+}
+
+
+BCMenu::~BCMenu()
+{
+	DestroyMenu();
+}
+
+BOOL BCMenu::IsNewShell ()
+{
+	return (g_Shell>=Win95);
+}
+
+BOOL BCMenu::IsWinXPLuna()
+{
+	if(g_Shell==WinXP){
+		if(IsWindowsClassicTheme())return(FALSE);
+		else return(TRUE);
+	}
+	return(FALSE);
+}
+
+BOOL BCMenu::IsLunaMenuStyle()
+{
+	if(IsWinXPLuna()){
+		if(xp_drawmode==BCMENU_DRAWMODE_XP)return(TRUE);
+	}
+	else{
+		if(original_drawmode==BCMENU_DRAWMODE_XP)return(TRUE);
+	}
+	return(FALSE);
+}
+
+BCMenuData::~BCMenuData()
+{
+	if(bitmap)
+		delete(bitmap);
+
+	delete[] m_szMenuText; //Need not check for NULL because ANSI X3J16 allows "delete NULL"
+}
+
+
+void BCMenuData::SetWideString(const wchar_t *szWideString)
+{
+	delete[] m_szMenuText;//Need not check for NULL because ANSI X3J16 allows "delete NULL"
+
+	if (szWideString)
+	{
+		m_szMenuText = new wchar_t[sizeof(wchar_t)*(wcslen(szWideString)+1)];
+		if (m_szMenuText)
+			wcscpy_s(m_szMenuText, sizeof(wchar_t) * (wcslen(szWideString) + 1), szWideString);
+	}
+	else
+		m_szMenuText=NULL;//set to NULL so we need not bother about dangling non-NULL Ptrs
+}
+
+BOOL BCMenu::IsMenu(CMenu *submenu)
+{
+	int m;
+	int numSubMenus = m_AllSubMenus.GetUpperBound();
+	for(m=0;m<=numSubMenus;++m){
+		if(submenu->m_hMenu==m_AllSubMenus[m])return(TRUE);
+	}
+	return(FALSE);
+}
+
+BOOL BCMenu::IsMenu(HMENU submenu)
+{
+	int m;
+	int numSubMenus = m_AllSubMenus.GetUpperBound();
+	for(m=0;m<=numSubMenus;++m){
+		if(submenu==m_AllSubMenus[m])return(TRUE);
+	}
+	return(FALSE);
+}
+
+BOOL BCMenu::DestroyMenu()
+{
+	// Destroy Sub menus:
+	int m,n;
+	int numAllSubMenus = m_AllSubMenus.GetUpperBound();
+	for(n = numAllSubMenus; n>= 0; n--){
+		if(m_AllSubMenus[n]==this->m_hMenu)m_AllSubMenus.RemoveAt(n);
+	}
+	int numSubMenus = m_SubMenus.GetUpperBound();
+	for(m = numSubMenus; m >= 0; m--){
+		numAllSubMenus = m_AllSubMenus.GetUpperBound();
+		for(n = numAllSubMenus; n>= 0; n--){
+			if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
+		}
+		CMenu *ptr=FromHandle(m_SubMenus[m]);
+		BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( BCMenu ));
+		if(flag)delete((BCMenu *)ptr);
+	}
+	m_SubMenus.RemoveAll();
+	// Destroy menu data
+	int numItems = m_MenuList.GetUpperBound();
+	for(m = 0; m <= numItems; m++)delete(m_MenuList[m]);
+	m_MenuList.RemoveAll();
+	if(checkmaps&&!checkmapsshare){
+		delete checkmaps;
+		checkmaps=NULL;
+	}
+	// Call base-class implementation last:
+	return(CMenu::DestroyMenu());
+};
+
+int BCMenu::GetMenuDrawMode(void)
+{
+	if(IsWinXPLuna())return(xp_drawmode);
+	return(original_drawmode);
+}
+
+BOOL BCMenu::GetSelectDisableMode(void)
+{
+	if(IsLunaMenuStyle())return(xp_select_disabled);
+	return(original_select_disabled);
+}
+
+
+/*
+==========================================================================
+void BCMenu::DrawItem(LPDRAWITEMSTRUCT)
+---------------------------------------
+
+Called by the framework when a particular item needs to be drawn.  We
+overide this to draw the menu item in a custom-fashion, including icons
+and the 3D rectangle bar.
+==========================================================================
+*/
+
+void BCMenu::DrawItem (LPDRAWITEMSTRUCT lpDIS)
+{
+	ASSERT(lpDIS != NULL);
+	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
+	if(pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE)DrawItem_Win9xNT2000(lpDIS);
+	else{
+		if(IsWinXPLuna()){
+			if(xp_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
+			else DrawItem_Win9xNT2000(lpDIS);
+		}
+		else{
+			if(original_drawmode==BCMENU_DRAWMODE_XP) DrawItem_WinXP(lpDIS);
+			else DrawItem_Win9xNT2000(lpDIS);
+		}	
+	}
+}
+
+void BCMenu::DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS)
+{
+	ASSERT(lpDIS != NULL);
+	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
+	CRect rect;
+	UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
+	CBrush m_brBackground;
+	COLORREF m_clrBack;
+
+	if(IsWinXPLuna())m_clrBack=GetSysColor(COLOR_3DFACE);
+	else m_clrBack=GetSysColor(COLOR_MENU);
+
+	m_brBackground.CreateSolidBrush(m_clrBack);
+
+	// remove the selected bit if it's grayed out
+	if(lpDIS->itemState & ODS_GRAYED&&!original_select_disabled){
+		if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
+	}
+
+	if(state & MF_SEPARATOR){
+		rect.CopyRect(&lpDIS->rcItem);
+		pDC->FillRect (rect,&m_brBackground);
+		rect.top += (rect.Height()>>1);
+		pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
+	}
+	else{
+		CRect rect2;
+		BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
+		BOOL checkflag=FALSE;
+		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
+		CBrush m_brSelect;
+		CPen m_penBack;
+		int x0,y0,dy;
+		int nIconNormal=-1,xoffset=-1,global_offset=-1;
+		CImageList *bitmap=NULL;
+
+		// set some colors
+		m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
+		m_brSelect.CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
+
+		// draw the colored rectangle portion
+
+		rect.CopyRect(&lpDIS->rcItem);
+		rect2=rect;
+
+		// draw the up/down/focused/disabled state
+
+		UINT state = lpDIS->itemState;
+		CString strText;
+
+		if(lpDIS->itemData != NULL){
+			nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
+			xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
+			global_offset = (((BCMenuData*)(lpDIS->itemData))->global_offset);
+			bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
+			strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
+
+			if(nIconNormal<0&&global_offset>=0){
+				xoffset=global_offset;
+				nIconNormal=0;
+				bitmap = &m_AllImages;
+			}
+
+			if(state&ODS_CHECKED && nIconNormal<0){
+				if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
+				else if(m_unselectcheck>0) checkflag=TRUE;
+			}
+			else if(nIconNormal != -1){
+				standardflag=TRUE;
+				if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
+				else if(state&ODS_GRAYED) disableflag=TRUE;
+			}
+		}
+		else{
+			strText.Empty();
+		}
+
+		if(state&ODS_SELECTED){ // draw the down edges
+
+			CPen *pOldPen = pDC->SelectObject (&m_penBack);
+
+			// You need only Text highlight and thats what you get
+
+			if(checkflag||standardflag||selectedflag||disableflag||state&ODS_CHECKED)
+				rect2.SetRect(rect.left+m_iconX+4+BCMENU_GAP,rect.top,rect.right,rect.bottom);
+			pDC->FillRect (rect2,&m_brSelect);
+
+			pDC->SelectObject (pOldPen);
+			crText = GetSysColor(COLOR_HIGHLIGHTTEXT);
+		}
+		else {
+			CPen *pOldPen = pDC->SelectObject (&m_penBack);
+			pDC->FillRect (rect,&m_brBackground);
+			pDC->SelectObject (pOldPen);
+
+			// draw the up edges	
+			pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
+		}
+
+		// draw the text if there is any
+		//We have to paint the text only if the image is nonexistant
+
+		dy = (rect.Height()-4-m_iconY)/2;
+		dy = dy<0 ? 0 : dy;
+
+		if(checkflag||standardflag||selectedflag||disableflag){
+			rect2.SetRect(rect.left+1,rect.top+1+dy,rect.left+m_iconX+3,
+				rect.top+m_iconY+3+dy);
+			pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
+			if(checkflag && checkmaps){
+				pDC->FillRect (rect2,&m_brBackground);
+				rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
+					rect.top+m_iconY+4+dy);
+
+				pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
+				CPoint ptImage(rect.left+2,rect.top+2+dy);
+
+				if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
+				else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
+			}
+			else if(disableflag){
+				if(!selectedflag){
+					CBitmap bitmapstandard;
+					GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
+					rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
+						rect.top+m_iconY+4+dy);
+					pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
+					if(disable_old_style)
+						DitherBlt(lpDIS->hDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
+						(HBITMAP)(bitmapstandard),0,0,m_clrBack);
+					else
+						DitherBlt2(pDC,rect.left+2,rect.top+2+dy,m_iconX,m_iconY,
+						bitmapstandard,0,0,m_clrBack);
+					bitmapstandard.DeleteObject();
+				}
+			}
+			else if(selectedflag){
+				pDC->FillRect (rect2,&m_brBackground);
+				rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
+					rect.top+m_iconY+4+dy);
+				if (IsNewShell()){
+					if(state&ODS_CHECKED)
+						pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
+						GetSysColor(COLOR_3DHILIGHT));
+					else
+						pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DHILIGHT),
+						GetSysColor(COLOR_3DSHADOW));
+				}
+				CPoint ptImage(rect.left+2,rect.top+2+dy);
+				if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
+			}
+			else{
+				if(state&ODS_CHECKED){
+					CBrush brush;
+					COLORREF col = m_clrBack;
+					col = LightenColor(col,0.6);
+					brush.CreateSolidBrush(col);
+					pDC->FillRect(rect2,&brush);
+					brush.DeleteObject();
+					rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
+						rect.top+m_iconY+4+dy);
+					if (IsNewShell())
+						pDC->Draw3dRect(rect2,GetSysColor(COLOR_3DSHADOW),
+						GetSysColor(COLOR_3DHILIGHT));
+				}
+				else{
+					pDC->FillRect (rect2,&m_brBackground);
+					rect2.SetRect(rect.left,rect.top+dy,rect.left+m_iconX+4,
+						rect.top+m_iconY+4+dy);
+					pDC->Draw3dRect (rect2,m_clrBack,m_clrBack);
+				}
+				CPoint ptImage(rect.left+2,rect.top+2+dy);
+				if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
+			}
+		}
+		if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
+			rect2.SetRect(rect.left+1,rect.top+2+dy,rect.left+m_iconX+1,
+				rect.top+m_iconY+2+dy);
+			CMenuItemInfo info;
+			info.fMask = MIIM_CHECKMARKS;
+			::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
+				MF_BYCOMMAND, &info);
+			if(state&ODS_CHECKED || info.hbmpUnchecked) {
+				Draw3DCheckmark(pDC, rect2, state&ODS_SELECTED,
+					state&ODS_CHECKED ? info.hbmpChecked :
+					info.hbmpUnchecked);
+			}
+		}
+
+		//This is needed always so that we can have the space for check marks
+
+		x0=rect.left;y0=rect.top;
+		rect.left = rect.left + m_iconX + 8 + BCMENU_GAP; 
+
+		if(!strText.IsEmpty()){
+
+			CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
+
+			//   Find tabs
+
+			CString leftStr,rightStr;
+			leftStr.Empty();rightStr.Empty();
+			int tablocr=strText.ReverseFind(_T('\t'));
+			if(tablocr!=-1){
+				rightStr=strText.Mid(tablocr+1);
+				leftStr=strText.Left(strText.Find(_T('\t')));
+				rectt.right-=m_iconX;
+			}
+			else leftStr=strText;
+
+			int iOldMode = pDC->GetBkMode();
+			pDC->SetBkMode( TRANSPARENT);
+
+			// Draw the text in the correct colour:
+
+			UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
+			UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
+			if(!(lpDIS->itemState & ODS_GRAYED)){
+				pDC->SetTextColor(crText);
+				pDC->DrawText (leftStr,rectt,nFormat);
+				if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
+			}
+			else{
+
+				// Draw the disabled text
+				if(!(state & ODS_SELECTED)){
+					RECT offset = *rectt;
+					offset.left+=1;
+					offset.right+=1;
+					offset.top+=1;
+					offset.bottom+=1;
+					pDC->SetTextColor(GetSysColor(COLOR_BTNHILIGHT));
+					pDC->DrawText(leftStr,&offset, nFormat);
+					if(tablocr!=-1) pDC->DrawText (rightStr,&offset,nFormatr);
+					pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
+					pDC->DrawText(leftStr,rectt, nFormat);
+					if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
+				}
+				else{
+					// And the standard Grey text:
+					pDC->SetTextColor(m_clrBack);
+					pDC->DrawText(leftStr,rectt, nFormat);
+					if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
+				}
+			}
+			pDC->SetBkMode( iOldMode );
+		}
+
+		m_penBack.DeleteObject();
+		m_brSelect.DeleteObject();
+	}
+	m_brBackground.DeleteObject();
+}
+
+COLORREF BCMenu::LightenColor(COLORREF col,double factor)
+{
+	if(factor>0.0&&factor<=1.0){
+		BYTE red,green,blue,lightred,lightgreen,lightblue;
+		red = GetRValue(col);
+		green = GetGValue(col);
+		blue = GetBValue(col);
+		lightred = (BYTE)((factor*(255-red)) + red);
+		lightgreen = (BYTE)((factor*(255-green)) + green);
+		lightblue = (BYTE)((factor*(255-blue)) + blue);
+		col = RGB(lightred,lightgreen,lightblue);
+	}
+	return(col);
+}
+
+COLORREF BCMenu::DarkenColor(COLORREF col,double factor)
+{
+	if(factor>0.0&&factor<=1.0){
+		BYTE red,green,blue,lightred,lightgreen,lightblue;
+		red = GetRValue(col);
+		green = GetGValue(col);
+		blue = GetBValue(col);
+		lightred = (BYTE)(red-(factor*red));
+		lightgreen = (BYTE)(green-(factor*green));
+		lightblue = (BYTE)(blue-(factor*blue));
+		col = RGB(lightred,lightgreen,lightblue);
+	}
+	return(col);
+}
+
+
+void BCMenu::DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS)
+{
+	ASSERT(lpDIS != NULL);
+	CDC* pDC = CDC::FromHandle(lpDIS->hDC);
+#ifdef BCMENU_USE_MEMDC
+	BCMenuMemDC *pMemDC=NULL;
+#endif
+	CRect rect,rect2;
+	UINT state = (((BCMenuData*)(lpDIS->itemData))->nFlags);
+	COLORREF m_newclrBack=GetSysColor(COLOR_3DFACE);
+	COLORREF m_clrBack=GetSysColor(COLOR_WINDOW);
+	CFont m_fontMenu,*pFont=NULL;
+	LOGFONT m_lf;
+	if(!IsWinXPLuna())m_newclrBack=LightenColor(m_newclrBack,0.25);
+	CBrush m_newbrBackground,m_brBackground;
+	m_brBackground.CreateSolidBrush(m_clrBack);
+	m_newbrBackground.CreateSolidBrush(m_newclrBack);
+	int BCMENU_PAD=4;
+	if(xp_draw_3D_bitmaps)BCMENU_PAD=7;
+	int barwidth=m_iconX+BCMENU_PAD;
+
+	// remove the selected bit if it's grayed out
+	if(lpDIS->itemState & ODS_GRAYED&&!xp_select_disabled){
+		if(lpDIS->itemState & ODS_SELECTED)lpDIS->itemState=lpDIS->itemState & ~ODS_SELECTED;
+#ifdef BCMENU_USE_MEMDC
+		pMemDC=new BCMenuMemDC(pDC,&lpDIS->rcItem);
+		pDC = pMemDC;
+		ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
+		NONCLIENTMETRICS nm;
+		nm.cbSize = sizeof (NONCLIENTMETRICS);
+		VERIFY (SystemParametersInfo(SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
+		m_lf =  nm.lfMenuFont;
+		m_fontMenu.CreateFontIndirect (&m_lf);
+		pFont = pDC->SelectObject (&m_fontMenu);
+#endif
+
+	}
+
+	if(state & MF_SEPARATOR){
+		rect.CopyRect(&lpDIS->rcItem);
+		pDC->FillRect (rect,&m_brBackground);
+		rect2.SetRect(rect.left,rect.top,rect.left+barwidth,rect.bottom);
+		rect.top+=rect.Height()>>1;
+		rect.left = rect2.right+BCMENU_PAD;
+		pDC->DrawEdge(&rect,EDGE_ETCHED,BF_TOP);
+		pDC->FillRect (rect2,&m_newbrBackground);
+		pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
+	}
+	else{
+		BOOL standardflag=FALSE,selectedflag=FALSE,disableflag=FALSE;
+		BOOL checkflag=FALSE;
+		COLORREF crText = GetSysColor(COLOR_MENUTEXT);
+		COLORREF crSelect = GetSysColor(COLOR_HIGHLIGHT);
+		COLORREF crSelectFill;
+		if(!IsWinXPLuna())crSelectFill=LightenColor(crSelect,0.85);
+		else crSelectFill=LightenColor(crSelect,0.7);
+		CBrush m_brSelect;
+		CPen m_penBack;
+		int x0,y0,dx,dy;
+		int nIconNormal=-1,xoffset=-1,global_offset=-1;
+		int faded_offset=1,shadow_offset=2;
+		CImageList *bitmap=NULL;
+		BOOL CanDraw3D=FALSE;
+
+		// set some colors
+		m_penBack.CreatePen (PS_SOLID,0,m_clrBack);
+		m_brSelect.CreateSolidBrush(crSelectFill);
+
+		// draw the colored rectangle portion
+
+		rect.CopyRect(&lpDIS->rcItem);
+		rect2=rect;
+
+		// draw the up/down/focused/disabled state
+
+		UINT state = lpDIS->itemState;
+		CString strText;
+
+		if(lpDIS->itemData != NULL){
+			nIconNormal = (((BCMenuData*)(lpDIS->itemData))->menuIconNormal);
+			xoffset = (((BCMenuData*)(lpDIS->itemData))->xoffset);
+			bitmap = (((BCMenuData*)(lpDIS->itemData))->bitmap);
+			strText = ((BCMenuData*) (lpDIS->itemData))->GetString();
+			global_offset = (((BCMenuData*)(lpDIS->itemData))->global_offset);
+
+			if(xoffset==0&&xp_draw_3D_bitmaps&&bitmap&&bitmap->GetImageCount()>2)CanDraw3D=TRUE;
+
+			if(nIconNormal<0&&xoffset<0&&global_offset>=0){
+				xoffset=global_offset;
+				nIconNormal=0;
+				bitmap = &m_AllImages;
+				if(xp_draw_3D_bitmaps&&CanDraw3DImageList(global_offset)){
+					CanDraw3D=TRUE;
+					faded_offset=global_offset+1;
+					shadow_offset=global_offset+2;
+				}
+			}
+
+
+			if(state&ODS_CHECKED && nIconNormal<0){
+				if(state&ODS_SELECTED && m_selectcheck>0)checkflag=TRUE;
+				else if(m_unselectcheck>0) checkflag=TRUE;
+			}
+			else if(nIconNormal != -1){
+				standardflag=TRUE;
+				if(state&ODS_SELECTED && !(state&ODS_GRAYED))selectedflag=TRUE;
+				else if(state&ODS_GRAYED) disableflag=TRUE;
+			}
+		}
+		else{
+			strText.Empty();
+		}
+
+		if(state&ODS_SELECTED){ // draw the down edges
+
+			CPen *pOldPen = pDC->SelectObject (&m_penBack);
+
+			pDC->FillRect (rect,&m_brSelect);
+			pDC->Draw3dRect (rect,crSelect,crSelect);
+
+			pDC->SelectObject (pOldPen);
+		}
+		else {
+			rect2.SetRect(rect.left,rect.top,rect.left+barwidth,rect.bottom);
+			CPen *pOldPen = pDC->SelectObject (&m_penBack);
+			pDC->FillRect (rect,&m_brBackground);
+			pDC->FillRect (rect2,&m_newbrBackground);
+			pDC->SelectObject (pOldPen);
+
+			// draw the up edges
+
+			pDC->Draw3dRect (rect,m_clrBack,m_clrBack);
+			pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
+		}
+
+		// draw the text if there is any
+		//We have to paint the text only if the image is nonexistant
+
+		dy = (int)(0.5+(rect.Height()-m_iconY)/2.0);
+		dy = dy<0 ? 0 : dy;
+		dx = (int)(0.5+(barwidth-m_iconX)/2.0);
+		dx = dx<0 ? 0 : dx;
+
+		if(checkflag||standardflag||selectedflag||disableflag){
+			rect2.SetRect(rect.left+1,rect.top+1,rect.left+barwidth-1,
+				rect.bottom-1);
+			if(checkflag && checkmaps){
+				pDC->FillRect (rect2,&m_newbrBackground);
+				CPoint ptImage(rect.left+dx,rect.top+dy);		
+				if(state&ODS_SELECTED)checkmaps->Draw(pDC,1,ptImage,ILD_TRANSPARENT);
+				else checkmaps->Draw(pDC,0,ptImage,ILD_TRANSPARENT);
+			}
+			else if(disableflag){
+				if(!selectedflag){
+					CBitmap bitmapstandard;
+					GetBitmapFromImageList(pDC,bitmap,xoffset,bitmapstandard);
+					COLORREF transparentcol=m_newclrBack;
+					if(state&ODS_SELECTED)transparentcol=crSelectFill;
+					if(disable_old_style)
+						DitherBlt(lpDIS->hDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
+						(HBITMAP)(bitmapstandard),0,0,transparentcol);
+					else
+						DitherBlt2(pDC,rect.left+dx,rect.top+dy,m_iconX,m_iconY,
+						bitmapstandard,0,0,transparentcol);
+					if(state&ODS_SELECTED)pDC->Draw3dRect (rect,crSelect,crSelect);
+					bitmapstandard.DeleteObject();
+				}
+			}
+			else if(selectedflag){
+				pDC->FillRect (rect2,&m_brSelect);
+				CPoint ptImage(rect.left+dx,rect.top+dy);
+				if(state&ODS_CHECKED){
+					pDC->Draw3dRect(rect2,crSelect,crSelect);
+					ptImage.x-=1;ptImage.y-=1;
+				}
+				if(bitmap){
+					if(CanDraw3D&&!(state&ODS_CHECKED)){
+						CPoint ptImage1(ptImage.x+1,ptImage.y+1);
+						CPoint ptImage2(ptImage.x-1,ptImage.y-1);
+						bitmap->Draw(pDC,shadow_offset,ptImage1,ILD_TRANSPARENT);
+						bitmap->Draw(pDC,xoffset,ptImage2,ILD_TRANSPARENT);
+					}
+					else bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
+				}
+			}
+			else{
+				if(state&ODS_CHECKED){
+					CBrush brushin;
+					brushin.CreateSolidBrush(LightenColor(crSelect,0.85));
+					pDC->FillRect(rect2,&brushin);
+					brushin.DeleteObject();
+					pDC->Draw3dRect(rect2,crSelect,crSelect);
+					CPoint ptImage(rect.left+dx-1,rect.top+dy-1);
+					if(bitmap)bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
+				}
+				else{
+					pDC->FillRect (rect2,&m_newbrBackground);
+					pDC->Draw3dRect (rect2,m_newclrBack,m_newclrBack);
+					CPoint ptImage(rect.left+dx,rect.top+dy);
+					if(bitmap){
+						if(CanDraw3D)
+							bitmap->Draw(pDC,faded_offset,ptImage,ILD_TRANSPARENT);
+						else
+							bitmap->Draw(pDC,xoffset,ptImage,ILD_TRANSPARENT);
+					}
+				}
+			}
+		}
+		if(nIconNormal<0 && state&ODS_CHECKED && !checkflag){
+			dy = (int)(0.5+(rect.Height()-16)/2.0);
+			dy = dy<0 ? 0 : dy;
+			dx = (int)(0.5+(barwidth-16)/2.0);
+			dx = dx<0 ? 0 : dx;
+			CMenuItemInfo info;
+			info.fMask = MIIM_CHECKMARKS;
+			::GetMenuItemInfo((HMENU)lpDIS->hwndItem,lpDIS->itemID,
+				MF_BYCOMMAND, &info);
+			if(state&ODS_CHECKED || info.hbmpUnchecked) {
+				rect2.SetRect(rect.left+dx,rect.top+dy,rect.left+dx+16,rect.top+dy+16);
+				DrawXPCheckmark(pDC, rect2,state&ODS_CHECKED ? info.hbmpChecked :
+					info.hbmpUnchecked,crSelect);
+			}
+		}
+
+		//This is needed always so that we can have the space for check marks
+
+		x0=rect.left;y0=rect.top;
+		rect.left = rect.left + barwidth + 8; 
+
+		if(!strText.IsEmpty()){
+
+			CRect rectt(rect.left,rect.top-1,rect.right,rect.bottom-1);
+
+			//   Find tabs
+
+			CString leftStr,rightStr;
+			leftStr.Empty();rightStr.Empty();
+			int tablocr=strText.ReverseFind(_T('\t'));
+			if(tablocr!=-1){
+				rightStr=strText.Mid(tablocr+1);
+				leftStr=strText.Left(strText.Find(_T('\t')));
+				rectt.right-=m_iconX;
+			}
+			else leftStr=strText;
+
+			int iOldMode = pDC->GetBkMode();
+			pDC->SetBkMode( TRANSPARENT);
+
+			// Draw the text in the correct colour:
+
+			UINT nFormat  = DT_LEFT|DT_SINGLELINE|DT_VCENTER;
+			UINT nFormatr = DT_RIGHT|DT_SINGLELINE|DT_VCENTER;
+			if(!(lpDIS->itemState & ODS_GRAYED)){
+				pDC->SetTextColor(crText);
+				pDC->DrawText (leftStr,rectt,nFormat);
+				if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
+			}
+			else{
+				RECT offset = *rectt;
+				offset.left+=1;
+				offset.right+=1;
+				offset.top+=1;
+				offset.bottom+=1;
+				if(!IsWinXPLuna()){
+					COLORREF graycol=GetSysColor(COLOR_GRAYTEXT);
+					if(!(state&ODS_SELECTED))graycol = LightenColor(graycol,0.4);
+					pDC->SetTextColor(graycol);
+				}
+				else pDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
+				pDC->DrawText(leftStr,rectt, nFormat);
+				if(tablocr!=-1) pDC->DrawText (rightStr,rectt,nFormatr);
+			}
+			pDC->SetBkMode( iOldMode );
+		}
+
+		m_penBack.DeleteObject();
+		m_brSelect.DeleteObject();
+	}
+	m_brBackground.DeleteObject();
+	m_newbrBackground.DeleteObject();
+#ifdef BCMENU_USE_MEMDC
+	if(pFont)pDC->SelectObject (pFont); //set it to the old font
+	m_fontMenu.DeleteObject();
+	if(pMemDC)delete pMemDC;
+#endif
+}
+
+BOOL BCMenu::GetBitmapFromImageList(CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp)
+{
+	HICON hIcon = imglist->ExtractIcon(nIndex);
+	CDC dc;
+	dc.CreateCompatibleDC(pDC);
+	bmp.CreateCompatibleBitmap(pDC,m_iconX,m_iconY);
+	CBitmap* pOldBmp = dc.SelectObject(&bmp);
+	CBrush brush ;
+	COLORREF m_newclrBack;
+	m_newclrBack=GetSysColor(COLOR_3DFACE);
+	brush.CreateSolidBrush(m_newclrBack);
+	::DrawIconEx(
+		dc.GetSafeHdc(),
+		0,
+		0,
+		hIcon,
+		m_iconX,
+		m_iconY,
+		0,
+		(HBRUSH)brush,
+		DI_NORMAL
+		);
+	dc.SelectObject( pOldBmp );
+	dc.DeleteDC();
+	// the icon is not longer needed
+	::DestroyIcon(hIcon);
+	return(TRUE);
+}
+
+/*
+==========================================================================
+void BCMenu::MeasureItem(LPMEASUREITEMSTRUCT)
+---------------------------------------------
+
+Called by the framework when it wants to know what the width and height
+of our item will be.  To accomplish this we provide the width of the
+icon plus the width of the menu text, and then the height of the icon.
+
+==========================================================================
+*/
+
+void BCMenu::MeasureItem( LPMEASUREITEMSTRUCT lpMIS )
+{
+	UINT state = (((BCMenuData*)(lpMIS->itemData))->nFlags);
+	int BCMENU_PAD=4;
+	if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps)BCMENU_PAD=7;
+	if(state & MF_SEPARATOR){
+		lpMIS->itemWidth = 0;
+		int temp = GetSystemMetrics(SM_CYMENU)>>1;
+		lpMIS->itemHeight = temp>(m_iconY+BCMENU_PAD)/2 ? temp : (m_iconY+BCMENU_PAD)/2;
+	}
+	else{
+		CFont m_fontMenu;
+		LOGFONT m_lf;
+		ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
+		NONCLIENTMETRICS nm;
+		nm.cbSize = sizeof (NONCLIENTMETRICS);
+		VERIFY(SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
+			nm.cbSize,&nm,0)); 
+		m_lf =  nm.lfMenuFont;
+		m_fontMenu.CreateFontIndirect (&m_lf);
+
+		// Obtain the width of the text:
+		CWnd *pWnd = AfxGetMainWnd();            // Get main window
+		if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
+		CDC *pDC = pWnd->GetDC();              // Get device context
+		CFont* pFont=NULL;    // Select menu font in...
+
+		if (IsNewShell())
+			pFont = pDC->SelectObject (&m_fontMenu);// Select menu font in...
+
+		//Get pointer to text SK
+		const wchar_t *lpstrText = ((BCMenuData*)(lpMIS->itemData))->GetWideString();//SK: we use const to prevent misuse
+
+		SIZE size;
+		size.cx=size.cy=0;
+
+		if (Win32s!=g_Shell)
+			VERIFY(::GetTextExtentPoint32W(pDC->m_hDC,lpstrText,
+			wcslen(lpstrText),&size)); //SK should also work on 95
+#ifndef UNICODE //can't be UNICODE for Win32s
+		else{//it's Win32suckx
+			RECT rect;
+			rect.left=rect.top=0;
+			size.cy=DrawText(pDC->m_hDC,(LPCTSTR)lpstrText,
+				wcslen(lpstrText),&rect,
+				DT_SINGLELINE|DT_LEFT|DT_VCENTER|DT_CALCRECT);
+			//+3 makes at least three pixels space to the menu border
+			size.cx=rect.right-rect.left+3;
+			size.cx += 3*(size.cx/wcslen(lpstrText));
+		}
+#endif    
+
+		CSize t = CSize(size);
+		if(IsNewShell())
+			pDC->SelectObject (pFont);  // Select old font in
+		pWnd->ReleaseDC(pDC);  // Release the DC
+
+		// Set width and height:
+
+		if(IsLunaMenuStyle())lpMIS->itemWidth = m_iconX+BCMENU_PAD+8+t.cx;
+		else lpMIS->itemWidth = m_iconX + t.cx + m_iconX + BCMENU_GAP;
+		int temp = GetSystemMetrics(SM_CYMENU);
+		lpMIS->itemHeight = temp>m_iconY+BCMENU_PAD ? temp : m_iconY+BCMENU_PAD;
+		m_fontMenu.DeleteObject();
+	}
+}
+
+void BCMenu::SetIconSize (int width, int height)
+{
+	m_iconX = width;
+	m_iconY = height;
+}
+
+BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
+						   int nIconNormal)
+{
+	USES_CONVERSION;
+	return AppendODMenuW(A2W(lpstrText),nFlags,nID,nIconNormal);//SK: See MFC Tech Note 059
+}
+
+
+BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
+						   int nIconNormal)
+{
+	// Add the MF_OWNERDRAW flag if not specified:
+	if(!nID){
+		if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
+		else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
+	}
+	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
+
+	if(nFlags & MF_POPUP){
+		m_AllSubMenus.Add((HMENU)nID);
+		m_SubMenus.Add((HMENU)nID);
+	}
+
+	BCMenuData *mdata = new BCMenuData;
+	m_MenuList.Add(mdata);
+	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
+
+	mdata->menuIconNormal = -1;
+	mdata->xoffset = -1;
+
+	if(nIconNormal>=0){
+		CImageList bitmap;
+		int xoffset=0;
+		LoadFromToolBar(nID,nIconNormal,xoffset);
+		if(mdata->bitmap){
+			mdata->bitmap->DeleteImageList();
+			mdata->bitmap=NULL;
+		}
+		bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(AddBitmapToImageList(&bitmap,nIconNormal)){
+			mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
+		}
+	}
+	else mdata->global_offset = GlobalImageListOffset(nID);
+
+	mdata->nFlags = nFlags;
+	mdata->nID = nID;
+	BOOL returnflag=CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata);
+	if(m_loadmenu)RemoveTopLevelOwnerDraw();
+	return(returnflag);
+}
+
+BOOL BCMenu::AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,
+						   CImageList *il,int xoffset)
+{
+	USES_CONVERSION;
+	return AppendODMenuW(A2W(lpstrText),nFlags,nID,il,xoffset);
+}
+
+BOOL BCMenu::AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,
+						   CImageList *il,int xoffset)
+{
+	// Add the MF_OWNERDRAW flag if not specified:
+	if(!nID){
+		if(nFlags&MF_BYPOSITION)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
+		else nFlags=MF_SEPARATOR|MF_OWNERDRAW;
+	}
+	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
+
+	if(nFlags & MF_POPUP){
+		m_AllSubMenus.Add((HMENU)nID);
+		m_SubMenus.Add((HMENU)nID);
+	}
+
+	BCMenuData *mdata = new BCMenuData;
+	m_MenuList.Add(mdata);
+	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
+
+	if(il){
+		mdata->menuIconNormal = 0;
+		mdata->xoffset=0;
+		if(mdata->bitmap)mdata->bitmap->DeleteImageList();
+		else mdata->bitmap=new(CImageList);
+		ImageListDuplicate(il,xoffset,mdata->bitmap);
+	}
+	else{
+		mdata->menuIconNormal = -1;
+		mdata->xoffset = -1;
+	}
+	mdata->nFlags = nFlags;
+	mdata->nID = nID;
+	return(CMenu::AppendMenu(nFlags, nID, (LPCTSTR)mdata));
+}
+
+BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
+						   int nIconNormal)
+{
+	USES_CONVERSION;
+	return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,nIconNormal);
+}
+
+
+BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
+						   int nIconNormal)
+{
+	if(!(nFlags & MF_BYPOSITION)){
+		int iPosition =0;
+		BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
+		if(pMenu){
+			return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,nIconNormal));
+		}
+		else return(FALSE);
+	}
+
+	if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
+	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
+
+	int menustart=0;
+
+	if(nFlags & MF_POPUP){
+		if(m_loadmenu){
+			menustart=GetMenuStart();
+			if(nPosition<(UINT)menustart)menustart=0;
+		}
+		m_AllSubMenus.Add((HMENU)nID);
+		m_SubMenus.InsertAt(nPosition,(HMENU)nID);
+	}
+
+	//Stephane Clog suggested adding this, believe it or not it's in the help 
+	if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
+
+	BCMenuData *mdata = new BCMenuData;
+	m_MenuList.InsertAt(nPosition-menustart,mdata);
+	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
+
+	mdata->menuIconNormal = nIconNormal;
+	mdata->xoffset=-1;
+	if(nIconNormal>=0){
+		CImageList bitmap;
+		int xoffset=0;
+		LoadFromToolBar(nID,nIconNormal,xoffset);
+		if(mdata->bitmap){
+			mdata->bitmap->DeleteImageList();
+			mdata->bitmap=NULL;
+		}
+		bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(AddBitmapToImageList(&bitmap,nIconNormal)){
+			mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
+		}
+	}
+	else mdata->global_offset = GlobalImageListOffset(nID);
+	mdata->nFlags = nFlags;
+	mdata->nID = nID;
+	BOOL returnflag=CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata);
+	if(m_loadmenu)RemoveTopLevelOwnerDraw();
+	return(returnflag);
+}
+
+BOOL BCMenu::InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,
+						   CImageList *il,int xoffset)
+{
+	USES_CONVERSION;
+	return InsertODMenuW(nPosition,A2W(lpstrText),nFlags,nID,il,xoffset);
+}
+
+BOOL BCMenu::InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,
+						   CImageList *il,int xoffset)
+{
+	if(!(nFlags & MF_BYPOSITION)){
+		int iPosition =0;
+		BCMenu* pMenu = FindMenuOption(nPosition,iPosition);
+		if(pMenu){
+			return(pMenu->InsertODMenuW(iPosition,lpstrText,nFlags|MF_BYPOSITION,nID,il,xoffset));
+		}
+		else return(FALSE);
+	}
+
+	if(!nID)nFlags=MF_SEPARATOR|MF_OWNERDRAW|MF_BYPOSITION;
+	else if(!(nFlags & MF_OWNERDRAW))nFlags |= MF_OWNERDRAW;
+
+	if(nFlags & MF_POPUP){
+		m_AllSubMenus.Add((HMENU)nID);
+		m_SubMenus.InsertAt(nPosition,(HMENU)nID);
+	}
+
+	//Stephane Clog suggested adding this, believe it or not it's in the help 
+	if(nPosition==(UINT)-1)nPosition=GetMenuItemCount();
+
+	BCMenuData *mdata = new BCMenuData;
+	m_MenuList.InsertAt(nPosition,mdata);
+	mdata->SetWideString(lpstrText);    //SK: modified for dynamic allocation
+
+	mdata->menuIconNormal = -1;
+	mdata->xoffset = -1;
+
+	if(il){
+		if(mdata->bitmap){
+			mdata->bitmap->DeleteImageList();
+			mdata->bitmap=NULL;
+		}
+		mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
+	}
+	mdata->nFlags = nFlags;
+	mdata->nID = nID;
+	return(CMenu::InsertMenu(nPosition,nFlags,nID,(LPCTSTR)mdata));
+}
+
+BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,int nIconNormal)
+{
+	USES_CONVERSION;
+	return ModifyODMenuW(A2W(lpstrText),nID,nIconNormal);//SK: see MFC Tech Note 059
+}
+
+BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,int nIconNormal)
+{
+	int nLoc;
+	BCMenuData *mdata;
+	CArray<BCMenu*,BCMenu*>bcsubs;
+	CArray<int,int&>bclocs;
+
+	// Find the old BCMenuData structure:
+	BCMenu *psubmenu = FindMenuOption(nID,nLoc);
+	do{
+		if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
+		else{
+			// Create a new BCMenuData structure:
+			mdata = new BCMenuData;
+			m_MenuList.Add(mdata);
+		}
+
+		ASSERT(mdata);
+		if(lpstrText)
+			mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
+		mdata->menuIconNormal = -1;
+		mdata->xoffset = -1;
+		if(nIconNormal>=0){
+			CImageList bitmap;
+			int xoffset=0;
+			LoadFromToolBar(nID,nIconNormal,xoffset);
+			if(mdata->bitmap){
+				mdata->bitmap->DeleteImageList();
+				mdata->bitmap=NULL;
+			}
+			bitmap.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+			if(AddBitmapToImageList(&bitmap,nIconNormal)){
+				mdata->global_offset = AddToGlobalImageList(&bitmap,xoffset,nID);
+			}
+		}
+		else mdata->global_offset = GlobalImageListOffset(nID);
+		mdata->nFlags &= ~(MF_BYPOSITION);
+		mdata->nFlags |= MF_OWNERDRAW;
+		mdata->nID = nID;
+		bcsubs.Add(psubmenu);
+		bclocs.Add(nLoc);
+		if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
+		else psubmenu=NULL;
+	}while(psubmenu);
+	return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
+}
+
+BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CImageList *il,int xoffset)
+{
+	USES_CONVERSION;
+	return ModifyODMenuW(A2W(lpstrText),nID,il,xoffset);
+}
+
+BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset)
+{
+	int nLoc;
+	BCMenuData *mdata;
+	CArray<BCMenu*,BCMenu*>bcsubs;
+	CArray<int,int&>bclocs;
+
+	// Find the old BCMenuData structure:
+	BCMenu *psubmenu = FindMenuOption(nID,nLoc);
+	do{
+		if(psubmenu && nLoc>=0)mdata = psubmenu->m_MenuList[nLoc];
+		else{
+			// Create a new BCMenuData structure:
+			mdata = new BCMenuData;
+			m_MenuList.Add(mdata);
+		}
+
+		ASSERT(mdata);
+		if(lpstrText)
+			mdata->SetWideString(lpstrText);  //SK: modified for dynamic allocation
+		mdata->menuIconNormal = -1;
+		mdata->xoffset = -1;
+		if(il){
+			if(mdata->bitmap){
+				mdata->bitmap->DeleteImageList();
+				mdata->bitmap=NULL;
+			}
+			mdata->global_offset = AddToGlobalImageList(il,xoffset,nID);
+		}
+		mdata->nFlags &= ~(MF_BYPOSITION);
+		mdata->nFlags |= MF_OWNERDRAW;
+		mdata->nID = nID;
+		bcsubs.Add(psubmenu);
+		bclocs.Add(nLoc);
+		if(psubmenu && nLoc>=0)psubmenu = FindAnotherMenuOption(nID,nLoc,bcsubs,bclocs);
+		else psubmenu=NULL;
+	}while(psubmenu);
+	return (CMenu::ModifyMenu(nID,mdata->nFlags,nID,(LPCTSTR)mdata));
+}
+
+BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,CBitmap *bmp)
+{
+	USES_CONVERSION;
+	return ModifyODMenuW(A2W(lpstrText),nID,bmp);
+}
+
+BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp)
+{
+	if(bmp){
+		CImageList temp;
+		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
+		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
+		return ModifyODMenuW(lpstrText,nID,&temp,0);
+	}
+	return ModifyODMenuW(lpstrText,nID,NULL,0);
+}
+
+// courtesy of Warren Stevens
+BOOL BCMenu::ModifyODMenuA(const char * lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
+{
+	USES_CONVERSION;
+	return ModifyODMenuW(A2W(lpstrText),nID,fill,border,hatchstyle,pSize);
+}
+
+BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle,CSize *pSize)
+{
+	CWnd *pWnd = AfxGetMainWnd();            // Get main window
+	CDC *pDC = pWnd->GetDC();              // Get device context
+	SIZE sz;
+	if(!pSize){
+		sz.cx = m_iconX;
+		sz.cy = m_iconY;
+	}
+	else{
+		sz.cx = pSize->cx;
+		sz.cy = pSize->cy;
+	}
+	CSize bitmap_size(sz);
+	CSize icon_size(m_iconX,m_iconY);
+	CBitmap bmp;
+	ColorBitmap(pDC,bmp,bitmap_size,icon_size,fill,border,hatchstyle);		
+	pWnd->ReleaseDC(pDC);
+	return ModifyODMenuW(lpstrText,nID,&bmp);
+}
+
+
+BOOL BCMenu::ModifyODMenuA(const char *lpstrText,const char *OptionText,int nIconNormal)
+{
+	USES_CONVERSION;
+	return ModifyODMenuW(A2W(lpstrText),A2W(OptionText),nIconNormal);//SK: see MFC  Tech Note 059
+}
+
+BOOL BCMenu::ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,int nIconNormal)
+{
+	BCMenuData *mdata;
+
+	// Find the old BCMenuData structure:
+	CStringW junk=OptionText;
+	mdata=FindMenuOption(OptionText);
+	if(mdata){
+		if(lpstrText)
+			mdata->SetWideString(lpstrText);//SK: modified for dynamic allocation
+		mdata->menuIconNormal = nIconNormal;
+		mdata->xoffset=-1;
+		if(nIconNormal>=0){
+			mdata->xoffset=0;
+			if(mdata->bitmap)mdata->bitmap->DeleteImageList();
+			else mdata->bitmap=new(CImageList);
+			mdata->bitmap->Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+			if(!AddBitmapToImageList(mdata->bitmap,nIconNormal)){
+				mdata->bitmap->DeleteImageList();
+				delete mdata->bitmap;
+				mdata->bitmap=NULL;
+				mdata->menuIconNormal = nIconNormal = -1;
+				mdata->xoffset = -1;
+			}
+		}
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+BCMenuData *BCMenu::NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string)
+{
+	BCMenuData *mdata;
+
+	mdata = new BCMenuData;
+	mdata->menuIconNormal = -1;
+	mdata->xoffset=-1;
+#ifdef UNICODE
+	mdata->SetWideString((LPCTSTR)string);//SK: modified for dynamic allocation
+#else
+	mdata->SetAnsiString(string);
+#endif
+	mdata->nFlags = nFlags;
+	mdata->nID = nID;
+
+	//	if(nFlags & MF_POPUP)m_AllSubMenus.Add((HMENU)nID);
+
+	if (nFlags&MF_OWNERDRAW){
+		ASSERT(!(nFlags&MF_STRING));
+		ModifyMenu(pos,nFlags,nID,(LPCTSTR)mdata);
+	}
+	else if (nFlags&MF_STRING){
+		ASSERT(!(nFlags&MF_OWNERDRAW));
+		ModifyMenu(pos,nFlags,nID,mdata->GetString());
+	}
+	else{
+		ASSERT(nFlags&MF_SEPARATOR);
+		ModifyMenu(pos,nFlags,nID);
+	}
+
+	return(mdata);
+};
+
+BOOL BCMenu::LoadToolbars(const UINT *arID,int n)
+{
+	ASSERT(arID);
+	BOOL returnflag=TRUE;
+	for(int i=0;i<n;++i){
+		if(!LoadToolbar(arID[i]))returnflag=FALSE;
+	}
+	return(returnflag);
+}
+
+BOOL BCMenu::LoadToolbar(UINT nToolBar)
+{
+	UINT nID,nStyle;
+	BOOL returnflag=FALSE;
+	BCMenuToolBar bar;
+	int xoffset=-1,xset;
+	int iconx,icony;
+
+	CWnd* pWnd = AfxGetMainWnd();
+	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
+	bar.Create(pWnd);
+	if(bar.LoadToolBar(nToolBar)){
+		bar.GetIconSize(iconx,icony);
+		if(iconx>m_iconX)m_iconX=iconx;
+		if(icony>m_iconY)m_iconY=icony;
+		CImageList imglist;
+		imglist.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(AddBitmapToImageList(&imglist,nToolBar)){
+			returnflag=TRUE;
+			for(int i=0;i<bar.GetCount();++i){
+				nID = bar.GetItemID(i); 
+				if(nID && GetMenuState(nID, MF_BYCOMMAND)
+					!=0xFFFFFFFF){
+						xoffset=bar.CommandToIndex(nID);
+						if(xoffset>=0){
+							bar.GetButtonInfo(xoffset,nID,nStyle,xset);
+							if(xset>0)xoffset=xset;
+						}
+						ModifyODMenu(NULL,nID,&imglist,xoffset);
+				}
+			}
+		}
+	}
+	return(returnflag);
+}
+
+BOOL BCMenu::LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset)
+{
+	int xset,offset;
+	UINT nStyle;
+	BOOL returnflag=FALSE;
+	CToolBar bar;
+
+	CWnd* pWnd = AfxGetMainWnd();
+	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
+	bar.Create(pWnd);
+	if(bar.LoadToolBar(nToolBar)){
+		offset=bar.CommandToIndex(nID);
+		if(offset>=0){
+			bar.GetButtonInfo(offset,nID,nStyle,xset);
+			if(xset>0)xoffset=xset;
+			returnflag=TRUE;
+		}
+	}
+	return(returnflag);
+}
+
+// O.S.
+BCMenuData *BCMenu::FindMenuItem(UINT nID)
+{
+	BCMenuData *pData = NULL;
+	int i;
+
+	for(i = 0; i <= m_MenuList.GetUpperBound(); i++){
+		if (m_MenuList[i]->nID == nID){
+			pData = m_MenuList[i];
+			break;
+		}
+	}
+	if (!pData){
+		int loc;
+		BCMenu *pMenu = FindMenuOption(nID, loc);
+		ASSERT(pMenu != this);
+		if (loc >= 0){
+			return pMenu->FindMenuItem(nID);
+		}
+	}
+	return pData;
+}
+
+
+BCMenu *BCMenu::FindAnotherMenuOption(int nId,int& nLoc,CArray<BCMenu*,BCMenu*>&bcsubs,
+									  CArray<int,int&>&bclocs)
+{
+	int i,numsubs,j;
+	BCMenu *psubmenu,*pgoodmenu;
+	BOOL foundflag;
+
+	for(i=0;i<(int)(GetMenuItemCount());++i){
+#ifdef _CPPRTTI 
+		psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
+#else
+		psubmenu=(BCMenu *)GetSubMenu(i);
+#endif
+		if(psubmenu){
+			pgoodmenu=psubmenu->FindAnotherMenuOption(nId,nLoc,bcsubs,bclocs);
+			if(pgoodmenu)return(pgoodmenu);
+		}
+		else if(nId==(int)GetMenuItemID(i)){
+			numsubs=bcsubs.GetSize();
+			foundflag=TRUE;
+			for(j=0;j<numsubs;++j){
+				if(bcsubs[j]==this&&bclocs[j]==i){
+					foundflag=FALSE;
+					break;
+				}
+			}
+			if(foundflag){
+				nLoc=i;
+				return(this);
+			}
+		}
+	}
+	nLoc = -1;
+	return(NULL);
+}
+
+BCMenu *BCMenu::FindMenuOption(int nId,int& nLoc)
+{
+	int i;
+	BCMenu *psubmenu,*pgoodmenu;
+
+	for(i=0;i<(int)(GetMenuItemCount());++i){
+#ifdef _CPPRTTI 
+		psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
+#else
+		psubmenu=(BCMenu *)GetSubMenu(i);
+#endif
+		if(psubmenu){
+			pgoodmenu=psubmenu->FindMenuOption(nId,nLoc);
+			if(pgoodmenu)return(pgoodmenu);
+		}
+		else if(nId==(int)GetMenuItemID(i)){
+			nLoc=i;
+			return(this);
+		}
+	}
+	nLoc = -1;
+	return(NULL);
+}
+
+BCMenuData *BCMenu::FindMenuOption(wchar_t *lpstrText)
+{
+	int i,j;
+	BCMenu *psubmenu;
+	BCMenuData *pmenulist;
+
+	for(i=0;i<(int)(GetMenuItemCount());++i){
+#ifdef _CPPRTTI 
+		psubmenu=dynamic_cast<BCMenu *>(GetSubMenu(i));
+#else
+		psubmenu=(BCMenu *)GetSubMenu(i);
+#endif
+		if(psubmenu){
+			pmenulist=psubmenu->FindMenuOption(lpstrText);
+			if(pmenulist)return(pmenulist);
+		}
+		else{
+			const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
+			for(j=0;j<=m_MenuList.GetUpperBound();++j){     
+				szWide = m_MenuList[j]->GetWideString ();
+				if(szWide && !wcscmp(lpstrText,szWide))//SK: modified for dynamic allocation
+					return(m_MenuList[j]);
+			}
+		}
+	}
+	return(NULL);
+}
+
+
+BOOL BCMenu::LoadMenu(int nResource)
+{
+	return(BCMenu::LoadMenu(MAKEINTRESOURCE(nResource)));
+};
+
+BOOL BCMenu::LoadMenu(LPCTSTR lpszResourceName)
+{
+	ASSERT_VALID(this);
+	ASSERT(lpszResourceName != NULL);
+
+	// Find the Menu Resource:
+	HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName,RT_MENU);
+	HRSRC hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
+	if (hRsrc == NULL){
+		hInst = NULL;
+		hRsrc = ::FindResource(hInst,lpszResourceName,RT_MENU);
+	}
+	if(hRsrc == NULL)return FALSE;
+
+	// Load the Menu Resource:
+
+	HGLOBAL hGlobal = LoadResource(hInst, hRsrc);
+	if(hGlobal == NULL)return FALSE;
+
+	// first destroy the menu if we're trying to loadmenu again
+	DestroyMenu();
+
+	// Attempt to create us as a menu...
+	if(!CMenu::CreateMenu())return FALSE;
+
+	// Get Item template Header, and calculate offset of MENUITEMTEMPLATES
+
+	MENUITEMTEMPLATEHEADER *pTpHdr=
+		(MENUITEMTEMPLATEHEADER*)LockResource(hGlobal);
+	BYTE* pTp=(BYTE*)pTpHdr + 
+		(sizeof(MENUITEMTEMPLATEHEADER) + pTpHdr->offset);
+
+
+	// Variables needed during processing of Menu Item Templates:
+
+	int j=0;
+	WORD    dwFlags = 0;              // Flags of the Menu Item
+	WORD    dwID  = 0;              // ID of the Menu Item
+	UINT    uFlags;                  // Actual Flags.
+	wchar_t *szCaption=NULL;
+	int      nLen   = 0;                // Length of caption
+	CTypedPtrArray<CPtrArray, BCMenu*>  m_Stack;    // Popup menu stack
+	CArray<BOOL,BOOL>  m_StackEnd;    // Popup menu stack
+	m_Stack.Add(this);                  // Add it to this...
+	m_StackEnd.Add(FALSE);
+
+	do{
+		// Obtain Flags and (if necessary), the ID...
+		memcpy(&dwFlags, pTp, sizeof(WORD));pTp+=sizeof(WORD);// Obtain Flags
+		if(!(dwFlags & MF_POPUP)){
+			memcpy(&dwID, pTp, sizeof(WORD)); // Obtain ID
+			pTp+=sizeof(WORD);
+		}
+		else dwID = 0;
+
+		uFlags = (UINT)dwFlags; // Remove MF_END from the flags that will
+		if(uFlags & MF_END) // be passed to the Append(OD)Menu functions.
+			uFlags -= MF_END;
+
+		// Obtain Caption (and length)
+
+		nLen = 0;
+		szCaption=new wchar_t[wcslen((wchar_t *)pTp)+1];
+		wcscpy_s(szCaption, wcslen((wchar_t*)pTp) + 1, (wchar_t *)pTp);
+		pTp=&pTp[(wcslen((wchar_t *)pTp)+1)*sizeof(wchar_t)];//modified SK
+
+		// Handle popup menus first....
+
+		//WideCharToMultiByte
+		if(dwFlags & MF_POPUP){
+			if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
+			BCMenu* pSubMenu = new BCMenu;
+			pSubMenu->m_unselectcheck=m_unselectcheck;
+			pSubMenu->m_selectcheck=m_selectcheck;
+			pSubMenu->checkmaps=checkmaps;
+			pSubMenu->checkmapsshare=TRUE;
+			pSubMenu->CreatePopupMenu();
+
+			// Append it to the top of the stack:
+
+			m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption,uFlags,
+				(UINT)pSubMenu->m_hMenu, -1);
+			m_Stack.Add(pSubMenu);
+			m_StackEnd.Add(FALSE);
+		}
+		else {
+			m_Stack[m_Stack.GetUpperBound()]->AppendODMenuW(szCaption, uFlags,
+				dwID, -1);
+			if(dwFlags & MF_END)m_StackEnd.SetAt(m_Stack.GetUpperBound(),TRUE);
+			j = m_Stack.GetUpperBound();
+			while(j>=0 && m_StackEnd.GetAt(j)){
+				m_Stack[m_Stack.GetUpperBound()]->InsertSpaces();
+				m_Stack.RemoveAt(j);
+				m_StackEnd.RemoveAt(j);
+				--j;
+			}
+		}
+
+		delete[] szCaption;
+	}while(m_Stack.GetUpperBound() != -1);
+
+	for(int i=0;i<(int)GetMenuItemCount();++i){
+		CString str=m_MenuList[i]->GetString();
+		if(GetSubMenu(i)){
+			m_MenuList[i]->nFlags=MF_POPUP|MF_BYPOSITION;
+			ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
+				(UINT)GetSubMenu(i)->m_hMenu,str);
+		}
+		else{
+			m_MenuList[i]->nFlags=MF_STRING|MF_BYPOSITION;
+			ModifyMenu(i,MF_STRING|MF_BYPOSITION,m_MenuList[i]->nID,str);
+		}
+	}
+
+	m_loadmenu=TRUE;
+
+	return(TRUE);
+}
+
+int BCMenu::GetMenuStart(void)
+{
+	if(!m_loadmenu)return(0);
+
+	CString name,str;
+	int menuloc=-1,listloc=-1,menustart=0,i=0,j=0;
+	int nummenulist=m_MenuList.GetSize();
+	int nummenu=(int)GetMenuItemCount();
+
+	while(i<nummenu&&menuloc==-1){
+		GetMenuString (i, name, MF_BYPOSITION);
+		if(name.GetLength()>0){
+			for(j=0;j<nummenulist;++j){
+				str=m_MenuList[j]->GetString();
+				if(name==str){
+					menuloc=i;
+					listloc=j;
+					break;
+				}
+			}
+		}
+		++i;
+	}
+	if(menuloc>=0&&listloc>=0&&menuloc>=listloc)menustart=menuloc-listloc;
+	return(menustart);
+}
+
+void BCMenu::RemoveTopLevelOwnerDraw(void)
+{
+	CString str;
+	int i=0,j=0;
+	int nummenulist=m_MenuList.GetSize(),menustart;
+
+	menustart=GetMenuStart();
+	for(i=menustart,j=0;i<(int)GetMenuItemCount();++i,++j){
+		if(j<nummenulist){
+			str=m_MenuList[j]->GetString();
+			if(GetSubMenu(i)){
+				m_MenuList[j]->nFlags=MF_POPUP|MF_BYPOSITION;
+				ModifyMenu(i,MF_POPUP|MF_BYPOSITION,
+					(UINT)GetSubMenu(i)->m_hMenu,str);
+			}
+		}
+	}
+
+}
+
+void BCMenu::InsertSpaces(void)
+{
+	int i,j,numitems,maxlength;
+	CString string,newstring;
+	CSize t;
+	CFont m_fontMenu;
+	LOGFONT m_lf;
+
+	ZeroMemory ((PVOID) &m_lf,sizeof (LOGFONT));
+	NONCLIENTMETRICS nm;
+	nm.cbSize = sizeof (NONCLIENTMETRICS);
+	VERIFY (SystemParametersInfo (SPI_GETNONCLIENTMETRICS,nm.cbSize,&nm,0)); 
+	m_lf =  nm.lfMenuFont;
+	m_fontMenu.CreateFontIndirect (&m_lf);
+
+	CWnd *pWnd = AfxGetMainWnd();  
+	if (pWnd == NULL)pWnd = CWnd::GetDesktopWindow();
+	CDC *pDC = pWnd->GetDC();
+	CFont* pFont = pDC->SelectObject (&m_fontMenu);
+
+	numitems=GetMenuItemCount();
+	maxlength = -1;
+	for(i=0;i<numitems;++i){
+		string=m_MenuList[i]->GetString();
+		j=string.Find((char)9);
+		newstring.Empty();
+		if(j!=-1)newstring=string.Left(j);
+		else newstring=string;
+		newstring+=_T(" ");//SK: modified for Unicode correctness. 
+		LPCTSTR lpstrText = (LPCTSTR)newstring;
+		t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
+		if(t.cx>maxlength)maxlength = t.cx;
+	}
+	for(i=0;i<numitems;++i){
+		string=m_MenuList[i]->GetString();
+		j=string.Find((char)9);
+		if(j!=-1){
+			newstring.Empty();
+			newstring=string.Left(j);
+			LPCTSTR lpstrText = (LPCTSTR)(newstring);
+			t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
+			while(t.cx<maxlength){
+				newstring+=_T(' ');//SK: modified for Unicode correctness
+				LPCTSTR lpstrText = (LPCTSTR)(newstring);
+				t=pDC->GetTextExtent(lpstrText,_tcslen(lpstrText));
+			}
+			newstring+=string.Mid(j);
+#ifdef UNICODE      
+			m_MenuList[i]->SetWideString(newstring);//SK: modified for dynamic allocation
+#else
+			m_MenuList[i]->SetAnsiString(newstring);
+#endif
+		}
+	}
+	pDC->SelectObject (pFont);              // Select old font in
+	pWnd->ReleaseDC(pDC);       // Release the DC
+	m_fontMenu.DeleteObject();
+}
+
+void BCMenu::LoadCheckmarkBitmap(int unselect, int select)
+{
+	if(unselect>0 && select>0){
+		m_selectcheck=select;
+		m_unselectcheck=unselect;
+		if(checkmaps)checkmaps->DeleteImageList();
+		else checkmaps=new(CImageList);
+		checkmaps->Create(m_iconX,m_iconY,ILC_MASK,2,1);
+		BOOL flag1=AddBitmapToImageList(checkmaps,unselect);
+		BOOL flag2=AddBitmapToImageList(checkmaps,select);
+		if(!flag1||!flag2){
+			checkmaps->DeleteImageList();
+			delete checkmaps;
+			checkmaps=NULL;
+		}
+	}
+}
+
+//--------------------------------------------------------------------------
+//[18.06.99 rj]
+BOOL BCMenu::GetMenuText(UINT id, CString& string, UINT nFlags/*= MF_BYPOSITION*/)
+{
+	BOOL returnflag=FALSE;
+
+	if(MF_BYPOSITION&nFlags){
+		UINT numMenuItems = m_MenuList.GetUpperBound();
+		if(id<=numMenuItems){
+			string=m_MenuList[id]->GetString();
+			returnflag=TRUE;
+		}
+	}
+	else{
+		int uiLoc;
+		BCMenu* pMenu = FindMenuOption(id,uiLoc);
+		if(NULL!=pMenu) returnflag = pMenu->GetMenuText(uiLoc,string);
+	}
+	return(returnflag);
+}
+
+
+void BCMenu::DrawRadioDot(CDC *pDC,int x,int y,COLORREF color)
+{
+	CRect rcDot(x,y,x+6,y+6);
+	CBrush brush;
+	CPen pen;
+	brush.CreateSolidBrush(color);
+	pen.CreatePen(PS_SOLID,0,color);
+	CBrush *pOldBrush=pDC->SelectObject(&brush);
+	CPen *pOldPen=pDC->SelectObject(&pen);
+	pDC->Ellipse(&rcDot);
+	pDC->SelectObject(pOldBrush);
+	pDC->SelectObject(pOldPen);
+	pen.DeleteObject();
+	brush.DeleteObject();
+}
+
+void BCMenu::DrawCheckMark(CDC* pDC,int x,int y,COLORREF color)
+{
+	CPen m_penBack;
+	m_penBack.CreatePen (PS_SOLID,0,color);
+	CPen *pOldPen = pDC->SelectObject (&m_penBack);
+	pDC->MoveTo(x,y+2);
+	pDC->LineTo(x,y+5);
+
+	pDC->MoveTo(x+1,y+3);
+	pDC->LineTo(x+1,y+6);
+
+	pDC->MoveTo(x+2,y+4);
+	pDC->LineTo(x+2,y+7);
+
+	pDC->MoveTo(x+3,y+3);
+	pDC->LineTo(x+3,y+6);
+
+	pDC->MoveTo(x+4,y+2);
+	pDC->LineTo(x+4,y+5);
+
+	pDC->MoveTo(x+5,y+1);
+	pDC->LineTo(x+5,y+4);
+
+	pDC->MoveTo(x+6,y);
+	pDC->LineTo(x+6,y+3);
+
+	pDC->SelectObject (pOldPen);
+	m_penBack.DeleteObject();
+}
+
+BCMenuData *BCMenu::FindMenuList(UINT nID)
+{
+	for(int i=0;i<=m_MenuList.GetUpperBound();++i){
+		if(m_MenuList[i]->nID==nID && !m_MenuList[i]->syncflag){
+			m_MenuList[i]->syncflag=1;
+			return(m_MenuList[i]);
+		}
+	}
+	return(NULL);
+}
+
+void BCMenu::InitializeMenuList(int value)
+{
+	for(int i=0;i<=m_MenuList.GetUpperBound();++i)
+		m_MenuList[i]->syncflag=value;
+}
+
+void BCMenu::DeleteMenuList(void)
+{
+	for(int i=0;i<=m_MenuList.GetUpperBound();++i){
+		if(!m_MenuList[i]->syncflag){
+			delete m_MenuList[i];
+		}
+	}
+}
+
+void BCMenu::SynchronizeMenu(void)
+{
+	CTypedPtrArray<CPtrArray, BCMenuData*> temp;
+	BCMenuData *mdata;
+	CString string;
+	UINT submenu,nID=0,state,j;
+
+	InitializeMenuList(0);
+	for(j=0;j<GetMenuItemCount();++j){
+		mdata=NULL;
+		state=GetMenuState(j,MF_BYPOSITION);
+		if(state&MF_POPUP){
+			submenu=(UINT)GetSubMenu(j)->m_hMenu;
+			mdata=FindMenuList(submenu);
+			GetMenuString(j,string,MF_BYPOSITION);
+			if(!mdata)mdata=NewODMenu(j,
+				(state&0xFF)|MF_BYPOSITION|MF_POPUP|MF_OWNERDRAW,submenu,string);
+			else if(string.GetLength()>0)
+#ifdef UNICODE
+				mdata->SetWideString(string);  //SK: modified for dynamic allocation
+#else
+				mdata->SetAnsiString(string);
+#endif
+		}
+		else if(state&MF_SEPARATOR){
+			mdata=FindMenuList(0);
+			if(!mdata)mdata=NewODMenu(j,
+				state|MF_BYPOSITION|MF_SEPARATOR|MF_OWNERDRAW,0,_T(""));//SK: modified for Unicode correctness
+			else ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
+		}
+		else{
+			nID=GetMenuItemID(j);
+			mdata=FindMenuList(nID);
+			GetMenuString(j,string,MF_BYPOSITION);
+			if(!mdata)mdata=NewODMenu(j,state|MF_BYPOSITION|MF_OWNERDRAW,
+				nID,string);
+			else{
+				mdata->nFlags=state|MF_BYPOSITION|MF_OWNERDRAW;
+				if(string.GetLength()>0)
+#ifdef UNICODE
+					mdata->SetWideString(string);//SK: modified for dynamic allocation
+#else
+					mdata->SetAnsiString(string);
+#endif
+
+				ModifyMenu(j,mdata->nFlags,nID,(LPCTSTR)mdata);
+			}
+		}
+		if(mdata)temp.Add(mdata);
+	}
+	DeleteMenuList();
+	m_MenuList.RemoveAll();
+	m_MenuList.Append(temp);
+	temp.RemoveAll(); 
+}
+
+void BCMenu::UpdateMenu(CMenu *pmenu)
+{
+#ifdef _CPPRTTI 
+	BCMenu *psubmenu = dynamic_cast<BCMenu *>(pmenu);
+#else
+	BCMenu *psubmenu = (BCMenu *)pmenu;
+#endif
+	if(psubmenu)psubmenu->SynchronizeMenu();
+}
+
+LRESULT BCMenu::FindKeyboardShortcut(UINT nChar, UINT nFlags,
+									 CMenu *pMenu)
+{
+#ifdef _CPPRTTI 
+	BCMenu *pBCMenu = dynamic_cast<BCMenu *>(pMenu);
+#else
+	BCMenu *pBCMenu = (BCMenu *)pMenu;
+#endif
+	if(pBCMenu && nFlags&MF_POPUP){
+		CString key(_T('&'),2);//SK: modified for Unicode correctness
+		key.SetAt(1,(TCHAR)nChar);
+		key.MakeLower();
+		CString menutext;
+		int menusize = (int)pBCMenu->GetMenuItemCount();
+		if(menusize!=(pBCMenu->m_MenuList.GetUpperBound()+1))
+			pBCMenu->SynchronizeMenu();
+		for(int i=0;i<menusize;++i){
+			if(pBCMenu->GetMenuText(i,menutext)){
+				menutext.MakeLower();
+				if(menutext.Find(key)>=0)return(MAKELRESULT(i,2));
+			}
+		}
+	}
+	return(0);
+}
+
+void BCMenu::DitherBlt (HDC hdcDest, int nXDest, int nYDest, int nWidth, 
+						int nHeight, HBITMAP hbm, int nXSrc, int nYSrc,
+						COLORREF bgcolor)
+{
+	ASSERT(hdcDest && hbm);
+	ASSERT(nWidth > 0 && nHeight > 0);
+
+	// Create a generic DC for all BitBlts
+	HDC hDC = CreateCompatibleDC(hdcDest);
+	ASSERT(hDC);
+
+	if (hDC)
+	{
+		// Create a DC for the monochrome DIB section
+		HDC bwDC = CreateCompatibleDC(hDC);
+		ASSERT(bwDC);
+
+		if (bwDC)
+		{
+			// Create the monochrome DIB section with a black and white palette
+			struct {
+				BITMAPINFOHEADER bmiHeader; 
+				RGBQUAD      bmiColors[2]; 
+			} RGBBWBITMAPINFO = {
+
+				{    // a BITMAPINFOHEADER
+					sizeof(BITMAPINFOHEADER),  // biSize 
+						nWidth,         // biWidth; 
+						nHeight,        // biHeight; 
+						1,            // biPlanes; 
+						1,            // biBitCount 
+						BI_RGB,         // biCompression; 
+						0,            // biSizeImage; 
+						0,            // biXPelsPerMeter; 
+						0,            // biYPelsPerMeter; 
+						0,            // biClrUsed; 
+						0            // biClrImportant; 
+				},    
+				{
+					{ 0x00, 0x00, 0x00, 0x00 }, { 0xFF, 0xFF, 0xFF, 0x00 }
+					} 
+			};
+			VOID *pbitsBW;
+			HBITMAP hbmBW = CreateDIBSection(bwDC,
+				(LPBITMAPINFO)&RGBBWBITMAPINFO, DIB_RGB_COLORS, &pbitsBW, NULL, 0);
+			ASSERT(hbmBW);
+
+			if (hbmBW)
+			{
+				// Attach the monochrome DIB section and the bitmap to the DCs
+				HBITMAP olddib = (HBITMAP)SelectObject(bwDC, hbmBW);
+				HBITMAP hdcolddib = (HBITMAP)SelectObject(hDC, hbm);
+
+				// BitBlt the bitmap into the monochrome DIB section
+				BitBlt(bwDC, 0, 0, nWidth, nHeight, hDC, nXSrc, nYSrc, SRCCOPY);
+
+				// Paint the destination rectangle in gray
+				FillRect(hdcDest, CRect(nXDest, nYDest, nXDest + nWidth, nYDest +
+					nHeight), GetSysColorBrush(bgcolor));
+				//SK: looks better on the old shell
+				// BitBlt the black bits in the monochrome bitmap into COLOR_3DHILIGHT
+				// bits in the destination DC
+				// The magic ROP comes from the Charles Petzold's book
+				HBRUSH hb = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
+				HBRUSH oldBrush = (HBRUSH)SelectObject(hdcDest, hb);
+				BitBlt(hdcDest,nXDest+1,nYDest+1,nWidth,nHeight,bwDC,0,0,0xB8074A);
+
+				// BitBlt the black bits in the monochrome bitmap into COLOR_3DSHADOW
+				// bits in the destination DC
+				hb = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
+				DeleteObject(SelectObject(hdcDest, hb));
+				BitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight,bwDC,0,0,0xB8074A);
+				DeleteObject(SelectObject(hdcDest, oldBrush));
+				VERIFY(DeleteObject(SelectObject(bwDC, olddib)));
+				SelectObject(hDC, hdcolddib);
+			}
+
+			VERIFY(DeleteDC(bwDC));
+		}
+
+		VERIFY(DeleteDC(hDC));
+	}
+}
+
+void BCMenu::GetFadedBitmap(CBitmap &bmp)
+{
+	CDC ddc;
+	COLORREF bgcol,col;
+	BITMAP BitMap;
+
+	bmp.GetBitmap(&BitMap);
+	ddc.CreateCompatibleDC(NULL);
+	CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
+
+	// use this to get the background color, takes into account color shifting
+	CDC ddc2;
+	CBrush brush;
+	CBitmap bmp2;
+	ddc2.CreateCompatibleDC(NULL);
+	bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
+	col=GetSysColor(COLOR_3DFACE);
+	brush.CreateSolidBrush(col);
+	CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
+	CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
+	ddc2.FillRect(rect,&brush);
+	bgcol=ddc2.GetPixel(1,1);
+	brush.DeleteObject();
+	ddc2.SelectObject(pddcOldBmp2);
+
+	for(int i=0;i<BitMap.bmWidth;++i){
+		for(int j=0;j<BitMap.bmHeight;++j){
+			col=ddc.GetPixel(i,j);
+			if(col!=bgcol)ddc.SetPixel(i,j,LightenColor(col,0.3));
+		}
+	}
+	ddc.SelectObject(pddcOldBmp);
+}
+
+void BCMenu::GetShadowBitmap(CBitmap &bmp)
+{
+	CDC ddc;
+	COLORREF bgcol,col,shadowcol=GetSysColor(COLOR_BTNSHADOW);
+	BITMAP BitMap;
+
+	if(!IsWinXPLuna())shadowcol=LightenColor(shadowcol,0.49);
+	bmp.GetBitmap(&BitMap);
+	ddc.CreateCompatibleDC(NULL);
+	CBitmap * pddcOldBmp = ddc.SelectObject(&bmp);
+
+	// use this to get the background color, takes into account color shifting
+	CDC ddc2;
+	CBrush brush;
+	CBitmap bmp2;
+	ddc2.CreateCompatibleDC(NULL);
+	bmp2.CreateCompatibleBitmap(&ddc,BitMap.bmWidth,BitMap.bmHeight);
+	col=GetSysColor(COLOR_3DFACE);
+	brush.CreateSolidBrush(col);
+	CBitmap * pddcOldBmp2 = ddc2.SelectObject(&bmp2);
+	CRect rect(0,0,BitMap.bmWidth,BitMap.bmHeight);
+	ddc2.FillRect(rect,&brush);
+	bgcol=ddc2.GetPixel(1,1);
+	brush.DeleteObject();
+	ddc2.SelectObject(pddcOldBmp2);
+
+	for(int i=0;i<BitMap.bmWidth;++i){
+		for(int j=0;j<BitMap.bmHeight;++j){
+			col=ddc.GetPixel(i,j);
+			if(col!=bgcol)ddc.SetPixel(i,j,shadowcol);
+		}
+	}
+	ddc.SelectObject(pddcOldBmp);
+}
+
+
+BOOL BCMenu::AddBitmapToImageList(CImageList *bmplist,UINT nResourceID)
+{
+	BOOL bReturn=FALSE;
+
+	// O.S.
+	if (m_bDynIcons){
+		bmplist->Add((HICON)nResourceID);
+		bReturn=TRUE;
+	}
+	else{
+		HBITMAP hbmp=LoadSysColorBitmap(nResourceID);
+		if(hbmp){
+			CBitmap bmp;
+			bmp.Attach(hbmp);
+			if(m_bitmapBackgroundFlag){
+				if(bmplist->Add(&bmp,m_bitmapBackground)>=0)bReturn=TRUE;
+			}
+			else{
+				if(bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
+			}
+			bmp.Detach();
+			DeleteObject(hbmp);
+		}
+		else{
+			CBitmap mybmp;
+			if(mybmp.LoadBitmap(nResourceID)){
+				if(m_bitmapBackgroundFlag){
+					if(bmplist->Add(&mybmp,m_bitmapBackground)>=0)bReturn=TRUE;
+				}
+				else{
+					if(bmplist->Add(&mybmp,GetSysColor(COLOR_3DFACE))>=0)bReturn=TRUE;
+				}
+			}
+		}
+	}
+	if(bReturn&&IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
+		CWnd *pWnd = AfxGetMainWnd();            // Get main window
+		if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
+		CDC *pDC = pWnd->GetDC();              // Get device context
+		CBitmap bmp,bmp2;
+		GetBitmapFromImageList(pDC,bmplist,0,bmp);
+		GetFadedBitmap(bmp);
+		bmplist->Add(&bmp,GetSysColor(COLOR_3DFACE));
+		GetBitmapFromImageList(pDC,bmplist,0,bmp2);
+		GetShadowBitmap(bmp2);
+		bmplist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
+		pWnd->ReleaseDC(pDC);  // Release the DC
+	}
+	return(bReturn);
+}
+
+void BCMenu::SetBitmapBackground(COLORREF color)
+{
+	m_bitmapBackground=color;
+	m_bitmapBackgroundFlag=TRUE;
+}
+
+void BCMenu::UnSetBitmapBackground(void)
+{
+	m_bitmapBackgroundFlag=FALSE;
+}
+
+// Given a toolbar, append all the options from it to this menu
+// Passed a ptr to the toolbar object and the toolbar ID
+// Author : Robert Edward Caldecott
+void BCMenu::AddFromToolBar(CToolBar* pToolBar, int nResourceID)
+{
+	for (int i = 0; i < pToolBar->GetCount(); i++) {
+		UINT nID = pToolBar->GetItemID(i);
+		// See if this toolbar option
+		// appears as a command on this
+		// menu or is a separator
+		if (nID == 0 || GetMenuState(nID, MF_BYCOMMAND) == 0xFFFFFFFF)
+			continue; // Item doesn't exist
+		UINT nStyle;
+		int nImage;
+		// Get the toolbar button info
+		pToolBar->GetButtonInfo(i, nID, nStyle, nImage);
+		// OK, we have the command ID of the toolbar
+		// option, and the tollbar bitmap offset
+		int nLoc;
+		BCMenuData* pData;
+		BCMenu *pSubMenu = FindMenuOption(nID, nLoc);
+		if (pSubMenu && nLoc >= 0)pData = pSubMenu->m_MenuList[nLoc];
+		else {
+			// Create a new BCMenuData structure
+			pData = new BCMenuData;
+			m_MenuList.Add(pData);
+		}
+		// Set some default structure members
+		pData->menuIconNormal = nResourceID;
+		pData->nID = nID;
+		pData->nFlags =  MF_BYCOMMAND | MF_OWNERDRAW;
+		pData->xoffset = nImage;
+		if (pData->bitmap)pData->bitmap->DeleteImageList();
+		else pData->bitmap = new CImageList;
+		pData->bitmap->Create(m_iconX, m_iconY,ILC_COLORDDB|ILC_MASK, 1, 1);
+
+		if(!AddBitmapToImageList(pData->bitmap, nResourceID)){
+			pData->bitmap->DeleteImageList();
+			delete pData->bitmap;
+			pData->bitmap=NULL;
+			pData->menuIconNormal = -1;
+			pData->xoffset = -1;
+		}
+
+		// Modify our menu
+		ModifyMenu(nID,pData->nFlags,nID,(LPCTSTR)pData);
+	}
+}
+
+BOOL BCMenu::Draw3DCheckmark(CDC *dc, const CRect& rc,
+							 BOOL bSelected, HBITMAP hbmCheck)
+{
+	CRect rcDest = rc;
+	CBrush brush;
+	COLORREF col;
+	if(IsWinXPLuna())col=GetSysColor(COLOR_3DFACE);
+	else col=GetSysColor(COLOR_MENU);
+	if(!bSelected)col = LightenColor(col,0.6);
+	brush.CreateSolidBrush(col);
+	dc->FillRect(rcDest,&brush);
+	brush.DeleteObject();
+	if (IsNewShell()) //SK: looks better on the old shell
+		dc->DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
+	if (!hbmCheck)DrawCheckMark(dc,rc.left+4,rc.top+4,GetSysColor(COLOR_MENUTEXT));
+	else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
+	return TRUE;
+}
+
+BOOL BCMenu::DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck,COLORREF &colorout)
+{
+	CBrush brushin;
+	brushin.CreateSolidBrush(LightenColor(colorout,0.85));
+	dc->FillRect(rc,&brushin);
+	brushin.DeleteObject();
+	dc->Draw3dRect (rc,colorout,colorout);
+	if (!hbmCheck)DrawCheckMark(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
+	else DrawRadioDot(dc,rc.left+5,rc.top+4,GetSysColor(COLOR_MENUTEXT));
+	return TRUE;
+}
+
+void BCMenu::DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
+						int nHeight, CBitmap &bmp, int nXSrc, int nYSrc,
+						COLORREF bgcolor)
+{
+	// create a monochrome memory DC
+	CDC ddc;
+	ddc.CreateCompatibleDC(0);
+	CBitmap bwbmp;
+	bwbmp.CreateCompatibleBitmap(&ddc, nWidth, nHeight);
+	CBitmap * pddcOldBmp = ddc.SelectObject(&bwbmp);
+
+	CDC dc;
+	dc.CreateCompatibleDC(0);
+	CBitmap * pdcOldBmp = dc.SelectObject(&bmp);
+
+	// build a mask
+	ddc.PatBlt(0, 0, nWidth, nHeight, WHITENESS);
+	dc.SetBkColor(GetSysColor(COLOR_BTNFACE));
+	ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCCOPY);
+	dc.SetBkColor(GetSysColor(COLOR_BTNHILIGHT));
+	ddc.BitBlt(0, 0, nWidth, nHeight, &dc, nXSrc,nYSrc, SRCPAINT);
+
+	// Copy the image from the toolbar into the memory DC
+	// and draw it (grayed) back into the toolbar.
+	dc.FillSolidRect(0,0, nWidth, nHeight, bgcolor);
+	//SK: Looks better on the old shell
+	dc.SetBkColor(RGB(0, 0, 0));
+	dc.SetTextColor(RGB(255, 255, 255));
+	CBrush brShadow, brHilight;
+	brHilight.CreateSolidBrush(GetSysColor(COLOR_BTNHILIGHT));
+	brShadow.CreateSolidBrush(GetSysColor(COLOR_BTNSHADOW));
+	CBrush * pOldBrush = dc.SelectObject(&brHilight);
+	dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
+	drawdc->BitBlt(nXDest+1,nYDest+1,nWidth, nHeight, &dc,0,0,SRCCOPY);
+	dc.BitBlt(1,1, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
+	dc.SelectObject(&brShadow);
+	dc.BitBlt(0,0, nWidth, nHeight, &ddc, 0, 0, 0x00E20746L);
+	drawdc->BitBlt(nXDest,nYDest,nWidth, nHeight, &dc,0,0,SRCCOPY);
+	// reset DCs
+	ddc.SelectObject(pddcOldBmp);
+	ddc.DeleteDC();
+	dc.SelectObject(pOldBrush);
+	dc.SelectObject(pdcOldBmp);
+	dc.DeleteDC();
+
+	brShadow.DeleteObject();
+	brHilight.DeleteObject();
+	bwbmp.DeleteObject();
+}
+
+void BCMenu::SetDisableOldStyle(void)
+{
+	disable_old_style=TRUE;
+}
+
+void BCMenu::UnSetDisableOldStyle(void)
+{
+	disable_old_style=FALSE;
+}
+
+BOOL BCMenu::GetDisableOldStyle(void)
+{
+	return(disable_old_style);
+}
+
+
+WORD BCMenu::NumBitmapColors(LPBITMAPINFOHEADER lpBitmap)
+{
+	if ( lpBitmap->biClrUsed != 0)
+		return (WORD)lpBitmap->biClrUsed;
+
+	switch (lpBitmap->biBitCount){
+		case 1:
+			return 2;
+		case 4:
+			return 16;
+		case 8:
+			return 256;
+		default:
+			return 0;
+	}
+	return 0;
+}
+
+HBITMAP BCMenu::LoadSysColorBitmap(int nResourceId)
+{
+	HINSTANCE hInst = 
+		AfxFindResourceHandle(MAKEINTRESOURCE(nResourceId),RT_BITMAP);
+	HRSRC hRsrc = 
+		::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
+	if (hRsrc == NULL){
+		hInst = NULL;
+		hRsrc = ::FindResource(hInst,MAKEINTRESOURCE(nResourceId),RT_BITMAP);
+	}
+	if (hRsrc == NULL)return NULL;
+
+	// determine how many colors in the bitmap
+	HGLOBAL hglb;
+	if ((hglb = LoadResource(hInst, hRsrc)) == NULL)
+		return NULL;
+	LPBITMAPINFOHEADER lpBitmap = (LPBITMAPINFOHEADER)LockResource(hglb);
+	if (lpBitmap == NULL)return NULL;
+	WORD numcol = NumBitmapColors(lpBitmap);
+	::FreeResource(hglb);
+
+	if(numcol!=16)return(NULL);
+
+	return AfxLoadSysColorBitmap(hInst, hRsrc, FALSE);
+}
+
+BOOL BCMenu::RemoveMenu(UINT uiId,UINT nFlags)
+{
+	if(MF_BYPOSITION&nFlags){
+		UINT uint = GetMenuState(uiId,MF_BYPOSITION);
+		if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
+			delete m_MenuList.GetAt(uiId);
+			m_MenuList.RemoveAt(uiId);
+		}
+		else{
+			BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
+			if(NULL==pSubMenu){
+				UINT uiCommandId = GetMenuItemID(uiId);
+				for(int i=0;i<m_MenuList.GetSize(); i++){
+					if(m_MenuList[i]->nID==uiCommandId){
+						delete m_MenuList.GetAt(i);
+						m_MenuList.RemoveAt(i);
+						break;
+					}
+				}
+			}
+			else{
+				int numSubMenus = m_SubMenus.GetUpperBound();
+				for(int m = numSubMenus; m >= 0; m--){
+					if(m_SubMenus[m]==pSubMenu->m_hMenu){
+						int numAllSubMenus = m_AllSubMenus.GetUpperBound();
+						for(int n = numAllSubMenus; n>= 0; n--){
+							if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
+						}
+						m_SubMenus.RemoveAt(m);
+					}
+				}
+				int num = pSubMenu->GetMenuItemCount();
+				for(int i=num-1;i>=0;--i)pSubMenu->RemoveMenu(i,MF_BYPOSITION);
+				for(int i=m_MenuList.GetUpperBound();i>=0;i--){
+					if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
+						delete m_MenuList.GetAt(i);
+						m_MenuList.RemoveAt(i);
+						break;
+					}
+				}
+				delete pSubMenu; 
+			}
+		}
+	}
+	else{
+		int iPosition =0;
+		BCMenu* pMenu = FindMenuOption(uiId,iPosition);
+		// bug fix RIA 14th September 2000 
+		// failed to return correct value on call to remove menu as the item was 
+		// removed twice. The second time its not found 
+		// so a value of 0 was being returned 
+		if(pMenu) return pMenu->RemoveMenu(iPosition,MF_BYPOSITION); // added return 
+	}
+	return CMenu::RemoveMenu(uiId,nFlags);
+}
+
+BOOL BCMenu::DeleteMenu(UINT uiId,UINT nFlags)
+{
+	if(MF_BYPOSITION&nFlags){
+		UINT uint = GetMenuState(uiId,MF_BYPOSITION);
+		if(uint&MF_SEPARATOR && !(uint&MF_POPUP)){
+			// make sure it's a separator
+			int menulistsize=m_MenuList.GetSize();	
+			if(uiId<(UINT)menulistsize){
+				CString str=m_MenuList[uiId]->GetString();
+				if(str==""){
+					delete m_MenuList.GetAt(uiId);
+					m_MenuList.RemoveAt(uiId);
+				}
+			}
+		}
+		else{
+			BCMenu* pSubMenu = (BCMenu*) GetSubMenu(uiId);
+			if(NULL==pSubMenu){
+				UINT uiCommandId = GetMenuItemID(uiId);
+				for(int i=0;i<m_MenuList.GetSize(); i++){
+					if(m_MenuList[i]->nID==uiCommandId){
+						delete m_MenuList.GetAt(i);
+						m_MenuList.RemoveAt(i);
+						break;
+					}
+				}
+			}
+			else{
+				int numSubMenus = m_SubMenus.GetUpperBound();
+				for(int m = numSubMenus; m >= 0; m--){
+					if(m_SubMenus[m]==pSubMenu->m_hMenu){
+						int numAllSubMenus = m_AllSubMenus.GetUpperBound();
+						for(int n = numAllSubMenus; n>= 0; n--){
+							if(m_AllSubMenus[n]==m_SubMenus[m])m_AllSubMenus.RemoveAt(n);
+						}
+						m_SubMenus.RemoveAt(m);
+					}
+				}
+				int num = pSubMenu->GetMenuItemCount();
+				for(int i=num-1;i>=0;--i)pSubMenu->DeleteMenu(i,MF_BYPOSITION);
+				for(int i=m_MenuList.GetUpperBound();i>=0;i--){
+					if(m_MenuList[i]->nID==(UINT)pSubMenu->m_hMenu){
+						delete m_MenuList.GetAt(i);
+						m_MenuList.RemoveAt(i);
+						break;
+					}
+				}
+				delete pSubMenu;
+			}
+		}
+	}
+	else{
+		int iPosition =0;
+		BCMenu* pMenu = FindMenuOption(uiId,iPosition);
+		if(pMenu)return pMenu->DeleteMenu(iPosition,MF_BYPOSITION);
+	}
+
+	return(CMenu::DeleteMenu(uiId,nFlags));
+}
+
+
+BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
+{
+	USES_CONVERSION;
+	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
+}
+
+BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
+{
+	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,nIconNormal);
+}
+
+BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
+{
+	USES_CONVERSION;
+	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
+}
+
+BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
+{
+	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,il,xoffset);
+}
+
+BOOL BCMenu::AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
+{
+	USES_CONVERSION;
+	return AppendMenuW(nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
+}
+
+BOOL BCMenu::AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
+{
+	if(bmp){
+		CImageList temp;
+		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
+		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
+		return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,&temp,0);
+	}
+	return AppendODMenuW(lpszNewItem,nFlags,nIDNewItem,NULL,0);
+}
+
+BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,int nIconNormal)
+{
+	USES_CONVERSION;
+	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),nIconNormal);
+}
+
+BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,int nIconNormal)
+{
+	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,nIconNormal);
+}
+
+BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset)
+{
+	USES_CONVERSION;
+	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),il,xoffset);
+}
+
+BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset)
+{
+	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,il,xoffset);
+}
+
+BOOL BCMenu::InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp)
+{
+	USES_CONVERSION;
+	return InsertMenuW(nPosition,nFlags,nIDNewItem,A2W(lpszNewItem),bmp);
+}
+
+BOOL BCMenu::InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp)
+{
+	if(bmp){
+		CImageList temp;
+		temp.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+		if(m_bitmapBackgroundFlag)temp.Add(bmp,m_bitmapBackground);
+		else temp.Add(bmp,GetSysColor(COLOR_3DFACE));
+		return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,&temp,0);
+	}
+	return InsertODMenuW(nPosition,lpszNewItem,nFlags,nIDNewItem,NULL,0);
+}
+
+//--------------------------------------------------------------------------
+//[21.06.99 rj]
+BCMenu* BCMenu::AppendODPopupMenuW(wchar_t *lpstrText)
+{
+	BCMenu* pSubMenu = new BCMenu;
+	pSubMenu->m_unselectcheck=m_unselectcheck;
+	pSubMenu->m_selectcheck=m_selectcheck;
+	pSubMenu->checkmaps=checkmaps;
+	pSubMenu->checkmapsshare=TRUE;
+	pSubMenu->CreatePopupMenu();
+	AppendODMenuW(lpstrText,MF_POPUP,(UINT)pSubMenu->m_hMenu, -1);
+	return pSubMenu;
+}
+
+//--------------------------------------------------------------------------
+//[21.06.99 rj]
+BCMenu* BCMenu::AppendODPopupMenuA(LPCSTR lpstrText)
+{
+	USES_CONVERSION;
+	return AppendODPopupMenuW(A2W(lpstrText));
+}
+
+BOOL BCMenu::ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist)
+{
+	if (il == NULL||newlist==NULL||xoffset<0) return FALSE;
+	HICON hIcon = il->ExtractIcon(xoffset);
+	int cx, cy;
+	ImageList_GetIconSize(il->m_hImageList, &cx, &cy);
+	newlist->Create(cx,cy,ILC_COLORDDB|ILC_MASK,1,1);
+	newlist->Add(hIcon);
+	::DestroyIcon(hIcon);
+	if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
+		CWnd *pWnd = AfxGetMainWnd();            // Get main window
+		if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
+		CDC *pDC = pWnd->GetDC();              // Get device context
+		CBitmap bmp,bmp2;
+		GetBitmapFromImageList(pDC,newlist,0,bmp);
+		GetFadedBitmap(bmp);
+		newlist->Add(&bmp,GetSysColor(COLOR_3DFACE));
+		GetBitmapFromImageList(pDC,newlist,0,bmp2);
+		GetShadowBitmap(bmp2);
+		newlist->Add(&bmp2,GetSysColor(COLOR_3DFACE));
+		pWnd->ReleaseDC(pDC);  // Release the DC
+	}
+	return TRUE;
+}
+
+// 2001-07-12, Damir Valiulin:
+//          Added GetSubMenu (LPCTSTR lpszSubMenuName) function
+//
+
+CMenu* BCMenu::GetSubMenu(int nPos)
+{
+	return CMenu::GetSubMenu (nPos);
+}
+
+CMenu* BCMenu::GetSubMenu(LPCTSTR lpszSubMenuName)
+{
+	int num = GetMenuItemCount ();
+	CString name;
+
+	for (int i=0; i<num; i++)
+	{
+		GetMenuString (i, name, MF_BYPOSITION);
+		if (name.Compare (lpszSubMenuName) == 0)
+		{
+			return CMenu::GetSubMenu (i);
+		}
+	}
+
+	return NULL;
+}
+
+BCMenu* BCMenu::GetSubBCMenu(char* pText)
+{
+	USES_CONVERSION;
+	return GetSubBCMenu(A2W(pText));
+}
+
+BCMenu* BCMenu::GetSubBCMenu(wchar_t* lpszSubMenuName)
+{
+	BCMenuData *mdata;
+	mdata=FindMenuOption(lpszSubMenuName);
+	if(mdata){
+		HMENU bchmenu=(HMENU)mdata->nID;
+		CMenu *ptr=FromHandle(bchmenu);
+		BOOL flag=ptr->IsKindOf(RUNTIME_CLASS( BCMenu ));
+		if(flag)return((BCMenu *)ptr);
+	}
+	return NULL;
+}
+
+
+// Tongzhe Cui, Functions to remove a popup menu based on its name. Seperators
+// before and after the popup menu can also be removed if they exist.
+int BCMenu::GetMenuPosition(char* pText)
+{
+	USES_CONVERSION;
+	return GetMenuPosition(A2W(pText));
+}
+
+int BCMenu::GetMenuPosition(wchar_t* pText)
+{
+	int i,j;
+	BCMenu* psubmenu;
+	for(i=0;i<(int)(GetMenuItemCount());++i)
+	{
+		psubmenu=(BCMenu *)GetSubMenu(i);
+		if(!psubmenu)
+		{
+			const wchar_t *szWide;//SK: we use const to prevent misuse of this Ptr
+			for(j=0;j<=m_MenuList.GetUpperBound();++j)
+			{     
+				szWide = m_MenuList[j]->GetWideString ();
+				if(szWide && !wcscmp(pText,szWide))//SK: modified for dynamic allocation
+					return j;
+			}
+		}
+	}
+	// means no found;
+	return -1;
+}
+
+int BCMenu::RemoveMenu(char* pText, BC_Seperator sPos)
+{
+	USES_CONVERSION;
+	return RemoveMenu(A2W(pText), sPos);
+}
+
+int BCMenu::RemoveMenu(wchar_t* pText, BC_Seperator sPos)
+{
+	int nPos = GetMenuPosition(pText);
+	if(nPos != -1)
+	{
+		RemoveMenu(nPos, MF_BYPOSITION);
+	}
+	if(sPos == BCMENU_HEAD)
+	{
+		ASSERT(nPos - 1 >= 0);
+		RemoveMenu(nPos-1, MF_BYPOSITION);
+	}
+	else if(sPos == BCMENU_TAIL)
+	{
+		RemoveMenu(nPos-1, MF_BYPOSITION);
+	}
+	else if(sPos == BCMENU_BOTH)
+	{
+		// remove the end first;
+		RemoveMenu(nPos-1, MF_BYPOSITION);
+		// remove the head;
+		ASSERT(nPos - 1 >= 0);
+		RemoveMenu(nPos-1, MF_BYPOSITION);
+	}
+	return nPos;
+}
+
+int BCMenu::DeleteMenu(char* pText, BC_Seperator sPos)
+{
+	USES_CONVERSION;
+	return DeleteMenu(A2W(pText), sPos);
+}
+
+int BCMenu::DeleteMenu(wchar_t* pText, BC_Seperator sPos)
+{
+	int nPos = GetMenuPosition(pText);
+	if(nPos != -1)
+	{
+		DeleteMenu(nPos, MF_BYPOSITION);
+	}
+	if(sPos == BCMENU_HEAD)
+	{
+		ASSERT(nPos - 1 >= 0);
+		DeleteMenu(nPos-1, MF_BYPOSITION);
+	}
+	else if(sPos == BCMENU_TAIL)
+	{
+		DeleteMenu(nPos-1, MF_BYPOSITION);
+	}
+	else if(sPos == BCMENU_BOTH)
+	{
+		// remove the end first;
+		DeleteMenu(nPos-1, MF_BYPOSITION);
+		// remove the head;
+		ASSERT(nPos - 1 >= 0);
+		DeleteMenu(nPos-1, MF_BYPOSITION);
+	}
+	return nPos;
+}
+
+// Larry Antram
+BOOL BCMenu::SetMenuText(UINT id, CString string, UINT nFlags/*= MF_BYPOSITION*/ )
+{
+	BOOL returnflag=FALSE;
+
+	if(MF_BYPOSITION&nFlags)
+	{
+		UINT numMenuItems = m_MenuList.GetUpperBound();
+		if(id<=numMenuItems){
+#ifdef UNICODE
+			m_MenuList[id]->SetWideString((LPCTSTR)string);
+#else
+			m_MenuList[id]->SetAnsiString(string);
+#endif
+			returnflag=TRUE;
+		}
+	}
+	else{
+		int uiLoc;
+		BCMenu* pMenu = FindMenuOption(id,uiLoc);
+		if(NULL!=pMenu) returnflag = pMenu->SetMenuText(uiLoc,string);
+	}
+	return(returnflag);
+}
+
+// courtesy of Warren Stevens
+void BCMenu::ColorBitmap(CDC* pDC,CBitmap& bmp,CSize bitmap_size,CSize icon_size,COLORREF fill,COLORREF border,int hatchstyle)
+{
+	CDC bmpdc;
+	COLORREF m_newclrBack;
+	int x1=0,y1=0,x2=bitmap_size.cx,y2=bitmap_size.cy;
+
+	if(IsWinXPLuna())m_newclrBack=GetSysColor(COLOR_3DFACE);
+	else m_newclrBack=GetSysColor(COLOR_MENU);
+
+	bmpdc.CreateCompatibleDC(pDC);
+
+	bmp.CreateCompatibleBitmap(pDC, icon_size.cx, icon_size.cy);	
+	CBitmap* pOldBitmap = bmpdc.SelectObject(&bmp);
+
+	if(bitmap_size!=icon_size){
+		CBrush background_brush;
+		background_brush.CreateSolidBrush(m_newclrBack);
+		CRect rect(0,0, icon_size.cx, icon_size.cy);
+		bmpdc.FillRect(rect,&background_brush);
+		x1 = (icon_size.cx-bitmap_size.cx)/2;
+		y1 = (icon_size.cy-bitmap_size.cy)/2;
+		x2 = x1+bitmap_size.cx;
+		y2 = y1+bitmap_size.cy;
+		background_brush.DeleteObject();
+	}
+
+	CPen border_pen(PS_SOLID, 1, border);
+	CBrush fill_brush;
+	if(hatchstyle!=-1) { fill_brush.CreateHatchBrush(hatchstyle, fill); }
+	else      { fill_brush.CreateSolidBrush(fill);             }
+
+	CPen*    pOldPen    = bmpdc.SelectObject(&border_pen);
+	CBrush*  pOldBrush  = bmpdc.SelectObject(&fill_brush);
+
+	bmpdc.Rectangle(x1,y1,x2,y2);
+
+	if(NULL!=pOldBrush)  { bmpdc.SelectObject(pOldBrush);  }
+	if(NULL!=pOldPen)    { bmpdc.SelectObject(pOldPen);    }
+	if(NULL!=pOldBitmap) { bmpdc.SelectObject(pOldBitmap); }
+}
+
+BOOL BCMenu::IsWindowsClassicTheme(void)
+{
+	TCHAR Buf[_MAX_PATH+10];
+	HKEY hKey;
+	DWORD size,type; 
+	long lRetCode; 
+	static BOOL XPTheme_returnflag=FALSE;
+	static BOOL XPTheme_checkflag=FALSE;
+
+	if(XPTheme_checkflag)return(XPTheme_returnflag);
+
+	XPTheme_checkflag=TRUE;
+	lRetCode = RegOpenKeyEx ( HKEY_CURRENT_USER, 
+		_T("Software\\Microsoft\\Plus!\\Themes\\Current"), 
+		0,KEY_READ,&hKey);  
+	if (lRetCode == ERROR_SUCCESS){ 
+		size = _MAX_PATH;type=REG_SZ;
+		lRetCode=::RegQueryValueEx(hKey,NULL,NULL,&type,
+			(unsigned char *)Buf,&size);
+		if(lRetCode == ERROR_SUCCESS){
+			TCHAR szClassicTheme[]=_T("Windows Classic.theme");
+			int len=lstrlen(Buf);
+			if(len>=lstrlen(szClassicTheme)){
+				if(!lstrcmpi(&Buf[len-lstrlen(szClassicTheme)],szClassicTheme)){
+					XPTheme_returnflag=TRUE;
+				}
+			}
+		}
+		RegCloseKey(hKey);  
+	}
+	return(XPTheme_returnflag);
+}
+
+int BCMenu::GlobalImageListOffset(int nID)
+{
+	int numcurrent=m_AllImagesID.GetSize();
+	int existsloc = -1;
+	for(int i=0;i<numcurrent;++i){
+		if(m_AllImagesID[i]==nID){
+			existsloc=i;
+			break;
+		}
+	}
+	return existsloc;
+}
+
+BOOL BCMenu::CanDraw3DImageList(int offset)
+{
+	BOOL retflag=FALSE;
+	int numcurrent=m_AllImagesID.GetSize();
+	if(offset+1<numcurrent&&offset+2<numcurrent){
+		int nID=m_AllImagesID[offset];
+		if(m_AllImagesID[offset+1]==nID&&m_AllImagesID[offset+2]==nID)retflag=TRUE;
+	}
+	return(retflag);
+}
+
+int BCMenu::AddToGlobalImageList(CImageList *il,int xoffset,int nID)
+{
+	int loc = -1;
+	HIMAGELIST hImageList = m_AllImages.m_hImageList;
+	if(!hImageList){
+		m_AllImages.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+	}
+	HICON hIcon = il->ExtractIcon(xoffset);
+	if(hIcon){
+		CBitmap bmp,bmp2;
+		if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
+			CWnd *pWnd = AfxGetMainWnd();            // Get main window
+			if (pWnd == NULL) pWnd = CWnd::GetDesktopWindow();
+			CDC *pDC = pWnd->GetDC();              // Get device context
+			GetBitmapFromImageList(pDC,il,xoffset,bmp);
+			GetFadedBitmap(bmp);
+			GetBitmapFromImageList(pDC,il,xoffset,bmp2);
+			GetShadowBitmap(bmp2);
+			pWnd->ReleaseDC(pDC);  // Release the DC
+		}
+		int numcurrent=m_AllImagesID.GetSize();
+		int existsloc = -1;
+		for(int i=0;i<numcurrent;++i){
+			if(m_AllImagesID[i]==nID){
+				existsloc=i;
+				break;
+			}
+		}
+		if(existsloc>=0){
+			m_AllImages.Replace(existsloc,hIcon);
+			loc = existsloc;
+			if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
+				if(existsloc+1<numcurrent&&m_AllImagesID[existsloc+1]==nID){
+					if(existsloc+2<numcurrent&&m_AllImagesID[existsloc+2]==nID){
+						CImageList il2;
+						il2.Create(m_iconX,m_iconY,ILC_COLORDDB|ILC_MASK,1,1);
+						il2.Add(&bmp,GetSysColor(COLOR_3DFACE));
+						HICON hIcon2 = il2.ExtractIcon(0);
+						m_AllImages.Replace(existsloc+1,hIcon2);
+						il2.Add(&bmp2,GetSysColor(COLOR_3DFACE));
+						HICON hIcon3 = il2.ExtractIcon(1);
+						m_AllImages.Replace(existsloc+2,hIcon3);
+						::DestroyIcon(hIcon2);
+						::DestroyIcon(hIcon3);
+					}
+				}
+			}
+		}
+		else{
+			m_AllImages.Add(hIcon);
+			m_AllImagesID.Add(nID);
+			loc=numcurrent;
+			if(IsLunaMenuStyle()&&xp_draw_3D_bitmaps){
+				m_AllImages.Add(&bmp,GetSysColor(COLOR_3DFACE));
+				m_AllImages.Add(&bmp2,GetSysColor(COLOR_3DFACE));
+				m_AllImagesID.Add(nID);
+				m_AllImagesID.Add(nID);
+			}
+		}
+		::DestroyIcon(hIcon);
+	}
+	return(loc);
+}
+
+//*************************************************************************
+
+/////////////////////////////////////////////////////////////////////////////
+// Toolbar for loading images
+/////////////////////////////////////////////////////////////////////////////
+
+struct CToolBarData
+{
+	WORD wVersion;
+	WORD wWidth;
+	WORD wHeight;
+	WORD wItemCount;
+	WORD* items(){
+		return (WORD*)(this+1);
+	}
+};
+
+BOOL BCMenuToolBar::LoadToolBar(LPCTSTR lpszResourceName)
+{
+	ASSERT_VALID(this);
+	ASSERT(lpszResourceName != NULL);
+
+	HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName,RT_TOOLBAR);
+	HRSRC hRsrc = ::FindResource(hInst,lpszResourceName,RT_TOOLBAR);
+	if (hRsrc == NULL){
+		hInst = NULL;
+		hRsrc = ::FindResource(hInst,lpszResourceName,RT_TOOLBAR);
+	}
+	if (hRsrc == NULL)
+		return FALSE;
+
+	HGLOBAL hGlobal = ::LoadResource(hInst,hRsrc);
+	if (hGlobal == NULL)
+		return FALSE;
+
+	CToolBarData* pData = (CToolBarData*)::LockResource(hGlobal);
+	if (pData == NULL)
+		return FALSE;
+	ASSERT(pData->wVersion == 1);
+
+	UINT* pItems = new UINT[pData->wItemCount];
+	for (int i = 0; i < pData->wItemCount; i++)
+		pItems[i] = pData->items()[i];
+	BOOL bResult = SetButtons(pItems,pData->wItemCount);
+	delete[] pItems;
+
+	if (bResult){
+		CSize sizeImage(pData->wWidth,pData->wHeight);
+		CSize sizeButton(pData->wWidth+7,pData->wHeight+7);
+		SetSizes(sizeButton,sizeImage);
+		m_iconX=pData->wWidth;
+		m_iconY=pData->wHeight;
+		bResult = LoadBitmap(lpszResourceName);
+	}
+
+	::UnlockResource(hGlobal);
+	::FreeResource(hGlobal);
+	return bResult;
+}
+
+BOOL BCMenuToolBar::LoadBitmap(LPCTSTR lpszResourceName)
+{
+	ASSERT_VALID(this);
+	ASSERT(lpszResourceName != NULL);
+
+	HINSTANCE hInstImageWell = AfxFindResourceHandle(lpszResourceName,RT_BITMAP);
+	HRSRC hRsrcImageWell = ::FindResource(hInstImageWell,lpszResourceName,RT_BITMAP);
+	if (hRsrcImageWell == NULL){
+		hInstImageWell = NULL;
+		hRsrcImageWell = ::FindResource(hInstImageWell,lpszResourceName,RT_BITMAP);
+	}
+	if (hRsrcImageWell == NULL)
+		return FALSE;
+
+	HBITMAP hbmImageWell;
+	hbmImageWell = AfxLoadSysColorBitmap(hInstImageWell,hRsrcImageWell);
+
+	if (!AddReplaceBitmap(hbmImageWell))
+		return FALSE;
+
+	m_hInstImageWell = hInstImageWell;
+	m_hRsrcImageWell = hRsrcImageWell;
+	return TRUE;
+}

+ 366 - 0
VideoCapture/UI/BCMenu.h

@@ -0,0 +1,366 @@
+#ifndef BCMenu_H
+#define BCMenu_H
+
+#include <afxtempl.h>
+
+// BCMenuData class. Fill this class structure to define a single menu item:
+class BCMenuData
+{
+	wchar_t *m_szMenuText;
+public:
+	BCMenuData () {menuIconNormal=-1;xoffset=-1;bitmap=NULL;pContext=NULL;
+	nFlags=0;nID=0;syncflag=0;m_szMenuText=NULL;global_offset=-1;threeD=FALSE;};
+	void SetAnsiString(LPCSTR szAnsiString);
+	void SetWideString(const wchar_t *szWideString);
+	const wchar_t *GetWideString(void) {return m_szMenuText;};
+	~BCMenuData ();
+	CString GetString(void);//returns the menu text in ANSI or UNICODE
+	int xoffset,global_offset;
+	BOOL threeD;
+	int menuIconNormal;
+	UINT nFlags,nID,syncflag;
+	CImageList *bitmap;
+	void *pContext; // used to attach user data
+};
+
+//struct CMenuItemInfo : public MENUITEMINFO {
+struct CMenuItemInfo : public 
+	//MENUITEMINFO 
+#ifndef UNICODE   //SK: this fixes warning C4097: typedef-name 'MENUITEMINFO' used as synonym for class-name 'tagMENUITEMINFOA'
+	tagMENUITEMINFOA
+#else
+	tagMENUITEMINFOW
+#endif
+{
+	CMenuItemInfo()
+	{
+		memset(this, 0, sizeof(MENUITEMINFO));
+		cbSize = sizeof(MENUITEMINFO);
+	}
+};
+
+// how the menu's are drawn, either original or XP style
+typedef enum {BCMENU_DRAWMODE_ORIGINAL,BCMENU_DRAWMODE_XP} BC_MenuDrawMode;
+
+// how seperators are handled when removing a menu (Tongzhe Cui)
+typedef enum {BCMENU_NONE, BCMENU_HEAD, BCMENU_TAIL, BCMENU_BOTH} BC_Seperator;
+
+// defines for unicode support
+#ifndef UNICODE
+#define AppendMenu AppendMenuA
+#define InsertMenu InsertMenuA
+#define InsertODMenu InsertODMenuA
+#define AppendODMenu AppendODMenuA
+#define AppendODPopupMenu AppendODPopupMenuA
+#define ModifyODMenu ModifyODMenuA
+#else
+#define AppendMenu AppendMenuW
+#define InsertMenu InsertMenuW
+#define InsertODMenu InsertODMenuW
+#define AppendODMenu AppendODMenuW
+#define ModifyODMenu ModifyODMenuW
+#define AppendODPopupMenu AppendODPopupMenuW
+#endif
+
+
+class BCMenu : public CMenu
+{
+	DECLARE_DYNAMIC( BCMenu )
+public:
+	BCMenu(); 
+	virtual ~BCMenu();
+
+	// Functions for loading and applying bitmaps to menus (see example application)
+	virtual BOOL LoadMenu(LPCTSTR lpszResourceName);
+	virtual BOOL LoadMenu(int nResource);
+	BOOL LoadToolbar(UINT nToolBar);
+	BOOL LoadToolbars(const UINT *arID,int n);
+	void AddFromToolBar(CToolBar* pToolBar, int nResourceID);
+	BOOL LoadFromToolBar(UINT nID,UINT nToolBar,int& xoffset);
+	BOOL AddBitmapToImageList(CImageList *list,UINT nResourceID);
+	static HBITMAP LoadSysColorBitmap(int nResourceId);
+	void LoadCheckmarkBitmap(int unselect,int select); // custom check mark bitmaps
+
+	// functions for appending a menu option, use the AppendMenu call (see above define)
+	BOOL AppendMenuA(UINT nFlags,UINT nIDNewItem=0,const char *lpszNewItem=NULL,int nIconNormal=-1);
+	BOOL AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset);
+	BOOL AppendMenuA(UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp);
+	BOOL AppendMenuW(UINT nFlags,UINT nIDNewItem=0,wchar_t *lpszNewItem=NULL,int nIconNormal=-1);
+	BOOL AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset);
+	BOOL AppendMenuW(UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp);
+	BOOL AppendODMenuA(LPCSTR lpstrText,UINT nFlags = MF_OWNERDRAW,UINT nID = 0,int nIconNormal = -1);  
+	BOOL AppendODMenuW(wchar_t *lpstrText,UINT nFlags = MF_OWNERDRAW,UINT nID = 0,int nIconNormal = -1);  
+	BOOL AppendODMenuA(LPCSTR lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset);
+	BOOL AppendODMenuW(wchar_t *lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset);
+
+	// for appending a popup menu (see example application)
+	BCMenu* AppendODPopupMenuA(LPCSTR lpstrText);
+	BCMenu* AppendODPopupMenuW(wchar_t *lpstrText);
+
+	// functions for inserting a menu option, use the InsertMenu call (see above define)
+	BOOL InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,const char *lpszNewItem=NULL,int nIconNormal=-1);
+	BOOL InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CImageList *il,int xoffset);
+	BOOL InsertMenuA(UINT nPosition,UINT nFlags,UINT nIDNewItem,const char *lpszNewItem,CBitmap *bmp);
+	BOOL InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem=0,wchar_t *lpszNewItem=NULL,int nIconNormal=-1);
+	BOOL InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CImageList *il,int xoffset);
+	BOOL InsertMenuW(UINT nPosition,UINT nFlags,UINT nIDNewItem,wchar_t *lpszNewItem,CBitmap *bmp);
+	BOOL InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags = MF_OWNERDRAW,UINT nID = 0,int nIconNormal = -1); 
+	BOOL InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags = MF_OWNERDRAW,UINT nID = 0,int nIconNormal = -1);  
+	BOOL InsertODMenuA(UINT nPosition,LPCSTR lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset);
+	BOOL InsertODMenuW(UINT nPosition,wchar_t *lpstrText,UINT nFlags,UINT nID,CImageList *il,int xoffset);
+
+	// functions for modifying a menu option, use the ModifyODMenu call (see above define)
+	BOOL ModifyODMenuA(const char *lpstrText,UINT nID=0,int nIconNormal=-1);
+	BOOL ModifyODMenuA(const char *lpstrText,UINT nID,CImageList *il,int xoffset);
+	BOOL ModifyODMenuA(const char *lpstrText,UINT nID,CBitmap *bmp);
+	BOOL ModifyODMenuA(const char *lpstrText,const char *OptionText,int nIconNormal);
+	BOOL ModifyODMenuW(wchar_t *lpstrText,UINT nID=0,int nIconNormal=-1);
+	BOOL ModifyODMenuW(wchar_t *lpstrText,UINT nID,CImageList *il,int xoffset);
+	BOOL ModifyODMenuW(wchar_t *lpstrText,UINT nID,CBitmap *bmp);
+	BOOL ModifyODMenuW(wchar_t *lpstrText,wchar_t *OptionText,int nIconNormal);
+	// use this method for adding a solid/hatched colored square beside a menu option
+	// courtesy of Warren Stevens
+	BOOL ModifyODMenuA(const char *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle=-1,CSize *pSize=NULL);
+	BOOL ModifyODMenuW(wchar_t *lpstrText,UINT nID,COLORREF fill,COLORREF border,int hatchstyle=-1,CSize *pSize=NULL);
+
+	// for deleting and removing menu options
+	BOOL	RemoveMenu(UINT uiId,UINT nFlags);
+	BOOL	DeleteMenu(UINT uiId,UINT nFlags);
+	// sPos means Seperator's position, since we have no way to find the seperator's position in the menu
+	// we have to specify them when we call the RemoveMenu to make sure the unused seperators are removed;
+	// sPos  = None no seperator removal;
+	//       = Head  seperator in front of this menu item;
+	//       = Tail  seperator right after this menu item;
+	//       = Both  seperators at both ends;
+	// remove the menu item based on their text, return -1 if not found, otherwise return the menu position;
+	int RemoveMenu(char* pText, BC_Seperator sPos=BCMENU_NONE);
+	int RemoveMenu(wchar_t* pText, BC_Seperator sPos=BCMENU_NONE);
+	int DeleteMenu(char* pText, BC_Seperator sPos=BCMENU_NONE);
+	int DeleteMenu(wchar_t* pText, BC_Seperator sPos=BCMENU_NONE);
+
+	// Destoying
+	virtual BOOL DestroyMenu();
+
+	// function for retrieving and setting a menu options text (use this function
+	// because it is ownerdrawn)
+	BOOL GetMenuText(UINT id,CString &string,UINT nFlags = MF_BYPOSITION);
+	BOOL SetMenuText(UINT id,CString string, UINT nFlags = MF_BYPOSITION);
+
+	// Getting a submenu from it's name or position
+	BCMenu* GetSubBCMenu(char* lpszSubMenuName);
+	BCMenu* GetSubBCMenu(wchar_t* lpszSubMenuName);
+	CMenu* GetSubMenu (LPCTSTR lpszSubMenuName);
+	CMenu* GetSubMenu (int nPos);
+	int GetMenuPosition(char* pText);
+	int GetMenuPosition(wchar_t* pText);
+
+	// Drawing: 
+	virtual void DrawItem( LPDRAWITEMSTRUCT);  // Draw an item
+	virtual void MeasureItem( LPMEASUREITEMSTRUCT );  // Measure an item
+
+	// Static functions used for handling menu's in the mainframe
+	static void UpdateMenu(CMenu *pmenu);
+	static BOOL IsMenu(CMenu *submenu);
+	static BOOL IsMenu(HMENU submenu);
+	static LRESULT FindKeyboardShortcut(UINT nChar,UINT nFlags,CMenu *pMenu);
+
+	// Function to set how menu is drawn, either original or XP style
+	static void SetMenuDrawMode(UINT mode){
+		BCMenu::original_drawmode=mode;
+		BCMenu::xp_drawmode=mode;
+	};
+	// Function to set how disabled items are drawn (mode=FALSE means they are not drawn selected)
+	static void SetSelectDisableMode(BOOL mode){
+		BCMenu::original_select_disabled=mode;
+		BCMenu::xp_select_disabled=mode;
+	};
+	static int BCMenu::GetMenuDrawMode(void);
+	static BOOL BCMenu::GetSelectDisableMode(void);
+
+	// how the bitmaps are drawn in XP Luna mode
+	static void SetXPBitmap3D(BOOL val){
+		BCMenu::xp_draw_3D_bitmaps=val;
+	};
+	static BOOL GetXPBitmap3D(void){return BCMenu::xp_draw_3D_bitmaps;}
+
+	// Customizing:
+	// Set icon size
+	void SetIconSize (int, int); 
+	// set the color in the bitmaps that is the background transparent color
+	void SetBitmapBackground(COLORREF color);
+	void UnSetBitmapBackground(void);
+	// obsolete functions for setting how menu images are dithered for disabled menu options
+	BOOL GetDisableOldStyle(void);
+	void SetDisableOldStyle(void);
+	void UnSetDisableOldStyle(void);
+	static COLORREF LightenColor(COLORREF col,double factor);
+	static COLORREF DarkenColor(COLORREF col,double factor);
+
+	// Miscellaneous Protected Member functions
+protected:
+	static BOOL IsNewShell(void);
+	static BOOL IsWinXPLuna(void);
+	static BOOL IsLunaMenuStyle(void);
+	static BOOL IsWindowsClassicTheme(void);
+	BCMenuData *BCMenu::FindMenuItem(UINT nID);
+	BCMenu *FindMenuOption(int nId,int& nLoc);
+	BCMenu *FindAnotherMenuOption(int nId,int& nLoc,CArray<BCMenu*,BCMenu*>&bcsubs,
+		CArray<int,int&>&bclocs);
+	BCMenuData *FindMenuOption(wchar_t *lpstrText);
+	void InsertSpaces(void);
+	void DrawCheckMark(CDC *pDC,int x,int y,COLORREF color);
+	void DrawRadioDot(CDC *pDC,int x,int y,COLORREF color);
+	BCMenuData *NewODMenu(UINT pos,UINT nFlags,UINT nID,CString string);
+	void SynchronizeMenu(void);
+	void BCMenu::InitializeMenuList(int value);
+	void BCMenu::DeleteMenuList(void);
+	BCMenuData *BCMenu::FindMenuList(UINT nID);
+	void DrawItem_Win9xNT2000 (LPDRAWITEMSTRUCT lpDIS);
+	void DrawItem_WinXP (LPDRAWITEMSTRUCT lpDIS);
+	BOOL Draw3DCheckmark(CDC *dc, const CRect& rc,BOOL bSelected,HBITMAP hbmCheck);
+	BOOL DrawXPCheckmark(CDC *dc, const CRect& rc, HBITMAP hbmCheck,COLORREF &colorout);
+	void DitherBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, 
+		int nHeight, HBITMAP hbm, int nXSrc, int nYSrc,COLORREF bgcolor);
+	void DitherBlt2(CDC *drawdc, int nXDest, int nYDest, int nWidth, 
+		int nHeight, CBitmap &bmp, int nXSrc, int nYSrc,COLORREF bgcolor);
+	BOOL GetBitmapFromImageList(CDC* pDC,CImageList *imglist,int nIndex,CBitmap &bmp);
+	BOOL ImageListDuplicate(CImageList *il,int xoffset,CImageList *newlist);
+	static WORD NumBitmapColors(LPBITMAPINFOHEADER lpBitmap);
+	void ColorBitmap(CDC* pDC, CBitmap& bmp,CSize bitmap_size,CSize icon_size,COLORREF fill,COLORREF border,int hatchstyle=-1);
+	void RemoveTopLevelOwnerDraw(void);
+	int GetMenuStart(void);
+	void GetFadedBitmap(CBitmap &bmp);
+	void GetShadowBitmap(CBitmap &bmp);
+	int AddToGlobalImageList(CImageList *il,int xoffset,int nID);
+	int GlobalImageListOffset(int nID);
+	BOOL CanDraw3DImageList(int offset);
+
+	// Member Variables
+protected:
+	CTypedPtrArray<CPtrArray, BCMenuData*> m_MenuList;  // Stores list of menu items 
+	// When loading an owner-drawn menu using a Resource, BCMenu must keep track of
+	// the popup menu's that it creates. Warning, this list *MUST* be destroyed
+	// last item first :)
+	CTypedPtrArray<CPtrArray, HMENU>  m_SubMenus;  // Stores list of sub-menus 
+	// Stores a list of all BCMenu's ever created 
+	static CTypedPtrArray<CPtrArray, HMENU>  m_AllSubMenus;
+	// Global ImageList
+	static CImageList m_AllImages;
+	static CArray<int,int&> m_AllImagesID;
+	// icon size
+	int m_iconX,m_iconY;
+	COLORREF m_bitmapBackground;
+	BOOL m_bitmapBackgroundFlag;
+	BOOL disable_old_style;
+	static UINT original_drawmode;
+	static BOOL original_select_disabled;
+	static UINT xp_drawmode;
+	static BOOL xp_select_disabled;
+	static BOOL xp_draw_3D_bitmaps;
+	CImageList *checkmaps;
+	BOOL checkmapsshare;
+	int m_selectcheck;
+	int m_unselectcheck;
+	BOOL m_bDynIcons;
+	BOOL m_loadmenu;
+}; 
+
+class BCMenuToolBar : public CToolBar{
+public:
+	BCMenuToolBar() : CToolBar() {m_iconX=m_iconY=0;}
+	BOOL LoadToolBar(LPCTSTR lpszResourceName);
+	BOOL LoadToolBar(UINT nIDResource){
+		return LoadToolBar(MAKEINTRESOURCE(nIDResource));
+	}
+	BOOL LoadBitmap(LPCTSTR lpszResourceName);
+	void GetIconSize(int &iconx,int &icony){iconx=m_iconX;icony=m_iconY;}
+protected:
+	int m_iconX,m_iconY;
+};
+
+#define BCMENU_USE_MEMDC
+
+#ifdef BCMENU_USE_MEMDC
+//////////////////////////////////////////////////
+// BCMenuMemDC - memory DC
+//
+// Author: Keith Rule
+// Email:  keithr@europa.com
+// Copyright 1996-1997, Keith Rule
+//
+// You may freely use or modify this code provided this
+// Copyright is included in all derived versions.
+//
+// History - 10/3/97 Fixed scrolling bug.
+//                   Added print support.
+//           25 feb 98 - fixed minor assertion bug
+//
+// This class implements a memory Device Context
+
+class BCMenuMemDC : public CDC
+{
+public:
+
+	// constructor sets up the memory DC
+	BCMenuMemDC(CDC* pDC,LPCRECT lpSrcRect) : CDC()
+	{
+		ASSERT(pDC != NULL);
+
+		m_rect.CopyRect(lpSrcRect);
+		m_pDC = pDC;
+		m_pOldBitmap = NULL;
+		m_bMemDC = !pDC->IsPrinting();
+
+		if (m_bMemDC)    // Create a Memory DC
+		{
+			CreateCompatibleDC(pDC);
+			m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height());
+			m_pOldBitmap = SelectObject(&m_bitmap);
+			SetWindowOrg(m_rect.left, m_rect.top);
+		}
+		else        // Make a copy of the relevent parts of the current DC for printing
+		{
+			m_bPrinting = pDC->m_bPrinting;
+			m_hDC       = pDC->m_hDC;
+			m_hAttribDC = pDC->m_hAttribDC;
+		}
+	}
+
+	// Destructor copies the contents of the mem DC to the original DC
+	~BCMenuMemDC()
+	{
+		if (m_bMemDC) 
+		{    
+			// Copy the offscreen bitmap onto the screen.
+			m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(),
+				this, m_rect.left, m_rect.top, SRCCOPY);
+
+			//Swap back the original bitmap.
+			SelectObject(m_pOldBitmap);
+		} else {
+			// All we need to do is replace the DC with an illegal value,
+			// this keeps us from accidently deleting the handles associated with
+			// the CDC that was passed to the constructor.
+			m_hDC = m_hAttribDC = NULL;
+		}
+	}
+
+	// Allow usage as a pointer
+	BCMenuMemDC* operator->() {return this;}
+
+	// Allow usage as a pointer
+	operator BCMenuMemDC*() {return this;}
+
+private:
+	CBitmap  m_bitmap;      // Offscreen bitmap
+	CBitmap* m_pOldBitmap;  // bitmap originally found in BCMenuMemDC
+	CDC*     m_pDC;         // Saves CDC passed in constructor
+	CRect    m_rect;        // Rectangle of drawing area.
+	BOOL     m_bMemDC;      // TRUE if CDC really is a Memory DC.
+};
+
+#endif
+
+#endif
+
+//*************************************************************************

+ 2559 - 0
VideoCapture/UI/BtnST.cpp

@@ -0,0 +1,2559 @@
+#include "stdafx.h"
+#include "BtnST.h"
+
+#ifdef	BTNST_USE_SOUND
+#pragma comment(lib, "winmm.lib")
+#include <Mmsystem.h>
+#endif
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CButtonST
+
+// Mask for control's type
+#define BS_TYPEMASK SS_TYPEMASK
+
+#ifndef	TTM_SETTITLE
+#define TTM_SETTITLEA           (WM_USER + 32)  // wParam = TTI_*, lParam = char* szTitle
+#define TTM_SETTITLEW           (WM_USER + 33)  // wParam = TTI_*, lParam = wchar* szTitle
+#ifdef	UNICODE
+#define TTM_SETTITLE            TTM_SETTITLEW
+#else
+#define TTM_SETTITLE            TTM_SETTITLEA
+#endif
+#endif
+
+#ifndef	TTS_BALLOON
+#define	TTS_BALLOON		0x40
+#endif
+
+CButtonST::CButtonST()
+{
+	m_bIsPressed		= FALSE;
+	m_bIsFocused		= FALSE;
+	m_bIsDisabled		= FALSE;
+	m_bMouseOnButton	= FALSE;
+
+	FreeResources(FALSE);
+
+	// Default type is "flat" button
+	m_bIsFlat = TRUE;
+	// Button will be tracked also if when the window is inactive (like Internet Explorer)
+	m_bAlwaysTrack = TRUE;
+  
+	// By default draw border in "flat" button 
+	m_bDrawBorder = TRUE; 
+  
+	// By default icon is aligned horizontally
+	m_byAlign = ST_ALIGN_HORIZ; 
+
+	// By default use usual pressed style
+	SetPressedStyle(BTNST_PRESSED_LEFTRIGHT, FALSE);
+  
+	// By default, for "flat" button, don't draw the focus rect
+	m_bDrawFlatFocus = FALSE;
+
+	// By default the button is not the default button
+	m_bIsDefault = FALSE;
+	// Invalid value, since type still unknown
+	m_nTypeStyle = BS_TYPEMASK;
+
+	// By default the button is not a checkbox
+	m_bIsCheckBox = FALSE;
+	m_nCheck = 0;
+
+	// Set default colors
+	SetDefaultColors(FALSE);
+
+	// No tooltip created
+	m_ToolTip.m_hWnd = NULL;
+	m_dwToolTipStyle = 0;
+
+	// Do not draw as a transparent button
+	m_bDrawTransparent = FALSE;
+	m_pbmpOldBk = NULL;
+
+	// No URL defined
+	SetURL(NULL);
+
+	// No cursor defined
+	m_hCursor = NULL;
+
+	// No associated menu
+#ifndef	BTNST_USE_BCMENU
+	m_hMenu = NULL;
+#endif
+	m_hParentWndMenu = NULL;
+	m_bMenuDisplayed = FALSE;
+
+	m_bShowDisabledBitmap = TRUE;
+
+	m_ptImageOrg.x = 3;
+	m_ptImageOrg.y = 3;
+
+	// No defined callbacks
+	::ZeroMemory(&m_csCallbacks, sizeof(m_csCallbacks));
+
+#ifdef	BTNST_USE_SOUND
+	// No defined sounds
+	::ZeroMemory(&m_csSounds, sizeof(m_csSounds));
+#endif
+} // End of CButtonST
+
+CButtonST::~CButtonST()
+{
+	m_font.DeleteObject();
+
+	// Restore old bitmap (if any)
+	if (m_dcBk.m_hDC && m_pbmpOldBk)
+	{
+		m_dcBk.SelectObject(m_pbmpOldBk);
+	} // if
+
+	FreeResources();
+
+	// Destroy the cursor (if any)
+	if (m_hCursor) ::DestroyCursor(m_hCursor);
+
+	// Destroy the menu (if any)
+#ifdef	BTNST_USE_BCMENU
+	if (m_menuPopup.m_hMenu)	m_menuPopup.DestroyMenu();
+#else
+	if (m_hMenu)	::DestroyMenu(m_hMenu);
+#endif
+} // End of ~CButtonST
+
+BEGIN_MESSAGE_MAP(CButtonST, CButton)
+    //{{AFX_MSG_MAP(CButtonST)
+	ON_WM_SETCURSOR()
+	ON_WM_KILLFOCUS()
+	ON_WM_MOUSEMOVE()
+	ON_WM_SYSCOLORCHANGE()
+	ON_CONTROL_REFLECT_EX(BN_CLICKED, OnClicked)
+	ON_WM_ACTIVATE()
+	ON_WM_ENABLE()
+	ON_WM_CANCELMODE()
+	ON_WM_GETDLGCODE()
+	ON_WM_CTLCOLOR_REFLECT()
+	//}}AFX_MSG_MAP
+#ifdef	BTNST_USE_BCMENU
+	ON_WM_MENUCHAR()
+	ON_WM_MEASUREITEM()
+#endif
+
+	ON_MESSAGE(BM_SETSTYLE, OnSetStyle)
+	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
+	ON_MESSAGE(BM_SETCHECK, OnSetCheck)
+	ON_MESSAGE(BM_GETCHECK, OnGetCheck)
+END_MESSAGE_MAP()
+
+void CButtonST::FreeResources(BOOL bCheckForNULL)
+{
+	if (bCheckForNULL)
+	{
+		// Destroy icons
+		// Note: the following two lines MUST be here! even if
+		// BoundChecker says they are unnecessary!
+		if (m_csIcons[0].hIcon)	::DestroyIcon(m_csIcons[0].hIcon);
+		if (m_csIcons[1].hIcon)	::DestroyIcon(m_csIcons[1].hIcon);
+
+		// Destroy bitmaps
+		if (m_csBitmaps[0].hBitmap)	::DeleteObject(m_csBitmaps[0].hBitmap);
+		if (m_csBitmaps[1].hBitmap)	::DeleteObject(m_csBitmaps[1].hBitmap);
+
+		// Destroy mask bitmaps
+		if (m_csBitmaps[0].hMask)	::DeleteObject(m_csBitmaps[0].hMask);
+		if (m_csBitmaps[1].hMask)	::DeleteObject(m_csBitmaps[1].hMask);
+	} // if
+
+	::ZeroMemory(&m_csIcons, sizeof(m_csIcons));
+	::ZeroMemory(&m_csBitmaps, sizeof(m_csBitmaps));
+} // End of FreeResources
+
+void CButtonST::PreSubclassWindow() 
+{
+	UINT nBS;
+
+	nBS = GetButtonStyle();
+
+	// Set initial control type
+	m_nTypeStyle = nBS & BS_TYPEMASK;
+
+	// Check if this is a checkbox
+	if (nBS & BS_CHECKBOX) m_bIsCheckBox = TRUE;
+
+	// Set initial default state flag
+	if (m_nTypeStyle == BS_DEFPUSHBUTTON)
+	{
+		// Set default state for a default button
+		m_bIsDefault = TRUE;
+
+		// Adjust style for default button
+		m_nTypeStyle = BS_PUSHBUTTON;
+	} // If
+
+	// You should not set the Owner Draw before this call
+	// (don't use the resource editor "Owner Draw" or
+	// ModifyStyle(0, BS_OWNERDRAW) before calling PreSubclassWindow() )
+	ASSERT(m_nTypeStyle != BS_OWNERDRAW);
+
+	// Switch to owner-draw
+	ModifyStyle(BS_TYPEMASK, BS_OWNERDRAW, SWP_FRAMECHANGED);
+
+#if 1 // »ñÈ¡³õʼ×ÖÌå;
+	CFont* cf = GetFont();
+	if(cf !=NULL)
+	{
+		cf->GetObject(sizeof(m_lf),&m_lf);
+	}
+	else
+	{
+		GetObject(GetStockObject(SYSTEM_FONT),sizeof(m_lf),&m_lf);
+	}
+
+	ReconstructFont();
+#endif
+
+	CButton::PreSubclassWindow();
+} // End of PreSubclassWindow
+
+UINT CButtonST::OnGetDlgCode() 
+{
+	UINT nCode = CButton::OnGetDlgCode();
+
+	// Tell the system if we want default state handling
+	// (losing default state always allowed)
+	nCode |= (m_bIsDefault ? DLGC_DEFPUSHBUTTON : DLGC_UNDEFPUSHBUTTON);
+
+	return nCode;
+} // End of OnGetDlgCode
+
+BOOL CButtonST::PreTranslateMessage(MSG* pMsg) 
+{
+	InitToolTip();
+	m_ToolTip.RelayEvent(pMsg);
+	
+	if (pMsg->message == WM_LBUTTONDBLCLK)
+		pMsg->message = WM_LBUTTONDOWN;
+
+	return CButton::PreTranslateMessage(pMsg);
+} // End of PreTranslateMessage
+
+HBRUSH CButtonST::CtlColor(CDC* pDC, UINT nCtlColor) 
+{
+	return (HBRUSH)::GetStockObject(NULL_BRUSH); 
+} // End of CtlColor
+
+void CButtonST::OnSysColorChange() 
+{
+	CButton::OnSysColorChange();
+
+	m_dcBk.DeleteDC();
+	m_bmpBk.DeleteObject();	
+	SetDefaultColors();
+} // End of OnSysColorChange
+
+LRESULT CButtonST::OnSetStyle(WPARAM wParam, LPARAM lParam)
+{
+	UINT nNewType = (wParam & BS_TYPEMASK);
+
+	// Update default state flag
+	if (nNewType == BS_DEFPUSHBUTTON)
+	{
+		m_bIsDefault = TRUE;
+	} // if
+	else if (nNewType == BS_PUSHBUTTON)
+	{
+		// Losing default state always allowed
+		m_bIsDefault = FALSE;
+	} // if
+
+	// Can't change control type after owner-draw is set.
+	// Let the system process changes to other style bits
+	// and redrawing, while keeping owner-draw style
+	return DefWindowProc(BM_SETSTYLE,
+		(wParam & ~BS_TYPEMASK) | BS_OWNERDRAW, lParam);
+} // End of OnSetStyle
+
+LRESULT CButtonST::OnSetCheck(WPARAM wParam, LPARAM lParam)
+{
+	ASSERT(m_bIsCheckBox);
+
+	switch (wParam)
+	{
+		case BST_CHECKED:
+		case BST_INDETERMINATE:	// Indeterminate state is handled like checked state
+			SetCheck(1);
+			break;
+		default:
+			SetCheck(0);
+			break;
+	} // switch
+
+	return 0;
+} // End of OnSetCheck
+
+LRESULT CButtonST::OnGetCheck(WPARAM wParam, LPARAM lParam)
+{
+	ASSERT(m_bIsCheckBox);
+	return GetCheck();
+} // End of OnGetCheck
+
+#ifdef	BTNST_USE_BCMENU
+LRESULT CButtonST::OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu) 
+{
+	LRESULT lResult;
+	if (BCMenu::IsMenu(pMenu))
+		lResult = BCMenu::FindKeyboardShortcut(nChar, nFlags, pMenu);
+	else
+		lResult = CButton::OnMenuChar(nChar, nFlags, pMenu);
+	return lResult;
+} // End of OnMenuChar
+#endif
+
+#ifdef	BTNST_USE_BCMENU
+void CButtonST::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
+{
+	BOOL bSetFlag = FALSE;
+	if (lpMeasureItemStruct->CtlType == ODT_MENU)
+	{
+		if (IsMenu((HMENU)lpMeasureItemStruct->itemID) && BCMenu::IsMenu((HMENU)lpMeasureItemStruct->itemID))
+		{
+			m_menuPopup.MeasureItem(lpMeasureItemStruct);
+			bSetFlag = TRUE;
+		} // if
+	} // if
+	if (!bSetFlag) CButton::OnMeasureItem(nIDCtl, lpMeasureItemStruct);
+} // End of OnMeasureItem
+#endif
+
+void CButtonST::OnEnable(BOOL bEnable) 
+{
+	CButton::OnEnable(bEnable);
+	
+	if (bEnable == FALSE)	
+	{
+		CWnd*	pWnd = GetParent()->GetNextDlgTabItem(this);
+		if (pWnd)
+			pWnd->SetFocus();
+		else
+			GetParent()->SetFocus();
+
+		CancelHover();
+	} // if
+} // End of OnEnable
+
+void CButtonST::OnKillFocus(CWnd * pNewWnd)
+{
+	CButton::OnKillFocus(pNewWnd);
+	CancelHover();
+} // End of OnKillFocus
+
+void CButtonST::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized) 
+{
+	CButton::OnActivate(nState, pWndOther, bMinimized);
+	if (nState == WA_INACTIVE)	CancelHover();
+} // End of OnActivate
+
+void CButtonST::OnCancelMode() 
+{
+	CButton::OnCancelMode();
+	CancelHover();
+} // End of OnCancelMode
+
+BOOL CButtonST::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
+{
+	// If a cursor was specified then use it!
+	if (m_hCursor != NULL)
+	{
+		::SetCursor(m_hCursor);
+		return TRUE;
+	} // if
+
+	return CButton::OnSetCursor(pWnd, nHitTest, message);
+} // End of OnSetCursor
+
+void CButtonST::CancelHover()
+{
+	// Only for flat buttons
+	if (m_bIsFlat)
+	{
+		if (m_bMouseOnButton)
+		{
+			m_bMouseOnButton = FALSE;
+			Invalidate();
+		} // if
+	} // if
+} // End of CancelHover
+
+void CButtonST::OnMouseMove(UINT nFlags, CPoint point)
+{
+	CWnd*				wndUnderMouse = NULL;
+	CWnd*				wndActive = this;
+	TRACKMOUSEEVENT		csTME;
+
+	CButton::OnMouseMove(nFlags, point);
+
+	ClientToScreen(&point);
+	wndUnderMouse = WindowFromPoint(point);
+
+	// If the mouse enter the button with the left button pressed then do nothing
+	if (nFlags & MK_LBUTTON && m_bMouseOnButton == FALSE) return;
+
+	// If our button is not flat then do nothing
+	if (m_bIsFlat == FALSE) return;
+
+	if (m_bAlwaysTrack == FALSE)	wndActive = GetActiveWindow();
+
+	if (wndUnderMouse && wndUnderMouse->m_hWnd == m_hWnd && wndActive)
+	{
+		if (!m_bMouseOnButton)
+		{
+			m_bMouseOnButton = TRUE;
+
+			Invalidate();
+
+#ifdef	BTNST_USE_SOUND
+			// Play sound ?
+			if (m_csSounds[0].lpszSound)
+				::PlaySound(m_csSounds[0].lpszSound, m_csSounds[0].hMod, m_csSounds[0].dwFlags);
+#endif
+
+			csTME.cbSize = sizeof(csTME);
+			csTME.dwFlags = TME_LEAVE;
+			csTME.hwndTrack = m_hWnd;
+			::_TrackMouseEvent(&csTME);
+		} // if
+	} else CancelHover();
+} // End of OnMouseMove
+
+// Handler for WM_MOUSELEAVE
+LRESULT CButtonST::OnMouseLeave(WPARAM wParam, LPARAM lParam)
+{
+	CancelHover();
+	return 0;
+} // End of OnMouseLeave
+
+BOOL CButtonST::OnClicked() 
+{	
+	SetFocus();
+
+#ifdef	BTNST_USE_SOUND
+	// Play sound ?
+	if (m_csSounds[1].lpszSound)
+		::PlaySound(m_csSounds[1].lpszSound, m_csSounds[1].hMod, m_csSounds[1].dwFlags);
+#endif
+
+	if (m_bIsCheckBox)
+	{
+		m_nCheck = !m_nCheck;
+		Invalidate();
+	} // if
+	else
+	{
+		// Handle the menu (if any)
+#ifdef	BTNST_USE_BCMENU
+		if (m_menuPopup.m_hMenu)
+#else
+		if (m_hMenu)
+#endif
+		{
+			CRect	rWnd;
+			GetWindowRect(rWnd);
+
+			m_bMenuDisplayed = TRUE;
+			Invalidate();
+
+#ifdef	BTNST_USE_BCMENU
+			BCMenu* psub = (BCMenu*)m_menuPopup.GetSubMenu(0);
+			if (m_csCallbacks.hWnd)	::SendMessage(m_csCallbacks.hWnd, m_csCallbacks.nMessage, (WPARAM)psub, m_csCallbacks.lParam);
+			DWORD dwRetValue = psub->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, rWnd.left, rWnd.bottom, this, NULL);
+#else
+			HMENU hSubMenu = ::GetSubMenu(m_hMenu, 0);
+			if (m_csCallbacks.hWnd)	::SendMessage(m_csCallbacks.hWnd, m_csCallbacks.nMessage, (WPARAM)hSubMenu, m_csCallbacks.lParam);
+			DWORD dwRetValue = ::TrackPopupMenuEx(hSubMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, rWnd.left, rWnd.bottom, m_hParentWndMenu, NULL);
+#endif
+
+			m_bMenuDisplayed = FALSE;
+			Invalidate();
+
+			if (dwRetValue)
+				::PostMessage(m_hParentWndMenu, WM_COMMAND, MAKEWPARAM(dwRetValue, 0), (LPARAM)NULL);
+		} // if
+		else
+		{
+			// Handle the URL (if any)
+			if (_tcslen(m_szURL) > 0)
+			{
+				SHELLEXECUTEINFO	csSEI;
+
+				memset(&csSEI, 0, sizeof(csSEI));
+				csSEI.cbSize = sizeof(SHELLEXECUTEINFO);
+				csSEI.fMask = SEE_MASK_FLAG_NO_UI;
+				csSEI.lpVerb = _T("open");
+				csSEI.lpFile = m_szURL;
+				csSEI.nShow = SW_SHOWMAXIMIZED;
+				::ShellExecuteEx(&csSEI);
+			} // if
+		} // else
+	} // else
+
+	return FALSE;
+} // End of OnClicked
+
+void CButtonST::DrawItem(LPDRAWITEMSTRUCT lpDIS)
+{
+	CDC*	pDC = CDC::FromHandle(lpDIS->hDC);
+
+	// Checkbox?
+	if (m_bIsCheckBox)
+	{
+		m_bIsPressed  =  (lpDIS->itemState & ODS_SELECTED) || (m_nCheck != 0);
+	} // if
+	else	// Normal button OR other button style ...
+	{
+		m_bIsPressed = (lpDIS->itemState & ODS_SELECTED);
+
+		// If there is a menu and it's displayed, draw the button as pressed
+		if (
+#ifdef	BTNST_USE_BCMENU
+			m_menuPopup.m_hMenu 
+#else
+			m_hMenu 
+#endif
+			&& m_bMenuDisplayed)	m_bIsPressed = TRUE;
+	} // else
+
+	m_bIsFocused  = (lpDIS->itemState & ODS_FOCUS);
+	m_bIsDisabled = (lpDIS->itemState & ODS_DISABLED);
+
+	CRect itemRect = lpDIS->rcItem;
+
+	pDC->SetBkMode(TRANSPARENT);
+
+	// Prepare draw... paint button background
+
+	// Draw transparent?
+	if (m_bDrawTransparent)
+		PaintBk(pDC);
+	else
+		OnDrawBackground(pDC, &itemRect);
+
+	// Draw button border
+	OnDrawBorder(pDC, &itemRect);
+
+	// Read the button's title
+	CString sTitle;
+	GetWindowText(sTitle);
+
+	CRect captionRect = lpDIS->rcItem;
+
+	// Draw the icon
+	if (m_csIcons[0].hIcon)
+	{
+		DrawTheIcon(pDC, !sTitle.IsEmpty(), &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
+	} // if
+
+	if (m_csBitmaps[0].hBitmap)
+	{
+		pDC->SetBkColor(RGB(255,255,255));
+		DrawTheBitmap(pDC, !sTitle.IsEmpty(), &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
+	} // if
+
+	// Write the button title (if any)
+	if (sTitle.IsEmpty() == FALSE)
+	{
+		DrawTheText(pDC, (LPCTSTR)sTitle, &lpDIS->rcItem, &captionRect, m_bIsPressed, m_bIsDisabled);
+	} // if
+
+	if (m_bIsFlat == FALSE || (m_bIsFlat && m_bDrawFlatFocus))
+	{
+		// Draw the focus rect
+		if (m_bIsFocused)
+		{
+			CRect focusRect = itemRect;
+			focusRect.DeflateRect(3, 3);
+			pDC->DrawFocusRect(&focusRect);
+		} // if
+	} // if
+} // End of DrawItem
+
+void CButtonST::PaintBk(CDC* pDC)
+{
+	CClientDC clDC(GetParent());
+	CRect rect;
+	CRect rect1;
+
+	GetClientRect(rect);
+
+	GetWindowRect(rect1);
+	GetParent()->ScreenToClient(rect1);
+
+	if (m_dcBk.m_hDC == NULL)
+	{
+		m_dcBk.CreateCompatibleDC(&clDC);
+		m_bmpBk.CreateCompatibleBitmap(&clDC, rect.Width(), rect.Height());
+		m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk);
+		m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), &clDC, rect1.left, rect1.top, SRCCOPY);
+	} // if
+
+	pDC->BitBlt(0, 0, rect.Width(), rect.Height(), &m_dcBk, 0, 0, SRCCOPY);
+} // End of PaintBk
+
+HBITMAP CButtonST::CreateBitmapMask(HBITMAP hSourceBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTransColor)
+{
+	HBITMAP		hMask		= NULL;
+	HDC			hdcSrc		= NULL;
+	HDC			hdcDest		= NULL;
+	HBITMAP		hbmSrcT		= NULL;
+	HBITMAP		hbmDestT	= NULL;
+	COLORREF	crSaveBk;
+	COLORREF	crSaveDestText;
+
+	hMask = ::CreateBitmap(dwWidth, dwHeight, 1, 1, NULL);
+	if (hMask == NULL)	return NULL;
+
+	hdcSrc	= ::CreateCompatibleDC(NULL);
+	hdcDest	= ::CreateCompatibleDC(NULL);
+
+	hbmSrcT = (HBITMAP)::SelectObject(hdcSrc, hSourceBitmap);
+	hbmDestT = (HBITMAP)::SelectObject(hdcDest, hMask);
+
+	crSaveBk = ::SetBkColor(hdcSrc, crTransColor);
+
+	::BitBlt(hdcDest, 0, 0, dwWidth, dwHeight, hdcSrc, 0, 0, SRCCOPY);
+
+	crSaveDestText = ::SetTextColor(hdcSrc, RGB(255, 255, 255));
+	::SetBkColor(hdcSrc,RGB(0, 0, 0));
+
+	::BitBlt(hdcSrc, 0, 0, dwWidth, dwHeight, hdcDest, 0, 0, SRCAND);
+
+	SetTextColor(hdcDest, crSaveDestText);
+
+	::SetBkColor(hdcSrc, crSaveBk);
+	::SelectObject(hdcSrc, hbmSrcT);
+	::SelectObject(hdcDest, hbmDestT);
+
+	::DeleteDC(hdcSrc);
+	::DeleteDC(hdcDest);
+
+	return hMask;
+} // End of CreateBitmapMask
+
+//
+// Parameters:
+//		[IN]	bHasTitle
+//				TRUE if the button has a text
+//		[IN]	rpItem
+//				A pointer to a RECT structure indicating the allowed paint area
+//		[IN/OUT]rpTitle
+//				A pointer to a CRect object indicating the paint area reserved for the
+//				text. This structure will be modified if necessary.
+//		[IN]	bIsPressed
+//				TRUE if the button is currently pressed
+//		[IN]	dwWidth
+//				Width of the image (icon or bitmap)
+//		[IN]	dwHeight
+//				Height of the image (icon or bitmap)
+//		[OUT]	rpImage
+//				A pointer to a CRect object that will receive the area available to the image
+//
+void CButtonST::PrepareImageRect(BOOL bHasTitle, RECT* rpItem, CRect* rpTitle, BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, CRect* rpImage)
+{
+	CRect rBtn;
+
+	rpImage->CopyRect(rpItem);
+
+	switch (m_byAlign)
+	{
+		case ST_ALIGN_HORIZ:
+			if (bHasTitle == FALSE)
+			{
+				// Center image horizontally
+				rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
+			}
+			else
+			{
+				// Image must be placed just inside the focus rect
+				rpImage->left += m_ptImageOrg.x;  
+				rpTitle->left += dwWidth + m_ptImageOrg.x;
+			}
+			// Center image vertically
+			rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);
+			break;
+
+		case ST_ALIGN_HORIZ_RIGHT:
+			GetClientRect(&rBtn);
+			if (bHasTitle == FALSE)
+			{
+				// Center image horizontally
+				rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
+			}
+			else
+			{
+				// Image must be placed just inside the focus rect
+				rpTitle->right = rpTitle->Width() - dwWidth - m_ptImageOrg.x;
+				rpTitle->left = m_ptImageOrg.x;
+				rpImage->left = rBtn.right - dwWidth - m_ptImageOrg.x;
+				// Center image vertically
+				rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);
+			}
+			break;
+		
+		case ST_ALIGN_VERT:
+			// Center image horizontally
+			rpImage->left += ((rpImage->Width() - (long)dwWidth)/2);
+			if (bHasTitle == FALSE)
+			{
+				// Center image vertically
+				rpImage->top += ((rpImage->Height() - (long)dwHeight)/2);           
+			}
+			else
+			{
+				rpImage->top = m_ptImageOrg.y;
+				rpTitle->top += dwHeight;
+			}
+			break;
+
+		case ST_ALIGN_OVERLAP:
+			break;
+	} // switch
+    
+	// If button is pressed then press image also
+	if (bIsPressed && m_bIsCheckBox == FALSE)
+		rpImage->OffsetRect(m_ptPressedOffset.x, m_ptPressedOffset.y);
+} // End of PrepareImageRect
+
+void CButtonST::DrawTheIcon(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
+{
+	BYTE		byIndex		= 0;
+
+	// Select the icon to use
+	if ((m_bIsCheckBox && bIsPressed) || (!m_bIsCheckBox && (bIsPressed || m_bMouseOnButton)))
+		byIndex = 0;
+	else
+		byIndex = (m_csIcons[1].hIcon == NULL ? 0 : 1);
+
+	CRect	rImage;
+	PrepareImageRect(bHasTitle, rpItem, rpCaption, bIsPressed, m_csIcons[byIndex].dwWidth, m_csIcons[byIndex].dwHeight, &rImage);
+
+	// Ole'!
+	pDC->DrawState(	rImage.TopLeft(),
+					rImage.Size(), 
+					m_csIcons[byIndex].hIcon,
+					(bIsDisabled ? DSS_DISABLED : DSS_NORMAL), 
+					(CBrush*)NULL);
+} // End of DrawTheIcon
+
+void CButtonST::DrawTheBitmap(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
+{
+	HDC			hdcBmpMem	= NULL;
+	HBITMAP		hbmOldBmp	= NULL;
+	HDC			hdcMem		= NULL;
+	HBITMAP		hbmT		= NULL;
+
+	BYTE		byIndex		= 0;
+
+	// Select the bitmap to use
+	if ((m_bIsCheckBox && bIsPressed) || (!m_bIsCheckBox && (bIsPressed || m_bMouseOnButton)))
+		byIndex = 0;
+	else
+		byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
+
+	CRect	rImage;
+	PrepareImageRect(bHasTitle, rpItem, rpCaption, bIsPressed, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, &rImage);
+
+	hdcBmpMem = ::CreateCompatibleDC(pDC->m_hDC);
+
+	hbmOldBmp = (HBITMAP)::SelectObject(hdcBmpMem, m_csBitmaps[byIndex].hBitmap);
+
+	hdcMem = ::CreateCompatibleDC(NULL);
+
+	hbmT = (HBITMAP)::SelectObject(hdcMem, m_csBitmaps[byIndex].hMask);
+
+	if (bIsDisabled && m_bShowDisabledBitmap)
+	{
+		HDC		hDC = NULL;
+		HBITMAP	hBitmap = NULL;
+
+		hDC = ::CreateCompatibleDC(pDC->m_hDC);
+		hBitmap = ::CreateCompatibleBitmap(pDC->m_hDC, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight);
+		HBITMAP	hOldBmp2 = (HBITMAP)::SelectObject(hDC, hBitmap);
+
+		RECT	rRect;
+		rRect.left = 0;
+		rRect.top = 0;
+		rRect.right = rImage.right + 1;
+		rRect.bottom = rImage.bottom + 1;
+		::FillRect(hDC, &rRect, (HBRUSH)RGB(255, 255, 255));
+
+		COLORREF crOldColor = ::SetBkColor(hDC, RGB(255,255,255));
+
+		::BitBlt(hDC, 0, 0, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
+		::BitBlt(hDC, 0, 0, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);
+
+		::SetBkColor(hDC, crOldColor);
+		::SelectObject(hDC, hOldBmp2);
+		::DeleteDC(hDC);
+
+		pDC->DrawState(	CPoint(rImage.left/*+1*/, rImage.top), 
+						CSize(m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight), 
+						hBitmap, DST_BITMAP | DSS_DISABLED);
+
+		::DeleteObject(hBitmap);
+	} // if
+	else
+	{
+		::BitBlt(pDC->m_hDC, rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
+
+		::BitBlt(pDC->m_hDC, rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);
+	} // else
+
+	::SelectObject(hdcMem, hbmT);
+	::DeleteDC(hdcMem);
+
+	::SelectObject(hdcBmpMem, hbmOldBmp);
+	::DeleteDC(hdcBmpMem);
+} // End of DrawTheBitmap
+
+void CButtonST::DrawTheText(CDC* pDC, LPCTSTR lpszText, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled)
+{
+	// Draw the button's title
+	// If button is pressed then "press" title also
+	if (m_bIsPressed && m_bIsCheckBox == FALSE)
+		rpCaption->OffsetRect(m_ptPressedOffset.x, m_ptPressedOffset.y);
+
+	// ONLY FOR DEBUG 
+	//CBrush brBtnShadow(RGB(255, 0, 0));
+	//pDC->FrameRect(rCaption, &brBtnShadow);
+
+	// Center text
+	CRect centerRect = rpCaption;
+	// ÉèÖÃ×ÖÌå;
+	CFont *pOldFont = pDC->SelectObject(&m_font);
+	pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER | DT_CALCRECT);
+	rpCaption->OffsetRect((centerRect.Width() - rpCaption->Width())/2, (centerRect.Height() - rpCaption->Height())/2);
+	/* RFU
+	rpCaption->OffsetRect(0, (centerRect.Height() - rpCaption->Height())/2);
+	rpCaption->OffsetRect((centerRect.Width() - rpCaption->Width())-4, (centerRect.Height() - rpCaption->Height())/2);
+	*/
+
+	pDC->SetBkMode(TRANSPARENT);
+	/*
+	pDC->DrawState(rCaption->TopLeft(), rCaption->Size(), (LPCTSTR)sTitle, (bIsDisabled ? DSS_DISABLED : DSS_NORMAL), 
+					TRUE, 0, (CBrush*)NULL);
+	*/
+	if (m_bIsDisabled)
+	{
+		rpCaption->OffsetRect(1, 1);
+		pDC->SetTextColor(::GetSysColor(COLOR_3DHILIGHT));
+		pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
+		rpCaption->OffsetRect(-1, -1);
+		pDC->SetTextColor(::GetSysColor(COLOR_3DSHADOW));
+		pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
+	} // if
+	else
+	{
+		if (m_bMouseOnButton || m_bIsPressed) 
+		{
+			pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_IN]);
+			pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_IN]);
+		} // if
+		else 
+		{
+			if (m_bIsFocused)
+			{ 
+				pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_FOCUS]); 
+				pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_FOCUS]); 
+			} // if
+			else 
+			{
+				pDC->SetTextColor(m_crColors[BTNST_COLOR_FG_OUT]); 
+				pDC->SetBkColor(m_crColors[BTNST_COLOR_BK_OUT]); 
+			} // else
+		} // else
+		pDC->DrawText(lpszText, -1, rpCaption, DT_WORDBREAK | DT_CENTER);
+	} // if
+
+	pDC->SelectObject(pOldFont);
+} // End of DrawTheText
+
+// This function creates a grayscale bitmap starting from a given bitmap.
+// The resulting bitmap will have the same size of the original one.
+//
+// Parameters:
+//		[IN]	hBitmap
+//				Handle to the original bitmap.
+//		[IN]	dwWidth
+//				Specifies the bitmap width, in pixels.
+//		[IN]	dwHeight
+//				Specifies the bitmap height, in pixels.
+//		[IN]	crTrans
+//				Color to be used as transparent color. This color will be left unchanged.
+//
+// Return value:
+//		If the function succeeds, the return value is the handle to the newly created
+//		grayscale bitmap.
+//		If the function fails, the return value is NULL.
+//
+HBITMAP CButtonST::CreateGrayscaleBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans)
+{
+	HBITMAP		hGrayBitmap = NULL;
+	HDC			hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
+	HBITMAP		hOldBmp1 = NULL, hOldBmp2 = NULL;
+
+	hMainDC = ::GetDC(NULL);
+	if (hMainDC == NULL)	return NULL;
+	hMemDC1 = ::CreateCompatibleDC(hMainDC);
+	if (hMemDC1 == NULL)
+	{
+		::ReleaseDC(NULL, hMainDC);
+		return NULL;
+	} // if
+	hMemDC2 = ::CreateCompatibleDC(hMainDC);
+	if (hMemDC2 == NULL)
+	{
+		::DeleteDC(hMemDC1);
+		::ReleaseDC(NULL, hMainDC);
+		return NULL;
+	} // if
+
+	hGrayBitmap = ::CreateCompatibleBitmap(hMainDC, dwWidth, dwHeight);
+	if (hGrayBitmap)
+	{
+		hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, hGrayBitmap);
+		hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, hBitmap);
+
+		//::BitBlt(hMemDC1, 0, 0, dwWidth, dwHeight, hMemDC2, 0, 0, SRCCOPY);
+
+		DWORD		dwLoopY = 0, dwLoopX = 0;
+		COLORREF	crPixel = 0;
+		BYTE		byNewPixel = 0;
+
+		for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
+		{
+			for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
+			{
+				crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
+				byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114));
+
+				if (crPixel != crTrans)
+					::SetPixel(hMemDC1, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel));
+				else
+					::SetPixel(hMemDC1, dwLoopX, dwLoopY, crPixel);
+			} // for
+		} // for
+
+		::SelectObject(hMemDC1, hOldBmp1);
+		::SelectObject(hMemDC2, hOldBmp2);
+	} // if
+
+	::DeleteDC(hMemDC1);
+	::DeleteDC(hMemDC2);
+	::ReleaseDC(NULL, hMainDC);
+
+	return hGrayBitmap;
+} // End of CreateGrayscaleBitmap
+
+// This function creates a bitmap that is 25% darker than the original.
+// The resulting bitmap will have the same size of the original one.
+//
+// Parameters:
+//		[IN]	hBitmap
+//				Handle to the original bitmap.
+//		[IN]	dwWidth
+//				Specifies the bitmap width, in pixels.
+//		[IN]	dwHeight
+//				Specifies the bitmap height, in pixels.
+//		[IN]	crTrans
+//				Color to be used as transparent color. This color will be left unchanged.
+//
+// Return value:
+//		If the function succeeds, the return value is the handle to the newly created
+//		darker bitmap.
+//		If the function fails, the return value is NULL.
+//
+HBITMAP CButtonST::CreateDarkerBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans)
+{
+	HBITMAP		hGrayBitmap = NULL;
+	HDC			hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
+	HBITMAP		hOldBmp1 = NULL, hOldBmp2 = NULL;
+
+	hMainDC = ::GetDC(NULL);
+	if (hMainDC == NULL)	return NULL;
+	hMemDC1 = ::CreateCompatibleDC(hMainDC);
+	if (hMemDC1 == NULL)
+	{
+		::ReleaseDC(NULL, hMainDC);
+		return NULL;
+	} // if
+	hMemDC2 = ::CreateCompatibleDC(hMainDC);
+	if (hMemDC2 == NULL)
+	{
+		::DeleteDC(hMemDC1);
+		::ReleaseDC(NULL, hMainDC);
+		return NULL;
+	} // if
+
+	hGrayBitmap = ::CreateCompatibleBitmap(hMainDC, dwWidth, dwHeight);
+	if (hGrayBitmap)
+	{
+		hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, hGrayBitmap);
+		hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, hBitmap);
+
+		//::BitBlt(hMemDC1, 0, 0, dwWidth, dwHeight, hMemDC2, 0, 0, SRCCOPY);
+
+		DWORD		dwLoopY = 0, dwLoopX = 0;
+		COLORREF	crPixel = 0;
+
+		for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
+		{
+			for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
+			{
+				crPixel = ::GetPixel(hMemDC2, dwLoopX, dwLoopY);
+
+				if (crPixel != crTrans)
+					::SetPixel(hMemDC1, dwLoopX, dwLoopY, DarkenColor(crPixel, 0.25));
+				else
+					::SetPixel(hMemDC1, dwLoopX, dwLoopY, crPixel);
+			} // for
+		} // for
+
+		::SelectObject(hMemDC1, hOldBmp1);
+		::SelectObject(hMemDC2, hOldBmp2);
+	} // if
+
+	::DeleteDC(hMemDC1);
+	::DeleteDC(hMemDC2);
+	::ReleaseDC(NULL, hMainDC);
+
+	return hGrayBitmap;
+} // End of CreateDarkerBitmap
+
+// This function creates a grayscale icon starting from a given icon.
+// The resulting icon will have the same size of the original one.
+//
+// Parameters:
+//		[IN]	hIcon
+//				Handle to the original icon.
+//
+// Return value:
+//		If the function succeeds, the return value is the handle to the newly created
+//		grayscale icon.
+//		If the function fails, the return value is NULL.
+//
+// Updates:
+//		26/Nov/2002	Restored 1 BitBlt operation
+//		03/May/2002	Removed dependancy from m_hWnd
+//					Removed 1 BitBlt operation
+//
+HICON CButtonST::CreateGrayscaleIcon(HICON hIcon)
+{
+	HICON		hGrayIcon = NULL;
+	HDC			hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
+	BITMAP		bmp;
+	HBITMAP		hOldBmp1 = NULL, hOldBmp2 = NULL;
+	ICONINFO	csII, csGrayII;
+	BOOL		bRetValue = FALSE;
+
+	bRetValue = ::GetIconInfo(hIcon, &csII);
+	if (bRetValue == FALSE)	return NULL;
+
+	hMainDC = ::GetDC(NULL);
+	hMemDC1 = ::CreateCompatibleDC(hMainDC);
+	hMemDC2 = ::CreateCompatibleDC(hMainDC);
+	if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL)	return NULL;
+  
+	if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
+	{
+		DWORD	dwWidth = csII.xHotspot*2;
+		DWORD	dwHeight = csII.yHotspot*2;
+
+		csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
+		if (csGrayII.hbmColor)
+		{
+			hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
+			hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
+
+			//::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
+
+			DWORD		dwLoopY = 0, dwLoopX = 0;
+			COLORREF	crPixel = 0;
+			BYTE		byNewPixel = 0;
+
+			for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
+			{
+				for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
+				{
+					crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
+					byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114));
+
+					if (crPixel)	
+						::SetPixel(hMemDC2, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel));
+					else
+						::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
+				} // for
+			} // for
+
+			::SelectObject(hMemDC1, hOldBmp1);
+			::SelectObject(hMemDC2, hOldBmp2);
+
+			csGrayII.hbmMask = csII.hbmMask;
+
+			csGrayII.fIcon = TRUE;
+			hGrayIcon = ::CreateIconIndirect(&csGrayII);
+		} // if
+
+		::DeleteObject(csGrayII.hbmColor);
+		//::DeleteObject(csGrayII.hbmMask);
+	} // if
+
+	::DeleteObject(csII.hbmColor);
+	::DeleteObject(csII.hbmMask);
+	::DeleteDC(hMemDC1);
+	::DeleteDC(hMemDC2);
+	::ReleaseDC(NULL, hMainDC);
+
+	return hGrayIcon;
+} // End of CreateGrayscaleIcon
+
+// This function creates a icon that is 25% darker than the original.
+// The resulting icon will have the same size of the original one.
+//
+// Parameters:
+//		[IN]	hIcon
+//				Handle to the original icon.
+//
+// Return value:
+//		If the function succeeds, the return value is the handle to the newly created
+//		darker icon.
+//		If the function fails, the return value is NULL.
+//
+HICON CButtonST::CreateDarkerIcon(HICON hIcon)
+{
+	HICON		hGrayIcon = NULL;
+	HDC			hMainDC = NULL, hMemDC1 = NULL, hMemDC2 = NULL;
+	BITMAP		bmp;
+	HBITMAP		hOldBmp1 = NULL, hOldBmp2 = NULL;
+	ICONINFO	csII, csGrayII;
+	BOOL		bRetValue = FALSE;
+
+	bRetValue = ::GetIconInfo(hIcon, &csII);
+	if (bRetValue == FALSE)	return NULL;
+
+	hMainDC = ::GetDC(NULL);
+	hMemDC1 = ::CreateCompatibleDC(hMainDC);
+	hMemDC2 = ::CreateCompatibleDC(hMainDC);
+	if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL)	return NULL;
+  
+	if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp))
+	{
+		DWORD	dwWidth = csII.xHotspot*2;
+		DWORD	dwHeight = csII.yHotspot*2;
+
+		csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
+		if (csGrayII.hbmColor)
+		{
+			hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor);
+			hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor);
+
+			//::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY);
+
+			DWORD		dwLoopY = 0, dwLoopX = 0;
+			COLORREF	crPixel = 0;
+
+			for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++)
+			{
+				for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++)
+				{
+					crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY);
+
+					if (crPixel)	
+						::SetPixel(hMemDC2, dwLoopX, dwLoopY, DarkenColor(crPixel, 0.25));
+					else
+						::SetPixel(hMemDC2, dwLoopX, dwLoopY, crPixel);
+				} // for
+			} // for
+
+			::SelectObject(hMemDC1, hOldBmp1);
+			::SelectObject(hMemDC2, hOldBmp2);
+
+			csGrayII.hbmMask = csII.hbmMask;
+
+			csGrayII.fIcon = TRUE;
+			hGrayIcon = ::CreateIconIndirect(&csGrayII);
+		} // if
+
+		::DeleteObject(csGrayII.hbmColor);
+		//::DeleteObject(csGrayII.hbmMask);
+	} // if
+
+	::DeleteObject(csII.hbmColor);
+	::DeleteObject(csII.hbmMask);
+	::DeleteDC(hMemDC1);
+	::DeleteDC(hMemDC2);
+	::ReleaseDC(NULL, hMainDC);
+
+	return hGrayIcon;
+} // End of CreateDarkerIcon
+
+COLORREF CButtonST::DarkenColor(COLORREF crColor, double dFactor)
+{
+	if (dFactor > 0.0 && dFactor <= 1.0)
+	{
+		BYTE red,green,blue,lightred,lightgreen,lightblue;
+		red = GetRValue(crColor);
+		green = GetGValue(crColor);
+		blue = GetBValue(crColor);
+		lightred = (BYTE)(red-(dFactor * red));
+		lightgreen = (BYTE)(green-(dFactor * green));
+		lightblue = (BYTE)(blue-(dFactor * blue));
+		crColor = RGB(lightred,lightgreen,lightblue);
+	} // if
+
+	return crColor;
+} // End of DarkenColor
+
+// This function assigns icons to the button.
+// Any previous icon or bitmap will be removed.
+//
+// Parameters:
+//		[IN]	nIconIn
+//				ID number of the icon resource to show when the mouse is over the button.
+//				Pass NULL to remove any icon from the button.
+//		[IN]	nCxDesiredIn
+//				Specifies the width, in pixels, of the icon to load.
+//		[IN]	nCyDesiredIn
+//				Specifies the height, in pixels, of the icon to load.
+//		[IN]	nIconOut
+//				ID number of the icon resource to show when the mouse is outside the button.
+//				Can be NULL.
+//				If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
+//				icon will be automatically created starting from nIconIn and converted to grayscale.
+//				If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
+//				icon will be automatically created 25% darker starting from nIconIn.
+//		[IN]	nCxDesiredOut
+//				Specifies the width, in pixels, of the icon to load.
+//		[IN]	nCyDesiredOut
+//				Specifies the height, in pixels, of the icon to load.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+DWORD CButtonST::SetIcon(int nIconIn, int nCxDesiredIn, int nCyDesiredIn, int nIconOut, int nCxDesiredOut, int nCyDesiredOut)
+{
+	HICON		hIconIn			= NULL;
+	HICON		hIconOut		= NULL;
+	HINSTANCE	hInstResource	= NULL;
+
+	// Find correct resource handle
+	hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconIn), RT_GROUP_ICON);
+
+	// Set icon when the mouse is IN the button
+	hIconIn = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconIn), IMAGE_ICON, nCxDesiredIn, nCyDesiredIn, 0);
+
+  	// Set icon when the mouse is OUT the button
+	switch (nIconOut)
+	{
+		case NULL:
+			break;
+		case (int)BTNST_AUTO_GRAY:
+			hIconOut = BTNST_AUTO_GRAY;
+			break;
+		case (int)BTNST_AUTO_DARKER:
+			hIconOut = BTNST_AUTO_DARKER;
+			break;
+		default:
+			hIconOut = (HICON)::LoadImage(hInstResource, MAKEINTRESOURCE(nIconOut), IMAGE_ICON, nCxDesiredOut, nCyDesiredOut, 0);
+			break;
+	} // switch
+
+	return SetIcon(hIconIn, hIconOut);
+} // End of SetIcon
+
+// This function assigns icons to the button.
+// Any previous icon or bitmap will be removed.
+//
+// Parameters:
+//		[IN]	nIconIn
+//				ID number of the icon resource to show when the mouse is over the button.
+//				Pass NULL to remove any icon from the button.
+//		[IN]	nIconOut
+//				ID number of the icon resource to show when the mouse is outside the button.
+//				Can be NULL.
+//				If this parameter is the special value BTNST_AUTO_GRAY (cast to int) the second
+//				icon will be automatically created starting from nIconIn and converted to grayscale.
+//				If this parameter is the special value BTNST_AUTO_DARKER (cast to int) the second
+//				icon will be automatically created 25% darker starting from nIconIn.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+DWORD CButtonST::SetIcon(int nIconIn, int nIconOut)
+{
+	return SetIcon(nIconIn, 0, 0, nIconOut, 0, 0);
+} // End of SetIcon
+
+// This function assigns icons to the button.
+// Any previous icon or bitmap will be removed.
+//
+// Parameters:
+//		[IN]	hIconIn
+//				Handle fo the icon to show when the mouse is over the button.
+//				Pass NULL to remove any icon from the button.
+//		[IN]	hIconOut
+//				Handle to the icon to show when the mouse is outside the button.
+//				Can be NULL.
+//				If this parameter is the special value BTNST_AUTO_GRAY the second
+//				icon will be automatically created starting from hIconIn and converted to grayscale.
+//				If this parameter is the special value BTNST_AUTO_DARKER the second
+//				icon will be automatically created 25% darker starting from hIconIn.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+DWORD CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
+{
+	BOOL		bRetValue;
+	ICONINFO	ii;
+
+	// Free any loaded resource
+	FreeResources();
+
+	if (hIconIn)
+	{
+		// Icon when mouse over button?
+		m_csIcons[0].hIcon = hIconIn;
+		// Get icon dimension
+		::ZeroMemory(&ii, sizeof(ICONINFO));
+		bRetValue = ::GetIconInfo(hIconIn, &ii);
+		if (bRetValue == FALSE)
+		{
+			FreeResources();
+			return BTNST_INVALIDRESOURCE;
+		} // if
+
+		m_csIcons[0].dwWidth	= (DWORD)(ii.xHotspot * 2);
+		m_csIcons[0].dwHeight	= (DWORD)(ii.yHotspot * 2);
+		::DeleteObject(ii.hbmMask);
+		::DeleteObject(ii.hbmColor);
+
+		// Icon when mouse outside button?
+		if (hIconOut)
+		{
+			switch ((int)hIconOut)
+			{
+				case (int)BTNST_AUTO_GRAY:
+					hIconOut = CreateGrayscaleIcon(hIconIn);
+					break;
+				case (int)BTNST_AUTO_DARKER:
+					hIconOut = CreateDarkerIcon(hIconIn);
+					break;
+			} // switch
+
+			m_csIcons[1].hIcon = hIconOut;
+			// Get icon dimension
+			::ZeroMemory(&ii, sizeof(ICONINFO));
+			bRetValue = ::GetIconInfo(hIconOut, &ii);
+			if (bRetValue == FALSE)
+			{
+				FreeResources();
+				return BTNST_INVALIDRESOURCE;
+			} // if
+
+			m_csIcons[1].dwWidth	= (DWORD)(ii.xHotspot * 2);
+			m_csIcons[1].dwHeight	= (DWORD)(ii.yHotspot * 2);
+			::DeleteObject(ii.hbmMask);
+			::DeleteObject(ii.hbmColor);
+		} // if
+	} // if
+
+	Invalidate();
+
+	return BTNST_OK;
+} // End of SetIcon
+
+// This function assigns bitmaps to the button.
+// Any previous icon or bitmap will be removed.
+//
+// Parameters:
+//		[IN]	nBitmapIn
+//				ID number of the bitmap resource to show when the mouse is over the button.
+//				Pass NULL to remove any bitmap from the button.
+//		[IN]	crTransColorIn
+//				Color (inside nBitmapIn) to be used as transparent color.
+//		[IN]	nBitmapOut
+//				ID number of the bitmap resource to show when the mouse is outside the button.
+//				Can be NULL.
+//		[IN]	crTransColorOut
+//				Color (inside nBitmapOut) to be used as transparent color.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//		BTNST_FAILEDMASK
+//			Failed creating mask bitmap.
+//
+DWORD CButtonST::SetBitmaps(int nBitmapIn, COLORREF crTransColorIn, int nBitmapOut, COLORREF crTransColorOut)
+{
+	HBITMAP		hBitmapIn		= NULL;
+	HBITMAP		hBitmapOut		= NULL;
+	HINSTANCE	hInstResource	= NULL;
+	
+	// Find correct resource handle
+	hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nBitmapIn), RT_BITMAP);
+
+	// Load bitmap In
+	hBitmapIn = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapIn), IMAGE_BITMAP, 0, 0, 0);
+
+	// Load bitmap Out
+	switch (nBitmapOut)
+	{
+		case NULL:
+			break;
+		case (int)BTNST_AUTO_GRAY:
+			hBitmapOut = (HBITMAP)BTNST_AUTO_GRAY;
+			break;
+		case (int)BTNST_AUTO_DARKER:
+			hBitmapOut = (HBITMAP)BTNST_AUTO_DARKER;
+			break;
+		default:
+			hBitmapOut = (HBITMAP)::LoadImage(hInstResource, MAKEINTRESOURCE(nBitmapOut), IMAGE_BITMAP, 0, 0, 0);
+			break;
+	} // if
+
+	return SetBitmaps(hBitmapIn, crTransColorIn, hBitmapOut, crTransColorOut);
+} // End of SetBitmaps
+
+// This function assigns bitmaps to the button.
+// Any previous icon or bitmap will be removed.
+//
+// Parameters:
+//		[IN]	hBitmapIn
+//				Handle fo the bitmap to show when the mouse is over the button.
+//				Pass NULL to remove any bitmap from the button.
+//		[IN]	crTransColorIn
+//				Color (inside hBitmapIn) to be used as transparent color.
+//		[IN]	hBitmapOut
+//				Handle to the bitmap to show when the mouse is outside the button.
+//				Can be NULL.
+//		[IN]	crTransColorOut
+//				Color (inside hBitmapOut) to be used as transparent color.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//		BTNST_FAILEDMASK
+//			Failed creating mask bitmap.
+//
+DWORD CButtonST::SetBitmaps(HBITMAP hBitmapIn, COLORREF crTransColorIn, HBITMAP hBitmapOut, COLORREF crTransColorOut)
+{
+	int		nRetValue = 0;
+	BITMAP	csBitmapSize;
+
+	// Free any loaded resource
+	FreeResources();
+
+	if (hBitmapIn)
+	{
+		m_csBitmaps[0].hBitmap = hBitmapIn;
+		m_csBitmaps[0].crTransparent = crTransColorIn;
+		// Get bitmap size
+		nRetValue = ::GetObject(hBitmapIn, sizeof(csBitmapSize), &csBitmapSize);
+		if (nRetValue == 0)
+		{
+			FreeResources();
+			return BTNST_INVALIDRESOURCE;
+		} // if
+		m_csBitmaps[0].dwWidth = (DWORD)csBitmapSize.bmWidth;
+		m_csBitmaps[0].dwHeight = (DWORD)csBitmapSize.bmHeight;
+
+		// Create grayscale/darker bitmap BEFORE mask (of hBitmapIn)
+		switch ((int)hBitmapOut)
+		{
+			case (int)BTNST_AUTO_GRAY:
+				hBitmapOut = CreateGrayscaleBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
+				m_csBitmaps[1].hBitmap = hBitmapOut;
+				crTransColorOut = crTransColorIn;
+				break;
+			case (int)BTNST_AUTO_DARKER:
+				hBitmapOut = CreateDarkerBitmap(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
+				m_csBitmaps[1].hBitmap = hBitmapOut;
+				crTransColorOut = crTransColorIn;
+				break;
+		} // switch
+
+		// Create mask for bitmap In
+		m_csBitmaps[0].hMask = CreateBitmapMask(hBitmapIn, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight, crTransColorIn);
+		if (m_csBitmaps[0].hMask == NULL)
+		{
+			FreeResources();
+			return BTNST_FAILEDMASK;
+		} // if
+
+		if (hBitmapOut)
+		{
+			m_csBitmaps[1].hBitmap = hBitmapOut;
+			m_csBitmaps[1].crTransparent = crTransColorOut;
+			// Get bitmap size
+			nRetValue = ::GetObject(hBitmapOut, sizeof(csBitmapSize), &csBitmapSize);
+			if (nRetValue == 0)
+			{
+				FreeResources();
+				return BTNST_INVALIDRESOURCE;
+			} // if
+			m_csBitmaps[1].dwWidth = (DWORD)csBitmapSize.bmWidth;
+			m_csBitmaps[1].dwHeight = (DWORD)csBitmapSize.bmHeight;
+
+			// Create mask for bitmap Out
+			m_csBitmaps[1].hMask = CreateBitmapMask(hBitmapOut, m_csBitmaps[1].dwWidth, m_csBitmaps[1].dwHeight, crTransColorOut);
+			if (m_csBitmaps[1].hMask == NULL)
+			{
+				FreeResources();
+				return BTNST_FAILEDMASK;
+			} // if
+		} // if
+	} // if
+
+	Invalidate();
+
+	return BTNST_OK;
+} // End of SetBitmaps
+
+// This functions sets the button to have a standard or flat style.
+//
+// Parameters:
+//		[IN]	bFlat
+//				If TRUE the button will have a flat style, else
+//				will have a standard style.
+//				By default, CButtonST buttons are flat.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetFlat(BOOL bFlat, BOOL bRepaint)
+{
+	m_bIsFlat = bFlat;
+	if (bRepaint)	Invalidate();
+
+	return BTNST_OK;
+} // End of SetFlat
+
+// This function sets the alignment type between icon/bitmap and text.
+//
+// Parameters:
+//		[IN]	byAlign
+//				Alignment type. Can be one of the following values:
+//				ST_ALIGN_HORIZ			Icon/bitmap on the left, text on the right
+//				ST_ALIGN_VERT			Icon/bitmap on the top, text on the bottom
+//				ST_ALIGN_HORIZ_RIGHT	Icon/bitmap on the right, text on the left
+//				ST_ALIGN_OVERLAP		Icon/bitmap on the same space as text
+//				By default, CButtonST buttons have ST_ALIGN_HORIZ alignment.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDALIGN
+//			Alignment type not supported.
+//
+DWORD CButtonST::SetAlign(BYTE byAlign, BOOL bRepaint)
+{
+	switch (byAlign)
+	{    
+		case ST_ALIGN_HORIZ:
+		case ST_ALIGN_HORIZ_RIGHT:
+		case ST_ALIGN_VERT:
+		case ST_ALIGN_OVERLAP:
+			m_byAlign = byAlign;
+			if (bRepaint)	Invalidate();
+			return BTNST_OK;
+			break;
+	} // switch
+
+	return BTNST_INVALIDALIGN;
+} // End of SetAlign
+
+// This function sets the pressed style.
+//
+// Parameters:
+//		[IN]	byStyle
+//				Pressed style. Can be one of the following values:
+//				BTNST_PRESSED_LEFTRIGHT		Pressed style from left to right (as usual)
+//				BTNST_PRESSED_TOPBOTTOM		Pressed style from top to bottom
+//				By default, CButtonST buttons have BTNST_PRESSED_LEFTRIGHT style.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDPRESSEDSTYLE
+//			Pressed style not supported.
+//
+DWORD CButtonST::SetPressedStyle(BYTE byStyle, BOOL bRepaint)
+{
+	switch (byStyle)
+	{
+		case BTNST_PRESSED_LEFTRIGHT:
+			m_ptPressedOffset.x = 1;
+			m_ptPressedOffset.y = 1;
+			break;
+		case BTNST_PRESSED_TOPBOTTOM:
+			m_ptPressedOffset.x = 0;
+			m_ptPressedOffset.y = 2;
+			break;
+		default:
+			return BTNST_INVALIDPRESSEDSTYLE;
+	} // switch
+
+	if (bRepaint)	Invalidate();
+
+	return BTNST_OK;
+} // End of SetPressedStyle
+
+// This function sets the state of the checkbox.
+// If the button is not a checkbox, this function has no meaning.
+//
+// Parameters:
+//		[IN]	nCheck
+//				1 to check the checkbox.
+//				0 to un-check the checkbox.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetCheck(int nCheck, BOOL bRepaint)
+{
+	if (m_bIsCheckBox)
+	{
+		if (nCheck == 0) m_nCheck = 0;
+		else m_nCheck = 1;
+
+		if (bRepaint) Invalidate();
+	} // if
+
+	return BTNST_OK;
+} // End of SetCheck
+
+// This function returns the current state of the checkbox.
+// If the button is not a checkbox, this function has no meaning.
+//
+// Return value:
+//		The current state of the checkbox.
+//			1 if checked.
+//			0 if not checked or the button is not a checkbox.
+//
+int CButtonST::GetCheck()
+{
+	return m_nCheck;
+} // End of GetCheck
+
+// This function sets all colors to a default value.
+//
+// Parameters:
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetDefaultColors(BOOL bRepaint)
+{
+	m_crColors[BTNST_COLOR_BK_IN]		= ::GetSysColor(COLOR_BTNFACE);
+	m_crColors[BTNST_COLOR_FG_IN]		= ::GetSysColor(COLOR_BTNTEXT);
+	m_crColors[BTNST_COLOR_BK_OUT]		= ::GetSysColor(COLOR_BTNFACE);
+	m_crColors[BTNST_COLOR_FG_OUT]		= ::GetSysColor(COLOR_BTNTEXT);
+	m_crColors[BTNST_COLOR_BK_FOCUS]	= ::GetSysColor(COLOR_BTNFACE);
+	m_crColors[BTNST_COLOR_FG_FOCUS]	= ::GetSysColor(COLOR_BTNTEXT);
+
+	if (bRepaint)	Invalidate();
+
+	return BTNST_OK;
+} // End of SetDefaultColors
+
+// This function sets the color to use for a particular state.
+//
+// Parameters:
+//		[IN]	byColorIndex
+//				Index of the color to set. Can be one of the following values:
+//				BTNST_COLOR_BK_IN		Background color when mouse is over the button
+//				BTNST_COLOR_FG_IN		Text color when mouse is over the button
+//				BTNST_COLOR_BK_OUT		Background color when mouse is outside the button
+//				BTNST_COLOR_FG_OUT		Text color when mouse is outside the button
+//				BTNST_COLOR_BK_FOCUS	Background color when the button is focused
+//				BTNST_COLOR_FG_FOCUS	Text color when the button is focused
+//		[IN]	crColor
+//				New color.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDINDEX
+//			Invalid color index.
+//
+DWORD CButtonST::SetColor(BYTE byColorIndex, COLORREF crColor, BOOL bRepaint)
+{
+	if (byColorIndex >= BTNST_MAX_COLORS)	return BTNST_INVALIDINDEX;
+
+	// Set new color
+	m_crColors[byColorIndex] = crColor;
+
+	if (bRepaint)	Invalidate();
+
+	return BTNST_OK;
+} // End of SetColor
+
+CButtonST& CButtonST::SetFontSize(int nSize)
+{
+
+	CFont cf;
+	LOGFONT lf;
+
+	cf.CreatePointFont(nSize * 10, m_lf.lfFaceName);
+	cf.GetLogFont(&lf);
+
+	m_lf.lfHeight = lf.lfHeight;
+	m_lf.lfWidth  = lf.lfWidth;
+
+	//	nSize*=-1;
+	//	m_lf.lfHeight = nSize;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+CButtonST& CButtonST::SetFontName(const CString& strFont, BYTE byCharSet /* Default = ANSI_CHARSET */)
+{	
+
+	m_lf.lfCharSet = byCharSet;
+
+	_tcscpy_s(m_lf.lfFaceName,strFont);
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+void CButtonST::ReconstructFont()
+{
+	m_font.DeleteObject();
+	BOOL bCreated = m_font.CreateFontIndirect(&m_lf);
+
+	ASSERT(bCreated);
+}
+
+CButtonST& CButtonST::SetFontItalic(BOOL bSet)
+{
+
+	m_lf.lfItalic = bSet;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;	
+}
+
+CButtonST& CButtonST::SetFontUnderline(BOOL bSet)
+{	
+	m_lf.lfUnderline = bSet;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+CButtonST& CButtonST::SetFontBold(BOOL bBold)
+{	
+
+	m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
+	ReconstructFont();
+	UpdateSurface();
+	return *this;
+}
+
+void CButtonST::UpdateSurface()
+{
+	CRect (rc);
+	GetWindowRect(rc);
+	RedrawWindow();
+
+	GetParent()->ScreenToClient(rc);
+	GetParent()->InvalidateRect(rc,TRUE);
+	GetParent()->UpdateWindow();
+}
+
+// This functions returns the color used for a particular state.
+//
+// Parameters:
+//		[IN]	byColorIndex
+//				Index of the color to get.
+//				See SetColor for the list of available colors.
+//		[OUT]	crpColor
+//				A pointer to a COLORREF that will receive the color.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDINDEX
+//			Invalid color index.
+//
+DWORD CButtonST::GetColor(BYTE byColorIndex, COLORREF* crpColor)
+{
+	if (byColorIndex >= BTNST_MAX_COLORS)	return BTNST_INVALIDINDEX;
+
+	// Get color
+	*crpColor = m_crColors[byColorIndex];
+
+	return BTNST_OK;
+} // End of GetColor
+
+// This function applies an offset to the RGB components of the specified color.
+// This function can be seen as an easy way to make a color darker or lighter than
+// its default value.
+//
+// Parameters:
+//		[IN]	byColorIndex
+//				Index of the color to set.
+//				See SetColor for the list of available colors.
+//		[IN]	shOffsetColor
+//				A short value indicating the offset to apply to the color.
+//				This value must be between -255 and 255.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDINDEX
+//			Invalid color index.
+//		BTNST_BADPARAM
+//			The specified offset is out of range.
+//
+DWORD CButtonST::OffsetColor(BYTE byColorIndex, short shOffset, BOOL bRepaint)
+{
+	BYTE	byRed = 0;
+	BYTE	byGreen = 0;
+	BYTE	byBlue = 0;
+	short	shOffsetR = shOffset;
+	short	shOffsetG = shOffset;
+	short	shOffsetB = shOffset;
+
+	if (byColorIndex >= BTNST_MAX_COLORS)	return BTNST_INVALIDINDEX;
+	if (shOffset < -255 || shOffset > 255)	return BTNST_BADPARAM;
+
+	// Get RGB components of specified color
+	byRed = GetRValue(m_crColors[byColorIndex]);
+	byGreen = GetGValue(m_crColors[byColorIndex]);
+	byBlue = GetBValue(m_crColors[byColorIndex]);
+
+	// Calculate max. allowed real offset
+	if (shOffset > 0)
+	{
+		if (byRed + shOffset > 255)		shOffsetR = 255 - byRed;
+		if (byGreen + shOffset > 255)	shOffsetG = 255 - byGreen;
+		if (byBlue + shOffset > 255)	shOffsetB = 255 - byBlue;
+
+		shOffset = min(min(shOffsetR, shOffsetG), shOffsetB);
+	} // if
+	else
+	{
+		if (byRed + shOffset < 0)		shOffsetR = -byRed;
+		if (byGreen + shOffset < 0)		shOffsetG = -byGreen;
+		if (byBlue + shOffset < 0)		shOffsetB = -byBlue;
+
+		shOffset = max(max(shOffsetR, shOffsetG), shOffsetB);
+	} // else
+
+	// Set new color
+	m_crColors[byColorIndex] = RGB(byRed + shOffset, byGreen + shOffset, byBlue + shOffset);
+
+	if (bRepaint)	Invalidate();
+
+	return BTNST_OK;
+} // End of OffsetColor
+
+// This function sets the hilight logic for the button.
+// Applies only to flat buttons.
+//
+// Parameters:
+//		[IN]	bAlwaysTrack
+//				If TRUE the button will be hilighted even if the window that owns it, is
+//				not the active window.
+//				If FALSE the button will be hilighted only if the window that owns it,
+//				is the active window.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetAlwaysTrack(BOOL bAlwaysTrack)
+{
+	m_bAlwaysTrack = bAlwaysTrack;
+	return BTNST_OK;
+} // End of SetAlwaysTrack
+
+// This function sets the cursor to be used when the mouse is over the button.
+//
+// Parameters:
+//		[IN]	nCursorId
+//				ID number of the cursor resource.
+//				Pass NULL to remove a previously loaded cursor.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+DWORD CButtonST::SetBtnCursor(int nCursorId, BOOL bRepaint)
+{
+	HINSTANCE	hInstResource = NULL;
+	// Destroy any previous cursor
+	if (m_hCursor)
+	{
+		::DestroyCursor(m_hCursor);
+		m_hCursor = NULL;
+	} // if
+
+	// Load cursor
+	if (nCursorId)
+	{
+		hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nCursorId), RT_GROUP_CURSOR);
+		// Load cursor resource
+		m_hCursor = (HCURSOR)::LoadImage(hInstResource, MAKEINTRESOURCE(nCursorId), IMAGE_CURSOR, 0, 0, 0);
+		// Repaint the button
+		if (bRepaint) Invalidate();
+		// If something wrong
+		if (m_hCursor == NULL) return BTNST_INVALIDRESOURCE;
+	} // if
+
+	return BTNST_OK;
+} // End of SetBtnCursor
+
+// This function sets if the button border must be drawn.
+// Applies only to flat buttons.
+//
+// Parameters:
+//		[IN]	bDrawBorder
+//				If TRUE the border will be drawn.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::DrawBorder(BOOL bDrawBorder, BOOL bRepaint)
+{
+	m_bDrawBorder = bDrawBorder;
+	// Repaint the button
+	if (bRepaint) Invalidate();
+
+	return BTNST_OK;
+} // End of DrawBorder
+
+// This function sets if the focus rectangle must be drawn for flat buttons.
+//
+// Parameters:
+//		[IN]	bDrawFlatFocus
+//				If TRUE the focus rectangle will be drawn also for flat buttons.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::DrawFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint)
+{
+	m_bDrawFlatFocus = bDrawFlatFocus;
+	// Repaint the button
+	if (bRepaint) Invalidate();
+
+	return BTNST_OK;
+} // End of DrawFlatFocus
+
+void CButtonST::InitToolTip()
+{
+	if (m_ToolTip.m_hWnd == NULL)
+	{
+		// Create ToolTip control
+		m_ToolTip.Create(this, m_dwToolTipStyle);
+		// Create inactive
+		m_ToolTip.Activate(FALSE);
+		// Enable multiline
+		m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, 400);
+		//m_ToolTip.SendMessage(TTM_SETTITLE, TTI_INFO, (LPARAM)_T("Title"));
+	} // if
+} // End of InitToolTip
+
+// This function sets the text to show in the button tooltip.
+//
+// Parameters:
+//		[IN]	nText
+//				ID number of the string resource containing the text to show.
+//		[IN]	bActivate
+//				If TRUE the tooltip will be created active.
+//
+void CButtonST::SetTooltipText(int nText, BOOL bActivate)
+{
+	CString sText;
+
+	// Load string resource
+	sText.LoadString(nText);
+	// If string resource is not empty
+	if (sText.IsEmpty() == FALSE) SetTooltipText((LPCTSTR)sText, bActivate);
+} // End of SetTooltipText
+
+// This function sets the text to show in the button tooltip.
+//
+// Parameters:
+//		[IN]	lpszText
+//				Pointer to a null-terminated string containing the text to show.
+//		[IN]	bActivate
+//				If TRUE the tooltip will be created active.
+//
+void CButtonST::SetTooltipText(LPCTSTR lpszText, BOOL bActivate)
+{
+	// We cannot accept NULL pointer
+	if (lpszText == NULL) return;
+
+	// Initialize ToolTip
+	InitToolTip();
+
+	// If there is no tooltip defined then add it
+	if (m_ToolTip.GetToolCount() == 0)
+	{
+		CRect rectBtn; 
+		GetClientRect(rectBtn);
+		m_ToolTip.AddTool(this, lpszText, rectBtn, 1);
+	} // if
+
+	// Set text for tooltip
+	m_ToolTip.UpdateTipText(lpszText, this, 1);
+	m_ToolTip.Activate(bActivate);
+} // End of SetTooltipText
+
+// This function enables or disables the button tooltip.
+//
+// Parameters:
+//		[IN]	bActivate
+//				If TRUE the tooltip will be activated.
+//
+void CButtonST::ActivateTooltip(BOOL bActivate)
+{
+	// If there is no tooltip then do nothing
+	if (m_ToolTip.GetToolCount() == 0) return;
+
+	// Activate tooltip
+	m_ToolTip.Activate(bActivate);
+} // End of EnableTooltip
+
+// This function enables the tooltip to be displayed using the balloon style.
+// This function must be called before any call to SetTooltipText is made.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::EnableBalloonTooltip()
+{
+	m_dwToolTipStyle |= TTS_BALLOON;
+	return BTNST_OK;
+} // End of EnableBalloonTooltip
+
+// This function returns if the button is the default button.
+//
+// Return value:
+//		TRUE
+//			The button is the default button.
+//		FALSE
+//			The button is not the default button.
+//
+BOOL CButtonST::GetDefault()
+{
+	return m_bIsDefault;
+} // End of GetDefault
+
+// This function enables the transparent mode.
+// Note: this operation is not reversible.
+// DrawTransparent should be called just after the button is created.
+// Do not use trasparent buttons until you really need it (you have a bitmapped
+// background) since each transparent button makes a copy in memory of its background.
+// This may bring unnecessary memory use and execution overload.
+//
+// Parameters:
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+void CButtonST::DrawTransparent(BOOL bRepaint)
+{
+	m_bDrawTransparent = TRUE;
+
+	// Restore old bitmap (if any)
+	if (m_dcBk.m_hDC != NULL && m_pbmpOldBk != NULL)
+	{
+		m_dcBk.SelectObject(m_pbmpOldBk);
+	} // if
+
+	m_bmpBk.DeleteObject();
+	m_dcBk.DeleteDC();
+
+	// Repaint the button
+	if (bRepaint) Invalidate();
+} // End of DrawTransparent
+
+DWORD CButtonST::SetBk(CDC* pDC)
+{
+	if (m_bDrawTransparent && pDC)
+	{
+		// Restore old bitmap (if any)
+		if (m_dcBk.m_hDC != NULL && m_pbmpOldBk != NULL)
+		{
+			m_dcBk.SelectObject(m_pbmpOldBk);
+		} // if
+
+		m_bmpBk.DeleteObject();
+		m_dcBk.DeleteDC();
+
+		CRect rect;
+		CRect rect1;
+
+		GetClientRect(rect);
+
+		GetWindowRect(rect1);
+		GetParent()->ScreenToClient(rect1);
+
+		m_dcBk.CreateCompatibleDC(pDC);
+		m_bmpBk.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
+		m_pbmpOldBk = m_dcBk.SelectObject(&m_bmpBk);
+		m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), pDC, rect1.left, rect1.top, SRCCOPY);
+
+		return BTNST_OK;
+	} // if
+
+	return BTNST_BADPARAM;
+} // End of SetBk
+
+// This function sets the URL that will be opened when the button is clicked.
+//
+// Parameters:
+//		[IN]	lpszURL
+//				Pointer to a null-terminated string that contains the URL.
+//				Pass NULL to removed any previously specified URL.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetURL(LPCTSTR lpszURL)
+{
+	// Remove any existing URL
+	memset(m_szURL, 0, sizeof(m_szURL));
+
+	if (lpszURL)
+	{
+		// Store the URL
+		_tcsncpy_s(m_szURL, lpszURL, _MAX_PATH);
+	} // if
+
+	return BTNST_OK;
+} // End of SetURL
+
+// This function associates a menu to the button.
+// The menu will be displayed clicking the button.
+//
+// Parameters:
+//		[IN]	nMenu
+//				ID number of the menu resource.
+//				Pass NULL to remove any menu from the button.
+//		[IN]	hParentWnd
+//				Handle to the window that owns the menu.
+//				This window receives all messages from the menu.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+#ifndef	BTNST_USE_BCMENU
+DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bRepaint)
+{
+	HINSTANCE	hInstResource	= NULL;
+
+	// Destroy any previous menu
+	if (m_hMenu)
+	{
+		::DestroyMenu(m_hMenu);
+		m_hMenu = NULL;
+		m_hParentWndMenu = NULL;
+		m_bMenuDisplayed = FALSE;
+	} // if
+
+	// Load menu
+	if (nMenu)
+	{
+		// Find correct resource handle
+		hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nMenu), RT_MENU);
+		// Load menu resource
+		m_hMenu = ::LoadMenu(hInstResource, MAKEINTRESOURCE(nMenu));
+		m_hParentWndMenu = hParentWnd;
+		// If something wrong
+		if (m_hMenu == NULL) return BTNST_INVALIDRESOURCE;
+	} // if
+
+	// Repaint the button
+	if (bRepaint) Invalidate();
+
+	return BTNST_OK;
+} // End of SetMenu
+#endif
+
+// This function associates a menu to the button.
+// The menu will be displayed clicking the button.
+// The menu will be handled by the BCMenu class.
+//
+// Parameters:
+//		[IN]	nMenu
+//				ID number of the menu resource.
+//				Pass NULL to remove any menu from the button.
+//		[IN]	hParentWnd
+//				Handle to the window that owns the menu.
+//				This window receives all messages from the menu.
+//		[IN]	bWinXPStyle
+//				If TRUE the menu will be displayed using the new Windows XP style.
+//				If FALSE the menu will be displayed using the standard style.
+//		[IN]	nToolbarID
+//				Resource ID of the toolbar to be associated to the menu.
+//		[IN]	sizeToolbarIcon
+//				A CSize object indicating the size (in pixels) of each icon into the toolbar.
+//				All icons into the toolbar must have the same size.
+//		[IN]	crToolbarBk
+//				A COLORREF value indicating the color to use as background for the icons into the toolbar.
+//				This color will be used as the "transparent" color.
+//		[IN]	bRepaint
+//				If TRUE the control will be repainted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//		BTNST_INVALIDRESOURCE
+//			Failed loading the specified resource.
+//
+#ifdef	BTNST_USE_BCMENU
+DWORD CButtonST::SetMenu(UINT nMenu, HWND hParentWnd, BOOL bWinXPStyle, UINT nToolbarID, CSize sizeToolbarIcon, COLORREF crToolbarBk, BOOL bRepaint)
+{
+	BOOL	bRetValue = FALSE;
+
+	// Destroy any previous menu
+	if (m_menuPopup.m_hMenu)
+	{
+		m_menuPopup.DestroyMenu();
+		m_hParentWndMenu = NULL;
+		m_bMenuDisplayed = FALSE;
+	} // if
+
+	// Load menu
+	if (nMenu)
+	{
+		m_menuPopup.SetMenuDrawMode(bWinXPStyle);
+		// Load menu
+		bRetValue = m_menuPopup.LoadMenu(nMenu);
+		// If something wrong
+		if (bRetValue == FALSE) return BTNST_INVALIDRESOURCE;
+
+		// Load toolbar
+		if (nToolbarID)
+		{
+			m_menuPopup.SetBitmapBackground(crToolbarBk);
+			m_menuPopup.SetIconSize(sizeToolbarIcon.cx, sizeToolbarIcon.cy);
+
+			bRetValue = m_menuPopup.LoadToolbar(nToolbarID);
+			// If something wrong
+			if (bRetValue == FALSE) 
+			{
+				m_menuPopup.DestroyMenu();
+				return BTNST_INVALIDRESOURCE;
+			} // if
+		} // if
+
+		m_hParentWndMenu = hParentWnd;
+	} // if
+
+	// Repaint the button
+	if (bRepaint) Invalidate();
+
+	return BTNST_OK;
+} // End of SetMenu
+#endif
+
+// This function sets the callback message that will be sent to the
+// specified window just before the menu associated to the button is displayed.
+//
+// Parameters:
+//		[IN]	hWnd
+//				Handle of the window that will receive the callback message.
+//				Pass NULL to remove any previously specified callback message.
+//		[IN]	nMessage
+//				Callback message to send to window.
+//		[IN]	lParam
+//				A 32 bits user specified value that will be passed to the callback function.
+//
+// Remarks:
+//		the callback function must be in the form:
+//		LRESULT On_MenuCallback(WPARAM wParam, LPARAM lParam)
+//		Where:
+//				[IN]	wParam
+//						If support for BCMenu is enabled: a pointer to BCMenu
+//						else a HMENU handle to the menu that is being to be displayed.
+//				[IN]	lParam
+//						The 32 bits user specified value.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::SetMenuCallback(HWND hWnd, UINT nMessage, LPARAM lParam)
+{
+	m_csCallbacks.hWnd = hWnd;
+	m_csCallbacks.nMessage = nMessage;
+	m_csCallbacks.lParam = lParam;
+
+	return BTNST_OK;
+} // End of SetMenuCallback
+
+// This function resizes the button to the same size of the image.
+// To get good results both the IN and OUT images should have the same size.
+//
+void CButtonST::SizeToContent()
+{
+	if (m_csIcons[0].hIcon)
+	{
+		m_ptImageOrg.x = 0;
+		m_ptImageOrg.y = 0;
+	    SetWindowPos(	NULL, -1, -1, m_csIcons[0].dwWidth, m_csIcons[0].dwHeight,
+						SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
+	} // if
+	else
+	if (m_csBitmaps[0].hBitmap)
+	{
+		m_ptImageOrg.x = 0;
+		m_ptImageOrg.y = 0;
+	    SetWindowPos(	NULL, -1, -1, m_csBitmaps[0].dwWidth, m_csBitmaps[0].dwHeight,
+						SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | SWP_NOACTIVATE);
+	} // if
+} // End of SizeToContent
+
+// This function sets the sound that must be played on particular button states.
+//
+// Parameters:
+//		[IN]	lpszSound
+//				A string that specifies the sound to play.
+//				If hMod is NULL this string is interpreted as a filename, else it
+//				is interpreted as a resource identifier.
+//				Pass NULL to remove any previously specified sound.
+//		[IN]	hMod
+//				Handle to the executable file that contains the resource to be loaded.
+//				This parameter must be NULL unless lpszSound specifies a resource identifier.
+//		[IN]	bPlayOnClick
+//				TRUE if the sound must be played when the button is clicked.
+//				FALSE if the sound must be played when the mouse is moved over the button.
+//		[IN]	bPlayAsync
+//				TRUE if the sound must be played asynchronously.
+//				FALSE if the sound must be played synchronously. The application takes control
+//				when the sound is completely played.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+#ifdef	BTNST_USE_SOUND
+DWORD CButtonST::SetSound(LPCTSTR lpszSound, HMODULE hMod, BOOL bPlayOnClick, BOOL bPlayAsync)
+{
+	BYTE	byIndex = bPlayOnClick ? 1 : 0;
+
+	// Store new sound
+	if (lpszSound)
+	{
+		if (hMod)	// From resource identifier ?
+		{
+			m_csSounds[byIndex].lpszSound = lpszSound;
+		} // if
+		else
+		{
+			_tcscpy_s(m_csSounds[byIndex].szSound, lpszSound);
+			m_csSounds[byIndex].lpszSound = m_csSounds[byIndex].szSound;
+		} // else
+
+		m_csSounds[byIndex].hMod = hMod;
+		m_csSounds[byIndex].dwFlags = SND_NODEFAULT | SND_NOWAIT;
+		m_csSounds[byIndex].dwFlags |= hMod ? SND_RESOURCE : SND_FILENAME;
+		m_csSounds[byIndex].dwFlags |= bPlayAsync ? SND_ASYNC : SND_SYNC;
+	} // if
+	else
+	{
+		// Or remove any existing
+		::ZeroMemory(&m_csSounds[byIndex], sizeof(STRUCT_SOUND));
+	} // else
+
+	return BTNST_OK;
+} // End of SetSound
+#endif
+
+// This function is called every time the button background needs to be painted.
+// If the button is in transparent mode this function will NOT be called.
+// This is a virtual function that can be rewritten in CButtonST-derived classes
+// to produce a whole range of buttons not available by default.
+//
+// Parameters:
+//		[IN]	pDC
+//				Pointer to a CDC object that indicates the device context.
+//		[IN]	pRect
+//				Pointer to a CRect object that indicates the bounds of the
+//				area to be painted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::OnDrawBackground(CDC* pDC, CRect* pRect)
+{
+	COLORREF	crColor;
+
+	if (m_bIsFlat == FALSE)
+	{
+		if (m_bIsFocused || m_bIsDefault)
+		{
+			CBrush br(RGB(0,0,0));  
+			pDC->FrameRect(pRect, &br);
+			pRect->DeflateRect(1, 1);
+		} // if
+	} // if
+
+	if (m_bMouseOnButton || m_bIsPressed)
+		crColor = m_crColors[BTNST_COLOR_BK_IN];
+	else
+	{
+		if (m_bIsFocused)
+			crColor = m_crColors[BTNST_COLOR_BK_FOCUS];
+		else
+			crColor = m_crColors[BTNST_COLOR_BK_OUT];
+	} // else
+
+	CBrush		brBackground(crColor);
+
+	pDC->FillRect(pRect, &brBackground);
+
+	return BTNST_OK;
+} // End of OnDrawBackground
+
+// This function is called every time the button border needs to be painted.
+// This is a virtual function that can be rewritten in CButtonST-derived classes
+// to produce a whole range of buttons not available by default.
+//
+// Parameters:
+//		[IN]	pDC
+//				Pointer to a CDC object that indicates the device context.
+//		[IN]	pRect
+//				Pointer to a CRect object that indicates the bounds of the
+//				area to be painted.
+//
+// Return value:
+//		BTNST_OK
+//			Function executed successfully.
+//
+DWORD CButtonST::OnDrawBorder(CDC* pDC, CRect* pRect)
+{
+	// Draw pressed button
+	if (m_bIsPressed)
+	{
+		if (m_bIsFlat)
+		{
+			if (m_bDrawBorder)
+				pDC->Draw3dRect(pRect, ::GetSysColor(COLOR_BTNSHADOW), ::GetSysColor(COLOR_BTNHILIGHT));
+		}
+		else    
+		{
+			CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
+			pDC->FrameRect(pRect, &brBtnShadow);
+		}
+	}
+	else // ...else draw non pressed button
+	{
+		CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // White
+		CPen pen3DLight(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));       // Light gray
+		CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));   // Dark gray
+		CPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black
+
+		if (m_bIsFlat)
+		{
+			if (m_bMouseOnButton && m_bDrawBorder)
+				pDC->Draw3dRect(pRect, ::GetSysColor(COLOR_BTNHILIGHT), ::GetSysColor(COLOR_BTNSHADOW));
+		}
+		else
+		{
+			// Draw top-left borders
+			// White line
+			CPen* pOldPen = pDC->SelectObject(&penBtnHiLight);
+			pDC->MoveTo(pRect->left, pRect->bottom-1);
+			pDC->LineTo(pRect->left, pRect->top);
+			pDC->LineTo(pRect->right, pRect->top);
+			// Light gray line
+			pDC->SelectObject(pen3DLight);
+			pDC->MoveTo(pRect->left+1, pRect->bottom-1);
+			pDC->LineTo(pRect->left+1, pRect->top+1);
+			pDC->LineTo(pRect->right, pRect->top+1);
+			// Draw bottom-right borders
+			// Black line
+			pDC->SelectObject(pen3DDKShadow);
+			pDC->MoveTo(pRect->left, pRect->bottom-1);
+			pDC->LineTo(pRect->right-1, pRect->bottom-1);
+			pDC->LineTo(pRect->right-1, pRect->top-1);
+			// Dark gray line
+			pDC->SelectObject(penBtnShadow);
+			pDC->MoveTo(pRect->left+1, pRect->bottom-2);
+			pDC->LineTo(pRect->right-2, pRect->bottom-2);
+			pDC->LineTo(pRect->right-2, pRect->top);
+			//
+			pDC->SelectObject(pOldPen);
+		} // else
+	} // else
+
+	return BTNST_OK;
+} // End of OnDrawBorder
+
+#undef BS_TYPEMASK

+ 321 - 0
VideoCapture/UI/BtnST.h

@@ -0,0 +1,321 @@
+//
+//	Class:		CButtonST
+//
+//	Compiler:	Visual C++
+//	Tested on:	Visual C++ 5.0
+//				Visual C++ 6.0
+//
+//	Version:	See GetVersionC() or GetVersionI()
+//
+//	Created:	xx/xxxx/1998
+//	Updated:	03/March/2003
+//
+//	Author:		Davide Calabro'		davide_calabro@yahoo.com
+//									http://www.softechsoftware.it
+//
+//	Note:		Code for the PreSubclassWindow and OnSetStyle functions
+//				has been taken from the COddButton class
+//				published by Paolo Messina and Jerzy Kaczorowski
+//
+//	Disclaimer
+//	----------
+//	THIS SOFTWARE AND THE ACCOMPANYING FILES ARE DISTRIBUTED "AS IS" AND WITHOUT
+//	ANY WARRANTIES WHETHER EXPRESSED OR IMPLIED. NO REPONSIBILITIES FOR POSSIBLE
+//	DAMAGES OR EVEN FUNCTIONALITY CAN BE TAKEN. THE USER MUST ASSUME THE ENTIRE
+//	RISK OF USING THIS SOFTWARE.
+//
+//	Terms of use
+//	------------
+//	THIS SOFTWARE IS FREE FOR PERSONAL USE OR FREEWARE APPLICATIONS.
+//	IF YOU USE THIS SOFTWARE IN COMMERCIAL OR SHAREWARE APPLICATIONS YOU
+//	ARE GENTLY ASKED TO DONATE 5$ (FIVE U.S. DOLLARS) TO THE AUTHOR:
+//
+//		Davide Calabro'
+//		P.O. Box 65
+//		21019 Somma Lombardo (VA)
+//		Italy
+//
+#ifndef _BTNST_H
+#define _BTNST_H
+
+// Uncomment the following 2 lines to enable support for BCMenu class
+#define	BTNST_USE_BCMENU
+#include "BCMenu.h"
+
+// Uncomment the following line to enable support for sound effects
+#define	BTNST_USE_SOUND
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+// Return values
+#ifndef	BTNST_OK
+#define	BTNST_OK						0
+#endif
+#ifndef	BTNST_INVALIDRESOURCE
+#define	BTNST_INVALIDRESOURCE			1
+#endif
+#ifndef	BTNST_FAILEDMASK
+#define	BTNST_FAILEDMASK				2
+#endif
+#ifndef	BTNST_INVALIDINDEX
+#define	BTNST_INVALIDINDEX				3
+#endif
+#ifndef	BTNST_INVALIDALIGN
+#define	BTNST_INVALIDALIGN				4
+#endif
+#ifndef	BTNST_BADPARAM
+#define	BTNST_BADPARAM					5
+#endif
+#ifndef	BTNST_INVALIDPRESSEDSTYLE
+#define	BTNST_INVALIDPRESSEDSTYLE		6
+#endif
+
+// Dummy identifier for grayscale icon
+#ifndef	BTNST_AUTO_GRAY
+#define	BTNST_AUTO_GRAY					(HICON)(0xffffffff - 1L)
+#endif
+// Dummy identifier for 15% darker icon
+#ifndef	BTNST_AUTO_DARKER
+#define	BTNST_AUTO_DARKER				(HICON)(0xffffffff - 2L)
+#endif
+
+class CButtonST : public CButton
+{
+public:
+    CButtonST();
+	~CButtonST();
+
+    enum	{	ST_ALIGN_HORIZ	= 0,			// Icon/bitmap on the left, text on the right
+				ST_ALIGN_VERT,					// Icon/bitmap on the top, text on the bottom
+				ST_ALIGN_HORIZ_RIGHT,			// Icon/bitmap on the right, text on the left
+				ST_ALIGN_OVERLAP				// Icon/bitmap on the same space as text
+			};
+
+	enum	{	BTNST_COLOR_BK_IN	= 0,		// Background color when mouse is INside
+				BTNST_COLOR_FG_IN,				// Text color when mouse is INside
+				BTNST_COLOR_BK_OUT,				// Background color when mouse is OUTside
+				BTNST_COLOR_FG_OUT,				// Text color when mouse is OUTside
+				BTNST_COLOR_BK_FOCUS,			// Background color when the button is focused
+				BTNST_COLOR_FG_FOCUS,			// Text color when the button is focused
+
+				BTNST_MAX_COLORS
+			};
+
+    enum	{	BTNST_PRESSED_LEFTRIGHT = 0,	// Pressed style from left to right (as usual)
+				BTNST_PRESSED_TOPBOTTOM			// Pressed style from top to bottom
+			};
+
+	// ClassWizard generated virtual function overrides
+    //{{AFX_VIRTUAL(CButtonST)
+	public:
+	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	protected:
+	virtual void PreSubclassWindow();
+	//}}AFX_VIRTUAL
+
+public:
+	void ReconstructFont();
+	void UpdateSurface();
+	virtual CButtonST& SetFontBold(BOOL bBold = TRUE);
+	virtual CButtonST& SetFontName(const CString& strFont, BYTE byCharSet = ANSI_CHARSET);
+	virtual CButtonST& SetFontUnderline(BOOL bSet = TRUE);
+	virtual CButtonST& SetFontItalic(BOOL bSet = TRUE);
+	virtual CButtonST& SetFontSize(int nSize);
+
+	DWORD SetDefaultColors(BOOL bRepaint = TRUE);
+	DWORD SetColor(BYTE byColorIndex, COLORREF crColor, BOOL bRepaint = TRUE);
+	DWORD GetColor(BYTE byColorIndex, COLORREF* crpColor);
+	DWORD OffsetColor(BYTE byColorIndex, short shOffset, BOOL bRepaint = TRUE);
+
+	DWORD SetCheck(int nCheck, BOOL bRepaint = TRUE);
+	int GetCheck();
+
+	DWORD SetURL(LPCTSTR lpszURL = NULL);
+	void DrawTransparent(BOOL bRepaint = FALSE);
+	DWORD SetBk(CDC* pDC);
+
+	BOOL GetDefault();
+	DWORD SetAlwaysTrack(BOOL bAlwaysTrack = TRUE);
+
+	void SetTooltipText(int nText, BOOL bActivate = TRUE);
+	void SetTooltipText(LPCTSTR lpszText, BOOL bActivate = TRUE);
+	void ActivateTooltip(BOOL bEnable = TRUE);
+	DWORD EnableBalloonTooltip();
+
+	DWORD SetBtnCursor(int nCursorId = NULL, BOOL bRepaint = TRUE);
+
+	DWORD SetFlat(BOOL bFlat = TRUE, BOOL bRepaint = TRUE);
+	DWORD SetAlign(BYTE byAlign, BOOL bRepaint = TRUE);
+	DWORD SetPressedStyle(BYTE byStyle, BOOL bRepaint = TRUE);
+
+	DWORD DrawBorder(BOOL bDrawBorder = TRUE, BOOL bRepaint = TRUE);
+	DWORD DrawFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint = TRUE);
+
+	DWORD SetIcon(int nIconIn, int nCxDesiredIn, int nCyDesiredIn, int nIconOut = NULL, int nCxDesiredOut = 0, int nCyDesiredOut = 0);
+	DWORD SetIcon(int nIconIn, int nIconOut = NULL);
+	DWORD SetIcon(HICON hIconIn, HICON hIconOut = NULL);
+
+	DWORD SetBitmaps(int nBitmapIn, COLORREF crTransColorIn, int nBitmapOut = NULL, COLORREF crTransColorOut = 0);
+	DWORD SetBitmaps(HBITMAP hBitmapIn, COLORREF crTransColorIn, HBITMAP hBitmapOut = NULL, COLORREF crTransColorOut = 0);
+
+	void SizeToContent();
+
+#ifdef	BTNST_USE_BCMENU
+	DWORD SetMenu(UINT nMenu, HWND hParentWnd, BOOL bWinXPStyle = TRUE, UINT nToolbarID = NULL, CSize sizeToolbarIcon = CSize(16, 16), COLORREF crToolbarBk = RGB(255, 0, 255), BOOL bRepaint = TRUE);
+#else
+	DWORD SetMenu(UINT nMenu, HWND hParentWnd, BOOL bRepaint = TRUE);
+#endif
+	DWORD SetMenuCallback(HWND hWnd, UINT nMessage, LPARAM lParam = 0);
+
+#ifdef	BTNST_USE_SOUND
+	DWORD SetSound(LPCTSTR lpszSound, HMODULE hMod = NULL, BOOL bPlayOnClick = FALSE, BOOL bPlayAsync = TRUE);
+#endif
+
+	static short GetVersionI()		{return 39;}
+	static LPCTSTR GetVersionC()	{return (LPCTSTR)_T("3.9");}
+
+	BOOL	m_bShowDisabledBitmap;
+	POINT	m_ptImageOrg;
+	POINT	m_ptPressedOffset;
+
+protected:
+    //{{AFX_MSG(CButtonST)
+	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
+	afx_msg void OnKillFocus(CWnd* pNewWnd);
+	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
+	afx_msg void OnSysColorChange();
+	afx_msg BOOL OnClicked();
+	afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
+	afx_msg void OnEnable(BOOL bEnable);
+	afx_msg void OnCancelMode();
+	afx_msg UINT OnGetDlgCode();
+	//}}AFX_MSG
+
+#ifdef	BTNST_USE_BCMENU
+	afx_msg LRESULT OnMenuChar(UINT nChar, UINT nFlags, CMenu* pMenu);
+	afx_msg void OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct);
+#endif
+
+	afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
+	HICON CreateGrayscaleIcon(HICON hIcon);
+	HICON CreateDarkerIcon(HICON hIcon);
+	HBITMAP CreateGrayscaleBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans);
+	HBITMAP CreateDarkerBitmap(HBITMAP hBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTrans);
+	COLORREF DarkenColor(COLORREF crColor, double dFactor);
+	virtual DWORD OnDrawBackground(CDC* pDC, CRect* pRect);
+	virtual DWORD OnDrawBorder(CDC* pDC, CRect* pRect);
+
+	BOOL		m_bIsFlat;			// Is a flat button?
+	BOOL		m_bMouseOnButton;	// Is mouse over the button?
+	BOOL		m_bDrawTransparent;	// Draw transparent?
+	BOOL		m_bIsPressed;		// Is button pressed?
+	BOOL		m_bIsFocused;		// Is button focused?
+	BOOL		m_bIsDisabled;		// Is button disabled?
+	BOOL		m_bIsDefault;		// Is default button?
+	BOOL		m_bIsCheckBox;		// Is the button a checkbox?
+	BYTE		m_byAlign;			// Align mode
+	BOOL		m_bDrawBorder;		// Draw border?
+	BOOL		m_bDrawFlatFocus;	// Draw focus rectangle for flat button?
+	COLORREF	m_crColors[BTNST_MAX_COLORS];	// Colors to be used
+	HWND		m_hParentWndMenu;	// Handle to window for menu selection
+	BOOL		m_bMenuDisplayed;	// Is menu displayed ?
+
+	LOGFONT			m_lf;
+	CFont			m_font;
+
+#ifdef	BTNST_USE_BCMENU
+	BCMenu		m_menuPopup;		// BCMenu class instance
+#else
+	HMENU		m_hMenu;			// Handle to associated menu
+#endif
+
+private:
+	LRESULT OnSetCheck(WPARAM wParam, LPARAM lParam);
+	LRESULT OnGetCheck(WPARAM wParam, LPARAM lParam);
+	LRESULT OnSetStyle(WPARAM wParam, LPARAM lParam);
+	LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
+
+	void CancelHover();
+	void FreeResources(BOOL bCheckForNULL = TRUE);
+	void PrepareImageRect(BOOL bHasTitle, RECT* rpItem, CRect* rpTitle, BOOL bIsPressed, DWORD dwWidth, DWORD dwHeight, CRect* rpImage);
+	HBITMAP CreateBitmapMask(HBITMAP hSourceBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTransColor);
+	virtual void DrawTheIcon(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled);
+	virtual void DrawTheBitmap(CDC* pDC, BOOL bHasTitle, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled);
+	virtual void DrawTheText(CDC* pDC, LPCTSTR lpszText, RECT* rpItem, CRect* rpCaption, BOOL bIsPressed, BOOL bIsDisabled);
+	void PaintBk(CDC* pDC);
+
+	void InitToolTip();
+
+	HCURSOR		m_hCursor;			// Handle to cursor
+	CToolTipCtrl m_ToolTip;			// Tooltip
+
+	CDC			m_dcBk;
+	CBitmap		m_bmpBk;
+	CBitmap*	m_pbmpOldBk;
+
+	BOOL		m_bAlwaysTrack;		// Always hilight button?
+	int			m_nCheck;			// Current value for checkbox
+	UINT		m_nTypeStyle;		// Button style
+	DWORD		m_dwToolTipStyle;	// Style of tooltip control
+
+	TCHAR		m_szURL[_MAX_PATH];	// URL to open when clicked
+
+#pragma pack(1)
+	typedef struct _STRUCT_ICONS
+	{
+		HICON		hIcon;			// Handle to icon
+		DWORD		dwWidth;		// Width of icon
+		DWORD		dwHeight;		// Height of icon
+	} STRUCT_ICONS;
+#pragma pack()
+
+#pragma pack(1)
+	typedef struct _STRUCT_BITMAPS
+	{
+		HBITMAP		hBitmap;		// Handle to bitmap
+		DWORD		dwWidth;		// Width of bitmap
+		DWORD		dwHeight;		// Height of bitmap
+		HBITMAP		hMask;			// Handle to mask bitmap
+		COLORREF	crTransparent;	// Transparent color
+	} STRUCT_BITMAPS;
+#pragma pack()
+
+#pragma pack(1)
+	typedef struct _STRUCT_CALLBACK
+	{
+		HWND		hWnd;			// Handle to window
+		UINT		nMessage;		// Message identifier
+		WPARAM		wParam;
+		LPARAM		lParam;
+	} STRUCT_CALLBACK;
+#pragma pack()
+
+	STRUCT_ICONS	m_csIcons[2];
+	STRUCT_BITMAPS	m_csBitmaps[2];
+
+	STRUCT_CALLBACK	m_csCallbacks;
+
+#ifdef	BTNST_USE_SOUND
+#pragma pack(1)
+	typedef struct _STRUCT_SOUND
+	{
+		TCHAR		szSound[_MAX_PATH];
+		LPCTSTR		lpszSound;
+		HMODULE		hMod;
+		DWORD		dwFlags;
+	} STRUCT_SOUND;
+#pragma pack()
+
+	STRUCT_SOUND	m_csSounds[2];	// Index 0 = Over	1 = Clicked
+#endif
+
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif

+ 161 - 0
VideoCapture/UI/ComboTreeCtrl.cpp

@@ -0,0 +1,161 @@
+// ComboTreeCtrl.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "ComboTreeCtrl.h"
+
+#include "TreeComboBox.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CComboTreeCtrl
+
+CComboTreeCtrl::CComboTreeCtrl() :m_pCombo(NULL)
+{
+}
+
+CComboTreeCtrl::~CComboTreeCtrl()
+{
+}
+
+
+BEGIN_MESSAGE_MAP(CComboTreeCtrl, CTreeCtrl)
+	ON_NOTIFY_REFLECT(NM_KILLFOCUS, OnKillfocus)
+	ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
+	ON_NOTIFY_REFLECT(TVN_KEYDOWN, OnKeydown)
+	ON_MESSAGE(TREECTRL_CHECK_STATE_CHANGE, OnTreeCtrlCheckStateChange)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CComboTreeCtrl message handlers
+
+void CComboTreeCtrl::Display(IN CRect rc)
+{
+	if (GetSafeHwnd() == NULL)
+		return;
+
+	SetWindowPos(&wndNoTopMost, rc.left, rc.top, rc.right, rc.bottom, SWP_SHOWWINDOW);
+
+	CWnd* pTopParent = GetParent()->GetParentOwner();
+	if (pTopParent != NULL)
+	{
+		pTopParent->SendMessage(WM_NCACTIVATE, TRUE);
+		pTopParent->SetRedraw(TRUE);
+	}
+}
+
+BOOL CComboTreeCtrl::PreTranslateMessage(MSG* pMsg)
+{
+	if (pMsg->hwnd != m_hWnd)
+		return FALSE;
+
+	// 过滤掉Alt+F4;
+	if (WM_SYSKEYDOWN == pMsg->message && VK_F4 == pMsg->wParam)
+		return TRUE;
+
+	// 回车键和esc键关闭控件;
+	if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE))
+	{
+		// WMU_CLOSE_CONTROL->关闭控件;
+		::PostMessage(m_pCombo->m_hWnd, WMU_CLOSE_CONTROL, (WPARAM)0, (LPARAM)0);
+		return TRUE;
+	}
+
+	return CTreeCtrl::PreTranslateMessage(pMsg);
+}
+
+void CComboTreeCtrl::OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	// WMU_CLOSE_CONTROL->关闭控件;
+	::PostMessage(m_pCombo->m_hWnd, WMU_CLOSE_CONTROL, (WPARAM)0, (LPARAM)0);
+}
+
+LRESULT CComboTreeCtrl::OnTreeCtrlCheckStateChange(WPARAM wParam, LPARAM lParam)
+{
+	HTREEITEM hItemChanged = (HTREEITEM)lParam;
+	BOOL bCheckState = GetCheck(hItemChanged);
+	SelectItem(hItemChanged);
+
+	while (hItemChanged = GetParentItem(hItemChanged))
+		SetCheck(hItemChanged);
+
+	return 1;
+}
+
+void CComboTreeCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	UINT nFlags;
+	HTREEITEM hItem;
+	// verify that we have a mouse click in the check box area 
+	DWORD dwPos = GetMessagePos();
+	CPoint point(LOWORD(dwPos), HIWORD(dwPos));
+	ScreenToClient(&point);
+	hItem = HitTest(point, &nFlags);
+	if (hItem)
+	{
+		if (GetParentItem(hItem))
+			::PostMessage(m_pCombo->m_hWnd, WMU_CLOSE_CONTROL, (WPARAM)0, (LPARAM)hItem);// WMU_CLOSE_CONTROL->关闭控件;
+	}
+
+	*pResult = 0;
+}
+
+void CComboTreeCtrl::OnKeydown(NMHDR* pNMHDR, LRESULT* pResult)
+{
+	TV_KEYDOWN* pTVKeyDown = (TV_KEYDOWN*)pNMHDR;
+	if (pTVKeyDown->wVKey == VK_SPACE)
+	{
+		HTREEITEM hItem = GetSelectedItem();
+		if (hItem != NULL)
+		{
+			// handle state change here or post message to another handler
+			// Post message state has changed
+			PostMessage(TREECTRL_CHECK_STATE_CHANGE, 0, (LPARAM)hItem);
+		}
+	}
+
+	*pResult = 0;
+}
+
+/************************************************************************/
+/*  函数:FindItem[12/7/2016 IT];
+/*  描述:从指定父项开始查找指定名称的项;
+/*  参数:;
+/*  	[IN] strName:要查找的项名称;
+/*  	[IN] hRoot:要开始查找的父项;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+HTREEITEM CComboTreeCtrl::FindItem(IN const CString& strName, IN HTREEITEM hRoot)
+{
+	// 判断父项是否就是要查找的项;
+	CString sText = GetItemText(hRoot);
+	if (sText.Compare(strName) == 0)
+		return hRoot;
+
+	HTREEITEM hItem = NULL;
+	// 获取第一个子项句柄;
+	HTREEITEM hSub = GetChildItem(hRoot);
+	// 遍历所有子项;
+	while (hSub)
+	{
+		// 当前子项是否是要查找的子项;
+		if ((hItem = FindItem(strName, hSub)) != NULL)
+			break;
+
+		// 若未到,查找下一个兄弟项;
+		hSub = GetNextSiblingItem(hSub);
+	}
+
+	return hItem;
+}

+ 59 - 0
VideoCapture/UI/ComboTreeCtrl.h

@@ -0,0 +1,59 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[IT];
+/*  日    期:[11/4/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __COMBO_TREE_CTRL__
+#define __COMBO_TREE_CTRL__
+
+
+#pragma once
+
+// 自定义函数;
+#define TREECTRL_CHECK_STATE_CHANGE		(WM_USER + 100)
+#define WMU_CLOSE_CONTROL				(WM_USER + 101)
+
+// 前置声明;
+class CTreeComboBox;
+class CComboTreeCtrl : public CTreeCtrl
+{
+public:
+	CComboTreeCtrl();
+	virtual ~CComboTreeCtrl();
+public:
+	void Display(IN CRect rc);
+
+public:
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+public:
+	void Init(CTreeComboBox* pCombo)
+	{
+		m_pCombo = pCombo;
+	};
+
+protected:
+	afx_msg void OnKillfocus(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg void OnKeydown(NMHDR* pNMHDR, LRESULT* pResult);
+	afx_msg LRESULT OnTreeCtrlCheckStateChange(WPARAM wParam, LPARAM lParam);
+	DECLARE_MESSAGE_MAP()
+private:
+	CTreeComboBox* m_pCombo;
+	HTREEITEM FindItem(IN const CString& strName, IN HTREEITEM hRoot);
+};
+
+#endif // __COMBO_TREE_CTRL__

+ 36 - 0
VideoCapture/UI/FontSize.cpp

@@ -0,0 +1,36 @@
+#include "stdafx.h"
+#include "FontSize.h"
+
+/***************************************************************************************/
+// GetFontPointSize
+int GetFontPointSize(int iHeight)
+{
+    HDC hDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
+    ASSERT(hDC);
+
+    int icyPixelsPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
+    DeleteDC(hDC);
+
+    int iPointSize = MulDiv(iHeight, 72, icyPixelsPerInch);
+    if(iPointSize < 0)
+    {
+        iPointSize = -iPointSize;
+    }
+
+    return iPointSize;
+}
+
+/***************************************************************************************/
+// GetFontHeight
+int GetFontHeight(int iPointSize)
+{
+    HDC hDC = CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
+    ASSERT(hDC);
+
+    int icyPixelsPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
+    DeleteDC(hDC);
+
+    int iHeight = -MulDiv(iPointSize, icyPixelsPerInch, 72);
+
+    return iHeight;
+}

+ 25 - 0
VideoCapture/UI/FontSize.h

@@ -0,0 +1,25 @@
+/*************************************************************************************
+ * FontSize.h
+ *
+ * 作者: 雷登似
+ * 公司: TCL多媒体科技控股有限公司
+ * 版本: 0.01
+ * 编程日期: 2010-04-21
+ * 联系方式: wp2.leids@tcl.com / 0752-3270423(81423)
+ *
+ * 功能: 获取字体大小
+ * 说明: 本软件释放给TCL公司, 只要你喜欢, 在TCL公司内部可以免费使用, 但在使用过程中
+ *       你必须保证此软件的说明信息完整!
+ *
+ * 此软件的最终解释权归原作者拥有, 作者不对软件的分发和使用负责, 如果你因使用此软
+ * 件而造成的任何损失或商业风险均由使用者自己承担所有责任.
+ *
+ *************************************************************************************/
+
+#ifndef __FONT_SIZE_H__
+#define __FONT_SIZE_H__
+
+int GetFontPointSize(int iHeight);
+int GetFontHeight(int iPointSize);
+
+#endif

+ 1216 - 0
VideoCapture/UI/PictureEx.cpp

@@ -0,0 +1,1216 @@
+
+
+#include "stdafx.h"
+#include "PictureEx.h"
+#include <process.h>
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Nested structures member functions
+//////////////////////////////////////////////////////////////////////
+
+inline int CPictureEx::TGIFControlExt::GetPackedValue(enum ControlExtValues Value)
+{
+ int nRet = (int)m_cPacked;
+ switch (Value)
+ {
+ case GCX_PACKED_DISPOSAL:
+  nRet = (nRet & 28) >> 2;
+  break;
+
+ case GCX_PACKED_USERINPUT:
+  nRet = (nRet & 2) >> 1;
+  break;
+
+ case GCX_PACKED_TRANSPCOLOR:
+  nRet &= 1;
+  break;
+ };
+
+ return nRet;
+}
+
+inline int CPictureEx::TGIFLSDescriptor::GetPackedValue(enum LSDPackedValues Value)
+{
+ int nRet = (int)m_cPacked;
+
+ switch (Value)
+ {
+ case LSD_PACKED_GLOBALCT:
+  nRet = nRet >> 7;
+  break;
+
+ case LSD_PACKED_CRESOLUTION:
+  nRet = ((nRet & 0x70) >> 4) + 1;
+  break;
+
+ case LSD_PACKED_SORT:
+  nRet = (nRet & 8) >> 3;
+  break;
+
+ case LSD_PACKED_GLOBALCTSIZE:
+  nRet &= 7;
+  break;
+ };
+
+ return nRet;
+}
+
+inline int CPictureEx::TGIFImageDescriptor::GetPackedValue(enum IDPackedValues Value)
+{
+ int nRet = (int)m_cPacked;
+
+ switch (Value)
+ {
+ case ID_PACKED_LOCALCT:
+  nRet >>= 7;
+  break;
+
+ case ID_PACKED_INTERLACE:
+  nRet = ((nRet & 0x40) >> 6);
+  break;
+
+ case ID_PACKED_SORT:
+  nRet = (nRet & 0x20) >> 5;
+  break;
+
+ case ID_PACKED_LOCALCTSIZE:
+  nRet &= 7;
+  break;
+ };
+
+ return nRet;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CPictureEx::CPictureEx()
+{
+ // check structures size
+ ASSERT(sizeof(TGIFImageDescriptor) == 10);
+ ASSERT(sizeof(TGIFAppExtension)    == 14);
+ ASSERT(sizeof(TGIFPlainTextExt)    == 15);
+ ASSERT(sizeof(TGIFLSDescriptor)    ==  7);
+ ASSERT(sizeof(TGIFControlExt)    ==  8);
+ ASSERT(sizeof(TGIFCommentExt)    ==  2);
+ ASSERT(sizeof(TGIFHeader)     ==  6);
+
+ m_pGIFLSDescriptor = NULL;
+ m_pGIFHeader    = NULL;
+ m_pPicture     = NULL;
+ m_pRawData     = NULL;
+ m_hThread     = NULL;
+ m_hBitmap          = NULL;
+ m_hMemDC     = NULL;
+
+ m_hDispMemDC       = NULL;
+ m_hDispMemBM       = NULL;
+ m_hDispOldBM       = NULL;
+
+ m_bIsInitialized   = FALSE;
+ m_bExitThread    = FALSE;
+ m_bIsPlaying       = FALSE;
+ m_bIsGIF     = FALSE;
+ m_clrBackground    = RGB(255,255,255); // white by default
+ m_nGlobalCTSize    = 0;
+ m_nCurrOffset    = 0;
+ m_nCurrFrame    = 0;
+ m_nDataSize     = 0;
+ m_PictureSize.cx = m_PictureSize.cy = 0;
+ SetRect(&m_PaintRect,0,0,0,0);
+
+ m_hExitEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
+}
+
+CPictureEx::~CPictureEx()
+{
+ UnLoad();
+ CloseHandle(m_hExitEvent);
+}
+
+BEGIN_MESSAGE_MAP(CPictureEx, CStatic)
+ //{{AFX_MSG_MAP(CPictureEx)
+ ON_WM_DESTROY()
+ ON_WM_PAINT()
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+BOOL CPictureEx::Load(HGLOBAL hGlobal, DWORD dwSize)
+{
+ IStream *pStream = NULL;
+ UnLoad();
+
+ if (!(m_pRawData = reinterpret_cast<unsigned char*> (GlobalLock(hGlobal))) )
+ {
+  TRACE(_T("Load: Error locking memory\n"));
+  return FALSE;
+ };
+
+ m_nDataSize = dwSize;
+ m_pGIFHeader = reinterpret_cast<TGIFHeader *> (m_pRawData);
+
+ if ((memcmp(&m_pGIFHeader->m_cSignature,"GIF",3) != 0) &&
+  ((memcmp(&m_pGIFHeader->m_cVersion,"87a",3) != 0) ||
+   (memcmp(&m_pGIFHeader->m_cVersion,"89a",3) != 0)) )
+ {
+ // it's neither GIF87a nor GIF89a
+ // do the default processing
+
+  // clear GIF variables
+  m_pRawData = NULL;
+  GlobalUnlock(hGlobal);
+
+  // don't delete memory on object's release
+  if (CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK)
+   return FALSE;
+
+  if (OleLoadPicture(pStream,dwSize,FALSE,IID_IPicture,
+   reinterpret_cast<LPVOID *>(&m_pPicture)) != S_OK)
+  {
+   pStream->Release();
+   return FALSE;
+  };
+  pStream->Release();
+
+  // store picture's size
+
+  long hmWidth;
+  long hmHeight;
+  m_pPicture->get_Width(&hmWidth);
+  m_pPicture->get_Height(&hmHeight);
+
+  HDC hDC = ::GetDC(m_hWnd);
+  m_PictureSize.cx = MulDiv(hmWidth, GetDeviceCaps(hDC,LOGPIXELSX), 2540);
+  m_PictureSize.cy = MulDiv(hmHeight, GetDeviceCaps(hDC,LOGPIXELSY), 2540);
+  ::ReleaseDC(m_hWnd,hDC);
+ }
+ else
+ {
+  // it's a GIF
+  m_bIsGIF = TRUE;
+  m_pGIFLSDescriptor = reinterpret_cast<TGIFLSDescriptor *>
+   (m_pRawData + sizeof(TGIFHeader));
+  if (m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCT) == 1)
+  {
+   // calculate the globat color table size
+   m_nGlobalCTSize = static_cast<int>
+    (3* (1 << (m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCTSIZE)+1)));
+   // get the background color if GCT is present
+   unsigned char *pBkClr = m_pRawData + sizeof(TGIFHeader) + 
+    sizeof(TGIFLSDescriptor) + 3*m_pGIFLSDescriptor->m_cBkIndex;
+   m_clrBackground = RGB(pBkClr[0],pBkClr[1],pBkClr[2]);
+  };
+
+  // store the picture's size
+  m_PictureSize.cx = m_pGIFLSDescriptor->m_wWidth;
+  m_PictureSize.cy = m_pGIFLSDescriptor->m_wHeight;
+
+  // determine frame count for this picture
+  UINT nFrameCount=0;
+  ResetDataPointer();
+  while (SkipNextGraphicBlock())
+   nFrameCount++;
+
+#ifdef GIF_TRACING
+  TRACE(
+   _T(" -= GIF encountered\n"
+      "Logical Screen dimensions = %dx%d\n"
+      "Global color table = %d\n"
+      "Color depth = %d\n"
+      "Sort flag = %d\n"
+      "Size of Global Color Table = %d\n"
+      "Background color index = %d\n"
+      "Pixel aspect ratio = %d\n"
+      "Frame count = %d\n"
+      "Background color = %06Xh\n\n"
+     ),
+   m_pGIFLSDescriptor->m_wWidth,
+   m_pGIFLSDescriptor->m_wHeight,
+   m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCT),
+   m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_CRESOLUTION),
+   m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_SORT),
+   m_pGIFLSDescriptor->GetPackedValue(LSD_PACKED_GLOBALCTSIZE),
+   m_pGIFLSDescriptor->m_cBkIndex,
+   m_pGIFLSDescriptor->m_cPixelAspect,
+   nFrameCount,
+   m_clrBackground
+   );
+  EnumGIFBlocks();
+#endif
+
+  if (nFrameCount == 0) // it's an empty GIF!
+  {
+   m_pRawData = NULL;
+   GlobalUnlock(hGlobal);
+   return FALSE;
+  };
+
+  // now check the frame count
+  // if there's only one frame, no need to animate this GIF
+  // therefore, treat it like any other pic
+
+  if (nFrameCount == 1)
+  {
+   // clear GIF variables
+   m_pRawData = NULL;
+   GlobalUnlock(hGlobal);
+
+   // don't delete memory on object's release
+   if (CreateStreamOnHGlobal(hGlobal,FALSE,&pStream) != S_OK)
+    return FALSE;
+
+   if (OleLoadPicture(pStream,dwSize,FALSE,IID_IPicture,
+    (LPVOID *)&m_pPicture) != S_OK)
+   {
+    pStream->Release();
+    return FALSE;
+   };
+
+   pStream->Release();
+  }
+  else
+  {
+  // if, on the contrary, there are several frames
+  // then store separate frames in an array
+
+   TFrame frame;
+   UINT nBlockLen;
+   HGLOBAL hFrameData;
+   UINT nCurFrame = 0;
+
+   ResetDataPointer();
+   while (hFrameData = GetNextGraphicBlock(&nBlockLen,
+    &frame.m_nDelay, &frame.m_frameSize,
+    &frame.m_frameOffset, &frame.m_nDisposal) )
+   {
+    #ifdef GIF_TRACING
+    //////////////////////////////////////////////
+    // uncomment the following strings if you want 
+    // to write separate frames on disk
+    //
+    // CString szName;
+    // szName.Format(_T("%.4d.gif"),nCurFrame);
+    // WriteDataOnDisk(szName,hFrameData,nBlockLen);
+    // nCurFrame++;
+    #endif // GIF_TRACING
+
+    IStream *pStream = NULL;
+
+    // delete memory on object's release
+    if (CreateStreamOnHGlobal(hFrameData,TRUE,&pStream) != S_OK)
+    {
+     GlobalFree(hFrameData);
+     continue;
+    };
+
+    if (OleLoadPicture(pStream,nBlockLen,FALSE,
+     IID_IPicture,
+     reinterpret_cast<LPVOID *>(&frame.m_pPicture)) != S_OK)
+    {
+     pStream->Release();
+     continue;
+    };
+    pStream->Release();
+   
+    // everything went well, add this frame
+    m_arrFrames.push_back(frame);
+   };
+
+   // clean after ourselves
+   m_pRawData = NULL;
+   GlobalUnlock(hGlobal);
+
+   if (m_arrFrames.empty()) // couldn't load any frames
+    return FALSE;
+  };
+ }; // if (!IsGIF...
+
+ return PrepareDC(m_PictureSize.cx,m_PictureSize.cy);
+}
+
+void CPictureEx::UnLoad()
+{
+ Stop();
+ if (m_pPicture)
+ {
+  m_pPicture->Release();
+  m_pPicture = NULL;
+ };
+ 
+ std::vector<TFrame>::iterator it;
+ for (it=m_arrFrames.begin();it<m_arrFrames.end();it++)
+  (*it).m_pPicture->Release();
+ m_arrFrames.clear();
+
+ if (m_hMemDC)
+ {
+  SelectObject(m_hMemDC,m_hOldBitmap);
+  ::DeleteDC(m_hMemDC);
+  ::DeleteObject(m_hBitmap);
+  m_hMemDC  = NULL;
+  m_hBitmap = NULL;
+ };
+
+ if (m_hDispMemDC)
+ {
+  SelectObject(m_hDispMemDC,m_hDispOldBM);
+  ::DeleteDC(m_hDispMemDC);
+  ::DeleteObject(m_hDispMemBM);
+  m_hDispMemDC  = NULL;
+  m_hDispMemBM = NULL;
+ };
+
+ SetRect(&m_PaintRect,0,0,0,0);
+ m_pGIFLSDescriptor = NULL;
+ m_pGIFHeader    = NULL;
+ m_pRawData     = NULL;
+ m_hThread     = NULL;
+ m_bIsInitialized   = FALSE;
+ m_bExitThread    = FALSE;
+ m_bIsGIF     = FALSE;
+ m_clrBackground    = RGB(255,255,255); // white by default
+ m_nGlobalCTSize    = 0;
+ m_nCurrOffset    = 0;
+ m_nCurrFrame    = 0;
+ m_nDataSize     = 0;
+}
+
+BOOL CPictureEx::Draw()
+{
+ if (!m_bIsInitialized)
+ {
+  TRACE(_T("Call one of the CPictureEx::Load() member functions before calling Draw()\n"));
+  return FALSE;
+ };
+
+ if (IsAnimatedGIF())
+ {
+ // the picture needs animation
+ // we'll start the thread that will handle it for us
+ 
+  unsigned int nDummy;
+  m_hThread = (HANDLE) _beginthreadex(NULL,0,_ThreadAnimation,this,
+   CREATE_SUSPENDED,&nDummy);
+  if (!m_hThread)
+  {
+   TRACE(_T("Draw: Couldn't start a GIF animation thread\n"));
+   return FALSE;
+  } 
+  else 
+   ResumeThread(m_hThread);
+ } 
+ else
+ {
+  if (m_pPicture)
+  {
+   long hmWidth;
+   long hmHeight;
+   m_pPicture->get_Width(&hmWidth);
+   m_pPicture->get_Height(&hmHeight);
+   if (m_pPicture->Render(m_hMemDC, 0, 0, m_PictureSize.cx, m_PictureSize.cy, 
+    0, hmHeight, hmWidth, -hmHeight, NULL) == S_OK)
+   {
+    Invalidate(FALSE);
+    return TRUE;
+   };
+  };
+ };
+
+ return FALSE; 
+}
+
+SIZE CPictureEx::GetSize() const
+{
+ return m_PictureSize;
+}
+
+BOOL CPictureEx::Load(LPCTSTR szFileName)
+{
+ ASSERT(szFileName);
+ 
+ CFile file;
+ HGLOBAL hGlobal;
+ DWORD dwSize;
+
+ if (!file.Open(szFileName,
+    CFile::modeRead | 
+    CFile::shareDenyWrite) )
+ {
+  TRACE(_T("Load (file): Error opening file %s\n"),szFileName);
+  return FALSE;
+ };
+
+ dwSize = file.GetLength();
+ hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
+ if (!hGlobal)
+ {
+  TRACE(_T("Load (file): Error allocating memory\n"));
+  return FALSE;
+ };
+ 
+ char *pData = reinterpret_cast<char*>(GlobalLock(hGlobal));
+ if (!pData)
+ {
+  TRACE(_T("Load (file): Error locking memory\n"));
+  GlobalFree(hGlobal);
+  return FALSE;
+ };
+
+ TRY
+ {
+  file.Read(pData,dwSize);
+ }
+ CATCH(CFileException, e);                                          
+ {
+  TRACE(_T("Load (file): An exception occured while reading the file %s\n"),
+   szFileName);
+  GlobalFree(hGlobal);
+  e->Delete();
+  file.Close();
+  return FALSE;
+ }
+ END_CATCH
+ GlobalUnlock(hGlobal);
+ file.Close();
+
+ BOOL bRetValue = Load(hGlobal,dwSize);
+ GlobalFree(hGlobal);
+ return bRetValue;
+}
+
+BOOL CPictureEx::Load(LPCTSTR szResourceName, LPCTSTR szResourceType)
+{
+ ASSERT(szResourceName);
+ ASSERT(szResourceType);
+
+ HRSRC hPicture = FindResource(AfxGetResourceHandle(),szResourceName,szResourceType);
+ HGLOBAL hResData;
+ if (!hPicture || !(hResData = LoadResource(AfxGetResourceHandle(),hPicture)))
+ {
+  TRACE(_T("Load (resource): Error loading resource %s\n"),szResourceName);
+  return FALSE;
+ };
+ DWORD dwSize = SizeofResource(AfxGetResourceHandle(),hPicture);
+
+ // hResData is not the real HGLOBAL (we can't lock it)
+ // let's make it real
+
+ HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD,dwSize);
+ if (!hGlobal)
+ {
+  TRACE(_T("Load (resource): Error allocating memory\n"));
+  FreeResource(hResData);
+  return FALSE;
+ };
+ 
+ char *pDest = reinterpret_cast<char *> (GlobalLock(hGlobal));
+ char *pSrc = reinterpret_cast<char *> (LockResource(hResData));
+ if (!pSrc || !pDest)
+ {
+  TRACE(_T("Load (resource): Error locking memory\n"));
+  GlobalFree(hGlobal);
+  FreeResource(hResData);
+  return FALSE;
+ };
+ CopyMemory(pDest,pSrc,dwSize);
+ FreeResource(hResData);
+ GlobalUnlock(hGlobal);
+
+ BOOL bRetValue = Load(hGlobal,dwSize);
+ GlobalFree(hGlobal);
+ return bRetValue;
+}
+
+void CPictureEx::ResetDataPointer()
+{
+ // skip header and logical screen descriptor
+ m_nCurrOffset = 
+  sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize;
+}
+
+BOOL CPictureEx::SkipNextGraphicBlock()
+{
+ if (!m_pRawData) return FALSE;
+
+ // GIF header + LSDescriptor [+ GCT] [+ Control block] + Data
+
+ enum GIFBlockTypes nBlock;
+
+ nBlock = GetNextBlock();
+
+ while ((nBlock != BLOCK_CONTROLEXT) &&
+     (nBlock != BLOCK_IMAGE) &&
+     (nBlock != BLOCK_PLAINTEXT) &&
+     (nBlock != BLOCK_UNKNOWN) &&
+     (nBlock != BLOCK_TRAILER) )
+ {
+  if (!SkipNextBlock()) return NULL;
+  nBlock = GetNextBlock();
+ };
+
+ if ((nBlock == BLOCK_UNKNOWN) ||
+  (nBlock == BLOCK_TRAILER))
+  return FALSE;
+
+ // it's either a control ext.block, an image or a plain text
+
+ if (GetNextBlockLen() <= 0) return FALSE;
+
+ if (nBlock == BLOCK_CONTROLEXT)
+ {
+  if (!SkipNextBlock()) return FALSE;
+  nBlock = GetNextBlock();
+
+  // skip everything until we meet an image block or a plain-text block
+  while ((nBlock != BLOCK_IMAGE) &&
+      (nBlock != BLOCK_PLAINTEXT) &&
+      (nBlock != BLOCK_UNKNOWN) &&
+      (nBlock != BLOCK_TRAILER) )
+  {
+   if (!SkipNextBlock()) return NULL;
+   nBlock = GetNextBlock();
+  };
+
+  if ((nBlock == BLOCK_UNKNOWN) ||
+   (nBlock == BLOCK_TRAILER))
+   return FALSE;
+ };
+
+ // skip the found data block (image or plain-text)
+ if (!SkipNextBlock()) return FALSE;
+
+ return TRUE;
+}
+
+UINT CPictureEx::GetSubBlocksLen(UINT nStartingOffset) const
+{
+ UINT nRet = 0;
+ UINT nCurOffset = nStartingOffset;
+ 
+ while (m_pRawData[nCurOffset] != 0)
+ {
+  nRet += m_pRawData[nCurOffset]+1;
+  nCurOffset += m_pRawData[nCurOffset]+1;
+ };
+
+ return nRet+1;
+}
+
+enum CPictureEx::GIFBlockTypes CPictureEx::GetNextBlock() const
+{
+ switch(m_pRawData[m_nCurrOffset])
+ {
+ case 0x21:
+ // extension block
+  switch(m_pRawData[m_nCurrOffset+1])
+  {
+  case 0x01:
+  // plain text extension
+   return BLOCK_PLAINTEXT;
+   break;
+
+  case 0xF9:
+  // graphic control extension
+   return BLOCK_CONTROLEXT;
+   break;
+
+  case 0xFE:
+  // comment extension
+   return BLOCK_COMMEXT;
+   break;
+
+  case 0xFF:
+  // application extension
+   return BLOCK_APPEXT;
+   break;
+  };
+  break;
+ 
+ case 0x3B:
+ // trailer
+  return BLOCK_TRAILER;
+  break;
+
+ case 0x2C:
+ // image data
+  return BLOCK_IMAGE;
+  break;
+ };
+
+ return BLOCK_UNKNOWN;
+}
+
+BOOL CPictureEx::SkipNextBlock()
+{
+ if (!m_pRawData) return FALSE;
+
+ int nLen = GetNextBlockLen();
+ if ((nLen <= 0) || ((m_nCurrOffset+nLen) > m_nDataSize))
+  return FALSE;
+
+ m_nCurrOffset += nLen;
+ return TRUE;
+}
+
+int CPictureEx::GetNextBlockLen() const
+{
+ GIFBlockTypes nBlock = GetNextBlock();
+
+ int nTmp;
+
+ switch(nBlock)
+ {
+ case BLOCK_UNKNOWN:
+  return -1;
+  break;
+
+ case BLOCK_TRAILER:
+  return 1;
+  break;
+
+ case BLOCK_APPEXT:
+  nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFAppExtension));
+  if (nTmp > 0)
+   return sizeof(TGIFAppExtension)+nTmp;
+  break;
+
+ case BLOCK_COMMEXT:
+  nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFCommentExt));
+  if (nTmp > 0)
+   return sizeof(TGIFCommentExt)+nTmp;
+  break;
+
+ case BLOCK_CONTROLEXT:
+  return sizeof(TGIFControlExt);
+  break;
+
+ case BLOCK_PLAINTEXT:
+  nTmp = GetSubBlocksLen(m_nCurrOffset+sizeof(TGIFPlainTextExt));
+  if (nTmp > 0)
+   return sizeof(TGIFPlainTextExt)+nTmp;
+  break;
+
+ case BLOCK_IMAGE:
+  TGIFImageDescriptor *pIDescr = 
+   reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
+  int nLCTSize = (int)
+   (pIDescr->GetPackedValue(ID_PACKED_LOCALCT)*3*
+   (1 << (pIDescr->GetPackedValue(ID_PACKED_LOCALCTSIZE)+1)));
+
+  int nTmp = GetSubBlocksLen(m_nCurrOffset+
+   sizeof(TGIFImageDescriptor) + nLCTSize + 1);
+  if (nTmp > 0)
+   return sizeof(TGIFImageDescriptor) + nLCTSize + 1 + nTmp;
+  break;
+ };
+
+ return 0;
+}
+
+UINT WINAPI CPictureEx::_ThreadAnimation(LPVOID pParam)
+{
+ ASSERT(pParam);
+ CPictureEx *pPic = reinterpret_cast<CPictureEx *> (pParam);
+
+ pPic->m_bIsPlaying = TRUE;
+ pPic->ThreadAnimation();
+ pPic->m_bIsPlaying = FALSE;
+
+ // this thread has finished its work so we close the handle
+ CloseHandle(pPic->m_hThread); 
+ // and init the handle to zero (so that Stop() doesn't Wait on it)
+ pPic->m_hThread = 0;
+ return 0;
+}
+
+void CPictureEx::ThreadAnimation()
+{
+ // first, restore background (for stop/draw support)
+ // disposal method #2
+ if (m_arrFrames[m_nCurrFrame].m_nDisposal == 2)
+ {
+  HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
+  if (hBrush)
+  {
+   RECT rect = {
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cx + m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cy + m_arrFrames[m_nCurrFrame].m_frameSize.cy };
+   FillRect(m_hMemDC,&rect,hBrush);
+   DeleteObject(hBrush);
+  };
+ } 
+ else
+  // disposal method #3
+  if (m_hDispMemDC && (m_arrFrames[m_nCurrFrame].m_nDisposal == 3) )
+  {
+   // put it back
+   BitBlt(m_hMemDC,
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
+    m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+    m_arrFrames[m_nCurrFrame].m_frameSize.cy,
+    m_hDispMemDC,0,0, SRCCOPY);
+   // init variables
+   SelectObject(m_hDispMemDC,m_hDispOldBM);
+   DeleteDC(m_hDispMemDC); m_hDispMemDC = NULL;
+   DeleteObject(m_hDispMemBM); m_hDispMemBM = NULL;
+  };
+
+ while (!m_bExitThread)
+ {
+  if (m_arrFrames[m_nCurrFrame].m_pPicture)
+  {
+  ///////////////////////////////////////////////////////
+  // Before rendering a frame we should take care of what's 
+  // behind that frame. TFrame::m_nDisposal will be our guide:
+  //   0 - no disposal specified (do nothing)
+  //   1 - do not dispose (again, do nothing)
+  //   2 - restore to background color (m_clrBackground)
+  //   3 - restore to previous
+
+   //////// disposal method #3
+   if (m_arrFrames[m_nCurrFrame].m_nDisposal == 3)
+   {
+    // prepare a memory DC and store the background in it
+    m_hDispMemDC = CreateCompatibleDC(m_hMemDC);
+    m_hDispMemBM = CreateCompatibleBitmap(m_hMemDC,
+       m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+       m_arrFrames[m_nCurrFrame].m_frameSize.cy);
+    
+    if (m_hDispMemDC && m_hDispMemBM)
+    {
+     m_hDispOldBM = reinterpret_cast<HBITMAP> (SelectObject(m_hDispMemDC,m_hDispMemBM));
+     BitBlt(m_hDispMemDC,0,0,
+      m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+      m_arrFrames[m_nCurrFrame].m_frameSize.cy,
+      m_hMemDC,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
+      SRCCOPY);
+    };
+   };
+   ///////////////////////
+
+   long hmWidth;
+   long hmHeight;
+   m_arrFrames[m_nCurrFrame].m_pPicture->get_Width(&hmWidth);
+   m_arrFrames[m_nCurrFrame].m_pPicture->get_Height(&hmHeight);
+
+   if (m_arrFrames[m_nCurrFrame].m_pPicture->Render(m_hMemDC, 
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cx, 
+    m_arrFrames[m_nCurrFrame].m_frameOffset.cy, 
+    m_arrFrames[m_nCurrFrame].m_frameSize.cx, 
+    m_arrFrames[m_nCurrFrame].m_frameSize.cy, 
+    0, hmHeight, hmWidth, -hmHeight, NULL) == S_OK)
+   {
+    Invalidate(FALSE);
+   };
+   
+   if (m_bExitThread) break;
+
+   // if the delay time is too short (like in old GIFs), wait for 100ms
+   if (m_arrFrames[m_nCurrFrame].m_nDelay < 5) 
+    WaitForSingleObject(m_hExitEvent, 100);
+   else
+    WaitForSingleObject(m_hExitEvent, 10*m_arrFrames[m_nCurrFrame].m_nDelay);
+
+   if (m_bExitThread) break;
+
+   // disposal method #2
+   if (m_arrFrames[m_nCurrFrame].m_nDisposal == 2)
+   {
+    HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
+    if (hBrush)
+    {
+     RECT rect = {
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cx + m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cy + m_arrFrames[m_nCurrFrame].m_frameSize.cy };
+     FillRect(m_hMemDC,&rect,hBrush);
+     DeleteObject(hBrush);
+    };
+   } 
+   else
+    if (m_hDispMemDC && (m_arrFrames[m_nCurrFrame].m_nDisposal == 3) )
+    {
+     // put it back
+     BitBlt(m_hMemDC,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cx,
+      m_arrFrames[m_nCurrFrame].m_frameOffset.cy,
+      m_arrFrames[m_nCurrFrame].m_frameSize.cx,
+      m_arrFrames[m_nCurrFrame].m_frameSize.cy,
+      m_hDispMemDC,0,0, SRCCOPY);
+     // init variables
+     SelectObject(m_hDispMemDC,m_hDispOldBM);
+     DeleteDC(m_hDispMemDC); m_hDispMemDC = NULL;
+     DeleteObject(m_hDispMemBM); m_hDispMemBM = NULL;
+    };
+  };
+  m_nCurrFrame++;
+  if (m_nCurrFrame == m_arrFrames.size())
+  {
+   m_nCurrFrame
+    = 0; 
+  // init the screen for the first frame,
+   HBRUSH hBrush = CreateSolidBrush(m_clrBackground);
+   if (hBrush)
+   {
+    RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy};
+    FillRect(m_hMemDC,&rect,hBrush);
+    DeleteObject(hBrush);
+   };
+  };
+ };
+}
+
+void CPictureEx::Stop()
+{
+ m_bIsPlaying = FALSE;
+ m_bExitThread = TRUE;
+ SetEvent(m_hExitEvent);
+ if (m_hThread)
+ {
+  // we'll wait for 5 seconds then continue execution
+  WaitForSingleObject(m_hThread,5000);
+  CloseHandle(m_hThread);
+  m_hThread = NULL;
+ }
+
+ // make it possible to Draw() again
+ ResetEvent(m_hExitEvent);
+ m_bExitThread = FALSE;
+}
+
+HGLOBAL CPictureEx::GetNextGraphicBlock(UINT *pBlockLen, 
+ UINT *pDelay, SIZE *pBlockSize, SIZE *pBlockOffset, 
+ UINT *pDisposal)
+{
+ if (!m_pRawData) return NULL;
+
+ // GIF header + LSDescriptor [+ GCT] [+ Control block] + Data
+
+ *pDisposal = 0;
+ enum GIFBlockTypes nBlock;
+ nBlock = GetNextBlock();
+
+ while (
+  (nBlock != BLOCK_CONTROLEXT) &&
+  (nBlock != BLOCK_IMAGE) &&
+  (nBlock != BLOCK_PLAINTEXT) &&
+  (nBlock != BLOCK_UNKNOWN) &&
+  (nBlock != BLOCK_TRAILER)
+  )
+ {
+  if (!SkipNextBlock()) return NULL;
+  nBlock = GetNextBlock();
+ };
+
+ if ((nBlock == BLOCK_UNKNOWN) ||
+  (nBlock == BLOCK_TRAILER))
+  return NULL;
+
+ // it's either a control ext.block, an image or a plain text
+
+ int nStart = m_nCurrOffset;
+ int nBlockLen = GetNextBlockLen();
+
+ if (nBlockLen <= 0) return NULL;
+
+ if (nBlock == BLOCK_CONTROLEXT)
+ {
+  // get the following data
+  TGIFControlExt *pControl = 
+   reinterpret_cast<TGIFControlExt *> (&m_pRawData[m_nCurrOffset]);
+  // store delay time
+  *pDelay = pControl->m_wDelayTime;
+  // store disposal method
+  *pDisposal = pControl->GetPackedValue(GCX_PACKED_DISPOSAL);
+
+  if (!SkipNextBlock()) return NULL;
+  nBlock = GetNextBlock();
+  
+  // skip everything until we find data to display 
+  // (image block or plain-text block)
+  
+  while (
+   (nBlock != BLOCK_IMAGE) &&
+   (nBlock != BLOCK_PLAINTEXT) &&
+   (nBlock != BLOCK_UNKNOWN) &&
+   (nBlock != BLOCK_TRAILER)
+   )
+  {
+   if (!SkipNextBlock()) return NULL;
+   nBlock = GetNextBlock();
+   nBlockLen += GetNextBlockLen();
+  };
+
+  if ((nBlock == BLOCK_UNKNOWN) || (nBlock == BLOCK_TRAILER))
+   return NULL;
+  nBlockLen += GetNextBlockLen();
+ }
+ else
+  *pDelay = -1; // to indicate that there was no delay value
+
+ if (nBlock == BLOCK_IMAGE)
+ {
+  // store size and offsets
+  TGIFImageDescriptor *pImage = 
+   reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
+  pBlockSize->cx = pImage->m_wWidth;
+  pBlockSize->cy = pImage->m_wHeight;
+  pBlockOffset->cx = pImage->m_wLeftPos;
+  pBlockOffset->cy = pImage->m_wTopPos;
+ };
+
+ if (!SkipNextBlock()) return NULL;
+
+ HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED,
+  sizeof(TGIFHeader) +
+  sizeof(TGIFLSDescriptor) +
+  m_nGlobalCTSize +
+  nBlockLen + 
+  1);  // for the trailer
+
+ if (!hGlobal) return NULL;
+
+ int nOffset = 0; 
+
+ // GMEM_FIXED means we get a pointer
+ unsigned char *pGlobal = reinterpret_cast<unsigned char *> (hGlobal);
+
+ CopyMemory(pGlobal,m_pRawData, 
+  sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize);
+ nOffset += sizeof(TGIFHeader)+sizeof(TGIFLSDescriptor)+m_nGlobalCTSize;
+
+ CopyMemory(pGlobal + nOffset,&m_pRawData[nStart], nBlockLen);
+ nOffset += nBlockLen;
+
+ pGlobal[nOffset] = 0x3B; // trailer
+ nOffset++;
+
+ *pBlockLen = nOffset;
+
+ return hGlobal;
+}
+
+BOOL CPictureEx::IsGIF() const
+{
+ return m_bIsGIF;
+}
+
+BOOL CPictureEx::IsAnimatedGIF() const
+{
+ return (m_bIsGIF && (m_arrFrames.size() > 1));
+}
+
+BOOL CPictureEx::IsPlaying() const
+{
+ return m_bIsPlaying;
+}
+
+int CPictureEx::GetFrameCount() const
+{
+ if (!IsAnimatedGIF())
+  return 0;
+
+ return m_arrFrames.size();
+}
+
+COLORREF CPictureEx::GetBkColor() const
+{
+ return m_clrBackground;
+}
+
+void CPictureEx::OnPaint() 
+{
+ CPaintDC dc(this); // device context for painting
+
+ LONG nPaintWidth = m_PaintRect.right-m_PaintRect.left;
+
+ if (nPaintWidth > 0)
+ {
+  LONG nPaintHeight = m_PaintRect.bottom - m_PaintRect.top;
+  ::BitBlt(dc.m_hDC, 0, 0, nPaintWidth, nPaintHeight, 
+   m_hMemDC, m_PaintRect.left, m_PaintRect.top, SRCCOPY);
+ }
+ else
+ {
+  ::BitBlt(dc.m_hDC, 0, 0, m_PictureSize.cx, m_PictureSize.cy,
+   m_hMemDC, 0, 0, SRCCOPY);
+ };
+}
+
+BOOL CPictureEx::PrepareDC(int nWidth, int nHeight)
+{
+ SetWindowPos(NULL,0,0,nWidth,nHeight,SWP_NOMOVE | SWP_NOZORDER);
+
+ HDC hWinDC = ::GetDC(m_hWnd);
+ if (!hWinDC) return FALSE;
+ 
+ m_hMemDC = CreateCompatibleDC(hWinDC);
+ if (!m_hMemDC) 
+ {
+  ::ReleaseDC(m_hWnd,hWinDC);
+  return FALSE;
+ };
+
+ m_hBitmap  = CreateCompatibleBitmap(hWinDC,nWidth,nHeight);
+ if (!m_hBitmap) 
+ {
+  ::ReleaseDC(m_hWnd,hWinDC);
+  ::DeleteDC(m_hMemDC);
+  return FALSE;
+ };
+
+ m_hOldBitmap = reinterpret_cast<HBITMAP> 
+      (SelectObject(m_hMemDC,m_hBitmap));
+ 
+ // fill the background
+ m_clrBackground = GetSysColor(COLOR_3DFACE);
+ RECT rect = {0,0,nWidth,nHeight};
+ FillRect(m_hMemDC,&rect,(HBRUSH)(COLOR_WINDOW));
+
+ ::ReleaseDC(m_hWnd,hWinDC);
+ m_bIsInitialized = TRUE;
+ return TRUE;
+}
+
+void CPictureEx::OnDestroy() 
+{
+ Stop(); 
+ CStatic::OnDestroy();
+}
+
+void CPictureEx::SetBkColor(COLORREF clr)
+{
+ if (!m_bIsInitialized) return;
+
+ m_clrBackground = clr;
+
+ HBRUSH hBrush = CreateSolidBrush(clr);
+ if (hBrush)
+ {
+  RECT rect = {0,0,m_PictureSize.cx,m_PictureSize.cy};
+  FillRect(m_hMemDC,&rect,hBrush);
+  DeleteObject(hBrush);
+ };
+}
+
+#ifdef GIF_TRACING
+void CPictureEx::WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize)
+{
+ CFile file;
+
+ if (!file.Open(szFileName,
+   CFile::modeCreate |
+   CFile::modeWrite |
+   CFile::shareDenyNone))
+ {
+  TRACE(_T("WriteData: Error creating file %s\n"),szFileName);
+  return;
+ };
+
+ char *pData = reinterpret_cast<char *> (GlobalLock(hData));
+ if (!pData)
+ {
+  TRACE(_T("WriteData: Error locking memory\n"));
+  return;
+ };
+
+ TRY
+ {
+  file.Write(pData,dwSize);
+ }
+ CATCH(CFileException, e);                                          
+ {
+  TRACE(_T("WriteData: An exception occured while writing to the file %s\n"),
+   szFileName);
+  e->Delete();
+  GlobalUnlock(hData);
+  file.Close();
+  return;
+ }
+ END_CATCH
+ 
+ GlobalUnlock(hData);
+ file.Close();
+}
+
+void CPictureEx::EnumGIFBlocks()
+{
+ enum GIFBlockTypes nBlock;
+
+ ResetDataPointer();
+ while(m_nCurrOffset < m_nDataSize)
+ {
+  nBlock = GetNextBlock();
+  switch(nBlock)
+  {
+  case BLOCK_UNKNOWN:
+   TRACE(_T("- Unknown block\n"));
+   return;
+   break;
+
+  case BLOCK_TRAILER:
+   TRACE(_T("- Trailer block\n"));
+   break;
+
+  case BLOCK_APPEXT:
+   TRACE(_T("- Application extension block\n"));
+   break;
+
+  case BLOCK_COMMEXT:
+   TRACE(_T("- Comment extension block\n"));
+   break;
+
+  case BLOCK_CONTROLEXT:
+   {
+   TGIFControlExt *pControl = 
+    reinterpret_cast<TGIFControlExt *> (&m_pRawData[m_nCurrOffset]);
+   TRACE(_T("- Graphic control extension block (delay %d, disposal %d)\n"),
+     pControl->m_wDelayTime, pControl->GetPackedValue(GCX_PACKED_DISPOSAL));
+   };
+   break;
+
+  case BLOCK_PLAINTEXT:
+   TRACE(_T("- Plain text extension block\n"));
+   break;
+
+  case BLOCK_IMAGE:
+   TGIFImageDescriptor *pIDescr = 
+    reinterpret_cast<TGIFImageDescriptor *> (&m_pRawData[m_nCurrOffset]);
+   TRACE(_T("- Image data block (%dx%d  %d,%d)\n"),
+     pIDescr->m_wWidth,
+     pIDescr->m_wHeight,
+     pIDescr->m_wLeftPos,
+     pIDescr->m_wTopPos);
+   break;
+  };
+
+  SkipNextBlock(); 
+ };
+
+ TRACE(_T("\n"));
+}
+#endif // GIF_TRACING
+
+BOOL CPictureEx::SetPaintRect(const RECT *lpRect)
+{
+ return CopyRect(&m_PaintRect, lpRect);
+}
+
+BOOL CPictureEx::GetPaintRect(RECT *lpRect)
+{
+ return CopyRect(lpRect, &m_PaintRect);
+}

+ 305 - 0
VideoCapture/UI/PictureEx.h

@@ -0,0 +1,305 @@
+//////////////////////////////////////////////////////////////////////
+// PictureEx.cpp: implementation of the CPictureEx class.
+//
+// Picture displaying control with support for the following formats:
+// GIF (including animated GIF87a and GIF89a), JPEG, BMP, WMF, ICO, CUR
+// 
+// Written by Oleg Bykov (oleg_bykoff@rsdn.ru)
+// Copyright (c) 2001
+//
+// To use CPictureEx, follow these steps:
+//   - place a static control on your dialog (either a text or a bitmap)
+//   - change its identifier to something else (e.g. IDC_MYPIC)
+//   - associate a CStatic with it using ClassWizard
+//   - in your dialog's header file replace CStatic with CPictureEx
+//     (don't forget to #include "PictureEx.h" and add 
+//     PictureEx.h and PictureEx.cpp to your project)
+//   - call one of the overloaded CPictureEx::Load() functions somewhere
+//     (OnInitDialog is a good place to start)
+//   - if the preceding Load() succeeded call Draw()
+//  
+// You can also add the control by defining a member variable of type 
+// CPictureEx, calling CPictureEx::Create (derived from CStatic), then 
+// CPictureEx::Load and CPictureEx::Draw.
+//
+// By default, the control initializes its background to COLOR_3DFACE
+// (see CPictureEx::PrepareDC()). You can change the background by
+// calling CPictureEx::SetBkColor(COLORREF) after CPictureEx::Load().
+//
+// I decided to leave in the class the functions to write separate frames from 
+// animated GIF to disk. If you want to use them, uncomment #define GIF_TRACING 
+// and an appropriate section in CPictureEx::Load(HGLOBAL, DWORD). These functions 
+// won't be compiled and linked to your project unless you uncomment #define GIF_TRACING,
+// so you don't have to worry.
+// 
+// Warning: this code hasn't been subject to a heavy testing, so
+// use it on your own risk. The author accepts no liability for the 
+// possible damage caused by this code.
+//
+// Version 1.0  7 Aug 2001
+//              Initial release
+//
+// Version 1.1  6 Sept 2001
+//              ATL version of the class
+//
+// Version 1.2  14 Oct 2001
+//              - Fixed a problem with loading GIFs from resources
+//                in MFC-version of the class for multi-modules apps.
+//                Thanks to Ruben Avila-Carretero for finding this out.
+//
+//              - Got rid of waitable timer in ThreadAnimation()
+//                Now CPictureEx[Wnd] works in Win95 too.
+//                Thanks to Alex Egiazarov and Wayne King for the idea.
+//
+//              - Fixed a visual glitch of using SetBkColor.
+//                Thanks to Kwangjin Lee for finding this out.
+//
+// Version 1.3  10 Nov 2001
+//              - Fixed a DC leak. One DC leaked per each UnLoad()
+//                (forgot to put a ReleaseDC() in the end of 
+//                CPictureExWnd::PrepareDC() function).
+//
+//              - Now it is possible to set a clipping rectangle using
+//                CPictureEx[Wnd]::SetPaintRect(const LPRECT) function.
+//                The LPRECT parameter tells the class what portion of
+//                a picture should it display. If the clipping rect is 
+//                not set, the whole picture is shown.
+//                Thanks to Fabrice Rodriguez for the idea.
+//
+//              - Added support for Stop/Draw. Now you can Stop() an
+//                animated GIF, then Draw() it again, it will continue
+//                animation from the frame it was stopped on. You can 
+//                also know if a GIF is currently playing with the 
+//                IsPlaying() function.
+//             
+//              - Got rid of math.h and made m_bExitThread volatile. 
+//                Thanks to Piotr Sawicki for the suggestion.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)
+#define AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include <vector>
+
+//#define GIF_TRACING  // uncomment it if you want detailed TRACEs
+
+class CPictureEx : public CStatic
+{
+public:
+
+	struct TFrame    // structure that keeps a single frame info
+	{
+		IPicture *m_pPicture;  // pointer to the interface used for drawing
+		SIZE     m_frameSize;
+		SIZE     m_frameOffset;
+		UINT     m_nDelay;     // delay (in 1/100s of a second)
+		UINT     m_nDisposal;  // disposal method
+	};
+
+#pragma pack(1)   // turn byte alignment on
+
+	enum GIFBlockTypes
+	{
+		BLOCK_UNKNOWN,
+		BLOCK_APPEXT,
+		BLOCK_COMMEXT,
+		BLOCK_CONTROLEXT,
+		BLOCK_PLAINTEXT,
+		BLOCK_IMAGE,
+		BLOCK_TRAILER
+	};
+
+	enum ControlExtValues // graphic control extension packed field values
+	{
+		GCX_PACKED_DISPOSAL,  // disposal method
+		GCX_PACKED_USERINPUT,
+		GCX_PACKED_TRANSPCOLOR
+	};
+
+	enum LSDPackedValues  // logical screen descriptor packed field values
+	{
+		LSD_PACKED_GLOBALCT,
+		LSD_PACKED_CRESOLUTION,
+		LSD_PACKED_SORT,
+		LSD_PACKED_GLOBALCTSIZE
+	};
+
+	enum IDPackedValues   // image descriptor packed field values
+	{
+		ID_PACKED_LOCALCT,
+		ID_PACKED_INTERLACE,
+		ID_PACKED_SORT,
+		ID_PACKED_LOCALCTSIZE
+	};
+
+	struct TGIFHeader       // GIF header  
+	{
+		char m_cSignature[3]; // Signature - Identifies the GIF Data Stream
+		// This field contains the fixed value 'GIF'
+		char m_cVersion[3]; // Version number. May be one of the following:
+		// "87a" or "89a"
+	};
+
+	struct TGIFLSDescriptor // Logical Screen Descriptor
+	{
+		WORD m_wWidth; // 2 bytes. Logical screen width
+		WORD m_wHeight; // 2 bytes. Logical screen height
+
+		unsigned char m_cPacked;      // packed field 
+
+		unsigned char m_cBkIndex;     // 1 byte. Background color index
+		unsigned char m_cPixelAspect; // 1 byte. Pixel aspect ratio
+		inline int GetPackedValue(enum LSDPackedValues Value);
+	};
+
+	struct TGIFAppExtension // application extension block
+	{
+		unsigned char m_cExtIntroducer; // extension introducer (0x21)
+		unsigned char m_cExtLabel; // app. extension label (0xFF)
+		unsigned char m_cBlockSize; // fixed value of 11
+		char m_cAppIdentifier[8];   // application identifier
+		char m_cAppAuth[3];  // application authentication code
+	};
+
+	struct TGIFControlExt // graphic control extension block
+	{
+		unsigned char m_cExtIntroducer; // extension introducer (0x21)
+		unsigned char m_cControlLabel;  // control extension label (0xF9)
+		unsigned char m_cBlockSize; // fixed value of 4
+		unsigned char m_cPacked;    // packed field
+		WORD m_wDelayTime; // delay time
+		unsigned char m_cTColorIndex; // transparent color index
+		unsigned char m_cBlockTerm;   // block terminator (0x00)
+	public:
+		inline int GetPackedValue(enum ControlExtValues Value);
+	};
+
+	struct TGIFCommentExt  // comment extension block
+	{
+		unsigned char m_cExtIntroducer; // extension introducer (0x21)
+		unsigned char m_cCommentLabel;  // comment extension label (0xFE)
+	};
+
+	struct TGIFPlainTextExt // plain text extension block
+	{
+		unsigned char m_cExtIntroducer;  // extension introducer (0x21)
+		unsigned char m_cPlainTextLabel; // text extension label (0x01)
+		unsigned char m_cBlockSize; // fixed value of 12
+		WORD m_wLeftPos;    // text grid left position
+		WORD m_wTopPos;     // text grid top position
+		WORD m_wGridWidth;  // text grid width
+		WORD m_wGridHeight; // text grid height
+		unsigned char m_cCellWidth;  // character cell width
+		unsigned char m_cCellHeight; // character cell height
+		unsigned char m_cFgColor; // text foreground color index
+		unsigned char m_cBkColor; // text background color index
+	};
+
+	struct TGIFImageDescriptor // image descriptor block
+	{
+		unsigned char m_cImageSeparator; // image separator byte (0x2C)
+		WORD m_wLeftPos; // image left position
+		WORD m_wTopPos;  // image top position
+		WORD m_wWidth;   // image width
+		WORD m_wHeight;  // image height
+		unsigned char m_cPacked; // packed field
+		inline int GetPackedValue(enum IDPackedValues Value);
+	};
+
+#pragma pack() // turn byte alignment off
+
+public:
+	BOOL GetPaintRect(RECT *lpRect);
+	BOOL SetPaintRect(const RECT *lpRect);
+	CPictureEx();
+	virtual ~CPictureEx();
+	void Stop();   // stops animation
+	void UnLoad(); // stops animation plus releases all resources
+
+	BOOL IsGIF() const;
+	BOOL IsPlaying() const;
+	BOOL IsAnimatedGIF() const;
+	SIZE GetSize() const;
+	int GetFrameCount() const;
+	COLORREF GetBkColor() const;
+	void SetBkColor(COLORREF clr);
+
+	// draws the picture (starts an animation thread if needed)
+	// if an animation was previously stopped by Stop(),
+	// continues it from the last displayed frame
+	BOOL Draw();
+
+	// loads a picture from a file
+	// i.e. Load(_T("mypic.gif"));
+	BOOL Load(LPCTSTR szFileName);
+
+	// loads a picture from a global memory block (allocated by GlobalAlloc)
+	// Warning: this function DOES NOT free the global memory, pointed to by hGlobal
+	BOOL Load(HGLOBAL hGlobal, DWORD dwSize);
+
+	// loads a picture from a program resource
+	// i.e. Load(MAKEINTRESOURCE(IDR_MYPIC),_T("GIFTYPE"));
+	BOOL Load(LPCTSTR szResourceName,LPCTSTR szResourceType);
+
+protected:
+
+#ifdef GIF_TRACING
+	void EnumGIFBlocks();
+	void WriteDataOnDisk(CString szFileName, HGLOBAL hData, DWORD dwSize);
+#endif // GIF_TRACING
+
+	RECT m_PaintRect;
+	SIZE m_PictureSize;
+	COLORREF m_clrBackground;
+	UINT m_nCurrFrame;
+	UINT m_nDataSize;
+	UINT m_nCurrOffset;
+	UINT m_nGlobalCTSize;
+	BOOL m_bIsGIF;
+	BOOL m_bIsPlaying;
+	volatile BOOL m_bExitThread;
+	BOOL m_bIsInitialized;
+	HDC m_hMemDC;
+
+	HDC m_hDispMemDC;
+	HBITMAP m_hDispMemBM;
+	HBITMAP m_hDispOldBM;
+
+	HBITMAP m_hBitmap;
+	HBITMAP m_hOldBitmap;
+	HANDLE m_hThread;
+	HANDLE m_hExitEvent;
+	IPicture * m_pPicture;
+	TGIFHeader * m_pGIFHeader;
+	unsigned char * m_pRawData;
+	TGIFLSDescriptor * m_pGIFLSDescriptor;
+	std::vector<TFrame> m_arrFrames;
+
+	void ThreadAnimation();
+	static UINT WINAPI _ThreadAnimation(LPVOID pParam);
+
+	int GetNextBlockLen() const;
+	BOOL SkipNextBlock();
+	BOOL SkipNextGraphicBlock();
+	BOOL PrepareDC(int nWidth, int nHeight);
+	void ResetDataPointer();
+	enum GIFBlockTypes GetNextBlock() const;
+	UINT GetSubBlocksLen(UINT nStartingOffset) const;
+	HGLOBAL GetNextGraphicBlock(UINT *pBlockLen, UINT *pDelay, 
+		SIZE *pBlockSize, SIZE *pBlockOffset, UINT *pDisposal);
+
+	// Generated message map functions
+	//{{AFX_MSG(CPictureEx)
+	afx_msg void OnDestroy();
+	afx_msg void OnPaint();
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+};
+
+#endif // !defined(AFX_PICTUREEX_H__0EFE5DE0_7B68_4DB7_8B34_5DC634948438__INCLUDED_)

+ 1364 - 0
VideoCapture/UI/SubLabel.cpp

@@ -0,0 +1,1364 @@
+// Label.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "SubLabel.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+BEGIN_MESSAGE_MAP(CLabel, CStatic)
+	//{{AFX_MSG_MAP(CLabel)
+	ON_WM_TIMER()
+	ON_WM_LBUTTONDOWN()
+	ON_WM_SETCURSOR()
+	ON_WM_SYSCOLORCHANGE()
+	ON_WM_PAINT()
+	ON_WM_ERASEBKGND()
+	//}}AFX_MSG_MAP
+	ON_WM_CTLCOLOR_REFLECT()
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CLabel Version 1.2
+//
+// From now on I'll try to keep a log of fixes and enhancements...
+// 
+// The new feature were added due to the response of people.
+// All I ask is to all you programmers out there, is if you add, fix or
+// enhance this code, sent me a copy and I'll send the copy on to www.codeproject.com
+//
+// Happy Software Engineer :)
+// 
+// New features include:
+//
+// A. Support for 3D Fonts
+// B. Support for background transparency
+// C. More comments provided
+// D. If alignment is 'centered' and the window text is seperated by '\r\n'
+//	  the will be centered accordingly - requested by someone @ nasa ;)
+// E. Support for font rotation.
+// F. Respond to System Color Change
+// G. OnPaint improved performance - using Double Buffering Technique
+//
+// Thanks to:
+// Mark McDowell	- For suggestion on 'Increasing the flexibility of "hypertext" setting...'
+// Erich Ruth		- For suggestion on 'Font Rotation'
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CLabel Version 1.3
+//
+// A. Added SS_LEFTNOWORDWRAP to include wordwrap
+// B. Fix repainting problem 
+// C. Fix SetBkColor
+// D. Added SS_CENTER
+
+// Thanks to:
+// Marius						- Added styling problem.
+// Azing Vondeling & Broker		- Spotting painting Problem.
+// Mel Stober					- Back Color & SS_CENTER
+// 
+/////////////////////////////////////////////////////////////////////////////
+// CLabel Version 1.4
+//
+// A. Fix to transparency mode
+// B. Added new SetText3DHiliteColor to change the 3D Font face color - default is white.
+// 
+// Thanks to:
+// michael.groeger				- Spotting Transparency with other controls bug.
+//
+//
+/////////////////////////////////////////////////////////////////////////////
+// CLabel Version 1.5
+//
+// A. Sanity handle check
+// B. Support Interface Charset
+// C. Check compilition with _UNICODE
+// D. Fix hyperlink feature
+// E. Support default Dialog Font
+// F. Inclusion of SS_OWNERDRAW via control creation and subclassing
+// G. Modification to Text aligmnent code
+// H. New background gradient fill function
+// 
+// Thanks to:
+// Steve Kowald				- Using null handles 
+// Alan Chan				- Supporting International Windows
+// Dieter Fauth				- Request for default Dialog font
+// Herb Illfelder			- Text Alignment code
+// 
+/////////////////////////////////////////////////////////////////////////////
+// CLabel Version 1.6
+// Jeroen Roosendaal		- SetFont suggestion
+// Laurent					- Spotting SelectObject bugs
+// Bernie					- Fix PreCreateWindow bug
+// Jignesh I. Patel			- Added expanded tabs feature
+// Jim Farmelant 			- Fix SetText crash
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::CLabel
+//
+// Description:		Default contructor
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel::CLabel()
+{
+	m_crText = GetSysColor(COLOR_WINDOWTEXT);
+
+	// 1.1
+	m_hBackBrush = NULL;
+
+
+	m_crHiColor =		0;
+	m_crLoColor	=		0;
+
+	m_bTimer =			FALSE;
+	m_bState =			FALSE;
+	m_bTransparent =	FALSE;
+	m_Link =			LinkNone;
+	m_hCursor =			NULL;
+	m_Type =			None;
+	m_bFont3d =			FALSE;
+	m_bNotifyParent =	FALSE;
+	m_bToolTips =		FALSE;
+	m_bRotation =		FALSE;
+	m_fillmode =		Normal;
+	m_cr3DHiliteColor =	RGB(255,255,255);
+	m_strText =			_T("");
+	m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::~CLabel
+//
+// Description:		
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+// NT ALMOND				15092000	1.5		Handle Check
+//////////////////////////////////////////////////////////////////////////
+CLabel::~CLabel()
+{
+	// Clean up
+	m_font.DeleteObject();
+	::DeleteObject(m_hwndBrush);
+
+	// Stop Checking complaining
+	if (m_hBackBrush)
+		::DeleteObject(m_hBackBrush);
+
+}
+
+void CLabel::UpdateSurface()
+{
+	CRect (rc);
+	GetWindowRect(rc);
+	RedrawWindow();
+
+	GetParent()->ScreenToClient(rc);
+	GetParent()->InvalidateRect(rc,TRUE);
+	GetParent()->UpdateWindow();
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::ReconstructFont
+//
+// Description:		Helper function to build font after it was changed
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			PROTECTED
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+void CLabel::ReconstructFont()
+{
+	m_font.DeleteObject();
+	BOOL bCreated = m_font.CreateFontIndirect(&m_lf);
+
+	ASSERT(bCreated);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::OnPaint
+//
+// Description:		Handles all the drawing code for the label
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			Called by Windows... not by USER
+//					Probably needs tiding up a some point.
+//					Different states will require this code to be reworked.
+//
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+// NT ALMOND				15092000	1.5		Handle Check
+// NT ALMOND				15092000	1.5		Alignment mods
+// NT ALMOND				15092000	1.5		Gradient Fill Mode
+// NT ALMOND				02072002	1.6		Fill SelectObject bugs
+// NT ALMOND				02072002	1.6		Added to expand tabs
+//////////////////////////////////////////////////////////////////////////
+
+void CLabel::OnPaint() 
+{
+	CPaintDC dc(this); // device context for painting
+
+	DWORD dwFlags = 0;
+
+	CRect rc;
+	GetClientRect(rc);
+	if (m_strText.IsEmpty())
+		GetWindowText(m_strText);
+	CBitmap bmp;
+
+
+	///////////////////////////////////////////////////////
+	//
+	// Set up for double buffering...
+	//
+	CDC* pDCMem;
+	CBitmap*	pOldBitmap = NULL;
+
+	if (!m_bTransparent)
+	{
+		pDCMem = new CDC;
+		pDCMem->CreateCompatibleDC(&dc);
+		bmp.CreateCompatibleBitmap(&dc,rc.Width(),rc.Height());
+		pOldBitmap = pDCMem->SelectObject(&bmp);
+	}
+	else
+	{
+		pDCMem = &dc;
+	}
+
+	UINT nMode = pDCMem->SetBkMode(TRANSPARENT);
+
+
+	COLORREF crText = pDCMem->SetTextColor(m_crText);
+	CFont *pOldFont = pDCMem->SelectObject(&m_font);
+
+
+	// Fill in backgound if not transparent
+	if (!m_bTransparent)
+	{
+		if (m_fillmode == Normal)
+		{
+			CBrush br;
+
+			if (m_hBackBrush != NULL)
+				br.Attach(m_hBackBrush);
+			else
+				br.Attach(m_hwndBrush);
+
+			pDCMem->FillRect(rc,&br);
+
+			br.Detach();
+		}
+		else // Gradient Fill
+		{
+			DrawGradientFill(pDCMem, &rc, m_crLoColor, m_crHiColor, 100);
+		}
+
+	}
+
+
+	// If the text is flashing turn the text color on
+	// then to the color of the window background.
+
+	LOGBRUSH lb;
+	ZeroMemory(&lb,sizeof(lb));
+
+	// Stop Checking complaining
+	if (m_hBackBrush)
+		::GetObject(m_hBackBrush,sizeof(lb),&lb);
+
+
+	// Something to do with flashing
+	if (!m_bState && m_Type == Text)
+	{
+		//ZeroMemory(&lb,sizeof(lb));
+		lb.lbColor = RGB(255,0,255);
+		pDCMem->SetTextColor(lb.lbColor);
+	}
+
+	DWORD style = GetStyle();
+
+	switch (style & SS_TYPEMASK)
+	{
+	case SS_RIGHT: 
+		dwFlags = DT_RIGHT | DT_WORDBREAK; 
+		break; 
+
+	case SS_CENTER: 
+		dwFlags = SS_CENTER | DT_WORDBREAK;
+		break;
+
+	case SS_LEFTNOWORDWRAP: 
+		dwFlags = DT_LEFT; 
+		break;
+
+	default: // treat other types as left
+	case SS_LEFT: 
+		dwFlags = DT_LEFT | DT_WORDBREAK; 
+		break;
+	}	
+
+
+	// Added to expand tabs...
+	if(m_strText.Find(_T('\t')) != -1)
+		dwFlags |= DT_EXPANDTABS;
+
+	// If the text centered make an assumtion that
+	// the will want to center verticly as well
+	if (style & SS_CENTERIMAGE)
+	{
+		dwFlags = DT_CENTER;
+
+		// Apply 
+		if (m_strText.Find(_T("\r\n")) == -1)
+		{
+			dwFlags |= DT_VCENTER;
+
+			// And because DT_VCENTER only works with single lines
+			dwFlags |= DT_SINGLELINE; 
+		}
+
+	}
+
+	//
+	// 3333   DDDDD
+	//     3  D    D
+	//   33   D     D    E F X 
+	//     3  D    D
+	// 3333   DDDDD
+	//
+	//
+	if (m_bRotation)
+	{
+		int nAlign = pDCMem->SetTextAlign (TA_BASELINE);
+
+		CPoint pt;
+		GetViewportOrgEx (pDCMem->m_hDC,&pt) ;
+		SetViewportOrgEx (pDCMem->m_hDC,rc.Width() / 2, rc.Height() / 2, NULL) ;
+		pDCMem->TextOut(0, 0, m_strText);
+		SetViewportOrgEx (pDCMem->m_hDC,pt.x / 2, pt.y / 2, NULL) ;
+		pDCMem->SetTextAlign (nAlign);
+	}
+	else
+	{
+		pDCMem->DrawText(m_strText, rc, dwFlags);
+		if (m_bFont3d)
+		{
+			pDCMem->SetTextColor(m_cr3DHiliteColor);
+
+			if (m_3dType == Raised)
+				rc.OffsetRect(-1,-1);
+			else
+				rc.OffsetRect(1,1);
+
+			pDCMem->DrawText(m_strText, rc, dwFlags);
+			m_3dType;
+
+		}
+	}
+
+	// Restore DC's State
+	pDCMem->SetBkMode(nMode);
+	pDCMem->SelectObject(pOldFont);
+	pDCMem->SetTextColor(crText);
+
+	if (!m_bTransparent)
+	{
+		dc.BitBlt(0, 0, rc.Width(), rc.Height(), pDCMem, 0, 0, SRCCOPY);
+		// continue DC restore 
+		pDCMem->SelectObject ( pOldBitmap ) ;
+		delete pDCMem;
+	}
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::OnTimer
+//
+// Description:		Used in conjunction with 'FLASH' functions
+//
+// INPUTS:          Windows API
+// 
+// RETURNS:         Windows API
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+void CLabel::OnTimer(UINT nIDEvent) 
+{
+
+	m_bState = !m_bState;
+
+	UpdateSurface();
+
+	CStatic::OnTimer(nIDEvent);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::OnSetCursor
+//
+// Description:		Used in conjunction with 'LINK' function
+//
+// INPUTS:          Windows API
+// 
+// RETURNS:         Windows API
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+BOOL CLabel::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
+{
+
+	if (m_hCursor)
+	{
+		::SetCursor(m_hCursor);
+		return TRUE;
+	}
+
+	return CStatic::OnSetCursor(pWnd, nHitTest, message);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::OnLButtonDown
+//
+// Description:		Called when a link is click on
+//
+// INPUTS:          Windows API
+// 
+// RETURNS:         Windows API
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+// NT ALMOND				02072002    1.6     Added Mail support
+//////////////////////////////////////////////////////////////////////////
+void CLabel::OnLButtonDown(UINT nFlags, CPoint point) 
+{
+
+	if (!m_bNotifyParent) // Fix
+	{
+		CString strLink;
+
+		GetWindowText(strLink);
+		if (m_Link == HyperLink)
+		{
+			ShellExecute(NULL,_T("open"),m_sLink.IsEmpty() ? strLink : m_sLink,NULL,NULL,SW_SHOWNORMAL);
+		}
+		if (m_Link == MailLink)
+		{
+			strLink = _T("mailto:") + strLink;
+			ShellExecute( NULL, NULL,  strLink,  NULL, NULL, SW_SHOWNORMAL );
+		}
+	}
+	else
+	{
+		// To use notification in parent window
+		// Respond to a OnNotify in parent and disassemble the message
+		//
+		NMHDR nm;
+
+		nm.hwndFrom = GetSafeHwnd();
+		nm.idFrom  = GetDlgCtrlID();
+		nm.code = NM_LINKCLICK;
+		GetParent()->SendMessage(WM_NOTIFY,nm.idFrom,(LPARAM) &nm);
+	}
+
+	CStatic::OnLButtonDown(nFlags, point);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+// THE FUNCTIONS START HERE :----
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetText
+//
+// Description:		Short cut to set window text - caption - label
+//
+// INPUTS:          Text to use
+// 
+// RETURNS:         Reference to this
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26081998    1.0     Origin
+// NT ALMOND				02072002    1.6     Crash Fix
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetText(const CString& strText)
+{
+	if(IsWindow(this->GetSafeHwnd())) 
+	{
+		//SetWindowText(strText);
+		m_strText = strText;
+		UpdateSurface();
+	}
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetTextColor
+//
+// Description:		Sets the text color 
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetTextColor(COLORREF crText)
+{
+
+	m_crText = crText;
+
+	UpdateSurface();
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFontBold
+//
+// Description:		Sets the font ot bold 
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFontBold(BOOL bBold)
+{	
+
+	m_lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
+	ReconstructFont();
+	UpdateSurface();
+	return *this;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFontUnderline
+//
+// Description:		Sets font underline attribue
+//
+// INPUTS:          True of false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFontUnderline(BOOL bSet)
+{	
+	m_lf.lfUnderline = bSet;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFontItalic
+//
+// Description:		Sets font italic attribute
+//
+// INPUTS:          True of false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFontItalic(BOOL bSet)
+{
+
+	m_lf.lfItalic = bSet;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;	
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetSunken
+//
+// Description:		Sets sunken effect on border
+//
+// INPUTS:          True of false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetSunken(BOOL bSet)
+{
+
+	if (!bSet)
+		ModifyStyleEx(WS_EX_STATICEDGE,0,SWP_DRAWFRAME);
+	else
+		ModifyStyleEx(0,WS_EX_STATICEDGE,SWP_DRAWFRAME);
+
+	return *this;	
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetBorder
+//
+// Description:		Toggles the border on/off
+//
+// INPUTS:          True of false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetBorder(BOOL bSet)
+{
+
+	if (!bSet)
+		ModifyStyle(WS_BORDER,0,SWP_DRAWFRAME);
+	else
+		ModifyStyle(0,WS_BORDER,SWP_DRAWFRAME);
+
+	return *this;	
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFontSize
+//
+// Description:		Sets the font size
+//
+// INPUTS:          True of false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFontSize(int nSize)
+{
+
+	CFont cf;
+	LOGFONT lf;
+
+	cf.CreatePointFont(nSize * 10, m_lf.lfFaceName);
+	cf.GetLogFont(&lf);
+
+	m_lf.lfHeight = lf.lfHeight;
+	m_lf.lfWidth  = lf.lfWidth;
+
+	//	nSize*=-1;
+	//	m_lf.lfHeight = nSize;
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetBkColor
+//
+// Description:		Sets background color
+//
+// INPUTS:          Colorref of background color
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetBkColor(COLORREF crBkgnd, COLORREF crBkgndHigh , BackFillMode mode)
+{
+
+	m_crLoColor = crBkgnd;
+	m_crHiColor = crBkgndHigh;
+
+	m_fillmode = mode;
+
+	if (m_hBackBrush)
+		::DeleteObject(m_hBackBrush);
+
+
+	if (m_fillmode == Normal)
+		m_hBackBrush = ::CreateSolidBrush(crBkgnd);
+
+	UpdateSurface();
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFontName
+//
+// Description:		Sets the fonts face name
+//
+// INPUTS:          String containing font name
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+// NT ALMOND				15092000	1.5		Support internation windows
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFontName(const CString& strFont, BYTE byCharSet /* Default = ANSI_CHARSET */)
+{	
+
+	m_lf.lfCharSet = byCharSet;
+
+	_tcscpy_s(m_lf.lfFaceName,strFont);
+	ReconstructFont();
+	UpdateSurface();
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::FlashText
+//
+// Description:		As the function states
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::FlashText(BOOL bActivate)
+{
+
+	if (m_bTimer)
+		KillTimer(1);
+
+	if (bActivate)
+	{
+		m_bState = FALSE;
+
+		m_bTimer = TRUE;
+
+		SetTimer(1,500,NULL);
+
+		m_Type = Text;
+	}
+	else
+		m_Type = None; // Fix
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::FlashBackground
+//
+// Description:		As the function states
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::FlashBackground(BOOL bActivate)
+{
+
+	if (m_bTimer)
+		KillTimer(1);
+
+	if (bActivate)
+	{
+		m_bState = FALSE;
+
+		m_bTimer = TRUE;
+		SetTimer(1,500,NULL);
+
+		m_Type = Background;
+	}
+
+	return *this;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetLink
+//
+// Description:		Indicates the string is a link
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+// NT ALMOND				26/08/99	1.2		Added flexbility of
+//												Sending Click meessage to parent
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetLink(BOOL bLink,BOOL bNotifyParent)
+{
+
+	if (bLink)
+		m_Link = HyperLink;
+	else
+		m_Link = LinkNone;
+
+	m_bNotifyParent = bNotifyParent;
+
+	if (m_Link != LinkNone)
+		ModifyStyle(0,SS_NOTIFY);
+	else
+		ModifyStyle(SS_NOTIFY,0);
+
+
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetLinkCursor
+//
+// Description:		Sets the internet browers link
+//
+// INPUTS:          Handle of cursor
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				26/08/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetLinkCursor(HCURSOR hCursor)
+{
+
+	m_hCursor = hCursor;
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetTransparent
+//
+// Description:		Sets the Label window to be transpaent
+//
+// INPUTS:          True or false
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetTransparent(BOOL bSet)
+{
+
+	m_bTransparent = bSet;
+	ModifyStyleEx(0,WS_EX_TRANSPARENT); // Fix for transparency
+	UpdateSurface();
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFont3D
+//
+// Description:		Sets the 3D attribute of the font.
+//
+// INPUTS:          True or false, Raised or Sunken
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFont3D(BOOL bSet,Type3D type)
+{
+
+	m_bFont3d = bSet;
+	m_3dType = type;
+	UpdateSurface();
+
+
+	return *this;
+}
+
+void CLabel::OnSysColorChange() 
+{
+
+	if (m_hwndBrush)
+		::DeleteObject(m_hwndBrush);
+
+	m_hwndBrush = ::CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+
+	UpdateSurface();
+
+
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetRotationAngle
+//
+// Description:		Sets the rotation angle for the current font.
+//
+// INPUTS:          Angle in Degress
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				22/10/98    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetRotationAngle(UINT nAngle,BOOL bRotation)
+{
+	// Arrrrh...
+	// Your looking in here why the font is rotating, aren't you?
+	// Well try setting the font name to 'Arial' or 'Times New Roman'
+	// Make the Angle 180 and set bRotation to true.
+	//
+	// Font rotation _ONLY_ works with TrueType fonts...
+	//
+	// 
+	m_lf.lfEscapement = m_lf.lfOrientation = (nAngle * 10);
+	m_bRotation = bRotation;
+
+	ReconstructFont();
+
+	UpdateSurface();
+
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetText3DHiliteColor
+//
+// Description:		Sets the 3D font hilite color
+//
+// INPUTS:          Color 
+// 
+// RETURNS:         Reference to 'this' object
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				17/07/00    1.0     Origin
+//
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetText3DHiliteColor(COLORREF cr3DHiliteColor)
+{
+	m_cr3DHiliteColor = cr3DHiliteColor;
+	UpdateSurface();
+
+
+	return *this;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::PreSubclassWindow
+//
+// Description:		Assigns default dialog font
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				15092000    1.5     Origin
+// NT ALMOND				02072002    1.6     Fix crash when GetFont returns NULL
+//////////////////////////////////////////////////////////////////////////
+void CLabel::PreSubclassWindow() 
+{
+
+	CStatic::PreSubclassWindow();
+
+	CFont* cf = GetFont();
+	if(cf !=NULL)
+	{
+		cf->GetObject(sizeof(m_lf),&m_lf);
+	}
+	else
+	{
+		GetObject(GetStockObject(SYSTEM_FONT),sizeof(m_lf),&m_lf);
+	}
+
+	ReconstructFont();
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::PreCreateWindow
+//
+// Description:		
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				15092000    1.5     Origin
+//////////////////////////////////////////////////////////////////////////
+BOOL CLabel::PreCreateWindow(CREATESTRUCT& cs) 
+{	
+	return CStatic::PreCreateWindow(cs);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::DrawGradientFill
+//
+// Description:		Internal help function to gradient fill background
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				15092000    1.5     Origin
+//////////////////////////////////////////////////////////////////////////
+void CLabel::DrawGradientFill(CDC* pDC, CRect* pRect, COLORREF crStart, COLORREF crEnd, int nSegments)
+{
+	// Get the starting RGB values and calculate the incremental
+	// changes to be applied.
+
+	COLORREF cr;
+	int nR = GetRValue(crStart);
+	int nG = GetGValue(crStart);
+	int nB = GetBValue(crStart);
+
+	int neB = GetBValue(crEnd);
+	int neG = GetGValue(crEnd);
+	int neR = GetRValue(crEnd);
+
+	if(nSegments > pRect->Width())
+		nSegments = pRect->Width();
+
+	int nDiffR = (neR - nR);
+	int nDiffG = (neG - nG);
+	int nDiffB = (neB - nB);
+
+	int ndR = 256 * (nDiffR) / (max(nSegments,1));
+	int ndG = 256 * (nDiffG) / (max(nSegments,1));
+	int ndB = 256 * (nDiffB) / (max(nSegments,1));
+
+	nR *= 256;
+	nG *= 256;
+	nB *= 256;
+
+	neR *= 256;
+	neG *= 256;
+	neB *= 256;
+
+	int nCX = pRect->Width() / max(nSegments,1), nLeft = pRect->left, nRight;
+	pDC->SelectStockObject(NULL_PEN);
+
+	for (int i = 0; i < nSegments; i++, nR += ndR, nG += ndG, nB += ndB)
+	{
+		// Use special code for the last segment to avoid any problems
+		// with integer division.
+
+		if (i == (nSegments - 1))
+			nRight = pRect->right;
+		else
+			nRight = nLeft + nCX;
+
+		cr = RGB(nR / 256, nG / 256, nB / 256);
+
+		{
+			CBrush br(cr);
+			CBrush* pbrOld = pDC->SelectObject(&br);
+			pDC->Rectangle(nLeft, pRect->top, nRight + 1, pRect->bottom);
+			pDC->SelectObject(pbrOld);
+		}
+
+		// Reset the left side of the drawing rectangle.
+
+		nLeft = nRight;
+	}
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetFont
+//
+// Description:		Sets font with LOGFONT structure
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				02072002    1.6     Origin
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetFont(LOGFONT lf)
+{
+	CopyMemory(&m_lf, &lf, sizeof(m_lf));
+	ReconstructFont();
+	UpdateSurface();
+	return *this;
+
+}
+
+BOOL CLabel::OnEraseBkgnd(CDC* pDC) 
+{
+	// TODO: Add your message handler code here and/or call default
+
+	return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetMailLink
+//
+// Description:		Sets the label so it becomes Mail enabled
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				02072002    1.6     Origin
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetMailLink(BOOL bEnable, BOOL bNotifyParent)
+{
+	if (bEnable)
+		m_Link = MailLink;
+	else
+		m_Link = LinkNone;
+
+
+	m_bNotifyParent = bNotifyParent;
+
+	if (m_Link != LinkNone)
+		ModifyStyle(0,SS_NOTIFY);
+	else
+		ModifyStyle(SS_NOTIFY,0);
+
+	return *this;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//
+// Function:		CLabel::SetHyperLink
+//
+// Description:		Sets the label so it becomes hyperlink enabled
+//
+// INPUTS:          
+// 
+// RETURNS:         
+//
+// NOTES:			
+// 
+// MODIFICATIONS:
+//
+// Name                     Date        Version Comments
+// NT ALMOND				02072002    1.6     Origin
+//////////////////////////////////////////////////////////////////////////
+CLabel& CLabel::SetHyperLink(const CString& sLink)
+{
+	m_sLink = sLink;
+
+	return *this;
+}
+
+/*************************************************************
+*add at  : 2014-08-11  by唐太闲
+*describe: 设置背景透明,返回空画刷                  
+*************************************************************/
+HBRUSH CLabel::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
+{
+	// TODO:  在此更改 DC 的任何属性
+
+	// TODO:  如果不应调用父级的处理程序,则返回非 null 画笔
+	//return NULL;
+	pDC->SetBkMode(TRANSPARENT);  
+	return (HBRUSH)GetStockObject(NULL_BRUSH);
+}

+ 117 - 0
VideoCapture/UI/SubLabel.h

@@ -0,0 +1,117 @@
+#if !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)
+#define AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// Label.h : header file
+//
+
+#define	NM_LINKCLICK	WM_APP + 0x200
+
+/////////////////////////////////////////////////////////////////////////////
+// CLabel window
+
+class CLabel : public CStatic
+{
+	// Construction
+public:
+
+
+	enum LinkStyle { LinkNone, HyperLink, MailLink };
+	enum FlashType {None, Text, Background };
+	enum Type3D { Raised, Sunken};
+	enum BackFillMode { Normal, Gradient };
+
+	CLabel();
+	virtual CLabel& SetBkColor(COLORREF crBkgnd, COLORREF crBkgndHigh = 0, BackFillMode mode = Normal);
+	virtual CLabel& SetTextColor(COLORREF crText);
+	virtual CLabel& SetText(const CString& strText);
+	virtual CLabel& SetFontBold(BOOL bBold = TRUE);
+	virtual CLabel& SetFontName(const CString& strFont, BYTE byCharSet = ANSI_CHARSET);
+	virtual CLabel& SetFontUnderline(BOOL bSet = TRUE);
+	virtual CLabel& SetFontItalic(BOOL bSet = TRUE);
+	virtual CLabel& SetFontSize(int nSize);
+	virtual CLabel& SetSunken(BOOL bSet );
+	virtual CLabel& SetBorder(BOOL bSet = TRUE);
+	virtual CLabel& SetTransparent(BOOL bSet);
+	virtual CLabel& FlashText(BOOL bActivate);
+	virtual CLabel& FlashBackground(BOOL bActivate);
+	virtual CLabel& SetLink(BOOL bLink,BOOL bNotifyParent);
+	virtual CLabel& SetLinkCursor(HCURSOR hCursor);
+	virtual CLabel& SetFont3D(BOOL bSet,Type3D type=Raised);
+	virtual CLabel& SetRotationAngle(UINT nAngle,BOOL bRotation);
+	virtual CLabel& SetText3DHiliteColor(COLORREF cr3DHiliteColor);
+	virtual CLabel& SetFont(LOGFONT lf);
+	virtual CLabel& SetMailLink(BOOL bEnable, BOOL bNotifyParent);
+	virtual CLabel& SetHyperLink(const CString& sLink);
+
+	// Attributes
+public:
+protected:
+	void UpdateSurface();
+	void ReconstructFont();
+	void DrawGradientFill(CDC* pDC, CRect* pRect, COLORREF crStart, COLORREF crEnd, int nSegments);
+	COLORREF		m_crText;
+	COLORREF		m_cr3DHiliteColor;
+	HBRUSH			m_hwndBrush;
+	HBRUSH			m_hBackBrush;
+	LOGFONT			m_lf;
+	CFont			m_font;
+	BOOL			m_bState;
+	BOOL			m_bTimer;
+	LinkStyle		m_Link;
+	BOOL			m_bTransparent;
+	BOOL			m_bFont3d;
+	BOOL			m_bToolTips;
+	BOOL			m_bNotifyParent;
+	BOOL			m_bRotation;
+	FlashType		m_Type;
+	HCURSOR			m_hCursor;
+	Type3D			m_3dType;
+	BackFillMode	m_fillmode;
+	COLORREF		m_crHiColor;
+	COLORREF		m_crLoColor;
+	CString			m_sLink;
+	CString			m_strText;
+	CDC* m_pMemDC;
+	//CDC* pDCMem;
+
+	// Operations
+public:
+
+	// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CLabel)
+protected:
+	virtual void PreSubclassWindow();
+	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+	//}}AFX_VIRTUAL
+
+	// Implementation
+public:
+	virtual ~CLabel();
+
+	// Generated message map functions
+protected:
+	//{{AFX_MSG(CLabel)
+	afx_msg void OnTimer(UINT nIDEvent);
+	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
+	afx_msg void OnSysColorChange();
+	afx_msg void OnPaint();
+	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	//}}AFX_MSG
+
+	DECLARE_MESSAGE_MAP()
+public:
+	//tc:这就是新添加的ON_WM_CTLCOLOR_REFLECT()消息的响应函数
+	afx_msg HBRUSH CtlColor(CDC* /*pDC*/, UINT /*nCtlColor*/);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_LABEL_H__A4EABEC5_2E8C_11D1_B79F_00805F9ECE10__INCLUDED_)

+ 244 - 0
VideoCapture/UI/TreeComboBox.cpp

@@ -0,0 +1,244 @@
+// TreeComboBox.cpp : implementation file
+//
+
+#include "stdafx.h"
+#include "TreeComboBox.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CTreeComboBox
+
+CTreeComboBox::CTreeComboBox()
+	:m_bTree(FALSE)
+	, m_bAlertBkg(FALSE)
+	, m_bAlertText(FALSE)
+	, m_droppedHeight(250)
+	, m_droppedWidth(100)
+{
+	m_hBrushAlert = CreateSolidBrush(COLOR_ALERT);
+}
+
+CTreeComboBox::~CTreeComboBox()
+{
+	DeleteObject(m_hBrushAlert);
+}
+
+
+BEGIN_MESSAGE_MAP(CTreeComboBox, CComboBox)
+	//{{AFX_MSG_MAP(CTreeComboBox)
+	ON_WM_LBUTTONDOWN()
+	ON_WM_LBUTTONDBLCLK()
+	ON_WM_CTLCOLOR_REFLECT()
+	//}}AFX_MSG_MAP
+	ON_MESSAGE(WMU_CLOSE_CONTROL, OnCloseControl)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CTreeComboBox message handlers
+void CTreeComboBox::PreSubclassWindow()
+{
+	// TODO: Add your specialized code here and/or call the base class
+	CComboBox::PreSubclassWindow();
+	CRect rect(0, 0, 0, 0);
+
+	DWORD dwStyle = WS_BORDER | TVS_DISABLEDRAGDROP | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_FULLROWSELECT | WS_POPUPWINDOW;
+	((CWnd&)m_Tree).CreateEx(0, WC_TREEVIEW, NULL, dwStyle, rect, GetParent(), NULL);
+	m_Tree.Init(this);
+
+	GetClientRect(rect);
+	SetDroppedWidth(rect.Width());
+	SetDroppedHeight(m_droppedHeight);
+}
+
+BOOL CTreeComboBox::PreTranslateMessage(MSG* pMsg)
+{
+	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DOWN)
+	{
+		DisplayTree();
+		return TRUE;
+	}
+
+	return CComboBox::PreTranslateMessage(pMsg);
+}
+
+void CTreeComboBox::OnLButtonDown(UINT nFlags, CPoint point)
+{
+	m_bTree = !m_bTree;
+	if (m_bTree)
+		DisplayTree();
+}
+
+void CTreeComboBox::OnLButtonDblClk(UINT nFlags, CPoint point)
+{
+	OnLButtonDown(nFlags, point);
+}
+
+void CTreeComboBox::TreeCtrlDone()
+{
+	CWnd* pParent = GetParent();
+	if (pParent != NULL)
+	{
+		CString str; GetWindowText(str);
+		if (m_pretext != str)
+		{
+			m_pretext = str;
+			WPARAM wParam = MAKEWPARAM(GetDlgCtrlID(), CBN_CLOSEUP);
+			pParent->SendMessage(WM_COMMAND, wParam, (LPARAM)m_hWnd);
+		}
+	}
+}
+
+LRESULT CTreeComboBox::OnCloseControl(WPARAM wParam, LPARAM lParam)
+{
+	m_Tree.ShowWindow(SW_HIDE);
+	m_bTree = FALSE;
+	HTREEITEM hItemChanged = (HTREEITEM)lParam;
+	if (hItemChanged)
+	{
+		SetTitle(m_Tree.GetItemText(hItemChanged));
+	}
+	AlertBkg(FALSE);
+	TreeCtrlDone();
+	return 1;
+}
+
+HBRUSH CTreeComboBox::CtlColor(CDC* pDC, UINT nCtlColor)
+{
+	HBRUSH hbr = NULL;
+	if (nCtlColor == CTLCOLOR_EDIT)
+	{
+		if (!m_bAlertText)pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
+		else pDC->SetTextColor(COLOR_RED);
+		if (!m_bAlertBkg)pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
+		else pDC->SetBkColor(COLOR_ALERT);
+		if (m_bAlertText || m_bAlertBkg)hbr = m_hBrushAlert;
+		pDC->SetBkMode(TRANSPARENT);
+	}
+
+	return hbr;
+}
+
+void CTreeComboBox::DisplayTree()
+{
+	CRect rc;
+	GetWindowRect(rc);
+	rc.top = rc.bottom + 1;
+	rc.right = GetDroppedWidth();
+	rc.bottom = GetDroppedHeight();
+
+	m_Tree.Display(rc);
+}
+
+void CTreeComboBox::SetTitle(CString sTitle)
+{
+	ResetContent();
+	AddString(sTitle);
+	SetCurSel(0);
+}
+
+void CTreeComboBox::RefDroppedWidth()
+{
+	CRect rect;
+	GetClientRect(rect);
+	SetDroppedWidth(rect.Width());
+}
+
+/************************************************************************/
+/*  函数:InsertMyItem[12/7/2016 IT];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[IN] :;
+/*  返回:void;
+/*  注意:只适合二层目录;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void CTreeComboBox::InsertMyItem(IN CString strRoot, IN CString strItem)
+{
+	BOOL bExist = FALSE;
+	HTREEITEM hRoot = m_Tree.GetRootItem();
+	if (hRoot == NULL)
+	{
+		hRoot = m_Tree.InsertItem(strRoot, NULL);
+		m_Tree.InsertItem(strItem, hRoot);
+		return;
+	}
+
+	CString strName = m_Tree.GetItemText(hRoot);
+	if (strName == strRoot)
+	{
+		HTREEITEM hSubItem = m_Tree.GetChildItem(hRoot);
+		// 遍历所有子项;
+		while (hSubItem)
+		{
+			// 当前子项是否是要查找的子项;
+			if (strItem == m_Tree.GetItemText(hSubItem))
+			{
+				bExist = TRUE;
+				break;
+			}
+
+			// 若未到,查找下一个兄弟项;
+			hSubItem = m_Tree.GetNextSiblingItem(hSubItem);
+		}
+
+		if (!bExist)
+		{
+			// 插入新项;
+			m_Tree.InsertItem(strItem, hRoot);
+		}
+	}
+	else
+	{
+		hRoot = m_Tree.GetNextSiblingItem(hRoot);
+		while (hRoot)
+		{
+			// 当前兄弟项是否是要查找的子项;
+			if (strRoot == m_Tree.GetItemText(hRoot))
+			{
+				HTREEITEM hSubItem = m_Tree.GetChildItem(hRoot);
+				// 遍历所有子项;
+				while (hSubItem)
+				{
+					// 当前子项是否是要查找的子项;
+					if (strItem == m_Tree.GetItemText(hSubItem))
+					{
+						bExist = TRUE;
+						break;
+					}
+
+					// 若未到,查找下一个兄弟项;
+					hSubItem = m_Tree.GetNextSiblingItem(hSubItem);
+				}
+
+				if (!bExist)
+				{
+					// 插入新项;
+					bExist = TRUE;
+					m_Tree.InsertItem(strItem, hRoot);
+				}
+
+				break;
+			}
+
+			// 若未到,查找下一个兄弟项;
+			hRoot = m_Tree.GetNextSiblingItem(hRoot);
+		}
+
+		if (!bExist)
+		{
+			// 插入新项;
+			hRoot = m_Tree.InsertItem(strRoot, NULL);
+			m_Tree.InsertItem(strItem, hRoot);
+		}
+	}
+}

+ 90 - 0
VideoCapture/UI/TreeComboBox.h

@@ -0,0 +1,90 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];
+/*  作    者:[IT];
+/*  日    期:[11/4/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __TREECOMBOBOX__
+#define __TREECOMBOBOX__
+
+#include "ComboTreeCtrl.h"
+
+#pragma once
+
+#ifndef	COLOR_RED
+#define COLOR_RED			RGB(220,0,0)
+#endif	//COLOR_RED
+#ifndef	COLOR_ALERT
+#define COLOR_ALERT			RGB(255,180,180)
+#endif	//COLOR_ALERT
+/////////////////////////////////////////////////////////////////////////////
+// CTreeComboBox  window
+
+class CTreeComboBox : public CComboBox
+{
+	CString m_pretext;
+	// Construction
+public:
+	CTreeComboBox();
+
+	// Attributes
+public:
+	BOOL m_bTree;
+
+	// Operations
+public:
+	void DisplayTree();
+	void SetTitle(CString sTitle);
+	BOOL IsAlertBkg(){ return m_bAlertBkg; }
+	BOOL IsAlertText(){ return m_bAlertText; }
+	CTreeCtrl& GetTreeCtrl(){ return m_Tree; }
+	int GetDroppedWidth(){ return m_droppedWidth; };
+	int GetDroppedHeight(){ return m_droppedHeight; };
+	void SetDroppedWidth(int nWidth){ m_droppedWidth = nWidth; };
+	void SetDroppedHeight(int nHeight){ m_droppedHeight = nHeight; };
+	void AlertBkg(BOOL bAlert = TRUE){ m_bAlertBkg = bAlert; Invalidate(); };
+	void AlertText(BOOL bAlert = TRUE){ m_bAlertText = bAlert; Invalidate(); };
+
+public:
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+protected:
+	virtual void PreSubclassWindow();
+
+public:
+	void RefDroppedWidth();
+	UINT GetTreeCount();
+	void TreeCtrlDone();
+	virtual ~CTreeComboBox();
+
+protected:
+	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
+	afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
+	afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
+	afx_msg LRESULT OnCloseControl(WPARAM wParam, LPARAM lParam);
+	DECLARE_MESSAGE_MAP()
+
+private:
+	BOOL m_bAlertBkg;
+	BOOL m_bAlertText;
+	int m_droppedWidth;
+	int m_droppedHeight;
+	HBRUSH m_hBrushAlert;
+	CComboTreeCtrl m_Tree;
+
+public:
+	void InsertMyItem(IN CString strRoot, IN CString strItem);
+};
+
+
+#endif // __TREECOMBOBOX__;

+ 260 - 0
VideoCapture/UI/XColorStatic.cpp

@@ -0,0 +1,260 @@
+#include "stdafx.h"
+#include "XColorStatic.h"
+#include "FontSize.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/***************************************************************************************/
+// CXColorStatic
+BEGIN_MESSAGE_MAP(CXColorStatic, CStatic)
+    // {{ AFX_MSG_MAP
+    ON_WM_PAINT()
+    ON_WM_ERASEBKGND()
+    // }} AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/***************************************************************************************/
+// CXColorStatic
+CXColorStatic::CXColorStatic()
+{
+    m_rgbText           = GetSysColor(COLOR_BTNTEXT);
+    m_rgbBackground     = GetSysColor(COLOR_BTNFACE);
+    m_pBrush            = new CBrush(m_rgbBackground);
+    m_bBold             = FALSE;
+    m_hIcon             = NULL;
+    m_iXMargin          = 0;
+    m_iYMargin          = 0;
+}
+
+/***************************************************************************************/
+// ~CXColorStatic
+CXColorStatic::~CXColorStatic()
+{
+    TRACE(_T("in CXColorStatic::!CXColorStatic\n"));
+
+    if(m_font.GetSafeHandle())
+        m_font.DeleteObject();
+
+    if(m_pBrush)
+    {
+        m_pBrush->DeleteObject();
+        delete m_pBrush;
+    }
+    m_pBrush = NULL;
+}
+
+/***************************************************************************************/
+// PreSubclassWindow
+void CXColorStatic::PreSubclassWindow()
+{
+    TRACE(_T("in CXColorStatic::PreSubclassWindow\n"));
+
+    // 获取字体
+    CFont* pFont = GetFont();
+    if(!pFont)
+    {
+        HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
+        if(hFont == NULL)
+            hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
+        if(hFont)
+            pFont = CFont::FromHandle(hFont);
+    }
+    ASSERT(pFont);
+    ASSERT(pFont->GetSafeHandle());
+
+    // 为这个控件创建一个字体
+    LOGFONT lf;
+    pFont->GetLogFont(&lf);
+    m_font.CreateFontIndirect(&lf);
+}
+
+/***************************************************************************************/
+// OnPaint
+void CXColorStatic::OnPaint()
+{
+    CPaintDC dc(this);  // 获取到绘制对象的设备上下文
+
+    dc.SaveDC();
+
+    dc.SetTextColor(m_rgbText);
+    dc.SetBkColor(m_rgbBackground);
+    dc.SetBkMode(OPAQUE);
+    dc.SelectObject(m_pBrush);
+
+    CRect rect;
+    GetClientRect(rect);
+
+    // 不能同时绘制图标和文本
+    if(m_hIcon)
+    {
+        int iIconX = GetSystemMetrics(SM_CXICON);
+        int iIconY = GetSystemMetrics(SM_CYICON);
+
+        rect.left = rect.left + (rect.Width() - iIconX) / 2;
+        rect.top = rect.top + (rect.Height() - iIconY) / 2;
+		 
+        dc.DrawIcon(rect.left, rect.top, m_hIcon);
+    }
+    else
+    {
+        dc.SelectObject(&m_font);
+
+        // 获取静态文本
+        CString strText = _T("");
+        GetWindowText(strText);
+
+        UINT uiFormat = 0;
+        DWORD dwStyle = GetStyle();
+
+        // 重新绘制静态文本
+        if(dwStyle && SS_CENTER)
+            uiFormat |= DT_CENTER;
+        else if(dwStyle && SS_LEFT)
+            uiFormat |= DT_LEFT;
+        else if(dwStyle && SS_RIGHT)
+            uiFormat |= DT_RIGHT;
+
+        if(dwStyle & SS_CENTERIMAGE)    // 垂直居中 ==> 仅对单行
+            uiFormat |= DT_VCENTER | DT_SINGLELINE;
+        else
+            uiFormat |= DT_WORDBREAK;
+		 
+		uiFormat  = DT_LEFT;
+	
+
+        rect.left += m_iXMargin;
+
+        rect.top += m_iYMargin;
+
+        dc.DrawText(strText, rect, uiFormat);
+    }
+
+    dc.RestoreDC(-1);
+}
+
+/***************************************************************************************/
+// OnEraseBkgnd
+BOOL CXColorStatic::OnEraseBkgnd(CDC *pDC)
+{
+    CRect cr;
+    GetClientRect(cr);
+    pDC->FillRect(&cr, m_pBrush);
+
+    return TRUE;
+}
+
+/***************************************************************************************/
+// SetFont
+void CXColorStatic::SetFont(LOGFONT *pLogFont, BOOL bRedraw /* = TRUE */)
+{
+    ASSERT(pLogFont);
+    if(!pLogFont)
+        return;
+
+    if(m_font.GetSafeHandle())
+        m_font.DeleteObject();
+
+    LOGFONT lf = *pLogFont;
+    lf.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
+
+    m_font.CreateFontIndirect(&lf);
+
+    if(bRedraw)
+        RedrawWindow();
+}
+
+/***************************************************************************************/
+// SetFont
+void CXColorStatic::SetFont(LPCTSTR lpszFaceName, int iPointSize, BOOL bRedraw /* = TRUE */)
+{
+    // 如果指定的字体名字不存在或未指定, 将使用默认的字体
+    LOGFONT lf;
+    memset(&lf, 0, sizeof(lf));
+
+    if(lpszFaceName == NULL)
+    {
+        CFont* pFont = GetFont();
+        ASSERT(pFont);
+        pFont->GetLogFont(&lf);
+    }
+    else
+    {
+        _tcsncpy_s(lf.lfFaceName, lpszFaceName, sizeof(lf.lfFaceName) / sizeof(TCHAR) - 1);
+    }
+
+    lf.lfHeight = GetFontHeight(iPointSize);
+    SetFont(&lf, bRedraw);
+}
+
+/***************************************************************************************/
+// SetFont
+void CXColorStatic::SetFont(CFont *pFont, BOOL bRedraw /* = TRUE */)
+{
+    ASSERT(pFont);
+    if(!pFont)
+        return;
+
+    LOGFONT lf;
+    memset(&lf, 0, sizeof(lf));
+
+    pFont->GetLogFont(&lf);
+
+    SetFont(&lf, bRedraw);
+}
+
+/***************************************************************************************/
+// SetTextColor
+void CXColorStatic::SetTextColor(COLORREF rgb, BOOL bRedraw /* = TRUE */)
+{
+    m_rgbText = rgb;
+    if(bRedraw)
+        RedrawWindow();
+}
+
+/***************************************************************************************/
+// SetBold
+void CXColorStatic::SetBold(BOOL bFlag, BOOL bRedraw /* = TRUE */)
+{
+    m_bBold = bFlag;
+
+    LOGFONT lf;
+    memset(&lf, 0, sizeof(lf));
+
+    CFont* pFont = GetFont();
+    ASSERT(pFont);
+    pFont->GetLogFont(&lf);
+
+    lf.lfWeight = m_bBold ? FW_BOLD : FW_NORMAL;
+	
+	SetFont(&lf, bRedraw);
+}
+
+/***************************************************************************************/
+// SetBackgroundColor
+void CXColorStatic::SetBackgroundColor(COLORREF rgb, BOOL bRedraw /* = TRUE */)
+{
+	m_rgbBackground = rgb;
+	if(m_pBrush)
+	{
+		m_pBrush->DeleteObject();
+		delete m_pBrush;
+	}
+	m_pBrush = new CBrush(m_rgbBackground);
+	if(bRedraw)
+		RedrawWindow();
+}
+
+/***************************************************************************************/
+// SetIcon
+void CXColorStatic::SetIcon(HICON hIcon, BOOL bRedraw /* = TRUE */)
+{
+	ASSERT(hIcon);
+	
+	m_hIcon = hIcon;
+	if(bRedraw)
+		RedrawWindow();
+}

+ 65 - 0
VideoCapture/UI/XColorStatic.h

@@ -0,0 +1,65 @@
+/*************************************************************************************
+ * FontSize.h
+ *
+ * 作者: 雷登似
+ * 公司: TCL多媒体科技控股有限公司
+ * 版本: 0.01
+ * 编程日期: 2010-04-21
+ * 联系方式: wp2.leids@tcl.com / 0752-3270423(81423)
+ *
+ * 功能: 设置字体样式
+ * 说明: 本软件释放给TCL公司, 只要你喜欢, 在TCL公司内部可以免费使用, 但在使用过程中
+ *       你必须保证此软件的说明信息完整!
+ *
+ * 此软件的最终解释权归原作者拥有, 作者不对软件的分发和使用负责, 如果你因使用此软
+ * 件而造成的任何损失或商业风险均由使用者自己承担所有责任.
+ *
+ *************************************************************************************/
+
+#ifndef __X_COLOR_STATIC_H__
+#define __X_COLOR_STATIC_H__
+
+class CXColorStatic : public CStatic
+{
+// 构造函数和析构函数声明
+public:
+    CXColorStatic();
+    virtual ~CXColorStatic();
+
+//成员函数声明
+public:
+    void SetBackgroundColor(COLORREF rgb, BOOL bRedraw = TRUE);
+    void SetTextColor(COLORREF rgb, BOOL bRedraw = TRUE);
+    void SetBold(BOOL bFlag, BOOL bRedraw = TRUE);
+    void SetFont(LPCTSTR lpszFaceName, int iPointSize, BOOL bRedraw = TRUE);
+    void SetFont(LOGFONT* pLogFont, BOOL bRedraw = TRUE);
+    void SetFont(CFont* pFont, BOOL bRedraw = TRUE);
+    void SetIcon(HICON hIcon, BOOL bRedraw = TRUE);
+    void SetMargins(int x, int y) {m_iXMargin = x; m_iYMargin = y;}
+
+// 方法覆盖
+// {{AFX_VIRTUAL
+protected:
+    virtual void PreSubclassWindow();
+// }}AFX_VIRTUAL
+
+// 数据成员
+protected:
+    CFont       m_font;
+    COLORREF    m_rgbText;
+    COLORREF    m_rgbBackground;
+    CBrush*     m_pBrush;
+    BOOL        m_bBold;
+    int         m_iXMargin, m_iYMargin;
+    HICON       m_hIcon;
+
+// 消息映射方法
+protected:
+    // {{AFX_MSG
+    afx_msg void OnPaint();
+    afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+    // }}AFX_MSG
+    DECLARE_MESSAGE_MAP();
+};
+
+#endif

+ 333 - 0
VideoCapture/VideoCapture/ClassView.cpp

@@ -0,0 +1,333 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+#include "MainFrm.h"
+#include "ClassView.h"
+#include "Resource.h"
+#include "VideoCapture.h"
+
+class CClassViewMenuButton : public CMFCToolBarMenuButton
+{
+	friend class CClassView;
+
+	DECLARE_SERIAL(CClassViewMenuButton)
+
+public:
+	CClassViewMenuButton(HMENU hMenu = nullptr) noexcept : CMFCToolBarMenuButton((UINT)-1, hMenu, -1)
+	{
+	}
+
+	virtual void OnDraw(CDC* pDC, const CRect& rect, CMFCToolBarImages* pImages, BOOL bHorz = TRUE,
+		BOOL bCustomizeMode = FALSE, BOOL bHighlight = FALSE, BOOL bDrawBorder = TRUE, BOOL bGrayDisabledButtons = TRUE)
+	{
+		pImages = CMFCToolBar::GetImages();
+
+		CAfxDrawState ds;
+		pImages->PrepareDrawImage(ds);
+
+		CMFCToolBarMenuButton::OnDraw(pDC, rect, pImages, bHorz, bCustomizeMode, bHighlight, bDrawBorder, bGrayDisabledButtons);
+
+		pImages->EndDrawImage(ds);
+	}
+};
+
+IMPLEMENT_SERIAL(CClassViewMenuButton, CMFCToolBarMenuButton, 1)
+
+//////////////////////////////////////////////////////////////////////
+// 构造/析构
+//////////////////////////////////////////////////////////////////////
+
+CClassView::CClassView() noexcept
+{
+	m_nCurrSort = ID_SORTING_GROUPBYTYPE;
+}
+
+CClassView::~CClassView()
+{
+}
+
+BEGIN_MESSAGE_MAP(CClassView, CDockablePane)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+	ON_WM_CONTEXTMENU()
+	ON_COMMAND(ID_CLASS_ADD_MEMBER_FUNCTION, OnClassAddMemberFunction)
+	ON_COMMAND(ID_CLASS_ADD_MEMBER_VARIABLE, OnClassAddMemberVariable)
+	ON_COMMAND(ID_CLASS_DEFINITION, OnClassDefinition)
+	ON_COMMAND(ID_CLASS_PROPERTIES, OnClassProperties)
+	ON_COMMAND(ID_NEW_FOLDER, OnNewFolder)
+	ON_WM_PAINT()
+	ON_WM_SETFOCUS()
+	ON_COMMAND_RANGE(ID_SORTING_GROUPBYTYPE, ID_SORTING_SORTBYACCESS, OnSort)
+	ON_UPDATE_COMMAND_UI_RANGE(ID_SORTING_GROUPBYTYPE, ID_SORTING_SORTBYACCESS, OnUpdateSort)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CClassView 消息处理程序
+
+int CClassView::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy;
+	rectDummy.SetRectEmpty();
+
+	// 创建视图: 
+	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+	if (!m_wndClassView.Create(dwViewStyle, rectDummy, this, 2))
+	{
+		TRACE0("未能创建类视图\n");
+		return -1;      // 未能创建
+	}
+
+	// 加载图像: 
+	m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_SORT);
+	m_wndToolBar.LoadToolBar(IDR_SORT, 0, 0, TRUE /* 已锁定*/);
+
+	OnChangeVisualStyle();
+
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM | CBRS_BORDER_LEFT | CBRS_BORDER_RIGHT));
+
+	m_wndToolBar.SetOwner(this);
+
+	// 所有命令将通过此控件路由,而不是通过主框架路由: 
+	m_wndToolBar.SetRouteCommandsViaFrame(FALSE);
+
+	CMenu menuSort;
+	menuSort.LoadMenu(IDR_POPUP_SORT);
+
+	m_wndToolBar.ReplaceButton(ID_SORT_MENU, CClassViewMenuButton(menuSort.GetSubMenu(0)->GetSafeHmenu()));
+
+	CClassViewMenuButton* pButton =  DYNAMIC_DOWNCAST(CClassViewMenuButton, m_wndToolBar.GetButton(0));
+
+	if (pButton != nullptr)
+	{
+		pButton->m_bText = FALSE;
+		pButton->m_bImage = TRUE;
+		pButton->SetImage(GetCmdMgr()->GetCmdImage(m_nCurrSort));
+		pButton->SetMessageWnd(this);
+	}
+
+	// 填入一些静态树视图数据(此处只需填入虚拟代码,而不是复杂的数据)
+	FillClassView();
+
+	return 0;
+}
+
+void CClassView::OnSize(UINT nType, int cx, int cy)
+{
+	CDockablePane::OnSize(nType, cx, cy);
+	AdjustLayout();
+}
+
+void CClassView::FillClassView()
+{
+	HTREEITEM hRoot = m_wndClassView.InsertItem(_T("FakeApp 类"), 0, 0);
+	m_wndClassView.SetItemState(hRoot, TVIS_BOLD, TVIS_BOLD);
+
+	HTREEITEM hClass = m_wndClassView.InsertItem(_T("CFakeAboutDlg"), 1, 1, hRoot);
+	m_wndClassView.InsertItem(_T("CFakeAboutDlg()"), 3, 3, hClass);
+
+	m_wndClassView.Expand(hRoot, TVE_EXPAND);
+
+	hClass = m_wndClassView.InsertItem(_T("CFakeApp"), 1, 1, hRoot);
+	m_wndClassView.InsertItem(_T("CFakeApp()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("InitInstance()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("OnAppAbout()"), 3, 3, hClass);
+
+	hClass = m_wndClassView.InsertItem(_T("CFakeAppDoc"), 1, 1, hRoot);
+	m_wndClassView.InsertItem(_T("CFakeAppDoc()"), 4, 4, hClass);
+	m_wndClassView.InsertItem(_T("~CFakeAppDoc()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("OnNewDocument()"), 3, 3, hClass);
+
+	hClass = m_wndClassView.InsertItem(_T("CFakeAppView"), 1, 1, hRoot);
+	m_wndClassView.InsertItem(_T("CFakeAppView()"), 4, 4, hClass);
+	m_wndClassView.InsertItem(_T("~CFakeAppView()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("GetDocument()"), 3, 3, hClass);
+	m_wndClassView.Expand(hClass, TVE_EXPAND);
+
+	hClass = m_wndClassView.InsertItem(_T("CFakeAppFrame"), 1, 1, hRoot);
+	m_wndClassView.InsertItem(_T("CFakeAppFrame()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("~CFakeAppFrame()"), 3, 3, hClass);
+	m_wndClassView.InsertItem(_T("m_wndMenuBar"), 6, 6, hClass);
+	m_wndClassView.InsertItem(_T("m_wndToolBar"), 6, 6, hClass);
+	m_wndClassView.InsertItem(_T("m_wndStatusBar"), 6, 6, hClass);
+
+	hClass = m_wndClassView.InsertItem(_T("Globals"), 2, 2, hRoot);
+	m_wndClassView.InsertItem(_T("theFakeApp"), 5, 5, hClass);
+	m_wndClassView.Expand(hClass, TVE_EXPAND);
+}
+
+void CClassView::OnContextMenu(CWnd* pWnd, CPoint point)
+{
+	CTreeCtrl* pWndTree = (CTreeCtrl*)&m_wndClassView;
+	ASSERT_VALID(pWndTree);
+
+	if (pWnd != pWndTree)
+	{
+		CDockablePane::OnContextMenu(pWnd, point);
+		return;
+	}
+
+	if (point != CPoint(-1, -1))
+	{
+		// 选择已单击的项: 
+		CPoint ptTree = point;
+		pWndTree->ScreenToClient(&ptTree);
+
+		UINT flags = 0;
+		HTREEITEM hTreeItem = pWndTree->HitTest(ptTree, &flags);
+		if (hTreeItem != nullptr)
+		{
+			pWndTree->SelectItem(hTreeItem);
+		}
+	}
+
+	pWndTree->SetFocus();
+	CMenu menu;
+	menu.LoadMenu(IDR_POPUP_SORT);
+
+	CMenu* pSumMenu = menu.GetSubMenu(0);
+
+	if (AfxGetMainWnd()->IsKindOf(RUNTIME_CLASS(CMDIFrameWndEx)))
+	{
+		CMFCPopupMenu* pPopupMenu = new CMFCPopupMenu;
+
+		if (!pPopupMenu->Create(this, point.x, point.y, (HMENU)pSumMenu->m_hMenu, FALSE, TRUE))
+			return;
+
+		((CMDIFrameWndEx*)AfxGetMainWnd())->OnShowPopupMenu(pPopupMenu);
+		UpdateDialogControls(this, FALSE);
+	}
+}
+
+void CClassView::AdjustLayout()
+{
+	if (GetSafeHwnd() == nullptr)
+	{
+		return;
+	}
+
+	CRect rectClient;
+	GetClientRect(rectClient);
+
+	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;
+
+	m_wndToolBar.SetWindowPos(nullptr, rectClient.left, rectClient.top, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
+	m_wndClassView.SetWindowPos(nullptr, rectClient.left + 1, rectClient.top + cyTlb + 1, rectClient.Width() - 2, rectClient.Height() - cyTlb - 2, SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+BOOL CClassView::PreTranslateMessage(MSG* pMsg)
+{
+	return CDockablePane::PreTranslateMessage(pMsg);
+}
+
+void CClassView::OnSort(UINT id)
+{
+	if (m_nCurrSort == id)
+	{
+		return;
+	}
+
+	m_nCurrSort = id;
+
+	CClassViewMenuButton* pButton =  DYNAMIC_DOWNCAST(CClassViewMenuButton, m_wndToolBar.GetButton(0));
+
+	if (pButton != nullptr)
+	{
+		pButton->SetImage(GetCmdMgr()->GetCmdImage(id));
+		m_wndToolBar.Invalidate();
+		m_wndToolBar.UpdateWindow();
+	}
+}
+
+void CClassView::OnUpdateSort(CCmdUI* pCmdUI)
+{
+	pCmdUI->SetCheck(pCmdUI->m_nID == m_nCurrSort);
+}
+
+void CClassView::OnClassAddMemberFunction()
+{
+	AfxMessageBox(_T("添加成员函数..."));
+}
+
+void CClassView::OnClassAddMemberVariable()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CClassView::OnClassDefinition()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CClassView::OnClassProperties()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CClassView::OnNewFolder()
+{
+	AfxMessageBox(_T("新建文件夹..."));
+}
+
+void CClassView::OnPaint()
+{
+	CPaintDC dc(this); // 用于绘制的设备上下文
+
+	CRect rectTree;
+	m_wndClassView.GetWindowRect(rectTree);
+	ScreenToClient(rectTree);
+
+	rectTree.InflateRect(1, 1);
+	dc.Draw3dRect(rectTree, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW));
+}
+
+void CClassView::OnSetFocus(CWnd* pOldWnd)
+{
+	CDockablePane::OnSetFocus(pOldWnd);
+
+	m_wndClassView.SetFocus();
+}
+
+void CClassView::OnChangeVisualStyle()
+{
+	m_ClassViewImages.DeleteImageList();
+
+	UINT uiBmpId = theApp.m_bHiColorIcons ? IDB_CLASS_VIEW_24 : IDB_CLASS_VIEW;
+
+	CBitmap bmp;
+	if (!bmp.LoadBitmap(uiBmpId))
+	{
+		TRACE(_T("无法加载位图: %x\n"), uiBmpId);
+		ASSERT(FALSE);
+		return;
+	}
+
+	BITMAP bmpObj;
+	bmp.GetBitmap(&bmpObj);
+
+	UINT nFlags = ILC_MASK;
+
+	nFlags |= (theApp.m_bHiColorIcons) ? ILC_COLOR24 : ILC_COLOR4;
+
+	m_ClassViewImages.Create(16, bmpObj.bmHeight, nFlags, 0, 0);
+	m_ClassViewImages.Add(&bmp, RGB(255, 0, 0));
+
+	m_wndClassView.SetImageList(&m_ClassViewImages, TVSIL_NORMAL);
+
+	m_wndToolBar.CleanUpLockedImages();
+	m_wndToolBar.LoadBitmap(theApp.m_bHiColorIcons ? IDB_SORT_24 : IDR_SORT, 0, 0, TRUE /* 锁定*/);
+}

+ 64 - 0
VideoCapture/VideoCapture/ClassView.h

@@ -0,0 +1,64 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+#include "ViewTree.h"
+
+class CClassToolBar : public CMFCToolBar
+{
+	virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
+	{
+		CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
+	}
+
+	virtual BOOL AllowShowOnList() const { return FALSE; }
+};
+
+class CClassView : public CDockablePane
+{
+public:
+	CClassView() noexcept;
+	virtual ~CClassView();
+
+	void AdjustLayout();
+	void OnChangeVisualStyle();
+
+protected:
+	CClassToolBar m_wndToolBar;
+	CViewTree m_wndClassView;
+	CImageList m_ClassViewImages;
+	UINT m_nCurrSort;
+
+	void FillClassView();
+
+// 重写
+public:
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+	afx_msg void OnClassAddMemberFunction();
+	afx_msg void OnClassAddMemberVariable();
+	afx_msg void OnClassDefinition();
+	afx_msg void OnClassProperties();
+	afx_msg void OnNewFolder();
+	afx_msg void OnPaint();
+	afx_msg void OnSetFocus(CWnd* pOldWnd);
+	afx_msg LRESULT OnChangeActiveTab(WPARAM, LPARAM);
+	afx_msg void OnSort(UINT id);
+	afx_msg void OnUpdateSort(CCmdUI* pCmdUI);
+
+	DECLARE_MESSAGE_MAP()
+};
+

+ 74 - 0
VideoCapture/VideoCapture/DlgIRControl.cpp

@@ -0,0 +1,74 @@
+// DlgIRControl.cpp: 实现文件
+//
+
+#include "stdafx.h"
+#include "VideoCapture.h"
+#include "DlgIRControl.h"
+#include "afxdialogex.h"
+
+
+// CDlgIRControl 对话框
+
+IMPLEMENT_DYNAMIC(CDlgIRControl, CDialogEx)
+
+CDlgIRControl::CDlgIRControl(CWnd* pParent /*=nullptr*/)
+	: CDialogEx(IDD_DLG_IRCONTROL, pParent)
+{
+
+}
+
+CDlgIRControl::~CDlgIRControl()
+{
+}
+
+void CDlgIRControl::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+
+BEGIN_MESSAGE_MAP(CDlgIRControl, CDialogEx)
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+
+// CDlgIRControl 消息处理程序
+
+
+void CDlgIRControl::OnOK()
+{
+	// TODO: 在此添加专用代码和/或调用基类
+
+	//CDialogEx::OnOK();
+}
+
+
+void CDlgIRControl::OnCancel()
+{
+	// TODO: 在此添加专用代码和/或调用基类
+
+	//CDialogEx::OnCancel();
+}
+
+
+void CDlgIRControl::AdjustLayout()
+{
+}
+
+BOOL CDlgIRControl::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  在此添加额外的初始化
+
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 异常: OCX 属性页应返回 FALSE
+}
+
+
+void CDlgIRControl::OnSize(UINT nType, int cx, int cy)
+{
+	CDialogEx::OnSize(nType, cx, cy);
+
+	// TODO: 在此处添加消息处理程序代码
+}

+ 29 - 0
VideoCapture/VideoCapture/DlgIRControl.h

@@ -0,0 +1,29 @@
+#pragma once
+
+
+// CDlgIRControl 对话框
+
+class CDlgIRControl : public CDialogEx
+{
+	DECLARE_DYNAMIC(CDlgIRControl)
+
+public:
+	CDlgIRControl(CWnd* pParent = nullptr);   // 标准构造函数
+	virtual ~CDlgIRControl();
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_DLG_IRCONTROL };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+	DECLARE_MESSAGE_MAP()
+	virtual void OnOK();
+	virtual void OnCancel();
+public:
+	void AdjustLayout();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+};

+ 267 - 0
VideoCapture/VideoCapture/FileView.cpp

@@ -0,0 +1,267 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+#include "mainfrm.h"
+#include "FileView.h"
+#include "Resource.h"
+#include "VideoCapture.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CFileView
+
+CFileView::CFileView() noexcept
+{
+}
+
+CFileView::~CFileView()
+{
+}
+
+BEGIN_MESSAGE_MAP(CFileView, CDockablePane)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+	ON_WM_CONTEXTMENU()
+	ON_COMMAND(ID_PROPERTIES, OnProperties)
+	ON_COMMAND(ID_OPEN, OnFileOpen)
+	ON_COMMAND(ID_OPEN_WITH, OnFileOpenWith)
+	ON_COMMAND(ID_DUMMY_COMPILE, OnDummyCompile)
+	ON_COMMAND(ID_EDIT_CUT, OnEditCut)
+	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
+	ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
+	ON_WM_PAINT()
+	ON_WM_SETFOCUS()
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CWorkspaceBar 消息处理程序
+
+int CFileView::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy;
+	rectDummy.SetRectEmpty();
+
+	// 创建视图: 
+	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
+
+	if (!m_wndFileView.Create(dwViewStyle, rectDummy, this, 4))
+	{
+		TRACE0("未能创建文件视图\n");
+		return -1;      // 未能创建
+	}
+
+	// 加载视图图像: 
+	m_FileViewImages.Create(IDB_FILE_VIEW, 16, 0, RGB(255, 0, 255));
+	m_wndFileView.SetImageList(&m_FileViewImages, TVSIL_NORMAL);
+
+	m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_EXPLORER);
+	m_wndToolBar.LoadToolBar(IDR_EXPLORER, 0, 0, TRUE /* 已锁定*/);
+
+	OnChangeVisualStyle();
+
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
+
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM | CBRS_BORDER_LEFT | CBRS_BORDER_RIGHT));
+
+	m_wndToolBar.SetOwner(this);
+
+	// 所有命令将通过此控件路由,而不是通过主框架路由: 
+	m_wndToolBar.SetRouteCommandsViaFrame(FALSE);
+
+	// 填入一些静态树视图数据(此处只需填入虚拟代码,而不是复杂的数据)
+	FillFileView();
+	AdjustLayout();
+
+	return 0;
+}
+
+void CFileView::OnSize(UINT nType, int cx, int cy)
+{
+	CDockablePane::OnSize(nType, cx, cy);
+	AdjustLayout();
+}
+
+void CFileView::FillFileView()
+{
+	HTREEITEM hRoot = m_wndFileView.InsertItem(_T("FakeApp 文件"), 0, 0);
+	m_wndFileView.SetItemState(hRoot, TVIS_BOLD, TVIS_BOLD);
+
+	HTREEITEM hSrc = m_wndFileView.InsertItem(_T("FakeApp 源文件"), 0, 0, hRoot);
+
+	m_wndFileView.InsertItem(_T("FakeApp.cpp"), 1, 1, hSrc);
+	m_wndFileView.InsertItem(_T("FakeApp.rc"), 1, 1, hSrc);
+	m_wndFileView.InsertItem(_T("FakeAppDoc.cpp"), 1, 1, hSrc);
+	m_wndFileView.InsertItem(_T("FakeAppView.cpp"), 1, 1, hSrc);
+	m_wndFileView.InsertItem(_T("MainFrm.cpp"), 1, 1, hSrc);
+	m_wndFileView.InsertItem(_T("pch.cpp"), 1, 1, hSrc);
+
+	HTREEITEM hInc = m_wndFileView.InsertItem(_T("FakeApp 头文件"), 0, 0, hRoot);
+
+	m_wndFileView.InsertItem(_T("FakeApp.h"), 2, 2, hInc);
+	m_wndFileView.InsertItem(_T("FakeAppDoc.h"), 2, 2, hInc);
+	m_wndFileView.InsertItem(_T("FakeAppView.h"), 2, 2, hInc);
+	m_wndFileView.InsertItem(_T("Resource.h"), 2, 2, hInc);
+	m_wndFileView.InsertItem(_T("MainFrm.h"), 2, 2, hInc);
+	m_wndFileView.InsertItem(_T("pch.h"), 2, 2, hInc);
+
+	HTREEITEM hRes = m_wndFileView.InsertItem(_T("FakeApp 资源文件"), 0, 0, hRoot);
+
+	m_wndFileView.InsertItem(_T("FakeApp.ico"), 2, 2, hRes);
+	m_wndFileView.InsertItem(_T("FakeApp.rc2"), 2, 2, hRes);
+	m_wndFileView.InsertItem(_T("FakeAppDoc.ico"), 2, 2, hRes);
+	m_wndFileView.InsertItem(_T("FakeToolbar.bmp"), 2, 2, hRes);
+
+	m_wndFileView.Expand(hRoot, TVE_EXPAND);
+	m_wndFileView.Expand(hSrc, TVE_EXPAND);
+	m_wndFileView.Expand(hInc, TVE_EXPAND);
+}
+
+void CFileView::OnContextMenu(CWnd* pWnd, CPoint point)
+{
+	CTreeCtrl* pWndTree = (CTreeCtrl*) &m_wndFileView;
+	ASSERT_VALID(pWndTree);
+
+	if (pWnd != pWndTree)
+	{
+		CDockablePane::OnContextMenu(pWnd, point);
+		return;
+	}
+
+	if (point != CPoint(-1, -1))
+	{
+		// 选择已单击的项: 
+		CPoint ptTree = point;
+		pWndTree->ScreenToClient(&ptTree);
+
+		UINT flags = 0;
+		HTREEITEM hTreeItem = pWndTree->HitTest(ptTree, &flags);
+		if (hTreeItem != nullptr)
+		{
+			pWndTree->SelectItem(hTreeItem);
+		}
+	}
+
+	pWndTree->SetFocus();
+	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EXPLORER, point.x, point.y, this, TRUE);
+}
+
+void CFileView::AdjustLayout()
+{
+	if (GetSafeHwnd() == nullptr)
+	{
+		return;
+	}
+
+	CRect rectClient;
+	GetClientRect(rectClient);
+
+	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;
+
+	m_wndToolBar.SetWindowPos(nullptr, rectClient.left, rectClient.top, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
+	m_wndFileView.SetWindowPos(nullptr, rectClient.left + 1, rectClient.top + cyTlb + 1, rectClient.Width() - 2, rectClient.Height() - cyTlb - 2, SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+void CFileView::OnProperties()
+{
+	AfxMessageBox(_T("属性...."));
+
+}
+
+void CFileView::OnFileOpen()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnFileOpenWith()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnDummyCompile()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnEditCut()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnEditCopy()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnEditClear()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CFileView::OnPaint()
+{
+	CPaintDC dc(this); // 用于绘制的设备上下文
+
+	CRect rectTree;
+	m_wndFileView.GetWindowRect(rectTree);
+	ScreenToClient(rectTree);
+
+	rectTree.InflateRect(1, 1);
+	dc.Draw3dRect(rectTree, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW));
+}
+
+void CFileView::OnSetFocus(CWnd* pOldWnd)
+{
+	CDockablePane::OnSetFocus(pOldWnd);
+
+	m_wndFileView.SetFocus();
+}
+
+void CFileView::OnChangeVisualStyle()
+{
+	m_wndToolBar.CleanUpLockedImages();
+	m_wndToolBar.LoadBitmap(theApp.m_bHiColorIcons ? IDB_EXPLORER_24 : IDR_EXPLORER, 0, 0, TRUE /* 锁定*/);
+
+	m_FileViewImages.DeleteImageList();
+
+	UINT uiBmpId = theApp.m_bHiColorIcons ? IDB_FILE_VIEW_24 : IDB_FILE_VIEW;
+
+	CBitmap bmp;
+	if (!bmp.LoadBitmap(uiBmpId))
+	{
+		TRACE(_T("无法加载位图: %x\n"), uiBmpId);
+		ASSERT(FALSE);
+		return;
+	}
+
+	BITMAP bmpObj;
+	bmp.GetBitmap(&bmpObj);
+
+	UINT nFlags = ILC_MASK;
+
+	nFlags |= (theApp.m_bHiColorIcons) ? ILC_COLOR24 : ILC_COLOR4;
+
+	m_FileViewImages.Create(16, bmpObj.bmHeight, nFlags, 0, 0);
+	m_FileViewImages.Add(&bmp, RGB(255, 0, 255));
+
+	m_wndFileView.SetImageList(&m_FileViewImages, TVSIL_NORMAL);
+}
+
+

+ 65 - 0
VideoCapture/VideoCapture/FileView.h

@@ -0,0 +1,65 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+#include "ViewTree.h"
+
+class CFileViewToolBar : public CMFCToolBar
+{
+	virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
+	{
+		CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
+	}
+
+	virtual BOOL AllowShowOnList() const { return FALSE; }
+};
+
+class CFileView : public CDockablePane
+{
+// 构造
+public:
+	CFileView() noexcept;
+
+	void AdjustLayout();
+	void OnChangeVisualStyle();
+
+// 特性
+protected:
+
+	CViewTree m_wndFileView;
+	CImageList m_FileViewImages;
+	CFileViewToolBar m_wndToolBar;
+
+protected:
+	void FillFileView();
+
+// 实现
+public:
+	virtual ~CFileView();
+
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+	afx_msg void OnProperties();
+	afx_msg void OnFileOpen();
+	afx_msg void OnFileOpenWith();
+	afx_msg void OnDummyCompile();
+	afx_msg void OnEditCut();
+	afx_msg void OnEditCopy();
+	afx_msg void OnEditClear();
+	afx_msg void OnPaint();
+	afx_msg void OnSetFocus(CWnd* pOldWnd);
+
+	DECLARE_MESSAGE_MAP()
+};
+

+ 522 - 0
VideoCapture/VideoCapture/Global.cpp

@@ -0,0 +1,522 @@
+#include "stdafx.h"
+#include "Global.h"
+#include <tchar.h>
+#include <direct.h>
+#include <SetupAPI.h>
+#include <InitGuid.h>
+#include <WinIoCtl.h>
+#pragma comment(lib, "SetupAPI.lib")
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	TCHAR g_szCurModuleDir[MAX_PATH] = {0};
+	TCHAR g_szCurModulePath[MAX_PATH] = {0};
+	TCHAR g_szFna[MAX_PATH] = {0};
+	TCHAR g_szConfig[MAX_PATH] = {0};
+	
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	/************************************************************************/
+	/*  函数:WriteTextLog[7/28/2009 Jeff];
+	/*  描述:写文本日志;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WriteTextLog(const TCHAR *format, ...)
+	{
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = { 0 };
+		_stprintf_s(szlogpath, _T("%s%s.txt"), g_szCurModuleDir, g_szFna);
+		// 打开或创建文件;
+		FILE *fp = NULL;
+		//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+		if (_access(szlogpath, 0) != -1)
+#else
+		if (_taccess(szlogpath, 0) != -1)
+#endif
+		{// 存在;
+			if ( 0 == _tfopen_s(&fp, szlogpath, _T("a+")))
+				// 移动到末尾;
+				fseek(fp, 0, SEEK_END);
+		}
+		else
+		{// 不存在;
+			_tfopen_s(&fp, szlogpath, _T("w+"));
+		}
+
+		if ( fp == NULL )
+			return;
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
+
+		// 格式化日志内容;
+		va_list		args = NULL;
+		int			len = 0;
+		TCHAR		*buffer = NULL;
+		va_start(args, format);
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf(format, args) + 1;
+		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+		_vstprintf_s(buffer, len, format, args);
+		// 将日志内容输入到文件中;
+		// 获取今年年份;
+		__time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+		struct tm gmtm = {0};
+		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year+1990, gmtm.tm_mon+1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free(buffer);
+		fclose(fp);
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale);//还原区域设定;
+	}
+
+	
+	// 读取配置文件-预留;
+	void GetConfig()
+	{
+		TCHAR szValue[MAX_PATH] = {0};
+		// config;
+		//g_ini_config.com = GetPrivateProfileInt(_T("config"), _T("COM"), NULL, g_szConfig);
+		//g_ini_config.baudrate = GetPrivateProfileInt(_T("config"), _T("Baudrate"), NULL, g_szConfig);
+		//g_ini_config.chasis = GetPrivateProfileInt(_T("config"), _T("Chasis"), NULL, g_szConfig);
+		//g_ini_config.mode = GetPrivateProfileInt(_T("config"), _T("ModeSelect"), NULL, g_szConfig);
+		//g_ini_config.warncount = GetPrivateProfileInt(_T("config"), _T("WarnCount"), NULL, g_szConfig);
+
+		//GetPrivateProfileString(_T("config"), _T("ChasisList"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_config.chasislist =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("config"), _T("SiacpCmdFile"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_config.siacpcmdfile =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("config"), _T("Server_url"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_config.serverurl =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//// folder;
+		//GetPrivateProfileString(_T("filefolder"), _T("DIDFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.DIDFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("MACFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.MACFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("KEYFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.KEYFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("ESNFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.ESNFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("WiDiFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.WiDiFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("WidevineFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.WidevineFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("HDCPKEY22Folder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.HDCPKEY22Folder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("CIKeyFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.CIKeyFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+		//GetPrivateProfileString(_T("filefolder"), _T("WBFolder"), NULL, szValue, MAX_PATH, g_szConfig);
+		//g_ini_folder.WBFolder =  szValue;
+		//memset(szValue, 0, MAX_PATH);
+
+	}
+	
+	BOOL GetOrientation(IN Image* pImg)
+	{
+		if (pImg == NULL) return FALSE;
+
+		UINT totalBufferSize;
+		UINT numProperties;
+		pImg->GetPropertySize(&totalBufferSize, &numProperties);
+		// Allocate the buffer that will receive the property items.
+		PropertyItem* pAllItems = (PropertyItem*)malloc(totalBufferSize);
+		// Fill the buffer.
+		pImg->GetAllPropertyItems(totalBufferSize, numProperties, pAllItems);
+		// Print the id data member of each property item.
+		for (UINT j = 0; j < numProperties; ++j)
+		{
+			if (PropertyTagOrientation == pAllItems[j].id)
+			{
+				short* ptrLong = (short*)(pAllItems[j].value);
+				int ret = (int)* ptrLong;
+				free(pAllItems);
+				return ret;
+			}
+		}
+		free(pAllItems);
+
+		return TRUE;
+	}
+
+
+	/************************************************************************/
+	/*
+	函数:GetEncoderClsid
+	描述:获取GDI+支持的图像格式编码器种类,以及所有种类编码器信息;
+	参数:
+	IN:  format 要获取的图像格式;
+	OUT: pClsid 返回符合条件的图像编码器信息;
+	返回:成功返回编码器索引,否则返回-1;
+	*/
+	/************************************************************************/
+	int GetEncoderClsid(IN CONST WCHAR* format, OUT CLSID* pClsid)
+	{
+		// GDI+支持的图像编码器数量;
+		UINT  numEncoders = 0;
+		// GDI+所有图像格式编码器详细信息所需要的空间大小;
+		UINT  nSize = 0;
+
+		ImageCodecInfo* pImageCodecInfo = NULL;
+
+		// 2.获取GDI+支持的所有图像格式编码器详细信息所需要的空间大小;
+		GetImageEncodersSize(&numEncoders, &nSize);
+		if (nSize == 0)
+			return -1;
+
+		//3.为ImageCodecInfo数组分配足额空间;
+		pImageCodecInfo = (ImageCodecInfo*)(malloc(nSize));
+		if (pImageCodecInfo == NULL)
+			return -1;
+
+		//4.获取所有的图像编码器信息;
+		GetImageEncoders(numEncoders, nSize, pImageCodecInfo);
+
+		//5.查找符合的图像编码器的Clsid;
+		for (UINT i = 0; i < numEncoders; ++i)
+		{
+			if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
+			{
+				*pClsid = pImageCodecInfo[i].Clsid;
+				free(pImageCodecInfo);
+				return i;  // Success
+			}
+		}
+
+		//6.释放步骤3分配的内存;
+		free(pImageCodecInfo);
+
+		return -1;
+	}
+
+
+	BOOL LoadImgFromFile(IN Image** pImg, LPCTSTR lpPath)
+	{
+		if (!PathFileExists(lpPath))
+			return FALSE;
+
+		if (*pImg)
+			delete* pImg;
+
+		*pImg = NULL;
+
+#ifdef UNICODE
+		* pImg = Image::FromFile(lpPath);
+#else
+		BSTR strtmp = _bstr_t(lpPath);
+		*pImg = Image::FromFile(strtmp, TRUE);
+		SysFreeString(strtmp);
+#endif
+
+		return (*pImg ? TRUE : FALSE);
+	}
+
+	BOOL LoadImgFromBuffer(IN Image** pImg, IN BYTE* pBuffer, IN CONST INT& nBufLen)
+	{
+		if (pBuffer == NULL)
+			return FALSE;
+
+		if (*pImg)
+			delete* pImg;
+
+		*pImg = NULL;
+		HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, nBufLen);
+		if (hMemery == NULL)
+			return FALSE;
+
+		BYTE* pMem = (BYTE*)GlobalLock(hMemery);
+		memcpy(pMem, pBuffer, nBufLen);
+
+		IStream* pstream = NULL;
+		CreateStreamOnHGlobal(hMemery, TRUE, &pstream);
+		*pImg = Image::FromStream(pstream);
+		GlobalUnlock(hMemery);
+		pstream->Release();
+
+		return (*pImg ? TRUE : FALSE);
+	}
+
+	// 先以只读方式从文件中读取二进制流出来,可以做到不独占文件;
+	BOOL LoadImgFromBuffer(IN Image** pImg, LPCTSTR lpPath)
+	{
+		if (!PathFileExists(lpPath))
+			return FALSE;
+
+		if (*pImg)
+			delete* pImg;
+		*pImg = NULL;
+
+		return LoadImgFromFile(pImg, lpPath);
+
+		CFile fp;
+		CFileException e;
+		BOOL bRet = FALSE;
+		if (fp.Open(lpPath, CFile::modeRead, &e))
+		{
+			DWORD dwLength = (DWORD)fp.GetLength();
+			BYTE* pData = new BYTE[dwLength];
+
+			fp.Read(pData, dwLength);
+			fp.Close();
+
+			bRet = LoadImgFromBuffer(pImg, pData, dwLength);
+
+			if (pData)
+				delete[]pData;
+		}
+
+		return bRet;
+	}
+
+	/************************************************************************/
+	/*  函数:LoadImgFromResource[9/21/2016 IT];
+	/*  描述:从资源中加载;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	Image* LoadImgFromResource(IN HMODULE hModule, IN LPCTSTR lpName, IN LPCTSTR lpType)
+	{
+		HGLOBAL	hGlobal = NULL;
+		HRSRC	hSource = NULL;
+		LPVOID  lpBuffer = NULL;
+		DWORD   dwSize = 0;
+		// 1.定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可
+		hSource = FindResource(hModule, lpName, lpType);
+		if (hSource == NULL)
+		{
+			_tprintf(_T("载入资源失败:%s"), lpName);
+			return NULL;
+		}
+
+		// 2.获取资源的大小;
+		dwSize = (UINT)SizeofResource(NULL, hSource);
+
+		// 3.加载资源;
+		hGlobal = LoadResource(NULL, hSource);
+		if (hGlobal == NULL)
+		{
+			_tprintf(_T("载入资源失败:%s"), lpName);
+			return NULL;
+		}
+
+		// 4.锁定资源,获取buffer;
+		lpBuffer = LockResource(hGlobal);
+		if (lpBuffer == NULL)
+		{
+			_tprintf(_T("载入资源失败:%s"), lpName);
+			return NULL;
+		}
+
+		// lpFileFullName需要先判断文件是否存在??不需要;
+		Image* pImg = NULL;
+		LoadImgFromBuffer(&pImg, (BYTE*)lpBuffer, dwSize);
+
+		UnlockResource(hGlobal);
+		FreeResource(hGlobal);
+
+		return pImg;
+	}
+
+	BOOL SaveImgByRotate(LPCTSTR lpszFileName, BYTE* pBuffer, const INT& nBufLen, BOOL bHoriontal, BOOL bVertically)
+	{
+		Image *pImg = NULL;
+		HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, nBufLen);
+		if (hMemery == NULL)
+			return FALSE;
+
+		BYTE* pMem = NULL;
+		pMem = (BYTE*)GlobalLock(hMemery);
+		if (pMem == NULL)
+			return FALSE;
+		memcpy(pMem, pBuffer, nBufLen);
+
+		IStream* pstream = NULL;
+	    HRESULT hr = CreateStreamOnHGlobal(hMemery, TRUE, &pstream);
+		if (pstream == NULL)
+			return FALSE;
+		pImg = Image::FromStream(pstream);
+		GlobalUnlock(hMemery);
+		pstream->Release();
+
+		if (bHoriontal && !bVertically)
+			pImg->RotateFlip(RotateNoneFlipX);// 水平翻转;
+		else if ( bHoriontal && bVertically)
+			pImg->RotateFlip(Rotate180FlipNone);// 270度;
+		else if (!bHoriontal && bVertically)
+			pImg->RotateFlip(Rotate180FlipX);// 垂直翻转;
+
+		CString strNewfile = lpszFileName;
+		// 需要判断路径是否存在,不存在创建目录;
+		int nIndex = strNewfile.ReverseFind(_T('\\'));
+		if (nIndex == -1)
+			return FALSE;
+
+		if (!PathFileExists(strNewfile.Left(nIndex)))
+		{
+			// 如果文件夹不存在,创建;
+			SHCreateDirectoryEx(NULL, strNewfile.Left(nIndex), NULL);
+		}
+
+		nIndex = strNewfile.ReverseFind(_T('.'));
+		if (nIndex == -1)
+			return FALSE;
+
+		Status stat = GenericError;
+		CLSID encoderClsid = { 0 };
+		BSTR newfile = strNewfile.AllocSysString();
+
+		strNewfile = strNewfile.Mid(nIndex + 1);
+		if (strNewfile.CompareNoCase(_T("bmp")) == 0)
+		{
+			GetEncoderClsid(L"image/bmp", &encoderClsid);
+			stat = pImg->Save(newfile, &encoderClsid, NULL);
+		}
+		else if (strNewfile.CompareNoCase(_T("png")) == 0)
+		{
+			GetEncoderClsid(L"image/png", &encoderClsid);
+			stat = pImg->Save(newfile, &encoderClsid, NULL);
+		}
+		else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
+		{
+			GetEncoderClsid(L"image/jpeg", &encoderClsid);
+
+			EncoderParameters encoderParameters;
+			encoderParameters.Count = 1;
+			encoderParameters.Parameter[0].Guid = EncoderQuality;
+			encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
+			encoderParameters.Parameter[0].NumberOfValues = 1;
+			// Save the image as a JPEG with quality level 100.
+			ULONG uQuality = 100;
+			encoderParameters.Parameter[0].Value = &uQuality;
+			stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
+		}
+
+		if (pImg)
+			delete pImg;
+		pImg = NULL;
+
+		SysFreeString(newfile);
+
+		return stat == Ok ? TRUE : FALSE;
+	}
+	
+
+	void MKDIR(LPCTSTR dir)
+	{
+		//////////////////////////////////////////////////////////////////////////
+		// 创建目录;
+		int nleft = 0;
+		int nIndex = -1;
+		TString strdir = dir;
+
+		if (strdir.at(strdir.size() - 1) != _T('\\'))
+			strdir.append(_T("\\"));
+
+		// 共享路径和硬盘盘符;
+		if (_tcscmp(strdir.substr(0, 2).c_str(), _T("\\\\")) == 0)
+			nleft = strdir.find_first_of(_T("\\"), 2) + 1;	// 去除共享主机名;
+		else if (strdir.at(2) == _T('\\'))
+			nleft = 3;
+
+		do
+		{
+			nIndex = strdir.substr(nleft, -1).find_first_of(_T("\\"));
+
+			if (nIndex != TString::npos)
+			{
+				if (_tmkdir(strdir.substr(0, nIndex + nleft).c_str()) == -1 && (errno != EEXIST))
+				{
+					WriteTextLog(_T("创建目录失败:%s,错误码:%d"), strdir.substr(0, nIndex + nleft).c_str(), errno);
+					break;
+				}
+
+				nleft += nIndex + 1;
+			}
+		} while (nIndex != -1);
+	}
+
+	// hModule 模块句柄 NULL表示当前模块;
+	bool GetVersion(OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion)
+	{
+		TCHAR szFilePath[MAX_PATH] = { 0 };
+		DWORD dwRet = GetModuleFileName(NULL, szFilePath, MAX_PATH);
+		if (dwRet == 0)
+			return false;
+
+		VS_FIXEDFILEINFO* pVi = NULL;
+		DWORD dwHandle = 0;
+		int size = GetFileVersionInfoSize(szFilePath, &dwHandle);
+		if (size > 0)
+		{
+			BYTE* buffer = new BYTE[size];
+			memset(buffer, 0, size);
+
+			if (GetFileVersionInfo(szFilePath, dwHandle, size, buffer))
+			{
+				if (VerQueryValue(buffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& size))
+				{
+					pdwFileVersion[0] = HIWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[1] = LOWORD(pVi->dwFileVersionMS);
+					pdwFileVersion[2] = HIWORD(pVi->dwFileVersionLS);
+					pdwFileVersion[3] = LOWORD(pVi->dwFileVersionLS);
+
+					pdwProductVerion[0] = HIWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[1] = LOWORD(pVi->dwProductVersionMS);
+					pdwProductVerion[2] = HIWORD(pVi->dwProductVersionLS);
+					pdwProductVerion[3] = LOWORD(pVi->dwProductVersionLS);
+
+					delete[]buffer;
+					return true;
+				}
+			}
+
+			delete[]buffer;
+		}
+
+		return false;
+	}
+}

+ 46 - 0
VideoCapture/VideoCapture/Global.h

@@ -0,0 +1,46 @@
+
+#pragma once
+#include <stdio.h>
+#include <locale.h>
+#include <stdlib.h>
+//#include <time.h> //»òÕß #include <ctime>
+#include <ctime>
+#include <io.h>
+#pragma comment(lib,"version.lib")
+#include <vector>
+#include <string>
+// GDI+
+#include <gdiplus.h>
+using namespace Gdiplus;
+#pragma comment(lib, "gdiplus.lib")
+
+
+#ifndef _UNICODE 
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// È«¾Ö±äÁ¿;
+	extern TCHAR g_szCurModuleDir[MAX_PATH];
+	extern TCHAR g_szCurModulePath[MAX_PATH];
+	extern TCHAR g_szFna[MAX_PATH];
+	extern TCHAR g_szConfig[MAX_PATH];
+
+
+	//////////////////////////////////////////////////////////////////////////
+	// È«¾Öº¯Êý;
+	void GetConfig();
+	void WriteTextLog(const TCHAR* format, ...);
+	BOOL LoadImgFromFile(IN Image** pImg, LPCTSTR lpPath);
+	BOOL LoadImgFromBuffer(IN Image** pImg, IN BYTE* pBuffer, IN CONST INT& nBufLen);
+	BOOL LoadImgFromBuffer(IN Image** pImg, LPCTSTR lpPath);
+	int GetEncoderClsid(IN CONST WCHAR* format, OUT CLSID* pClsid);
+	Image* LoadImgFromResource(IN HMODULE hModule, IN LPCTSTR lpName, IN LPCTSTR lpType);
+	BOOL SaveImgByRotate(LPCTSTR lpszFileName, BYTE* pBuffer, CONST INT& nBufLen, BOOL bHoriontal, BOOL bVertically);
+	void MKDIR(LPCTSTR dir);
+	bool GetVersion(OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion);
+};

+ 187 - 0
VideoCapture/VideoCapture/IRControlWnd.cpp

@@ -0,0 +1,187 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+
+#include "IRControlWnd.h"
+#include "Resource.h"
+#include "MainFrm.h"
+#include "VideoCapture.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CResourceViewBar
+
+CIRControlWnd::CIRControlWnd() noexcept
+{
+	m_nComboHeight = 0;
+}
+
+CIRControlWnd::~CIRControlWnd()
+{
+}
+
+BEGIN_MESSAGE_MAP(CIRControlWnd, CDockablePane)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+	ON_COMMAND(ID_EXPAND_ALL, OnExpandAllProperties)
+	ON_UPDATE_COMMAND_UI(ID_EXPAND_ALL, OnUpdateExpandAllProperties)
+	ON_COMMAND(ID_SORTPROPERTIES, OnSortProperties)
+	ON_UPDATE_COMMAND_UI(ID_SORTPROPERTIES, OnUpdateSortProperties)
+	ON_COMMAND(ID_PROPERTIES1, OnProperties1)
+	ON_UPDATE_COMMAND_UI(ID_PROPERTIES1, OnUpdateProperties1)
+	ON_COMMAND(ID_PROPERTIES2, OnProperties2)
+	ON_UPDATE_COMMAND_UI(ID_PROPERTIES2, OnUpdateProperties2)
+	ON_WM_SETFOCUS()
+	ON_WM_SETTINGCHANGE()
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CResourceViewBar 消息处理程序
+
+void CIRControlWnd::AdjustLayout()
+{
+	if (GetSafeHwnd () == nullptr || (AfxGetMainWnd() != nullptr && AfxGetMainWnd()->IsIconic()))
+	{
+		return;
+	}
+
+	CRect rectClient;
+	GetClientRect(rectClient);
+
+	m_wndObjectCombo.SetWindowPos(nullptr, rectClient.left, rectClient.top, rectClient.Width(), m_nComboHeight+200, SWP_NOACTIVATE | SWP_NOZORDER);
+	m_dlgIRControl.SetWindowPos(nullptr, rectClient.left, rectClient.top + m_nComboHeight, rectClient.Width(), rectClient.Height(), SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+int CIRControlWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy;
+	rectDummy.SetRectEmpty();
+
+	// 创建组合: 
+	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+	if (!m_wndObjectCombo.Create(dwViewStyle, rectDummy, this, 1))
+	{
+		TRACE0("未能创建遥控器组合 \n");
+		return -1;      // 未能创建
+	}
+
+	m_wndObjectCombo.AddString(_T("红老鼠 3.0"));
+	m_wndObjectCombo.AddString(_T("红老鼠 4.0"));
+	m_wndObjectCombo.SetCurSel(0);
+
+	CRect rectCombo;
+	m_wndObjectCombo.GetClientRect (&rectCombo);
+
+	m_nComboHeight = rectCombo.Height();
+
+	if (!m_dlgIRControl.Create(IDD_DLG_IRCONTROL, this))
+	{
+		TRACE0("未能创建遥控器主窗口 \n");
+		return -1;      // 未能创建
+	}
+	m_dlgIRControl.ShowWindow(SW_SHOW);
+
+	// 设置最小窗体;
+	SetMinSize((350,300));
+
+	// 校正布局;
+	AdjustLayout();
+
+	return 0;
+}
+
+void CIRControlWnd::OnSize(UINT nType, int cx, int cy)
+{
+	CDockablePane::OnSize(nType, cx, cy);
+	AdjustLayout();
+}
+
+void CIRControlWnd::OnExpandAllProperties()
+{
+	//m_wndPropList.ExpandAll();
+}
+
+void CIRControlWnd::OnUpdateExpandAllProperties(CCmdUI* /* pCmdUI */)
+{
+}
+
+void CIRControlWnd::OnSortProperties()
+{
+	//m_wndPropList.SetAlphabeticMode(!m_wndPropList.IsAlphabeticMode());
+}
+
+void CIRControlWnd::OnUpdateSortProperties(CCmdUI* pCmdUI)
+{
+	//pCmdUI->SetCheck(m_wndPropList.IsAlphabeticMode());
+}
+
+void CIRControlWnd::OnProperties1()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CIRControlWnd::OnUpdateProperties1(CCmdUI* /*pCmdUI*/)
+{
+	// TODO: 在此处添加命令更新 UI 处理程序代码
+}
+
+void CIRControlWnd::OnProperties2()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CIRControlWnd::OnUpdateProperties2(CCmdUI* /*pCmdUI*/)
+{
+	// TODO: 在此处添加命令更新 UI 处理程序代码
+}
+
+void CIRControlWnd::OnSetFocus(CWnd* pOldWnd)
+{
+	CDockablePane::OnSetFocus(pOldWnd);
+}
+
+void CIRControlWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
+{
+	CDockablePane::OnSettingChange(uFlags, lpszSection);
+	SetPropListFont();
+}
+
+void CIRControlWnd::SetPropListFont()
+{
+	::DeleteObject(m_fntPropList.Detach());
+
+	LOGFONT lf;
+	afxGlobalData.fontRegular.GetLogFont(&lf);
+
+	NONCLIENTMETRICS info;
+	info.cbSize = sizeof(info);
+
+	afxGlobalData.GetNonClientMetrics(info);
+
+	lf.lfHeight = info.lfMenuFont.lfHeight;
+	lf.lfWeight = info.lfMenuFont.lfWeight;
+	lf.lfItalic = info.lfMenuFont.lfItalic;
+
+	m_fntPropList.CreateFontIndirect(&lf);
+
+	m_wndObjectCombo.SetFont(&m_fntPropList);
+}

+ 72 - 0
VideoCapture/VideoCapture/IRControlWnd.h

@@ -0,0 +1,72 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "DlgIRControl.h"
+#pragma once
+
+class CIRControlToolBar : public CMFCToolBar
+{
+public:
+	virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
+	{
+		CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
+	}
+
+	virtual BOOL AllowShowOnList() const { return FALSE; }
+};
+
+class CIRControlWnd : public CDockablePane
+{
+// 构造
+public:
+	CIRControlWnd() noexcept;
+
+	void AdjustLayout();
+
+// 特性
+public:
+
+protected:
+	CFont m_fntPropList;
+	CComboBox m_wndObjectCombo;
+	CDlgIRControl m_dlgIRControl;
+// 实现
+public:
+	virtual ~CIRControlWnd();
+	// 去掉关闭按钮;但组合多个pane时无效;
+	virtual BOOL CanBeClosed() const { return FALSE; };
+	// 禁止拖动Pane;
+	virtual BOOL FloatPane(CRect rectFloat, AFX_DOCK_METHOD dockMethod = DM_UNKNOWN, bool bShow = true) { return FALSE; }
+	// 禁用停靠,双击底部无效(不会停靠)
+	virtual BOOL CanFloat() const { return FALSE; };
+	// 禁用大小;//崩溃;
+	//virtual BOOL IsResizable() const {return FALSE;}
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnExpandAllProperties();
+	afx_msg void OnUpdateExpandAllProperties(CCmdUI* pCmdUI);
+	afx_msg void OnSortProperties();
+	afx_msg void OnUpdateSortProperties(CCmdUI* pCmdUI);
+	afx_msg void OnProperties1();
+	afx_msg void OnUpdateProperties1(CCmdUI* pCmdUI);
+	afx_msg void OnProperties2();
+	afx_msg void OnUpdateProperties2(CCmdUI* pCmdUI);
+	afx_msg void OnSetFocus(CWnd* pOldWnd);
+	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+
+	DECLARE_MESSAGE_MAP()
+
+	void SetPropListFont();
+
+	int m_nComboHeight;
+};
+

+ 633 - 0
VideoCapture/VideoCapture/MainFrm.cpp

@@ -0,0 +1,633 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// MainFrm.cpp: CMainFrame 类的实现
+//
+
+#include "stdafx.h"
+#include "framework.h"
+#include "VideoCapture.h"
+
+#include "MainFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+#if USE_TRAYICON
+#define WM_MY_TRAY_NOTIFICATION WM_USER + 108
+const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(_T("UB530"));
+#endif
+
+// CMainFrame
+
+IMPLEMENT_DYNCREATE(CMainFrame, CFrameWndEx)
+
+BEGIN_MESSAGE_MAP(CMainFrame, CFrameWndEx)
+	ON_WM_CREATE()
+	ON_COMMAND_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnApplicationLook)
+	ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_APPLOOK_WIN_2000, ID_VIEW_APPLOOK_WINDOWS_7, &CMainFrame::OnUpdateApplicationLook)
+	ON_COMMAND(ID_VIEW_CAPTION_BAR, &CMainFrame::OnViewCaptionBar)
+	ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTION_BAR, &CMainFrame::OnUpdateViewCaptionBar)
+	ON_COMMAND(ID_TOOLS_OPTIONS, &CMainFrame::OnOptions)
+	ON_COMMAND(ID_FILE_PRINT, &CMainFrame::OnFilePrint)
+	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CMainFrame::OnFilePrint)
+	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CMainFrame::OnFilePrintPreview)
+	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, &CMainFrame::OnUpdateFilePrintPreview)
+#if USE_TRAYICON
+	ON_MESSAGE(WM_MY_TRAY_NOTIFICATION, OnTrayNotification)
+	ON_REGISTERED_MESSAGE(WM_TASKBARCREATED, OnTaskBarCreated)
+#endif
+	ON_WM_SETTINGCHANGE()
+	ON_COMMAND(ID_TRAYMENU_EXIT, &CMainFrame::OnTraymenuExit)
+	ON_MESSAGE(MSG_STATUS_BAR, &CMainFrame::OnMsgStatusBar)
+	ON_WM_CLOSE()
+END_MESSAGE_MAP()
+
+// CMainFrame 构造/析构
+
+CMainFrame::CMainFrame() noexcept :m_trayIcon(IDR_MAINFRAME)
+{
+	// TODO: 在此添加成员初始化代码
+	theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_VS_2008);
+#if USE_TRAYICON
+	m_isNotify = TRUE;
+	m_bNoticeTray = TRUE;
+#endif
+}
+
+CMainFrame::~CMainFrame()
+{
+}
+
+
+#if USE_TRAYICON
+void CMainFrame::InitTrayIcon()
+{
+	m_trayIcon.SetNotificationWnd(this, WM_MY_TRAY_NOTIFICATION);
+	m_trayIcon.SetIcon(IDR_MAINFRAME, _T("UB530"));
+	m_trayIcon.SetIconInfos(IDR_MAINFRAME, IDR_MAINFRAME, IDR_MAINFRAME);
+	m_trayIcon.SetDefaultTip(_T("UB530"));
+}
+
+LRESULT CMainFrame::OnTaskBarCreated(WPARAM wp, LPARAM lp)
+{
+	Shell_NotifyIcon(NIM_ADD, &m_trayIcon.m_nid);
+	return 0;
+}
+
+// Handle notification from tray icon: display a message.
+LRESULT CMainFrame::OnTrayNotification(WPARAM uID, LPARAM lEvent)
+{
+	if (m_isNotify)
+	{
+		static LPCSTR MouseMessages[] = { "WM_MOUSEMOVE",
+			"WM_LBUTTONDOWN", "WM_LBUTTONUP", "WM_LBUTTONDBLCLK",
+			"WM_RBUTTONDOWN", "WM_RBUTTONUP", "WM_RBUTTONDBLCLK",
+			"WM_MBUTTONDOWN", "WM_MBUTTONUP", "WM_MBUTTONDBLCLK" };
+	}
+
+	if (uID != IDR_MAINFRAME)
+		return m_trayIcon.OnTrayNotification(uID, lEvent);
+
+	switch (lEvent)
+	{
+	case WM_RBUTTONUP:
+		TrayRight();
+		break;
+	case WM_LBUTTONUP:
+		break;
+	case WM_LBUTTONDBLCLK:
+		TaskNotifyIcon();
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
+
+void CMainFrame::TrayRight()
+{
+	CMenu menu;
+	if (!menu.LoadMenu(IDR_MAINFRAME))
+		return;
+
+	CMenu* pSubMenu = menu.GetSubMenu(4);
+	if (!pSubMenu)
+		return;
+
+	CPoint point;
+	GetCursorPos(&point);
+	::SetForegroundWindow(m_hWnd);
+	pSubMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
+}
+
+void CMainFrame::TaskNotifyIcon()
+{
+	if (!m_bNoticeTray)
+	{
+		m_trayIcon.SetIcon(IDR_MAINFRAME, _T("UB530采集程序"));
+		ShowWindow(SW_SHOWNORMAL);
+		m_bNoticeTray = TRUE;
+	}
+	else
+	{
+		m_trayIcon.SetIcon(IDR_MAINFRAME, _T("UB530采集程序"));
+		ShowWindow(SW_HIDE);
+		m_bNoticeTray = FALSE;
+	}
+}
+#endif
+
+int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CFrameWndEx::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+#if USE_TRAYICON
+	InitTrayIcon();
+#endif
+
+	BOOL bNameValid;
+
+	m_wndRibbonBar.Create(this);
+	m_wndRibbonBar.LoadFromResource(IDR_RIBBON);
+
+#if !__QUICKACCESS_COMMAND__
+	// 添加以下代码段,禁用快速启动栏;
+	CMFCRibbonQuickAccessToolBar* pQAToolbar = m_wndRibbonBar.GetQuickAccessToolbar();
+	pQAToolbar->RemoveAll();
+#endif
+
+	if (!m_wndStatusBar.Create(this))
+	{
+		TRACE0("未能创建状态栏\n");
+		return -1;      // 未能创建
+	}
+
+	CString strTitlePane1;
+	CString strTitlePane2;
+	bNameValid = strTitlePane1.LoadString(IDS_STATUS_PANE1);
+	ASSERT(bNameValid);
+	bNameValid = strTitlePane2.LoadString(IDS_STATUS_PANE2);
+	ASSERT(bNameValid);
+	m_wndStatusBar.AddElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE1, strTitlePane1, TRUE), strTitlePane1);
+	m_wndStatusBar.AddExtendedElement(new CMFCRibbonStatusBarPane(ID_STATUSBAR_PANE2, strTitlePane2, TRUE), strTitlePane2);
+
+	// 启用 Visual Studio 2005 样式停靠窗口行为
+	CDockingManager::SetDockingMode(DT_SMART);
+	// 启用 Visual Studio 2005 样式停靠窗口自动隐藏行为
+	EnableAutoHidePanes(CBRS_ALIGN_ANY);
+
+#if __OUTLOOKBAR__
+	// 导航窗格将创建在左侧,因此将暂时禁用左侧的停靠: 
+	EnableDocking(CBRS_ALIGN_TOP | CBRS_ALIGN_BOTTOM | CBRS_ALIGN_RIGHT);
+
+	// 创建并设置“Outlook”导航栏: 
+	if (!CreateOutlookBar(m_wndNavigationBar, ID_VIEW_NAVIGATION, m_wndTree, m_wndCalendar, 250))
+	{
+		TRACE0("未能创建导航窗格\n");
+		return -1;      // 未能创建
+	}
+#endif
+
+#if __CAPTIONBAR__
+	// 创建标题栏: 
+	if (!CreateCaptionBar())
+	{
+		TRACE0("未能创建标题栏\n");
+		return -1;      // 未能创建
+	}
+#endif
+
+#if __OUTLOOKBAR__
+	// 已创建 Outlook 栏,应允许在左侧停靠。
+	EnableDocking(CBRS_ALIGN_LEFT);
+	EnableAutoHidePanes(CBRS_ALIGN_RIGHT);
+#endif
+	// 加载菜单项图像(不在任何标准工具栏上): 
+	CMFCToolBar::AddToolBarForImageCollection(IDR_MENU_IMAGES, theApp.m_bHiColorIcons ? IDB_MENU_IMAGES_24 : 0);
+
+#if __DOCKINGBAR__
+	// 创建停靠窗口
+	if (!CreateDockingWindows())
+	{
+		TRACE0("未能创建停靠窗口\n");
+		return -1;
+	}
+
+	m_wndFileView.EnableDocking(CBRS_ALIGN_ANY);
+	m_wndClassView.EnableDocking(CBRS_ALIGN_ANY);
+	DockPane(&m_wndFileView);
+	CDockablePane* pTabbedBar = nullptr;
+	m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
+	m_wndOutput.EnableDocking(CBRS_ALIGN_ANY);
+	DockPane(&m_wndOutput);
+	m_wndIRControl.EnableDocking(CBRS_ALIGN_ANY);
+	DockPane(&m_wndIRControl);
+#endif
+
+	// 基于持久值设置视觉管理器和样式
+	OnApplicationLook(theApp.m_nAppLook);
+
+	return 0;
+}
+
+BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
+{
+	if( !CFrameWndEx::PreCreateWindow(cs) )
+		return FALSE;
+	// TODO: 在此处通过修改
+	//  CREATESTRUCT cs 来修改窗口类或样式
+	//不把子框架标题添加到主框架标题(主框架中就不会再处理WM_SETTEXT消息)
+	cs.style &= ~FWS_ADDTOTITLE;
+
+	return TRUE;
+}
+
+#if __DOCKINGBAR__
+BOOL CMainFrame::CreateDockingWindows()
+{
+	BOOL bNameValid;
+
+	// 创建类视图
+	CString strClassView;
+	bNameValid = strClassView.LoadString(IDS_CLASS_VIEW);
+	ASSERT(bNameValid);
+	if (!m_wndClassView.Create(strClassView, this, CRect(0, 0, 200, 200), TRUE, ID_VIEW_CLASSVIEW, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI))
+	{
+		TRACE0("未能创建“类视图”窗口\n");
+		return FALSE; // 未能创建
+	}
+
+	// 创建文件视图
+	CString strFileView;
+	bNameValid = strFileView.LoadString(IDS_FILE_VIEW);
+	ASSERT(bNameValid);
+	if (!m_wndFileView.Create(strFileView, this, CRect(0, 0, 200, 200), TRUE, ID_VIEW_FILEVIEW, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT| CBRS_FLOAT_MULTI))
+	{
+		TRACE0("未能创建“文件视图”窗口\n");
+		return FALSE; // 未能创建
+	}
+
+	// 创建输出窗口
+	CString strOutputWnd;
+	bNameValid = strOutputWnd.LoadString(IDS_OUTPUT_WND);
+	ASSERT(bNameValid);
+	if (!m_wndOutput.Create(strOutputWnd, this, CRect(0, 0, 100, 100), TRUE, ID_VIEW_OUTPUTWND, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_BOTTOM | CBRS_FLOAT_MULTI))
+	{
+		TRACE0("未能创建输出窗口\n");
+		return FALSE; // 未能创建
+	}
+
+	// 创建遥控器窗口
+	CString strPropertiesWnd = _T("遥控器");
+	if (!m_wndIRControl.Create(strPropertiesWnd, this, CRect(0, 0, 350, 200), TRUE, ID_VIEW_PROPERTIESWND, 
+		WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_RIGHT | CBRS_FLOAT_MULTI , AFX_CBRS_REGULAR_TABS, AFX_CBRS_RESIZE))
+	{
+		TRACE0("未能创建“遥控器”窗口\n");
+		return FALSE; // 未能创建
+	}
+
+	SetDockingWindowIcons(theApp.m_bHiColorIcons);
+	return TRUE;
+}
+
+void CMainFrame::SetDockingWindowIcons(BOOL bHiColorIcons)
+{
+	HICON hFileViewIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(), MAKEINTRESOURCE(bHiColorIcons ? IDI_FILE_VIEW_HC : IDI_FILE_VIEW), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
+	m_wndFileView.SetIcon(hFileViewIcon, FALSE);
+
+	HICON hClassViewIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(), MAKEINTRESOURCE(bHiColorIcons ? IDI_CLASS_VIEW_HC : IDI_CLASS_VIEW), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
+	m_wndClassView.SetIcon(hClassViewIcon, FALSE);
+
+	HICON hOutputBarIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(), MAKEINTRESOURCE(bHiColorIcons ? IDI_OUTPUT_WND_HC : IDI_OUTPUT_WND), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
+	m_wndOutput.SetIcon(hOutputBarIcon, FALSE);
+
+	HICON hPropertiesBarIcon = (HICON) ::LoadImage(::AfxGetResourceHandle(), MAKEINTRESOURCE(bHiColorIcons ? IDI_PROPERTIES_WND_HC : IDI_PROPERTIES_WND), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), 0);
+	m_wndIRControl.SetIcon(hPropertiesBarIcon, FALSE);
+
+}
+#endif
+
+#if __OUTLOOKBAR__
+BOOL CMainFrame::CreateOutlookBar(CMFCOutlookBar& bar, UINT uiID, CMFCShellTreeCtrl& tree, CCalendarBar& calendar, int nInitialWidth)
+{
+	bar.SetMode2003();
+
+	BOOL bNameValid;
+	CString strTemp;
+	bNameValid = strTemp.LoadString(IDS_SHORTCUTS);
+	ASSERT(bNameValid);
+	if (!bar.Create(strTemp, this, CRect(0, 0, nInitialWidth, 32000), uiID, WS_CHILD | WS_VISIBLE | CBRS_LEFT))
+	{
+		return FALSE; // 未能创建
+	}
+
+	CMFCOutlookBarTabCtrl* pOutlookBar = (CMFCOutlookBarTabCtrl*)bar.GetUnderlyingWindow();
+
+	if (pOutlookBar == nullptr)
+	{
+		ASSERT(FALSE);
+		return FALSE;
+	}
+
+	pOutlookBar->EnableInPlaceEdit(TRUE);
+
+	static UINT uiPageID = 1;
+
+	// 可浮动,可自动隐藏,可调整大小,但不能关闭
+	DWORD dwStyle = AFX_CBRS_FLOAT | AFX_CBRS_AUTOHIDE | AFX_CBRS_RESIZE;
+
+	CRect rectDummy(0, 0, 0, 0);
+	const DWORD dwTreeStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
+
+	tree.Create(dwTreeStyle, rectDummy, &bar, 1200);
+	bNameValid = strTemp.LoadString(IDS_FOLDERS);
+	ASSERT(bNameValid);
+	pOutlookBar->AddControl(&tree, strTemp, 2, TRUE, dwStyle);
+
+	calendar.Create(rectDummy, &bar, 1201);
+	bNameValid = strTemp.LoadString(IDS_CALENDAR);
+	ASSERT(bNameValid);
+	pOutlookBar->AddControl(&calendar, strTemp, 3, TRUE, dwStyle);
+
+	bar.SetPaneStyle(bar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
+
+	pOutlookBar->SetImageList(theApp.m_bHiColorIcons ? IDB_PAGES_HC : IDB_PAGES, 24);
+	pOutlookBar->SetToolbarImageList(theApp.m_bHiColorIcons ? IDB_PAGES_SMALL_HC : IDB_PAGES_SMALL, 16);
+	pOutlookBar->RecalcLayout();
+
+	BOOL bAnimation = theApp.GetInt(_T("OutlookAnimation"), TRUE);
+	CMFCOutlookBarTabCtrl::EnableAnimation(bAnimation);
+
+	bar.SetButtonsFont(&afxGlobalData.fontBold);
+
+// 	bar.ShowCaret();
+// 	bar.ShowOwnedPopups();
+// 	bar.ShowPane(TRUE, FALSE, TRUE);
+// 	
+// 	bar.ShowWindow(SW_SHOW);
+
+	return TRUE;
+}
+#endif
+
+#if __CAPTIONBAR__
+BOOL CMainFrame::CreateCaptionBar()
+{
+	if (!m_wndCaptionBar.Create(WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, this, ID_VIEW_CAPTION_BAR, -1, TRUE))
+	{
+		TRACE0("未能创建标题栏\n");
+		return FALSE;
+	}
+
+	BOOL bNameValid;
+
+	CString strTemp, strTemp2;
+	bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON);
+	ASSERT(bNameValid);
+	m_wndCaptionBar.SetButton(strTemp, ID_TOOLS_OPTIONS, CMFCCaptionBar::ALIGN_LEFT, FALSE);
+	bNameValid = strTemp.LoadString(IDS_CAPTION_BUTTON_TIP);
+	ASSERT(bNameValid);
+	m_wndCaptionBar.SetButtonToolTip(strTemp);
+
+	bNameValid = strTemp.LoadString(IDS_CAPTION_TEXT);
+	ASSERT(bNameValid);
+	m_wndCaptionBar.SetText(strTemp, CMFCCaptionBar::ALIGN_LEFT);
+
+	m_wndCaptionBar.SetBitmap(IDB_INFO, RGB(255, 255, 255), FALSE, CMFCCaptionBar::ALIGN_LEFT);
+	bNameValid = strTemp.LoadString(IDS_CAPTION_IMAGE_TIP);
+	ASSERT(bNameValid);
+	bNameValid = strTemp2.LoadString(IDS_CAPTION_IMAGE_TEXT);
+	ASSERT(bNameValid);
+	m_wndCaptionBar.SetImageToolTip(strTemp, strTemp2);
+
+	return TRUE;
+}
+#endif
+
+// CMainFrame 诊断
+
+#ifdef _DEBUG
+void CMainFrame::AssertValid() const
+{
+	CFrameWndEx::AssertValid();
+}
+
+void CMainFrame::Dump(CDumpContext& dc) const
+{
+	CFrameWndEx::Dump(dc);
+}
+#endif //_DEBUG
+
+
+// CMainFrame 消息处理程序
+
+void CMainFrame::OnApplicationLook(UINT id)
+{
+	CWaitCursor wait;
+
+	theApp.m_nAppLook = id;
+
+	switch (theApp.m_nAppLook)
+	{
+	case ID_VIEW_APPLOOK_WIN_2000:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManager));
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_OFF_XP:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOfficeXP));
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_WIN_XP:
+		CMFCVisualManagerWindows::m_b3DTabsXPTheme = TRUE;
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_OFF_2003:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2003));
+		CDockingManager::SetDockingMode(DT_SMART);
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_VS_2005:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2005));
+		CDockingManager::SetDockingMode(DT_SMART);
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_VS_2008:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerVS2008));
+		CDockingManager::SetDockingMode(DT_SMART);
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+		break;
+
+	case ID_VIEW_APPLOOK_WINDOWS_7:
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows7));
+		CDockingManager::SetDockingMode(DT_SMART);
+		m_wndRibbonBar.SetWindows7Look(TRUE);
+		break;
+
+	default:
+		switch (theApp.m_nAppLook)
+		{
+		case ID_VIEW_APPLOOK_OFF_2007_BLUE:
+			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_LunaBlue);
+			break;
+
+		case ID_VIEW_APPLOOK_OFF_2007_BLACK:
+			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_ObsidianBlack);
+			break;
+
+		case ID_VIEW_APPLOOK_OFF_2007_SILVER:
+			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Silver);
+			break;
+
+		case ID_VIEW_APPLOOK_OFF_2007_AQUA:
+			CMFCVisualManagerOffice2007::SetStyle(CMFCVisualManagerOffice2007::Office2007_Aqua);
+			break;
+		}
+
+		CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerOffice2007));
+		CDockingManager::SetDockingMode(DT_SMART);
+		m_wndRibbonBar.SetWindows7Look(FALSE);
+	}
+
+#if __DOCKINGBAR__
+	m_wndOutput.UpdateFonts();
+#endif
+
+	RedrawWindow(nullptr, nullptr, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME | RDW_ERASE);
+
+	theApp.WriteInt(_T("ApplicationLook"), theApp.m_nAppLook);
+}
+
+void CMainFrame::OnUpdateApplicationLook(CCmdUI* pCmdUI)
+{
+	pCmdUI->SetRadio(theApp.m_nAppLook == pCmdUI->m_nID);
+}
+
+void CMainFrame::OnViewCaptionBar()
+{
+#if __CAPTIONBAR__
+	m_wndCaptionBar.ShowWindow(m_wndCaptionBar.IsVisible() ? SW_HIDE : SW_SHOW);
+	RecalcLayout(FALSE);
+#endif
+}
+
+void CMainFrame::OnUpdateViewCaptionBar(CCmdUI* pCmdUI)
+{
+#if __CAPTIONBAR__
+	pCmdUI->SetCheck(m_wndCaptionBar.IsVisible());
+#endif
+}
+
+void CMainFrame::OnOptions()
+{
+	CMFCRibbonCustomizeDialog *pOptionsDlg = new CMFCRibbonCustomizeDialog(this, &m_wndRibbonBar);
+	ASSERT(pOptionsDlg != nullptr);
+
+	pOptionsDlg->DoModal();
+	delete pOptionsDlg;
+}
+
+
+void CMainFrame::OnFilePrint()
+{
+	if (IsPrintPreview())
+	{
+		PostMessage(WM_COMMAND, AFX_ID_PREVIEW_PRINT);
+	}
+}
+
+void CMainFrame::OnFilePrintPreview()
+{
+	if (IsPrintPreview())
+	{
+		PostMessage(WM_COMMAND, AFX_ID_PREVIEW_CLOSE);  // 强制关闭“打印预览”模式
+	}
+}
+
+void CMainFrame::OnUpdateFilePrintPreview(CCmdUI* pCmdUI)
+{
+	pCmdUI->SetCheck(IsPrintPreview());
+}
+
+void CMainFrame::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
+{
+	CFrameWndEx::OnSettingChange(uFlags, lpszSection);
+#if __DOCKINGBAR__
+	m_wndOutput.UpdateFonts();
+#endif
+}
+
+LRESULT CMainFrame::OnMsgStatusBar(WPARAM wParam, LPARAM lParam)
+{
+	CString strMSG = *(CString*)wParam;
+	int uId = lParam;
+
+	SetRibbonStatusBarText(strMSG, uId);
+
+	return LRESULT();
+}
+
+
+BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
+{
+	// TODO: 在此添加专用代码和/或调用基类
+	static BOOL bTopWnd = FALSE;
+	if (pMsg->message == WM_KEYDOWN)
+	{
+		switch (pMsg->wParam)
+		{
+		case VK_F3:
+			if (bTopWnd == FALSE)
+			{
+				SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);//窗口置顶
+				SetWindowText(_T("视频采集卡-前置窗口(请按F3取消或开启前置)"));
+			}
+			else
+			{
+				SetWindowPos(&wndNoTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);//取消窗口置顶	
+				SetWindowText(_T("视频采集卡-取消前置(请按F3取消或开启前置)"));
+			}
+			bTopWnd = !bTopWnd;
+			break;
+		default:
+			break;
+		}
+	}
+	return CFrameWndEx::PreTranslateMessage(pMsg);
+}
+
+
+void CMainFrame::OnTraymenuExit()
+{
+	// TODO: 在此添加命令处理程序代码
+	//GetActiveView();
+	CFrameWnd::OnClose();
+}
+
+
+void CMainFrame::OnClose()
+{
+	// TODO: 在此添加消息处理程序代码和/或调用默认值
+#ifndef _DEBUG
+	ShowWindow(SW_HIDE);
+	m_bNoticeTray = FALSE;
+#else
+	CFrameWnd::OnClose();
+#endif
+}

+ 157 - 0
VideoCapture/VideoCapture/MainFrm.h

@@ -0,0 +1,157 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// MainFrm.h: CMainFrame 类的接口
+//
+
+#pragma once
+#include "FileView.h"
+#include "ClassView.h"
+#include "OutputWnd.h"
+#include "IRControlWnd.h"
+#include "CalendarBar.h"
+#include "Resource.h"
+#include "TrayIcon.h"
+#define USE_TRAYICON 1
+// 状态栏消息;
+#define MSG_STATUS_BAR (WM_USER + 101)
+
+class COutlookBar : public CMFCOutlookBar
+{
+	virtual BOOL AllowShowOnPaneMenu() const { return TRUE; }
+	virtual void GetPaneName(CString& strName) const { BOOL bNameValid = strName.LoadString(IDS_OUTLOOKBAR); ASSERT(bNameValid); if (!bNameValid) strName.Empty(); }
+};
+
+class CMainFrame : public CFrameWndEx
+{
+	
+protected: // 仅从序列化创建
+	CMainFrame() noexcept;
+	DECLARE_DYNCREATE(CMainFrame)
+
+// 特性
+public:
+
+// 操作
+public:
+
+// 重写
+public:
+	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+
+// 实现
+public:
+	virtual ~CMainFrame();
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:  // 控件条嵌入成员
+	CMFCRibbonBar     m_wndRibbonBar;
+	CMFCRibbonApplicationButton m_MainButton;
+	CMFCToolBarImages m_PanelImages;
+	CMFCRibbonStatusBar  m_wndStatusBar;
+#if __DOCKINGBAR__
+	CFileView         m_wndFileView;
+	CClassView        m_wndClassView;
+	COutputWnd        m_wndOutput;
+	CIRControlWnd     m_wndIRControl;
+#endif
+
+#if __OUTLOOKBAR__
+	COutlookBar       m_wndNavigationBar;
+	CMFCShellTreeCtrl m_wndTree;
+	CCalendarBar      m_wndCalendar;
+#endif
+
+#if __CAPTIONBAR__
+	CMFCCaptionBar    m_wndCaptionBar;
+#endif
+
+public:
+#if USE_TRAYICON
+	void InitTrayIcon();
+
+	// 托盘是否显示;
+	BOOL			m_isNotify;
+
+	// 启动程序时,隐藏或显示对话框,在消息处理程序OnNcPaint()中使用;
+	BOOL            m_bShowNc;
+
+	// 是否响应托盘消息;
+	BOOL            m_bNoticeTray;
+
+	// 托盘工作类;
+	ITrayIcon		m_trayIcon;
+	BOOL			m_bAutoRuning;
+
+	afx_msg LRESULT OnTrayNotification(WPARAM wp, LPARAM lp);
+	afx_msg LRESULT OnTaskBarCreated(WPARAM   wp, LPARAM   lp);
+	void TaskNotifyIcon();	// 托盘的工作内容;
+	void TrayRight();
+#endif
+
+	CMFCRibbonButton* GetRibbonButton(int uId) {
+		return DYNAMIC_DOWNCAST(CMFCRibbonButton, m_wndRibbonBar.FindByID(uId));
+	}
+
+	// 设置状态栏文本;
+	void SetRibbonStatusBarText(CString strText, int uId) {
+		if ( IsWindow(m_wndStatusBar) )
+		{
+			CMFCRibbonBaseElement *pElement = m_wndStatusBar.FindByID(uId);
+			if ( pElement )
+			{
+				pElement->SetText(strText);
+				pElement->Redraw();
+			}
+		}
+	}
+	// 生成的消息映射函数
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnApplicationLook(UINT id);
+	afx_msg void OnUpdateApplicationLook(CCmdUI* pCmdUI);
+	afx_msg void OnViewCaptionBar();
+	afx_msg void OnUpdateViewCaptionBar(CCmdUI* pCmdUI);
+	afx_msg void OnOptions();
+	afx_msg void OnFilePrint();
+	afx_msg void OnFilePrintPreview();
+	afx_msg void OnUpdateFilePrintPreview(CCmdUI* pCmdUI);
+	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+	afx_msg LRESULT OnMsgStatusBar(WPARAM wParam, LPARAM lParam);
+	DECLARE_MESSAGE_MAP()
+
+#if __DOCKINGBAR__
+	BOOL CreateDockingWindows();
+	void SetDockingWindowIcons(BOOL bHiColorIcons);
+#endif
+
+#if __OUTLOOKBAR__
+	BOOL CreateOutlookBar(CMFCOutlookBar& bar, UINT uiID, CMFCShellTreeCtrl& tree, CCalendarBar& calendar, int nInitialWidth);
+#endif
+
+#if __CAPTIONBAR__
+	BOOL CreateCaptionBar();
+#endif
+	int FindFocusedOutlookWnd(CMFCOutlookBarTabCtrl** ppOutlookWnd);
+
+	CMFCOutlookBarTabCtrl* FindOutlookParent(CWnd* pWnd);
+	CMFCOutlookBarTabCtrl* m_pCurrOutlookWnd;
+	CMFCOutlookBarPane*    m_pCurrOutlookPage;
+public:
+	virtual BOOL PreTranslateMessage(MSG* pMsg);
+	afx_msg void OnTraymenuExit();
+	afx_msg void OnClose();
+};
+
+

+ 338 - 0
VideoCapture/VideoCapture/MemoryClient.cpp

@@ -0,0 +1,338 @@
+#include "stdafx.h"
+#include "MemoryClient.h"
+#include "resource.h"
+#include <Shlwapi.h>
+#include "Global.h"
+#include "MainFrm.h"
+
+CVideoCaptureView* CMemoryClient::m_pView = NULL;
+HANDLE CMemoryClient::m_hRecordFile = NULL;
+HANDLE CMemoryClient::m_hThreadAudio = NULL;
+BOOL CMemoryClient::m_bCapture = FALSE;
+BOOL CMemoryClient::m_bIsConnect = FALSE;
+
+CMemoryClient::CMemoryClient(void)
+{
+	m_hThread = NULL;
+	m_hEvent = NULL;
+}
+
+CMemoryClient::~CMemoryClient(void)
+{
+	EndOfThread();
+}
+
+BOOL CMemoryClient::StartThread()
+{
+	// 创建事件对象;
+	if ( m_hEvent == NULL )
+		m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+	if ( m_hEvent == NULL )
+		return FALSE;
+
+	// 创建线程;
+	if ( m_hThread == NULL )
+	{
+		m_hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
+		if ( m_hThread == NULL )
+		{
+			CloseHandle(m_hEvent);
+			m_hEvent = NULL;
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+void CMemoryClient::EndOfThread()
+{
+	if ( m_hEvent )
+		SetEvent(m_hEvent);
+
+	if ( m_hThread )
+		WaitForSingleObject(m_hThread, INFINITE);
+
+	if (m_hThread) CloseHandle(m_hThread);
+	m_hThread = NULL;
+	if (m_hEvent) CloseHandle(m_hEvent);
+	m_hEvent = NULL;
+}
+
+DWORD CMemoryClient::ThreadProc(LPVOID lpVoid)
+{
+	CMemoryClient *pThis = (CMemoryClient*)lpVoid;
+	if ( pThis )
+	{
+		CommandHead cmdHead;
+		do 
+		{
+			// 读取内存信息;
+			pThis->Lock(INFINITE);
+			// 解析命令;
+			memcpy(&cmdHead, pThis->m_pMemory, sizeof(CommandHead));
+			// 获取设置命令;
+			if ( cmdHead.cmdFlag == 0x7F && cmdHead.cmdUser == TRUE )
+			{
+				switch( cmdHead.cmdType )
+				{
+					// 显示窗口;
+				case SHOW_APP:
+				{
+					CMainFrame* pFrameWnd = (CMainFrame*)m_pView->GetParentFrame();
+					pFrameWnd->ShowWindow(SW_SHOWNORMAL);
+					pFrameWnd->m_bNoticeTray = TRUE;
+					memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+				}
+					break;
+					// 隐藏窗口;
+				case HIDE_APP:
+				{
+					CMainFrame* pFrameWnd = (CMainFrame*)m_pView->GetParentFrame();
+					pFrameWnd->ShowWindow(SW_HIDE);
+					pFrameWnd->m_bNoticeTray = FALSE;
+					memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+				}
+					break;
+					// 连接设备;
+				case CONNECT_DEVICE:
+					{
+						CMD_Result result;
+						unsigned short nIndex = 0;
+						memcpy(&nIndex, ((BYTE*)pThis->m_pMemory) + sizeof(CommandHead), sizeof(unsigned short));
+						result.bResult = m_pView->HwInitialize();
+
+						// 返回结果;						
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));
+					}
+					break;
+					// 断开设备;
+				case DIS_CONNECT_DEVICE:
+					{
+						CMD_Result result;
+						unsigned short nIndex = 0;
+						memcpy(&nIndex, ((BYTE*)pThis->m_pMemory) + sizeof(CommandHead), sizeof(unsigned short));
+						result.bResult = m_pView->HwUninitialize();
+						m_pView->Invalidate();
+
+						// 返回结果;						
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));
+					}
+					break;
+					// 开始、停止流操作;
+				case START_STREAMING:
+				case STOP_STREAMING:
+					{
+						CMD_Result result;
+						BOOL bStartStreaming = TRUE;
+						memcpy(&bStartStreaming, ((BYTE*)pThis->m_pMemory) + sizeof(CommandHead), sizeof(BOOL));
+						if (bStartStreaming)
+							result.bResult = Startstreaming();
+						else
+							result.bResult = Stoptstreaming();
+
+						// 返回结果;
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));
+					}
+					break;
+					// 截图;
+				case CAPTURE_IMAGE_COUNT:
+				case CAPTURE_IMAGE_TIME:
+				case CAPTURE_IMAGE_SINGLE:
+					{
+						CMD_Result result;
+						CMD_CaputerImage cmd;
+						memcpy(&cmd, pThis->m_pMemory, sizeof(CMD_CaputerImage));
+						result.bResult = CaptureImage(cmd, cmd.bSingle = (cmdHead.cmdType == CAPTURE_IMAGE_SINGLE));
+
+						// 返回结果;
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));
+					}
+					break;
+					// 停止截图;
+				case STOP_CAPTUREIMAGE:
+					{// 停止截图;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+					}
+					break;
+					// 同步录频;
+				case SYN_CAPTURE_AUDIO:
+					{
+						CMD_Result result;
+						CMD_CaputerAudio cmd;
+						memcpy(&cmd, pThis->m_pMemory, sizeof(CMD_CaputerAudio));
+						
+						result.bResult = SynCaptureAudio(cmd);
+
+						// 返回结果;
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));						
+					}
+					break;
+					// 异步录频;
+				case ASY_CAPTURE_AUDIO:
+					{
+						CMD_Result result;
+						CMD_CaputerAudio cmd;
+						memcpy(&cmd, pThis->m_pMemory, sizeof(CMD_CaputerAudio));
+
+						result.bResult = AsyCaptureAudio(cmd);
+
+						// 返回结果;
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));						
+					}
+					break;
+					// 停止录屏;
+				case STOP_CAPTUREAUDIO:
+					if (m_hRecordFile != NULL)
+					{
+						CMD_Result result;
+						CMD_CaputerAudio cmd;
+						memcpy(&cmd, pThis->m_pMemory, sizeof(CMD_CaputerAudio));
+
+						result.bResult = StopCaptureAudio();
+
+						// 返回结果;
+						result.cmdHead = cmdHead;
+						result.cmdHead.cmdUser = FALSE;
+						memset(pThis->m_pMemory, 0, sizeof(MEMERY_SIZE));
+						memcpy(pThis->m_pMemory, &result, sizeof(CMD_Result));
+					}
+					break;
+				default:
+					break;
+				}
+			}
+			pThis->Unlock();
+		} while ( WaitForSingleObject(pThis->m_hEvent, 10) == WAIT_TIMEOUT);
+	}
+
+	return 0L;
+}
+
+// 异步线程;
+DWORD CMemoryClient::ThreadAsyAudio(LPVOID lpVoid)
+{
+	DWORD dwDuration = *(DWORD*)lpVoid;
+	
+	return 0L;
+}
+
+
+BOOL CMemoryClient::Startstreaming()
+{
+	
+	return TRUE;
+}
+
+BOOL CMemoryClient::Stoptstreaming()
+{
+
+	return TRUE;
+}
+
+BOOL CMemoryClient::CaptureImage(const CMD_CaputerImage& cmd, BOOL bSingle)
+{
+	BOOL bIsJPG = FALSE;
+	TString strFilePath = cmd.szSaveDir;
+	if ( cmd.dwImageType == 2 )
+		bIsJPG = TRUE;
+
+	if ( !bSingle )
+	{// 不是单张;
+		m_bCapture = TRUE;
+		if (!PathFileExists(cmd.szSaveDir))
+		{// 目录不存在,创建;
+			Global::MKDIR(cmd.szSaveDir);
+			if ( !PathFileExists(cmd.szSaveDir) )
+			{
+				// 创建目录失败,返回结果;
+				m_bCapture = FALSE;
+				return FALSE;
+			}
+		}
+
+		m_pView->CaptureMultiImageEx(cmd.szSaveDir, cmd.szPrefix, bIsJPG, cmd.nKeepTime);
+	}
+	else
+	{// 单张;
+		TString strFile = cmd.szSaveDir;
+		int nIndex = strFile.find_last_of(_T('\\'));
+		if ( TString::npos != nIndex )
+		{
+			Global::MKDIR(strFile.substr(0, nIndex).c_str());
+			if (!PathFileExists(strFile.substr(0, nIndex).c_str()))
+				return FALSE;
+		}
+		else
+		{
+			return FALSE;
+		}
+
+		if (cmd.IsAutoName)
+		{
+			nIndex = strFile.find_last_of(_T('.'));
+			if (nIndex != TString::npos)
+			{
+				nIndex = strFile.find_last_of(_T('\\'));
+				if (nIndex != TString::npos)
+					strFile = strFile.substr(0, nIndex + 1);
+				else
+					strFile.append(_T("\\"));
+			}
+			else
+			{
+				if (strFile.at(strFile.length() - 1) != _T('\\'))
+					strFile.append(_T("\\"));
+			}
+
+			m_pView->CaptureSingleImageAutoNameEx(strFile.c_str(), bIsJPG);
+		}
+		else
+		{
+			TCHAR szFile[MAX_PATH] = { 0 };
+			_stprintf_s(szFile, _T("%s"), cmd.szSaveDir);
+			m_pView->CaptureSingleImageEx(szFile, bIsJPG);
+		}
+		// 等待磁盘完成写入;
+		//Sleep(bIsJPG ? 200 : 200);
+	}
+
+	return TRUE;
+}
+
+BOOL CMemoryClient::SynCaptureAudio(const CMD_CaputerAudio& cmd)
+{
+
+	return TRUE;
+}
+
+BOOL CMemoryClient::AsyCaptureAudio(const CMD_CaputerAudio& cmd)
+{
+	m_pView->StartRecord(cmd.dwDuration, cmd.szSaveDir);
+	return TRUE;
+}
+
+BOOL CMemoryClient::StopCaptureAudio()
+{
+	m_pView->StopRecord();
+	return TRUE;
+}

+ 41 - 0
VideoCapture/VideoCapture/MemoryClient.h

@@ -0,0 +1,41 @@
+#ifndef __CD750_CLIENT__
+#define __CD750_CLIENT__
+
+#pragma once
+
+#include "MemoryDef.h"
+#include "MemoryComm.h"
+#include "VideoCaptureView.h"
+ class CVideoCaptureView;
+
+class CMemoryClient:public CMemoryComm
+{
+public:
+	CMemoryClient(void);
+	~CMemoryClient(void);
+
+private:
+	HANDLE m_hThread;
+	HANDLE m_hEvent;
+	static BOOL m_bCapture;
+	static BOOL m_bIsConnect;
+	static HANDLE m_hThreadAudio;
+public:
+	static CVideoCaptureView* m_pView;
+	static HANDLE m_hRecordFile;
+	BOOL StartThread();
+	void EndOfThread();
+	static DWORD WINAPI ThreadProc(LPVOID lpVoid);
+	static DWORD WINAPI ThreadAsyAudio(LPVOID lpVoid);
+	//static BOOL WINAPI NotifyEventCallback(DWORD dwEventCode, LPVOID lpEventData, LPVOID lpUserData);
+	//static void ModifyName(const CAPTUREIMAGE_NOTIFY_INFO* pCapImageNotifyInfo);
+private:
+	static BOOL CaptureImage(const CMD_CaputerImage& cmd, BOOL bSingle = TRUE);
+	static BOOL SynCaptureAudio(const CMD_CaputerAudio& cmd);
+	static BOOL AsyCaptureAudio(const CMD_CaputerAudio& cmd);
+	static BOOL StopCaptureAudio();
+	static BOOL Startstreaming();
+	static BOOL Stoptstreaming();
+};
+
+#endif // __CD750_CLIENT__

+ 139 - 0
VideoCapture/VideoCapture/MemoryComm.cpp

@@ -0,0 +1,139 @@
+#include "stdafx.h"
+#include "MemoryComm.h"
+#include "MemoryDef.h"
+
+CMemoryComm::CMemoryComm(void) :m_hLock(NULL),
+m_hFileMap(NULL),
+m_pMemory(NULL)
+{
+
+}
+
+CMemoryComm::~CMemoryComm(void)
+{
+	Close();
+	if (m_hLock != NULL)
+	{
+		CloseHandle(m_hLock);
+	}
+}
+
+
+CMemoryComm::CMemoryComm(const CMemoryComm& other)
+{
+	//if ( this != other)
+	//{
+	//	m_hLock = other.m_hLock;
+	//	m_hFileMap = other.m_hFileMap;
+	//	m_pMemory = other.m_pMemory;
+	//}
+}
+
+CMemoryComm& CMemoryComm::operator=(const CMemoryComm& other)
+{
+	// TODO: 在此处插入 return 语句
+	//if (this != other)
+	//{
+	//	m_hLock = other.m_hLock;
+	//	m_hFileMap = other.m_hFileMap;
+	//	m_pMemory = other.m_pMemory;
+	//}
+
+	return *this;
+}
+
+
+void CMemoryComm::Unmap()
+{
+	if (m_pMemory)
+	{
+		::UnmapViewOfFile(m_pMemory);
+		m_pMemory = NULL;
+	}
+}
+
+
+// 锁定共享内存
+BOOL CMemoryComm::Lock(DWORD dwTime)
+{
+	// 如果还没有创建锁就先创建一个
+	if (!m_hLock)
+	{
+		// 初始化的时候不被任何线程占用
+		m_hLock = ::CreateMutex(NULL, FALSE, MEMERY_NAME);
+		if (!m_hLock)
+			return FALSE;
+	}
+
+	// 哪个线程最先调用等待函数就最先占用这个互斥量
+	DWORD dwRet = ::WaitForSingleObject(m_hLock, dwTime);
+	return (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_ABANDONED);
+}
+
+void CMemoryComm::Unlock()
+{
+	if (m_hLock)
+	{
+		::ReleaseMutex(m_hLock);
+	}
+}
+
+void CMemoryComm::Close()
+{
+	Unmap();
+
+	if (m_hFileMap)
+	{
+		::CloseHandle(m_hFileMap);
+		m_hFileMap = NULL;
+	}
+}
+
+/************************************************************************/
+/*  函数:[7/3/2018 Wang];
+/*  描述:初始化共享内存,若已创建内存则打开;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+BOOL CMemoryComm::InitMemery(DWORD dwOffset /* = 0*/)
+{
+	if (m_hFileMap == NULL)
+	{
+		// 创建共享内存;
+		m_hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MEMERY_SIZE, MEMERY_NAME);
+		if (ERROR_ALREADY_EXISTS == GetLastError())
+		{
+			CloseHandle(m_hFileMap);
+			m_hFileMap = NULL;
+
+			// 打开共享内存;
+			m_hFileMap = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MEMERY_NAME);
+			if (!m_hFileMap)
+				return FALSE;
+		}
+	}
+
+	// 将内存映射出来;
+	if (m_pMemory == NULL)
+	{
+		ULARGE_INTEGER ui;
+		ui.QuadPart = static_cast<ULONGLONG>(dwOffset);
+		m_pMemory = ::MapViewOfFile(m_hFileMap, FILE_MAP_ALL_ACCESS, ui.HighPart, ui.LowPart, MEMERY_SIZE);
+		if (m_pMemory == NULL)
+		{
+			//ShowSystemErrorInfo(_T("映射内存失败"), GetLastError());
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}

+ 30 - 0
VideoCapture/VideoCapture/MemoryComm.h

@@ -0,0 +1,30 @@
+#ifndef __MEMORY_COMM_HEADER__
+#define __MEMORY_COMM_HEADER__
+
+#pragma once
+
+class CMemoryComm
+{
+public:
+	CMemoryComm(void);
+	~CMemoryComm(void);
+
+protected:
+	HANDLE m_hLock;
+	HANDLE m_hFileMap;
+	LPVOID m_pMemory;
+
+	CMemoryComm(const CMemoryComm& other);
+	CMemoryComm& operator = (const CMemoryComm& other);
+
+public:
+	BOOL InitMemery(DWORD dwOffset = 0);
+	void Unmap();
+	LPVOID GetMemory() const { return m_pMemory; }
+	HANDLE GetHandle() const { return m_hFileMap; }
+	BOOL Lock(DWORD dwTime);
+	void Unlock();
+	void Close();
+};
+
+#endif

+ 134 - 0
VideoCapture/VideoCapture/MemoryDef.h

@@ -0,0 +1,134 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [Wang], 保留所有权利;
+/*  模 块 名:内存共享C/S通信协议;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[Wang];
+/*  日    期:[7/4/2018];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[Wang];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+#ifndef __CD750_PROTO__
+#define __CD750_PROTO__
+
+// 命令类型;
+enum CommandType {
+	SHOW_APP,
+	HIDE_APP,
+	CONNECT_DEVICE,
+	DIS_CONNECT_DEVICE,
+	START_STREAMING,
+	STOP_STREAMING,
+	STOP_CAPTUREIMAGE,
+	CAPTURE_IMAGE_COUNT,
+	CAPTURE_IMAGE_TIME,
+	CAPTURE_IMAGE_SINGLE,
+	STOP_CAPTUREAUDIO,
+	SYN_CAPTURE_AUDIO,
+	ASY_CAPTURE_AUDIO
+};
+
+// 命令头;
+typedef struct COMMANDHAED{
+	unsigned short cmdFlag;		// 命令标识符;//固定:0x7F;
+	unsigned short cmdType;		// 命令类型;
+	BOOL  cmdUser;				// 命令者:C端=false,S端=true;
+	DWORD cmdCRC32;				// 对具体命令的crc32校验;//校验耗时,暂不做;
+
+	COMMANDHAED()
+	{
+		cmdFlag = 0x7F;
+		cmdType = 0;
+		cmdUser = TRUE;
+		cmdCRC32 = 0;
+	}
+	// 拷贝构造函数;
+	COMMANDHAED(const COMMANDHAED& other)
+	{
+		if (this != &other)
+		{
+			cmdFlag = other.cmdFlag;
+			cmdType = other.cmdType;
+			cmdUser = other.cmdUser;
+			cmdCRC32 = other.cmdCRC32;
+		}
+	}
+
+	// 赋值重载函数;
+	COMMANDHAED& operator = (const COMMANDHAED& other)
+	{
+		if (this != &other)
+		{
+			cmdFlag = other.cmdFlag;
+			cmdType = other.cmdType;
+			cmdUser = other.cmdUser;
+			cmdCRC32 = other.cmdCRC32;
+		}
+
+		return *this;
+	}
+}CommandHead,*pCommandHead;
+
+// 连接设备;
+typedef struct CMD_CONECTDEVICE {
+	CommandHead cmdHead;
+	unsigned short nIndex;		// 设备索引;
+}CMD_ConnectDevice, *pCMD_ConnectDevice;
+
+// 截图;
+typedef struct CMD_CAPUTERIMAGE{
+	// 命令头;
+	CommandHead cmdHead;
+	// 图片格式;
+	unsigned short dwImageType;
+	// 持续方式;//false=以张数为单位; true以秒为单位;
+	BOOL bContinuType;	
+	// 持续时间;
+	int nKeepTime;
+	// 每秒抓取张数;
+	int nCaputerCount;
+	// 保存路径;
+	TCHAR szSaveDir[MAX_PATH];
+	// 文件名前缀;
+	TCHAR szPrefix[64];
+	// 是否自动命名;
+	BOOL IsAutoName;
+	// 是否单张截图;
+	BOOL bSingle;
+}CMD_CaputerImage,*pCMD_CaputerImage;
+
+// 视屏保存;
+typedef struct CMD_CAPUTERAUDIO {
+	// 命令头;
+	CommandHead cmdHead;
+	// 录制时长//单位毫秒;
+	DWORD dwDuration;
+	// 保存路径;
+	TCHAR szSaveDir[MAX_PATH];
+}CMD_CaputerAudio,*pCMD_CaputerAudio;
+
+// 开始/停止流命令;
+typedef struct CMD_STREAMOPT{
+	CommandHead cmdHead;
+	BOOL bStartStreaming;
+}CMD_StreamOpt, *pCMD_StreamOpt;
+
+// 返回结果;
+typedef struct CMD_RESULT{
+	CommandHead cmdHead;
+	BOOL bResult;
+}CMD_Result,*pCMD_Result;
+
+// 共享内存名称;
+#define MEMERY_NAME _T("UB530#TCL#ShareMemery")
+// 共享内存的大小;
+#define MEMERY_SIZE 1024*8	//8k;
+
+#endif // __CD750_PROTO__

+ 210 - 0
VideoCapture/VideoCapture/OutputWnd.cpp

@@ -0,0 +1,210 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+
+#include "OutputWnd.h"
+#include "Resource.h"
+#include "MainFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// COutputBar
+
+COutputWnd::COutputWnd() noexcept
+{
+}
+
+COutputWnd::~COutputWnd()
+{
+}
+
+BEGIN_MESSAGE_MAP(COutputWnd, CDockablePane)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+END_MESSAGE_MAP()
+
+int COutputWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy;
+	rectDummy.SetRectEmpty();
+
+	// 创建选项卡窗口: 
+	if (!m_wndTabs.Create(CMFCTabCtrl::STYLE_FLAT, rectDummy, this, 1))
+	{
+		TRACE0("未能创建输出选项卡窗口\n");
+		return -1;      // 未能创建
+	}
+
+	// 创建输出窗格: 
+	const DWORD dwStyle = LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
+
+	if (!m_wndOutputBuild.Create(dwStyle, rectDummy, &m_wndTabs, 2) ||
+		!m_wndOutputDebug.Create(dwStyle, rectDummy, &m_wndTabs, 3) ||
+		!m_wndOutputFind.Create(dwStyle, rectDummy, &m_wndTabs, 4))
+	{
+		TRACE0("未能创建输出窗口\n");
+		return -1;      // 未能创建
+	}
+
+	UpdateFonts();
+
+	CString strTabName;
+	BOOL bNameValid;
+
+	// 将列表窗口附加到选项卡: 
+	bNameValid = strTabName.LoadString(IDS_BUILD_TAB);
+	ASSERT(bNameValid);
+	m_wndTabs.AddTab(&m_wndOutputBuild, strTabName, (UINT)0);
+	bNameValid = strTabName.LoadString(IDS_DEBUG_TAB);
+	ASSERT(bNameValid);
+	m_wndTabs.AddTab(&m_wndOutputDebug, strTabName, (UINT)1);
+	bNameValid = strTabName.LoadString(IDS_FIND_TAB);
+	ASSERT(bNameValid);
+	m_wndTabs.AddTab(&m_wndOutputFind, strTabName, (UINT)2);
+
+	// 使用一些虚拟文本填写输出选项卡(无需复杂数据)
+	FillBuildWindow();
+	FillDebugWindow();
+	FillFindWindow();
+
+	return 0;
+}
+
+void COutputWnd::OnSize(UINT nType, int cx, int cy)
+{
+	CDockablePane::OnSize(nType, cx, cy);
+
+	// 选项卡控件应覆盖整个工作区: 
+	m_wndTabs.SetWindowPos (nullptr, -1, -1, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+void COutputWnd::AdjustHorzScroll(CListBox& wndListBox)
+{
+	CClientDC dc(this);
+	CFont* pOldFont = dc.SelectObject(&afxGlobalData.fontRegular);
+
+	int cxExtentMax = 0;
+
+	for (int i = 0; i < wndListBox.GetCount(); i ++)
+	{
+		CString strItem;
+		wndListBox.GetText(i, strItem);
+
+		cxExtentMax = max(cxExtentMax, (int)dc.GetTextExtent(strItem).cx);
+	}
+
+	wndListBox.SetHorizontalExtent(cxExtentMax);
+	dc.SelectObject(pOldFont);
+}
+
+void COutputWnd::FillBuildWindow()
+{
+	m_wndOutputBuild.AddString(_T("生成输出正显示在此处。"));
+	m_wndOutputBuild.AddString(_T("输出正显示在列表视图的行中"));
+	m_wndOutputBuild.AddString(_T("但您可以根据需要更改其显示方式..."));
+}
+
+void COutputWnd::FillDebugWindow()
+{
+	m_wndOutputDebug.AddString(_T("调试输出正显示在此处。"));
+	m_wndOutputDebug.AddString(_T("输出正显示在列表视图的行中"));
+	m_wndOutputDebug.AddString(_T("但您可以根据需要更改其显示方式..."));
+}
+
+void COutputWnd::FillFindWindow()
+{
+	m_wndOutputFind.AddString(_T("查找输出正显示在此处。"));
+	m_wndOutputFind.AddString(_T("输出正显示在列表视图的行中"));
+	m_wndOutputFind.AddString(_T("但您可以根据需要更改其显示方式..."));
+}
+
+void COutputWnd::UpdateFonts()
+{
+	m_wndOutputBuild.SetFont(&afxGlobalData.fontRegular);
+	m_wndOutputDebug.SetFont(&afxGlobalData.fontRegular);
+	m_wndOutputFind.SetFont(&afxGlobalData.fontRegular);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// COutputList1
+
+COutputList::COutputList() noexcept
+{
+}
+
+COutputList::~COutputList()
+{
+}
+
+BEGIN_MESSAGE_MAP(COutputList, CListBox)
+	ON_WM_CONTEXTMENU()
+	ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
+	ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
+	ON_COMMAND(ID_VIEW_OUTPUTWND, OnViewOutput)
+	ON_WM_WINDOWPOSCHANGING()
+END_MESSAGE_MAP()
+/////////////////////////////////////////////////////////////////////////////
+// COutputList 消息处理程序
+
+void COutputList::OnContextMenu(CWnd* /*pWnd*/, CPoint point)
+{
+	CMenu menu;
+	menu.LoadMenu(IDR_OUTPUT_POPUP);
+
+	CMenu* pSumMenu = menu.GetSubMenu(0);
+
+	if (AfxGetMainWnd()->IsKindOf(RUNTIME_CLASS(CMDIFrameWndEx)))
+	{
+		CMFCPopupMenu* pPopupMenu = new CMFCPopupMenu;
+
+		if (!pPopupMenu->Create(this, point.x, point.y, (HMENU)pSumMenu->m_hMenu, FALSE, TRUE))
+			return;
+
+		((CMDIFrameWndEx*)AfxGetMainWnd())->OnShowPopupMenu(pPopupMenu);
+		UpdateDialogControls(this, FALSE);
+	}
+
+	SetFocus();
+}
+
+void COutputList::OnEditCopy()
+{
+	MessageBox(_T("复制输出"));
+}
+
+void COutputList::OnEditClear()
+{
+	MessageBox(_T("清除输出"));
+}
+
+void COutputList::OnViewOutput()
+{
+	CDockablePane* pParentBar = DYNAMIC_DOWNCAST(CDockablePane, GetOwner());
+	CMDIFrameWndEx* pMainFrame = DYNAMIC_DOWNCAST(CMDIFrameWndEx, GetTopLevelFrame());
+
+	if (pMainFrame != nullptr && pParentBar != nullptr)
+	{
+		pMainFrame->SetFocus();
+		pMainFrame->ShowPane(pParentBar, FALSE, FALSE, FALSE);
+		pMainFrame->RecalcLayout();
+
+	}
+}

+ 69 - 0
VideoCapture/VideoCapture/OutputWnd.h

@@ -0,0 +1,69 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// COutputList 窗口
+
+class COutputList : public CListBox
+{
+// 构造
+public:
+	COutputList() noexcept;
+
+// 实现
+public:
+	virtual ~COutputList();
+
+protected:
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+	afx_msg void OnEditCopy();
+	afx_msg void OnEditClear();
+	afx_msg void OnViewOutput();
+
+	DECLARE_MESSAGE_MAP()
+};
+
+class COutputWnd : public CDockablePane
+{
+// 构造
+public:
+	COutputWnd() noexcept;
+
+	void UpdateFonts();
+
+// 特性
+protected:
+	CMFCTabCtrl	m_wndTabs;
+
+	COutputList m_wndOutputBuild;
+	COutputList m_wndOutputDebug;
+	COutputList m_wndOutputFind;
+
+protected:
+	void FillBuildWindow();
+	void FillDebugWindow();
+	void FillFindWindow();
+
+	void AdjustHorzScroll(CListBox& wndListBox);
+
+// 实现
+public:
+	virtual ~COutputWnd();
+
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+
+	DECLARE_MESSAGE_MAP()
+};
+

+ 283 - 0
VideoCapture/VideoCapture/PropertiesWnd.cpp

@@ -0,0 +1,283 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+
+#include "PropertiesWnd.h"
+#include "Resource.h"
+#include "MainFrm.h"
+#include "VideoCapture.h"
+
+#ifdef _DEBUG
+#undef THIS_FILE
+static char THIS_FILE[]=__FILE__;
+#define new DEBUG_NEW
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CResourceViewBar
+
+CPropertiesWnd::CPropertiesWnd() noexcept
+{
+	m_nComboHeight = 0;
+}
+
+CPropertiesWnd::~CPropertiesWnd()
+{
+}
+
+BEGIN_MESSAGE_MAP(CPropertiesWnd, CDockablePane)
+	ON_WM_CREATE()
+	ON_WM_SIZE()
+	ON_COMMAND(ID_EXPAND_ALL, OnExpandAllProperties)
+	ON_UPDATE_COMMAND_UI(ID_EXPAND_ALL, OnUpdateExpandAllProperties)
+	ON_COMMAND(ID_SORTPROPERTIES, OnSortProperties)
+	ON_UPDATE_COMMAND_UI(ID_SORTPROPERTIES, OnUpdateSortProperties)
+	ON_COMMAND(ID_PROPERTIES1, OnProperties1)
+	ON_UPDATE_COMMAND_UI(ID_PROPERTIES1, OnUpdateProperties1)
+	ON_COMMAND(ID_PROPERTIES2, OnProperties2)
+	ON_UPDATE_COMMAND_UI(ID_PROPERTIES2, OnUpdateProperties2)
+	ON_WM_SETFOCUS()
+	ON_WM_SETTINGCHANGE()
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CResourceViewBar 消息处理程序
+
+void CPropertiesWnd::AdjustLayout()
+{
+	if (GetSafeHwnd () == nullptr || (AfxGetMainWnd() != nullptr && AfxGetMainWnd()->IsIconic()))
+	{
+		return;
+	}
+
+	CRect rectClient;
+	GetClientRect(rectClient);
+
+	int cyTlb = m_wndToolBar.CalcFixedLayout(FALSE, TRUE).cy;
+
+	m_wndObjectCombo.SetWindowPos(nullptr, rectClient.left, rectClient.top, rectClient.Width(), m_nComboHeight+200, SWP_NOACTIVATE | SWP_NOZORDER);
+	m_wndToolBar.SetWindowPos(nullptr, rectClient.left, rectClient.top + m_nComboHeight, rectClient.Width(), cyTlb, SWP_NOACTIVATE | SWP_NOZORDER);
+	m_wndPropList.SetWindowPos(nullptr, rectClient.left, rectClient.top + m_nComboHeight + cyTlb, rectClient.Width(), rectClient.Height() -(m_nComboHeight+cyTlb), SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+int CPropertiesWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CDockablePane::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy;
+	rectDummy.SetRectEmpty();
+
+	// 创建组合: 
+	const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_BORDER | CBS_SORT | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+	if (!m_wndObjectCombo.Create(dwViewStyle, rectDummy, this, 1))
+	{
+		TRACE0("未能创建属性组合 \n");
+		return -1;      // 未能创建
+	}
+
+	m_wndObjectCombo.AddString(_T("应用程序"));
+	m_wndObjectCombo.AddString(_T("属性窗口"));
+	m_wndObjectCombo.SetCurSel(0);
+
+	CRect rectCombo;
+	m_wndObjectCombo.GetClientRect (&rectCombo);
+
+	m_nComboHeight = rectCombo.Height();
+
+	if (!m_wndPropList.Create(WS_VISIBLE | WS_CHILD, rectDummy, this, 2))
+	{
+		TRACE0("未能创建属性网格\n");
+		return -1;      // 未能创建
+	}
+
+	InitPropList();
+
+	m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, IDR_PROPERTIES);
+	m_wndToolBar.LoadToolBar(IDR_PROPERTIES, 0, 0, TRUE /* 已锁定*/);
+	m_wndToolBar.CleanUpLockedImages();
+	m_wndToolBar.LoadBitmap(theApp.m_bHiColorIcons ? IDB_PROPERTIES_HC : IDR_PROPERTIES, 0, 0, TRUE /* 锁定*/);
+
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() | CBRS_TOOLTIPS | CBRS_FLYBY);
+	m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_TOP | CBRS_BORDER_BOTTOM | CBRS_BORDER_LEFT | CBRS_BORDER_RIGHT));
+	m_wndToolBar.SetOwner(this);
+
+	// 所有命令将通过此控件路由,而不是通过主框架路由: 
+	m_wndToolBar.SetRouteCommandsViaFrame(FALSE);
+
+	AdjustLayout();
+	return 0;
+}
+
+void CPropertiesWnd::OnSize(UINT nType, int cx, int cy)
+{
+	CDockablePane::OnSize(nType, cx, cy);
+	AdjustLayout();
+}
+
+void CPropertiesWnd::OnExpandAllProperties()
+{
+	m_wndPropList.ExpandAll();
+}
+
+void CPropertiesWnd::OnUpdateExpandAllProperties(CCmdUI* /* pCmdUI */)
+{
+}
+
+void CPropertiesWnd::OnSortProperties()
+{
+	m_wndPropList.SetAlphabeticMode(!m_wndPropList.IsAlphabeticMode());
+}
+
+void CPropertiesWnd::OnUpdateSortProperties(CCmdUI* pCmdUI)
+{
+	pCmdUI->SetCheck(m_wndPropList.IsAlphabeticMode());
+}
+
+void CPropertiesWnd::OnProperties1()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CPropertiesWnd::OnUpdateProperties1(CCmdUI* /*pCmdUI*/)
+{
+	// TODO: 在此处添加命令更新 UI 处理程序代码
+}
+
+void CPropertiesWnd::OnProperties2()
+{
+	// TODO: 在此处添加命令处理程序代码
+}
+
+void CPropertiesWnd::OnUpdateProperties2(CCmdUI* /*pCmdUI*/)
+{
+	// TODO: 在此处添加命令更新 UI 处理程序代码
+}
+
+void CPropertiesWnd::InitPropList()
+{
+	SetPropListFont();
+
+	m_wndPropList.EnableHeaderCtrl(FALSE);
+	m_wndPropList.EnableDescriptionArea();
+	m_wndPropList.SetVSDotNetLook();
+	m_wndPropList.MarkModifiedProperties();
+
+	CMFCPropertyGridProperty* pGroup1 = new CMFCPropertyGridProperty(_T("外观"));
+
+	pGroup1->AddSubItem(new CMFCPropertyGridProperty(_T("三维外观"), (_variant_t) false, _T("指定窗口的字体不使用粗体,并且控件将使用三维边框")));
+
+	CMFCPropertyGridProperty* pProp = new CMFCPropertyGridProperty(_T("边框"), _T("对话框外框"), _T("其中之一: “无”、“细”、“可调整大小”或“对话框外框”"));
+	pProp->AddOption(_T("无"));
+	pProp->AddOption(_T("细"));
+	pProp->AddOption(_T("可调整大小"));
+	pProp->AddOption(_T("对话框外框"));
+	pProp->AllowEdit(FALSE);
+
+	pGroup1->AddSubItem(pProp);
+	pGroup1->AddSubItem(new CMFCPropertyGridProperty(_T("标题"), (_variant_t) _T("关于"), _T("指定窗口标题栏中显示的文本")));
+
+	m_wndPropList.AddProperty(pGroup1);
+
+	CMFCPropertyGridProperty* pSize = new CMFCPropertyGridProperty(_T("窗口大小"), 0, TRUE);
+
+	pProp = new CMFCPropertyGridProperty(_T("高度"), (_variant_t) 250l, _T("指定窗口的高度"));
+	pProp->EnableSpinControl(TRUE, 50, 300);
+	pSize->AddSubItem(pProp);
+
+	pProp = new CMFCPropertyGridProperty( _T("宽度"), (_variant_t) 150l, _T("指定窗口的宽度"));
+	pProp->EnableSpinControl(TRUE, 50, 200);
+	pSize->AddSubItem(pProp);
+
+	m_wndPropList.AddProperty(pSize);
+
+	CMFCPropertyGridProperty* pGroup2 = new CMFCPropertyGridProperty(_T("字体"));
+
+	LOGFONT lf;
+	CFont* font = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
+	font->GetLogFont(&lf);
+
+	_tcscpy_s(lf.lfFaceName, _T("宋体, Arial"));
+
+	pGroup2->AddSubItem(new CMFCPropertyGridFontProperty(_T("字体"), lf, CF_EFFECTS | CF_SCREENFONTS, _T("指定窗口的默认字体")));
+	pGroup2->AddSubItem(new CMFCPropertyGridProperty(_T("使用系统字体"), (_variant_t) true, _T("指定窗口使用“MS Shell Dlg”字体")));
+
+	m_wndPropList.AddProperty(pGroup2);
+
+	CMFCPropertyGridProperty* pGroup3 = new CMFCPropertyGridProperty(_T("杂项"));
+	pProp = new CMFCPropertyGridProperty(_T("(名称)"), _T("应用程序"));
+	pProp->Enable(FALSE);
+	pGroup3->AddSubItem(pProp);
+
+	CMFCPropertyGridColorProperty* pColorProp = new CMFCPropertyGridColorProperty(_T("窗口颜色"), RGB(210, 192, 254), nullptr, _T("指定默认的窗口颜色"));
+	pColorProp->EnableOtherButton(_T("其他..."));
+	pColorProp->EnableAutomaticButton(_T("默认"), ::GetSysColor(COLOR_3DFACE));
+	pGroup3->AddSubItem(pColorProp);
+
+	static const TCHAR szFilter[] = _T("图标文件(*.ico)|*.ico|所有文件(*.*)|*.*||");
+	pGroup3->AddSubItem(new CMFCPropertyGridFileProperty(_T("图标"), TRUE, _T(""), _T("ico"), 0, szFilter, _T("指定窗口图标")));
+
+	pGroup3->AddSubItem(new CMFCPropertyGridFileProperty(_T("文件夹"), _T("c:\\")));
+
+	m_wndPropList.AddProperty(pGroup3);
+
+	CMFCPropertyGridProperty* pGroup4 = new CMFCPropertyGridProperty(_T("层次结构"));
+
+	CMFCPropertyGridProperty* pGroup41 = new CMFCPropertyGridProperty(_T("第一个子级"));
+	pGroup4->AddSubItem(pGroup41);
+
+	CMFCPropertyGridProperty* pGroup411 = new CMFCPropertyGridProperty(_T("第二个子级"));
+	pGroup41->AddSubItem(pGroup411);
+
+	pGroup411->AddSubItem(new CMFCPropertyGridProperty(_T("项 1"), (_variant_t) _T("值 1"), _T("此为说明")));
+	pGroup411->AddSubItem(new CMFCPropertyGridProperty(_T("项 2"), (_variant_t) _T("值 2"), _T("此为说明")));
+	pGroup411->AddSubItem(new CMFCPropertyGridProperty(_T("项 3"), (_variant_t) _T("值 3"), _T("此为说明")));
+
+	pGroup4->Expand(FALSE);
+	m_wndPropList.AddProperty(pGroup4);
+}
+
+void CPropertiesWnd::OnSetFocus(CWnd* pOldWnd)
+{
+	CDockablePane::OnSetFocus(pOldWnd);
+	m_wndPropList.SetFocus();
+}
+
+void CPropertiesWnd::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
+{
+	CDockablePane::OnSettingChange(uFlags, lpszSection);
+	SetPropListFont();
+}
+
+void CPropertiesWnd::SetPropListFont()
+{
+	::DeleteObject(m_fntPropList.Detach());
+
+	LOGFONT lf;
+	afxGlobalData.fontRegular.GetLogFont(&lf);
+
+	NONCLIENTMETRICS info;
+	info.cbSize = sizeof(info);
+
+	afxGlobalData.GetNonClientMetrics(info);
+
+	lf.lfHeight = info.lfMenuFont.lfHeight;
+	lf.lfWeight = info.lfMenuFont.lfWeight;
+	lf.lfItalic = info.lfMenuFont.lfItalic;
+
+	m_fntPropList.CreateFontIndirect(&lf);
+
+	m_wndPropList.SetFont(&m_fntPropList);
+	m_wndObjectCombo.SetFont(&m_fntPropList);
+}

+ 72 - 0
VideoCapture/VideoCapture/PropertiesWnd.h

@@ -0,0 +1,72 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+class CPropertiesToolBar : public CMFCToolBar
+{
+public:
+	virtual void OnUpdateCmdUI(CFrameWnd* /*pTarget*/, BOOL bDisableIfNoHndler)
+	{
+		CMFCToolBar::OnUpdateCmdUI((CFrameWnd*) GetOwner(), bDisableIfNoHndler);
+	}
+
+	virtual BOOL AllowShowOnList() const { return FALSE; }
+};
+
+class CPropertiesWnd : public CDockablePane
+{
+// 构造
+public:
+	CPropertiesWnd() noexcept;
+
+	void AdjustLayout();
+
+// 特性
+public:
+	void SetVSDotNetLook(BOOL bSet)
+	{
+		m_wndPropList.SetVSDotNetLook(bSet);
+		m_wndPropList.SetGroupNameFullWidth(bSet);
+	}
+
+protected:
+	CFont m_fntPropList;
+	CComboBox m_wndObjectCombo;
+	CPropertiesToolBar m_wndToolBar;
+	CMFCPropertyGridCtrl m_wndPropList;
+
+// 实现
+public:
+	virtual ~CPropertiesWnd();
+
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnExpandAllProperties();
+	afx_msg void OnUpdateExpandAllProperties(CCmdUI* pCmdUI);
+	afx_msg void OnSortProperties();
+	afx_msg void OnUpdateSortProperties(CCmdUI* pCmdUI);
+	afx_msg void OnProperties1();
+	afx_msg void OnUpdateProperties1(CCmdUI* pCmdUI);
+	afx_msg void OnProperties2();
+	afx_msg void OnUpdateProperties2(CCmdUI* pCmdUI);
+	afx_msg void OnSetFocus(CWnd* pOldWnd);
+	afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);
+
+	DECLARE_MESSAGE_MAP()
+
+	void InitPropList();
+	void SetPropListFont();
+
+	int m_nComboHeight;
+};
+

+ 2837 - 0
VideoCapture/VideoCapture/QCAP.H

@@ -0,0 +1,2837 @@
+#ifndef QCAP_H
+#define QCAP_H
+
+#ifdef BUILD_QCAP_DLL
+
+#define QCAP_EXT_API __declspec(dllexport) 
+
+#else 
+
+#define QCAP_EXT_API __declspec(dllimport) 
+#endif
+
+#ifdef _QCAP_VB_EXPORT
+
+#define QCAP_EXPORT __stdcall
+
+#else // _QCAP_VB_EXPORT
+
+#define QCAP_EXPORT __cdecl
+
+#endif // _QCAP_VB_EXPORT
+
+// LABVIEW 2010/2012 SUPPORT
+// 
+#ifdef _QCAP_LABVIEW_IMPORT
+
+#define QCAP_EXT_API __declspec(dllimport)
+
+#define QCAP_EXPORT __cdecl
+
+typedef void VOID;
+
+typedef void * PVOID;
+ 
+typedef unsigned int UINT;
+
+typedef unsigned long ULONG;
+
+typedef unsigned long DWORD;
+
+typedef unsigned long long ULONGLONG;
+
+typedef char CHAR;
+
+typedef unsigned char BYTE;
+
+#endif // _QCAP_LABVIEW_IMPORT
+
+typedef unsigned short * WSTRING;
+
+// RESULT OF FUNCTION
+//
+typedef enum {
+
+	QCAP_RS_SUCCESSFUL								= 0x00000000,
+
+	QCAP_RS_ERROR_GENERAL							= 0x00000001,
+
+	QCAP_RS_ERROR_OUT_OF_MEMORY						= 0x00000002,
+
+	QCAP_RS_ERROR_OUT_OF_RESOURCE					= 0x00000003,
+
+	QCAP_RS_ERROR_INVALID_DEVICE					= 0x00000004,
+
+	QCAP_RS_ERROR_INVALID_PARAMETER					= 0x00000005,
+
+	QCAP_RS_ERROR_NON_SUPPORT						= 0x00000006,
+
+	QCAP_RS_ERROR_TIMEOUT							= 0x00000007,
+
+	QCAP_RS_ERROR_INVALID_ANIMATION_SCRIPT			= 0x00000008,
+
+	QCAP_RS_ERROR_NO_SIGNAL_DETECTED				= 0x00000009,
+
+	QCAP_RS_ERROR_NEED_MORE_DATA					= 0x0000000A,
+
+	QCAP_RS_ERROR_CONNECT_FAIL						= 0x0000000B,
+
+	QCAP_RS_ERROR_FILE_ACCESS_FAIL					= 0x0000000C,
+
+	QCAP_RS_ERROR_NETWORK_ACCESS_FAIL				= 0x0000000D,
+
+	QCAP_RS_ERROR_FILE_IS_BOX_MOVED					= 0x0000000E,
+
+	QCAP_RS_ERROR_FRAME_IS_COPIED					= 0x0000000F,
+
+	QCAP_RS_ERROR_VIDEO_ENCODER_ACCESS_FAIL			= 0x00000010,
+
+	QCAP_RS_ERROR_AUDIO_ENCODER_ACCESS_FAIL			= 0x00000011,
+
+	QCAP_RS_ERROR_NETWORK_CONNECT_UNKNOWN_FAIL		= 0x80000000,
+
+	QCAP_RS_ERROR_NETWORK_CONNECT_URL_FAIL			= 0x80000001,
+
+	QCAP_RS_ERROR_NETWORK_CONNECT_PASSWORD_FAIL		= 0x80000002,
+
+	QCAP_RS_ERROR_NETWORK_CONNECT_SESSION_NAME_FAIL = 0x80000003,
+
+} QRESULT;
+
+// RETURN OF CALLBACK
+//
+typedef enum {
+
+	QCAP_RT_OK					= 0x00000000,
+	
+	QCAP_RT_FAIL				= 0x00000001,
+
+	QCAP_RT_SKIP_RECORD_NUM_00	= 0x00010002, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_SKIP_RECORD_NUM_01	= 0x00020002, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_SKIP_RECORD_NUM_02	= 0x00040002, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_SKIP_RECORD_NUM_03	= 0x00080002, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_SKIP_DISPLAY		= 0x00000004, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK / 
+											  //
+											  //		  PF_VIDEO_BROADCAST_CLIENT_CALLBACK / PF_AUDIO_BROADCAST_CLIENT_CALLBACK / 
+											  //
+											  //		  PF_VIDEO_DECODER_BROADCAST_CLIENT_CALLBACK / PF_AUDIO_DECODER_BROADCAST_CLIENT_CALLBACK /
+											  //
+											  //		  PF_VIDEO_DECODER_FILE_CALLBACK / PF_AUDIO_DECODER_FILE_CALLBACK
+											  
+	QCAP_RT_SKIP_CLONE_DISPLAY	= 0x00000008, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_RESET_RECORD_NUM_00	= 0x01000010, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_RESET_RECORD_NUM_01	= 0x02000010, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_RESET_RECORD_NUM_02	= 0x04000010, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+	QCAP_RT_RESET_RECORD_NUM_03	= 0x08000010, // ONLY FOR PF_VIDEO_PREVIEW_CALLBACK / PF_AUDIO_PREVIEW_CALLBACK
+
+} QRETURN;
+
+// DEVICE ENUMERATION TYPE
+//
+enum {
+
+	QCAP_ENUM_TYPE_DEVICE_NAME		= 0,
+
+	QCAP_ENUM_TYPE_SERIAL_NUMBER	= 1,
+};
+
+// INPUT VIDEO SOURCE
+//
+enum {
+
+	QCAP_INPUT_TYPE_COMPOSITE	 = 0,
+
+	QCAP_INPUT_TYPE_SVIDEO		 = 1,
+
+	QCAP_INPUT_TYPE_HDMI		 = 2,
+
+	QCAP_INPUT_TYPE_DVI_D		 = 3,
+
+	QCAP_INPUT_TYPE_COMPONENTS	 = 4,
+
+	QCAP_INPUT_TYPE_YCBCR		 = 4,
+
+	QCAP_INPUT_TYPE_DVI_A		 = 5,
+
+	QCAP_INPUT_TYPE_RGB			 = 5,
+
+	QCAP_INPUT_TYPE_VGA			 = 5,
+
+	QCAP_INPUT_TYPE_SDI			 = 6,
+
+	QCAP_INPUT_TYPE_DISPLAY_PORT = 8,
+
+	QCAP_INPUT_TYPE_AUTO		 = 7,
+};
+
+// INPUT AUDIO SOURCE
+//
+enum {	
+
+	QCAP_INPUT_TYPE_EMBEDDED_AUDIO			= 0,
+
+	QCAP_INPUT_TYPE_LINE_IN					= 1,
+
+	QCAP_INPUT_TYPE_SOUNDCARD_MICROPHONE	= 2,
+
+	QCAP_INPUT_TYPE_SOUNDCARD_LINE_IN		= 3,
+};
+
+// VIDEO STANDARD TYPE
+//
+enum {	
+
+	QCAP_STANDARD_TYPE_NTSC_M		= 0x00000001,
+
+	QCAP_STANDARD_TYPE_NTSC_M_J		= 0x00000002,
+
+	QCAP_STANDARD_TYPE_NTSC_433		= 0x00000004,
+
+	QCAP_STANDARD_TYPE_PAL_M		= 0x00000200,
+
+	QCAP_STANDARD_TYPE_PAL_60		= 0x00000800,
+
+	QCAP_STANDARD_TYPE_PAL_B		= 0x00000010,
+
+	QCAP_STANDARD_TYPE_PAL_D		= 0x00000020,
+
+	QCAP_STANDARD_TYPE_PAL_G		= 0x00000040,
+
+	QCAP_STANDARD_TYPE_PAL_H		= 0x00000080,
+
+	QCAP_STANDARD_TYPE_PAL_I		= 0x00000100,
+
+	QCAP_STANDARD_TYPE_PAL_N		= 0x00000400,
+
+	QCAP_STANDARD_TYPE_PAL_N_COMBO	= 0x00100000,
+
+	QCAP_STANDARD_TYPE_AUTO			= 0x80000000, // DEFAULT, [P.S. SC310N8/N16            (CX2581 PCI) DON'T SUPPORT AUTO STANDARD DETECTION]
+												  //
+												  //		  [P.S. SC290N4/SC390N4/N8/N16 (AH8400 PCI) DON'T SUPPORT AUTO STANDARD DETECTION]
+												  //
+												  //		  [P.S. SC2B0N4/SC3B0N4/N8/N16 (TW5864 PCI) DON'T SUPPORT AUTO STANDARD DETECTION]
+												  //
+												  //		  [P.S. SC3A0N4/N8/N16         (FH8735 PCI) DON'T SUPPORT AUTO STANDARD DETECTION]
+												  //
+												  //		  [P.S. SC3C0N4/N8/N16         (MZ0380 PCI) DON'T SUPPORT AUTO STANDARD DETECTION]
+};
+
+// VIDEO DEINTERLACE TYPE
+//
+enum {	
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_BLENDING			    = 0x00000000, // DEFAULT
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_MOTION_ADAPTIVE	    = 0x00000001,
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_FILTER_TRIANGLE	    = 0x00000002,
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_BOB				    = 0x00000003,
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_ADVANCED_3D_ADAPTIVE = 0x00000004,
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_BEST_QUALITY         = 0x00000004,
+
+	QCAP_SOFTWARE_DEINTERLACE_TYPE_MEDICAL_RGB_REPACK   = 0x00000010, // BEST QUALITY FOR OLYMPUS RGB ENDOSCOPY
+};
+
+// COLORRANGE TYPE
+//
+enum {
+
+	QCAP_COLORRANGE_TYPE_FULL		        =  0, //  0 ~ 255 (ITU BT.709 )
+
+	QCAP_COLORRANGE_TYPE_LIMIT		        =  1, // 16 ~ 235 (ITU BT.709 )
+
+	QCAP_COLORRANGE_TYPE_FULL_BGR32	        =  2, //  0 ~ 255 (ITU BT.709 ) (RENDERER @ RGB32) 
+
+	QCAP_COLORRANGE_TYPE_LIMIT_BGR32        =  3, // 16 ~ 235 (ITU BT.709 ) (RENDERER @ RGB32) 
+
+//	QCAP_COLORRANGE_TYPE_BT0709_FULL		=  0, //  0 ~ 255 (ITU BT.709 )
+//
+//	QCAP_COLORRANGE_TYPE_BT0709_LIMIT		=  1, // 16 ~ 235 (ITU BT.709 )
+//
+//	QCAP_COLORRANGE_TYPE_BT0709_FULL_BGR32	=  2, //  0 ~ 255 (ITU BT.709 ) (RENDERER @ RGB32) 
+//
+//	QCAP_COLORRANGE_TYPE_BT0709_LIMIT_BGR32 =  3, // 16 ~ 235 (ITU BT.709 ) (RENDERER @ RGB32) 
+
+	QCAP_COLORRANGE_TYPE_BT0601_LIMIT       =  5, // 16 ~ 235 (ITU BT.601 )
+ 
+	QCAP_COLORRANGE_TYPE_BT0601_LIMIT_BGR32 =  7, // 16 ~ 235 (ITU BT.601 ) (RENDERER @ RGB32)
+
+	QCAP_COLORRANGE_TYPE_BT2020_FULL        =  8, //  0 ~ 255 (ITU BT.2020)
+
+	QCAP_COLORRANGE_TYPE_BT2020_LIMIT       =  9, // 16 ~ 235 (ITU BT.2020)
+
+	QCAP_COLORRANGE_TYPE_BT2020_FULL_BGR32  = 10, //  0 ~ 255 (ITU BT.2020) (RENDERER @ RGB32)
+
+	QCAP_COLORRANGE_TYPE_BT2020_LIMIT_BGR32 = 11, // 16 ~ 235 (ITU BT.2020) (RENDERER @ RGB32)
+};
+
+// COLORSPACE TYPE
+//
+enum {
+
+	QCAP_COLORSPACE_TYPE_RGB24	= 0,		  //   0xBBGGRR -> R0 G0 B0 R1 G1 B1 R2 G2 B2 ... >>
+	QCAP_COLORSPACE_TYEP_RGB24	= 0,
+
+	QCAP_COLORSPACE_TYPE_BGR24	= 1,		  //   0xRRGGBB -> B0 G0 R0 B1 G1 R1 B2 G2 R2 ... >>
+	QCAP_COLORSPACE_TYEP_BGR24	= 1,
+
+	QCAP_COLORSPACE_TYPE_ARGB32	= 2,		  // 0xAABBGGRR -> R0 G0 B0 A0 R1 G1 B1 A1 R2 G2 B2 A2 ... >>
+	QCAP_COLORSPACE_TYEP_ARGB32	= 2,
+
+	QCAP_COLORSPACE_TYPE_ABGR32	= 3,		  // 0xAARRGGBB -> B0 G0 R0 A0 B1 G1 R1 A1 B2 G2 R2 A2 ... >>
+	QCAP_COLORSPACE_TYEP_ABGR32	= 3,
+
+	QCAP_COLORSPACE_TYPE_YUY2	= 0x32595559, // 0x32595559 -> MAKEFOURCC('Y', 'U', 'Y', '2')
+	QCAP_COLORSPACE_TYEP_YUY2	= 0x32595559,
+
+	QCAP_COLORSPACE_TYPE_UYVY	= 0x59565955, // 0x59565955 -> MAKEFOURCC('U', 'Y', 'V', 'Y')
+	QCAP_COLORSPACE_TYEP_UYVY	= 0x59565955,
+
+	QCAP_COLORSPACE_TYPE_YV12	= 0x32315659, // 0x32315659 -> MAKEFOURCC('Y', 'V', '1', '2') (Y V U)
+	QCAP_COLORSPACE_TYEP_YV12	= 0x32315659,
+
+	QCAP_COLORSPACE_TYPE_I420	= 0x30323449, // 0x30323449 -> MAKEFOURCC('I', '4', '2', '0') (Y U V)
+	QCAP_COLORSPACE_TYEP_I420	= 0x30323449,
+
+	QCAP_COLORSPACE_TYPE_NV12	= 0x3231564E, // 0x3231564E -> MAKEFOURCC('N', 'V', '1', '2')
+	QCAP_COLORSPACE_TYEP_NV12	= 0x3231564E,
+
+	QCAP_COLORSPACE_TYPE_Y800	= 0x30303859, // 0x30303859 -> MAKEFOURCC('Y', '8', '0', '0') -> Y
+	QCAP_COLORSPACE_TYEP_Y800	= 0x30303859,
+
+	QCAP_COLORSPACE_TYPE_MJPG	= 0x47504A4D, // 0x47504A4D -> MAKEFOURCC('M', 'J', 'P', 'G')
+	QCAP_COLORSPACE_TYEP_MJPG	= 0x47504A4D,
+
+	QCAP_COLORSPACE_TYPE_H264	= 0x34363248, // 0x34363248 -> MAKEFOURCC('H', '2', '6', '4')
+	QCAP_COLORSPACE_TYEP_H264	= 0x34363248,
+
+	QCAP_COLORSPACE_TYPE_H265	= 0x35363248, // 0x35363248 -> MAKEFOURCC('H', '2', '6', '5')
+	QCAP_COLORSPACE_TYEP_H265	= 0x35363248,
+
+	QCAP_COLORSPACE_TYPE_MPG2	= 0x3247504D, // 0x3247504D -> MAKEFOURCC('M', 'P', 'G', '2')
+	QCAP_COLORSPACE_TYEP_MPG2	= 0x3247504D,
+};
+
+// ENCODER TYPE (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_ENCODER_TYPE_SOFTWARE			= 0,
+
+	QCAP_ENCODER_TYPE_HARDWARE			= 1, // IT IS ONLY USED FOR HARDWARE COMPRESSION CAPTURE CARD, SUCH AS SC580 & SC590 & SC5A0 & SC5C0
+
+	QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK	= 2,
+
+	QCAP_ENCODER_TYPE_AMD_VCE			= 3,
+
+	QCAP_ENCODER_TYPE_NVIDIA_CUDA		= 4,
+
+	QCAP_ENCODER_TYPE_NVIDIA_NVENC		= 5,
+};
+
+// ENCODER VIDEO FORMAT (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_ENCODER_FORMAT_MPEG2		=  1,
+
+	QCAP_ENCODER_FORMAT_H264		=  0,
+
+	QCAP_ENCODER_FORMAT_H264_3D		=  2, // H264 MVC (STEREOSCOPIC 3D)
+
+	QCAP_ENCODER_FORMAT_H264_VC		=  3, // H264 SVC (MULTIPLE TEMPORAL SCALABILITY)
+
+	QCAP_ENCODER_FORMAT_RAW			=  4,
+
+	QCAP_ENCODER_FORMAT_RAW_NATIVE	=  4,
+
+	QCAP_ENCODER_FORMAT_H265		=  5,
+
+	QCAP_ENCODER_FORMAT_RAW_YUY2	= 20,
+
+	QCAP_ENCODER_FORMAT_RAW_UYVY	= 21, // DEVELOPING ...
+
+	QCAP_ENCODER_FORMAT_RAW_YV12	= 22,
+
+	QCAP_ENCODER_FORMAT_RAW_I420	= 23,
+
+	QCAP_ENCODER_FORMAT_RAW_NV12	= 25,
+
+	QCAP_ENCODER_FORMAT_RAW_Y800	= 24,
+};
+
+// ENCODER AUDIO FORMAT (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_ENCODER_FORMAT_PCM			= 0,
+
+	QCAP_ENCODER_FORMAT_AAC			= 1,
+
+	QCAP_ENCODER_FORMAT_AAC_RAW		= 1,
+
+	QCAP_ENCODER_FORMAT_AAC_ADTS	= 2,
+
+	QCAP_ENCODER_FORMAT_MP2			= 4, // MPEG AUDIO LAYER 2
+
+	QCAP_ENCODER_FORMAT_MP3			= 5, // MPEG AUDIO LAYER 3
+
+	QCAP_ENCODER_FORMAT_OPUS		= 6,
+
+	QCAP_ENCODER_FORMAT_AC3			= 7,
+};
+
+// RECORD PROFILE (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_PROFILE_BASELINE	         = 0, // DEFAULT
+
+	QCAP_RECORD_PROFILE_MAIN		         = 1,
+
+	QCAP_RECORD_PROFILE_HIGH		         = 2,
+
+	QCAP_RECORD_PROFILE_CONSTRAINED_BASELINE = 3, // ONLY FOR QCAP_ENCODER_FORMAT_H264_VC
+
+	QCAP_RECORD_PROFILE_CONSTRAINED_HIGH     = 4, // ONLY FOR QCAP_ENCODER_FORMAT_H264_VC
+};
+
+// RECORD LEVEL (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_LEVEL_1		= 10,
+
+	QCAP_RECORD_LEVEL_1B	=  9,
+
+	QCAP_RECORD_LEVEL_11	= 11,
+
+	QCAP_RECORD_LEVEL_12	= 12,
+
+	QCAP_RECORD_LEVEL_13	= 13,
+
+	QCAP_RECORD_LEVEL_2		= 20,
+
+	QCAP_RECORD_LEVEL_21	= 21,
+
+	QCAP_RECORD_LEVEL_22	= 22,
+
+	QCAP_RECORD_LEVEL_3		= 30,
+
+	QCAP_RECORD_LEVEL_31	= 31,
+
+	QCAP_RECORD_LEVEL_32	= 32,
+
+	QCAP_RECORD_LEVEL_4		= 40,
+
+	QCAP_RECORD_LEVEL_41	= 41, // DEFAULT
+
+	QCAP_RECORD_LEVEL_42	= 42,
+
+	QCAP_RECORD_LEVEL_50	= 50,
+
+	QCAP_RECORD_LEVEL_51	= 51,
+
+	QCAP_RECORD_LEVEL_52	= 52,
+
+	QCAP_RECORD_LEVEL_60	= 60,
+
+	QCAP_RECORD_LEVEL_61	= 61,
+
+	QCAP_RECORD_LEVEL_62	= 62,
+};
+
+// RECORD ENTROPY (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_ENTROPY_CAVLC	= 0, // DEFAULT
+
+	QCAP_RECORD_ENTROPY_CABAC	= 1,
+};
+
+// RECORD COMPLEXITY (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_COMPLEXITY_0	= 0, // BEST SPEED, DEFAULT
+
+	QCAP_RECORD_COMPLEXITY_1	= 1,
+
+	QCAP_RECORD_COMPLEXITY_2	= 2,
+
+	QCAP_RECORD_COMPLEXITY_3	= 3,
+
+	QCAP_RECORD_COMPLEXITY_4	= 4,
+
+	QCAP_RECORD_COMPLEXITY_5	= 5,
+
+	QCAP_RECORD_COMPLEXITY_6	= 6, // BEST QUALITY
+};
+
+// RECORD MODE (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_MODE_VBR		= 0, 
+
+	QCAP_RECORD_MODE_CBR		= 1, 
+
+	QCAP_RECORD_MODE_ABR		= 2, 
+
+	QCAP_RECORD_MODE_CQP		= 3, // DEVELOPING ...
+
+	QCAP_RECORD_MODE_LOSSLESS	= 4, 
+};
+
+// DOWNSCALE MODE (RECORD PROPERTY)
+// 
+enum {
+
+	QCAP_DOWNSCALE_MODE_OFF	= 0, // (1920, 1080) * (1 / 1) = (1920, 1080)
+
+	QCAP_DOWNSCALE_MODE_2_3	= 1, // (1920, 1080) * (2 / 3) = (1280,  720)
+
+	QCAP_DOWNSCALE_MODE_1_2	= 2, // (1920, 1080) * (1 / 2) = ( 960,  540)
+
+	QCAP_DOWNSCALE_MODE_1_4	= 3, // (1920, 1080) * (1 / 4) = ( 480,  270)
+};
+
+// RECORD FLAG (RECORD PROPERTY)
+//
+enum {
+
+	QCAP_RECORD_FLAG_FULL						= 0x00000007,
+
+	QCAP_RECORD_FLAG_FILE						= 0x00000001,
+
+	QCAP_RECORD_FLAG_ENCODE						= 0x00000002,
+
+	QCAP_RECORD_FLAG_DISPLAY					= 0x00000004,
+
+	QCAP_RECORD_FLAG_DECODE						= 0x00000008,
+
+	QCAP_RECORD_FLAG_VIDEO_ONLY					= 0x00000010,
+
+	QCAP_RECORD_FLAG_AUDIO_ONLY					= 0x00000020,
+
+	QCAP_RECORD_FLAG_VIDEO_USE_IDEAL_TIMESTAMP	= 0x00000040,
+
+	QCAP_RECORD_FLAG_AUDIO_USE_IDEAL_TIMESTAMP	= 0x00000080,
+
+	QCAP_RECORD_FLAG_INGNORE_FORMAT_CHANGED		= 0x00000100,
+
+	QCAP_RECORD_FLAG_SYNCHRONIZED_RECORD		= 0x00000200, // START BY QCAP_RESUME_RECORD
+
+	QCAP_RECORD_FLAG_VIDEO_USE_MEDIA_TIMER		= 0x00000400, // ONLY FOR QCAP_SET_VIDEO_*_UNCOMPRESSION_BUFFER_*
+
+	QCAP_RECORD_FLAG_AUDIO_USE_MEDIA_TIMER		= 0x00000800, // ONLY FOR QCAP_SET_AUDIO_*_UNCOMPRESSION_BUFFER_*
+};
+
+// BROADCAST FLAG (BROADCAST PROPERTY)
+//
+enum {
+
+	QCAP_BROADCAST_FLAG_FULL						= 0x00000007,
+
+	QCAP_BROADCAST_FLAG_NETWORK						= 0x00000001,
+
+	QCAP_BROADCAST_FLAG_ENCODE						= 0x00000002,
+
+	QCAP_BROADCAST_FLAG_DISPLAY						= 0x00000004,
+
+	QCAP_BROADCAST_FLAG_DECODE						= 0x00000008,
+
+	QCAP_BROADCAST_FLAG_VIDEO_ONLY					= 0x00000010,
+	
+	QCAP_BROADCAST_FLAG_AUDIO_ONLY					= 0x00000020,
+
+	QCAP_BROADCAST_FLAG_VIDEO_USE_IDEAL_TIMESTAMP	= 0x00000040,
+
+	QCAP_BROADCAST_FLAG_AUDIO_USE_IDEAL_TIMESTAMP	= 0x00000080,
+
+	QCAP_BROADCAST_FLAG_VIDEO_USE_MEDIA_TIMER		= 0x00000400, // ONLY FOR QCAP_SET_VIDEO_*_UNCOMPRESSION_BUFFER_*
+
+	QCAP_BROADCAST_FLAG_AUDIO_USE_MEDIA_TIMER		= 0x00000800, // ONLY FOR QCAP_SET_AUDIO_*_UNCOMPRESSION_BUFFER_*
+};
+
+// BROADCAST PROTOCOL (BROADCAST PROPERTY)
+//
+enum {
+
+	QCAP_BROADCAST_PROTOCOL_UDP	 = 0x00000000,
+
+	QCAP_BROADCAST_PROTOCOL_TCP	 = 0x00000001, // BPS >= 12MBPS, SUGGEST TO SUE QCAP_BROADCAST_PROTOCOL_TCP
+
+	QCAP_BROADCAST_PROTOCOL_HTTP = 0x00000002,
+};
+
+// OSD FONT STYLE (OSD PROPERTY)
+//
+enum {
+
+    QCAP_FONT_STYLE_REGULAR     = 0x00000000,
+    
+	QCAP_FONT_STYLE_BOLD        = 0x00000001,
+    
+	QCAP_FONT_STYLE_ITALIC      = 0x00000002,
+    
+	QCAP_FONT_STYLE_BOLDITALIC  = 0x00000003,
+    
+	QCAP_FONT_STYLE_UNDERLINE   = 0x00000004,
+    
+	QCAP_FONT_STYLE_STRIKEOUT   = 0x00000008,
+};
+
+// OSD STRING ALIGNMENT (OSD PROPERTY)
+//
+enum {
+
+	QCAP_STRING_ALIGNMENT_STYLE_LEFT    = 0x00000000,
+
+    QCAP_STRING_ALIGNMENT_STYLE_NEAR    = 0x00000000,
+    
+	QCAP_STRING_ALIGNMENT_STYLE_CENTER  = 0x00000001,
+    
+	QCAP_STRING_ALIGNMENT_STYLE_RIGHT   = 0x00000002,
+    
+	QCAP_STRING_ALIGNMENT_STYLE_FAR		= 0x00000002,
+};
+
+// OSD SEQUENCE STYLE (OSD PROPERTY)
+//
+enum {
+
+	//  GENERAL DEVICE: FOREMOST -> PREVIEW CALLBACK -> BEFORE_ENCODE -> RECORDING (ENCODING) -> AFTERMOST
+	//
+	// SHARE RECORDING: FOREMOST -> RECORDING (ENCODING) -> AFTERMOST
+	//
+	// SHARE STREAMING: FOREMOST -> STREAMING (ENCODING) -> AFTERMOST
+	//
+	//  VIRTUAL CAMERA: FOREMOST -> AFTERMOST -> SHARING
+	//
+	//   FILE PLAYBACK: PLAYBACK (DECODING) -> FOREMOST -> DECODER CALLBACK -> AFTERMOST
+	//
+	QCAP_SEQUENCE_STYLE_FOREMOST		= 0x00000000,
+
+    QCAP_SEQUENCE_STYLE_BEFORE_ENCODE	= 0x00000001, // IT IS ONLY USED FOR GENERAL DEVICE
+    
+	QCAP_SEQUENCE_STYLE_AFTERMOST		= 0x00000002,
+};
+
+// BUFFER SCALE STYLE (BUFFER PROPERTY)
+//
+enum {
+
+	QCAP_SCALE_STYLE_STRETCH	= 0x00000000,
+
+    QCAP_SCALE_STYLE_FIT		= 0x00000001,
+    
+	QCAP_SCALE_STYLE_FILL		= 0x00000002,
+};
+
+// DECODER TYPE (PLAYBACK PROPERTY)
+//
+enum {
+
+	QCAP_DECODER_TYPE_SOFTWARE			= 0,
+
+	QCAP_DECODER_TYPE_HARDWARE			= 1, // DEVELOPING ...
+
+	QCAP_DECODER_TYPE_INTEL_MEDIA_SDK	= 2,
+
+	QCAP_DECODER_TYPE_AMD_UVD			= 3, // DEVELOPING ...
+
+	QCAP_DECODER_TYPE_AMD_VCE			= 3, // == QCAP_DECODER_TYPE_AMD_UVD
+
+	QCAP_DECODER_TYPE_NVIDIA_CUDA		= 4,
+
+	QCAP_DECODER_TYPE_NVIDIA_NVDEC		= 5,
+
+	QCAP_DECODER_TYPE_NVIDIA_NVENC		= 5, // == QCAP_DECODER_TYPE_NVIDIA_NVDEC
+};
+
+// DECODER VIDEO FORMAT (PLAYBACK PROPERTY)
+//
+enum {
+
+	QCAP_DECODER_FORMAT_MPEG2		=  1,
+
+	QCAP_DECODER_FORMAT_H264		=  0,
+
+	QCAP_DECODER_FORMAT_H264_3D		=  2, // H264 MVC (STEREOSCOPIC 3D)
+
+	QCAP_DECODER_FORMAT_H264_VC		=  3, // H264 SVC (MULTIPLE TEMPORAL SCALABILITY)
+
+	QCAP_DECODER_FORMAT_RAW			=  4,
+
+	QCAP_DECODER_FORMAT_H265		=  5,
+};
+
+// 3D STEREO BUFFER TYPE
+//
+enum {
+
+	QCAP_3D_STEREO_BUFFER_SIDE_BY_SIDE		= 0,
+
+	QCAP_3D_STEREO_BUFFER_TOP_BOTTOM		= 1,
+
+	QCAP_3D_STEREO_BUFFER_LINE_BY_LINE		= 2,
+};
+
+// 3D STEREO DISPLAY MODE
+//
+enum {
+
+	QCAP_3D_STEREO_DISPLAY_MODE_SIDE_BY_SIDE	= 0,
+
+	QCAP_3D_STEREO_DISPLAY_MODE_TOP_BOTTOM		= 1,
+
+	QCAP_3D_STEREO_DISPLAY_MODE_LINE_BY_LINE	= 2,
+
+	QCAP_3D_STEREO_DISPLAY_MODE_LEFT_ONLY		= 3,
+
+	QCAP_3D_STEREO_DISPLAY_MODE_RIGHT_ONLY		= 4,
+};
+
+// DICOM QUERY LEVEL (DICOM QUERY/RETRIEVE INFORMATION MODEL)
+//
+enum {	
+
+	QCAP_DICOM_QUERY_LEVEL_PATIENT	= 0,
+
+	QCAP_DICOM_QUERY_LEVEL_STUDY	= 1,
+
+	QCAP_DICOM_QUERY_LEVEL_SERIES	= 2,
+
+	QCAP_DICOM_QUERY_LEVEL_IMAGE	= 3, // COMPOSITE OBJECT INSTANCE
+};
+
+// FILE TIMEUNIT
+//
+enum {
+
+	QCAP_FILE_TIMEUNIT_TIME		= 0,
+
+	QCAP_FILE_TIMEUNIT_FRAME	= 1,
+};
+
+// ANIMATION CLIP BLINDS TYPE
+//
+enum {
+
+	QCAP_ANIMATION_CLIP_BLINDS_TYPE_NONE		= 0,
+
+	QCAP_ANIMATION_CLIP_BLINDS_TYPE_VERTICAL	= 1,
+
+	QCAP_ANIMATION_CLIP_BLINDS_TYPE_HORIZONTAL	= 2,
+};
+
+// SERIAL PORT PARITY CHECK (SERIAL PORT PROPERTY)
+//
+enum {
+
+	QCAP_SERIAL_PORT_PARITY_CHECK_NONE	= 0x00000000,
+
+	QCAP_SERIAL_PORT_PARITY_CHECK_ODD	= 0x00000001,
+
+	QCAP_SERIAL_PORT_PARITY_CHECK_EVEN	= 0x00000002,
+
+	QCAP_SERIAL_PORT_PARITY_CHECK_MARK	= 0x00000003,		
+
+	QCAP_SERIAL_PORT_PARITY_CHECK_SPACE	= 0x00000004,
+};
+
+// SERIAL PORT FLOW CONTROL (SERIAL PORT PROPERTY)
+//
+enum {
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_NONE		= 0x00000000,
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_CTS_RTS	= 0x00000001,
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_CTS_DTR	= 0x00000002,
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_DSR_RTS	= 0x00000003,
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_DSR_DTR	= 0x00000004,
+
+	QCAP_SERIAL_PORT_FLOW_CONTROL_XON_XOFF	= 0x00000005,
+};
+
+// SERIAL PORT STOP BITS (SERIAL PORT PROPERTY)
+//
+enum {
+
+	QCAP_SERIAL_PORT_STOP_BITS_ONE				= 0x00000000,
+
+	QCAP_SERIAL_PORT_STOP_BITS_ONE_POINT_FIVE	= 0x00000001,
+
+	QCAP_SERIAL_PORT_STOP_BITS_TWO				= 0x00000002,
+};
+
+// SERIAL PORT SIGNAL TYPE (SERIAL PORT PROPERTY)
+//
+enum {
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_CLEAR_DTR		= 0x00000000, // CLEAR THE DTR (DATA-TERMINAL-READY) SIGNAL
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_CLEAR_RTS		= 0x00000001, // CLEAR THE RTS (REQUEST-TO-SEND) SIGNAL
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_SET_DTR		= 0x00000002, // SEND THE DTR (DATA-TERMINAL-READY) SIGNAL
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_SET_RTS		= 0x00000003, // SEND THE RTS (REQUEST-TO-SEND) SIGNAL
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_SET_XOFF		= 0x00000004, // CAUSE TRANSMISSION TO ACT AS IF AN XOFF CHARACTER HAS BEEN RECEIVED
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_SET_XON		= 0x00000005, // CAUSE TRANSMISSION TO ACT AS IF AN XON CHARACTER HAS BEEN RECEIVED
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_SET_BREAK		= 0x00000006, // SUSPEND CHARACTER TRANSMISSION FOR A SPECIFIED COMMUNICATIONS DEVICE AND PLACES THE TRANSMISSION LINE IN A BREAK STATE UNTIL THE CLEARCOMMBREAK FUNCTION IS CALLED
+
+	QCAP_SERIAL_PORT_SIGNAL_TYPE_CLEAR_BREAK	= 0x00000007, // RESTORE CHARACTER TRANSMISSION FOR A SPECIFIED COMMUNICATIONS DEVICE AND PLACES THE TRANSMISSION LINE IN A NONBREAK STATE
+};
+
+// CALLBACK FUNCTION TYPES //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+typedef QRETURN (QCAP_EXPORT *PF_NO_SIGNAL_DETECTED_CALLBACK)( PVOID pDevice /*IN*/, ULONG nVideoInput /*IN*/, ULONG nAudioInput /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SIGNAL_REMOVED_CALLBACK)( PVOID pDevice /*IN*/, ULONG nVideoInput /*IN*/, ULONG nAudioInput /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_FORMAT_CHANGED_CALLBACK)( PVOID pDevice /*IN*/, ULONG nVideoInput /*IN*/, ULONG nAudioInput /*IN*/, ULONG nVideoWidth /*IN*/, ULONG nVideoHeight /*IN*/, BOOL bVideoIsInterleaved /*IN*/, double dVideoFrameRate /*IN*/, ULONG nAudioChannels /*IN*/, ULONG nAudioBitsPerSample /*IN*/, ULONG nAudioSampleFrequency /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_FORMAT_CHANGED_CALLBACK_EX)( PVOID pDevice /*IN*/, ULONG nVideoInput /*IN*/, ULONG nAudioInput /*IN*/, ULONG nVideoWidth /*IN*/, ULONG nVideoHeight /*IN*/, BOOL bVideoIsInterleaved /*IN*/, double dVideoNativeFrameRate /*IN*/, double dVideoGrabFrameRate /*IN*/, ULONG nAudioChannels /*IN*/, ULONG nAudioBitsPerSample /*IN*/, ULONG nAudioSampleFrequency /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SNAPSHOT_DONE_CALLBACK)( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SNAPSHOT_STREAM_CALLBACK)( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_RECORD_DONE_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_RECORD_FAIL_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, QRESULT nErrorStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SHARE_RECORD_DONE_CALLBACK)( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SHARE_RECORD_FAIL_CALLBACK)( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, QRESULT nErrorStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SHARE_RECORD_SNAPSHOT_DONE_CALLBACK)( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_SHARE_RECORD_SNAPSHOT_STREAM_CALLBACK)( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_VERTICAL_ANCILLARY_DATA_CALLBACK)( PVOID pDevice /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_PREVIEW_CALLBACK)( PVOID pDevice /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_PREVIEW_CALLBACK)( PVOID pDevice /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_HARDWARE_ENCODER_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, BOOL bIsKeyFrame /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_RECORD_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, BOOL bIsKeyFrame /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_RECORD_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_MEDIA_RECORD_CALLBACK)( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, BOOL bIsKeyFrame /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_MX_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_MEDIA_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_MX_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DISPLAY_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DISPLAY_SHARE_RECORD_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_SHARE_RECORD_MEDIA_TIMER_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, double dDelayTime /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_SHARE_RECORD_MEDIA_TIMER_CALLBACK)( UINT iRecNum /*IN*/, double dSampleTime /*IN*/, double dDelayTime /*IN*/, PVOID pUserData /*IN*/ );
+
+// CALLBACK FUNCTIONS PART.I (EVENT) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_NO_SIGNAL_DETECTED_CALLBACK( PVOID pDevice /*IN*/, PF_NO_SIGNAL_DETECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SIGNAL_REMOVED_CALLBACK( PVOID pDevice /*IN*/, PF_SIGNAL_REMOVED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_FORMAT_CHANGED_CALLBACK( PVOID pDevice /*IN*/, PF_FORMAT_CHANGED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_FORMAT_CHANGED_CALLBACK_EX( PVOID pDevice /*IN*/, PF_FORMAT_CHANGED_CALLBACK_EX pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SNAPSHOT_DONE_CALLBACK( PVOID pDevice /*IN*/, PF_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_RECORD_DONE_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_RECORD_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_RECORD_FAIL_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_RECORD_FAIL_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_DONE_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_FAIL_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_FAIL_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_SNAPSHOT_DONE_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// CALLBACK FUNCTIONS PART.II (DATA) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_VERTICAL_ANCILLARY_DATA_CALLBACK( PVOID pDevice /*IN*/, PF_VIDEO_VERTICAL_ANCILLARY_DATA_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // VANC
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_PREVIEW_CALLBACK( PVOID pDevice /*IN*/, PF_VIDEO_PREVIEW_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_PREVIEW_CALLBACK( PVOID pDevice /*IN*/, PF_AUDIO_PREVIEW_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_HARDWARE_ENCODER_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_VIDEO_HARDWARE_ENCODER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// CALLBACK FUNCTIONS PART.III (DATA) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SNAPSHOT_STREAM_CALLBACK( PVOID pDevice /*IN*/, PF_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_SNAPSHOT_STREAM_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// CALLBACK FUNCTIONS PART.IIII (DATA) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_VIDEO_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_AUDIO_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_MEDIA_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_MEDIA_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR TS & FLV FILE FORMAT
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_MX_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_MX_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_MEDIA_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_MEDIA_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR TS & FLV FILE FORMAT
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_DECODER_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_DECODER_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DECODER_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DECODER_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DECODER_MX_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DECODER_MX_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_DISPLAY_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_DISPLAY_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DISPLAY_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DISPLAY_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_SHARE_RECORD_MEDIA_TIMER_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_SHARE_RECORD_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_SHARE_RECORD_MEDIA_TIMER_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_SHARE_RECORD_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// SYSTEM FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VERSION( ULONG * pMajorVersion /*OUT*/, ULONG * pMinorVersion /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_SYSTEM_CONFIGURATION( BOOL   bEnableMultipleUsersAccess = TRUE,					 /*IN*/ // If true, qcap will alllow multiple users to access the device.
+
+															    BOOL   bEnableVideoPreviewDevice = TRUE,					 /*IN*/ // If true, the video capture device will be enabled.
+
+															    BOOL   bEnableAudioPreviewDevice = TRUE,					 /*IN*/ // If true, the audio capture device will be enabled.
+
+															    BOOL   bEnableVideoHardwareMainEncoderDevice = TRUE,		 /*IN*/ // If true, the main hardware encoder will be enabled.
+
+															    BOOL   bEnableVideoHardwareSubEncoderDevice = TRUE,			 /*IN*/ // If true, the sub hardware encoder will be enabled.
+
+															    ULONG  nAutoInputDetectionTimeout = 3000,					 /*IN*/ // The parameter allows you to specify the timeout duration of the auto input detection, default is 3sec.
+
+															    BOOL   bEnableSCF = FALSE,									 /*IN*/ // If true, the SCF file recording function will be turned on.
+															   
+															    CHAR * pszDB3 = NULL,										 /*IN*/ // The parameter allows you to specify the file path of SQL database.
+															   
+															    BOOL   bEnableAsyncBackgroundSnapshot = FALSE,				 /*IN*/ // If true, snapshot function will be moved from preview callback into another thread. 
+															   
+															    BOOL   bEnableEnhancedVideoRenderer = TRUE,					 /*IN*/ // If true, QCAP will enable the DirectShow's Enhanced Video Renderer Filter.
+															   
+															    BOOL   bEnableSystemTimeCallback = FALSE,					 /*IN*/ // If true, the preview's and encoder's callbacks will return one local system time at dSampleTime.
+															   
+															    BOOL   bEnableFileRepairFunction = TRUE,					 /*IN*/ // If true, the recording file will own self-repaired ability.
+															   
+															    BOOL   bEnableNewRTSPLibrary = TRUE,						 /*IN*/ // If true, we will use new rtsp lib to repalce old one after 1.1.0.130.0
+																
+																CHAR * pszWebServerRootFolderPath = NULL,					 /*IN*/ // The parameter allows you to specify the web server's root folder path.
+
+																CHAR * pszWebServerIP = NULL,								 /*IN*/ // The parameter allows you to specify the web server's ip address.
+																
+																ULONG  nSystemColorRangeType = QCAP_COLORRANGE_TYPE_FULL,    /*IN*/ // The parameter allows you to specify the system color range setting.
+																
+																BOOL   bEnableVideoMixingRendererBugPatch = TRUE,            /*IN*/ // If true, QCAP will enable the bug patch for DirectShow's Video Mixing Renderer, but it will delay the device's initialized time.
+																
+																ULONG  nEnableCustomVideoRenderer = 0x00000000,              /*IN*/ // If non-zero, QCAP will enable the Custom Video Renderer as major display engine.
+																
+																BOOL   bEnableGraphicMemoryForVideoEncoder = FALSE,          /*IN*/ // If true, QCAP will use the graph memory for all gpu encoders.
+																
+																BOOL   bEnableSingleGraphCaptureMode = FALSE,				 /*IN*/ // If true, QCAP will use single DirectShow's graph to capture video and audio streams.
+																
+																ULONG  nSignalDetectionDuration = 1000,                      /*IN*/ // The parameter allows you to specify the duration of the signal detection, default is 1sec.
+																
+																BOOL   bEnableNewChromaKeyLibrary = FALSE,                   /*IN*/ // If true, we will use new chroma key lib to repalce old one after 1.1.0.183.5            
+
+																BOOL   bEnableNewSnapshotLibrary = TRUE );                   /*IN*/ // If true, we will use new snapshot lib to repalce old one after 1.1.0.165.4                  
+																	
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_QUERY_ENCODER_TYPE_CAP( ULONG nEncoderType /*IN*/, ULONG nEncoderFormat /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_QUERY_DECODER_TYPE_CAP( ULONG nDecoderType /*IN*/, ULONG nDecoderFormat /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_QUERY_ENCODER_STATUS( ULONG nEncoderType /*IN*/, ULONG * pExistInstances /*OUT*/ );
+
+// DEVICE FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DEVICE_ENUMERATION( ULONGLONG * * ppVideoDeviceList /*OUT*/, ULONG * pVideoDeviceSize /*OUT*/, ULONGLONG * * ppVideoEncoderDeviceList /*OUT*/, ULONG * pVideoEncoderDeviceSize /*OUT*/, ULONGLONG * * ppAudioDeviceList /*OUT*/, ULONG * pAudioDeviceSize /*OUT*/, ULONGLONG * * ppAudioEncoderDeviceList /*OUT*/, ULONG * pAudioEncoderDeviceSize /*OUT*/, ULONG nDeviceEnumType = QCAP_ENUM_TYPE_DEVICE_NAME /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_DEVICE_ENUMERATION_ITEM_INFO( UINT iDevNum /*IN*/, ULONGLONG * pDeviceList /*IN*/, ULONG * pDeviceInfoH /*OUT*/, ULONG * pDeviceInfoL /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE( CHAR * pszDevName /*IN*/, UINT iDevNum /*IN*/, HWND hAttachedWindow /*IN*/, PVOID * ppDevice /*OUT*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+// DEVICE NAME TABLE:
+//
+// "DC1150 USB" IS FOR PD652, PD652.3D
+//
+// "QP0204 USB" IS FOR PD5A0
+//
+// "UB658G USB" IS FOR UB658
+//
+// "CY3014 USB" IS FOR UB530
+//
+// "UB3200 USB" IS FOR PD560
+//
+// "UB3300 USB" IS FOR PD570
+//
+// "UB3400 USB" IS FOR UB5H0
+//
+// "TW6802 PCI" IS FOR SC200, SC300, SC230, SC330
+//
+// "CX2581 PCI" IS FOR SC310, SC340
+//
+// "CX2385 PCI" IS FOR SC350
+//
+// "AH8400 PCI" IS FOR SC290, SC390
+//
+// "FH8735 PCI" IS FOR SC2A0, SC3A0
+//
+// "TW5864 PCI" IS FOR SC2B0, SC3B0
+//
+// "MZ0380 PCI" IS FOR SC3C0
+//
+// "SA7160 PCI" IS FOR SC500, SC510, TB510
+//
+// "FH8735 PCI" IS FOR SC580
+//
+// "TW2809 PCI" IS FOR SC590
+//
+// "QP0203 PCI" IS FOR SC540, SC5A0
+//
+// "MZ0380 PCI" IS FOR SC350, SC3C0, SC550, SC560, SC5C0
+//
+// "SC0700 PCI" IS FOR SC700
+//
+// "SC0710 PCI" IS FOR SC710
+//
+//     "CAMERA" IS FOR GENERAL USB CAMERA
+//
+//  "SOUNDCARD" IS FOR GENERAL SOUND CARD
+//
+//    "DESKTOP" IS FOR GENERAL DESKTOP SCREEN GRABBER
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY( PVOID pDevice /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RUN( PVOID pDevice /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RUN_EX( PVOID pDevice /*IN*/, BOOL bStopAfterSignalRemoved = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP( PVOID pDevice /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_QUERY_DEVICE_CAP( PVOID pDevice /*IN*/, DWORD * pDeviceSerialNumber /*OUT*/, CHAR * pszDeviceSystemPath /*OUT*/, BOOL * pHasHardwareMainEncoder /*OUT*/, BOOL * pHasHardwareSubEncoder /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_INPUT_CONFIG( PVOID pDevice /*IN*/, DWORD * pConfig /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_INPUT_CONFIG( PVOID pDevice /*IN*/, DWORD dwConfig /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_INPUT( PVOID pDevice /*IN*/, ULONG * pInput /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_INPUT( PVOID pDevice /*IN*/, ULONG nInput /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_INPUT( PVOID pDevice /*IN*/, ULONG * pInput /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_INPUT( PVOID pDevice /*IN*/, ULONG nInput /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_STANDARD( PVOID pDevice /*IN*/, ULONG * pStandard /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_STANDARD( PVOID pDevice /*IN*/, ULONG nStandard /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_CURRENT_CONTENT_PROTECTION_STATUS( PVOID pDevice /*IN*/, ULONG * pStatus /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_CURRENT_INPUT_FORMAT( PVOID pDevice /*IN*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, BOOL * pIsInterleaved /*OUT*/, double * pFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_CURRENT_INPUT_FORMAT_EX( PVOID pDevice /*IN*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, BOOL * pIsInterleaved /*OUT*/, double * pNativeFrameRate /*OUT*/, double * pGrabFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_CURRENT_INPUT_FORMAT( PVOID pDevice /*IN*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_DEFAULT_OUTPUT_FORMAT( PVOID pDevice /*IN*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, BOOL * pIsInterleaved /*OUT*/, double * pFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_DEFAULT_OUTPUT_FORMAT( PVOID pDevice /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BOOL bIsInterleaved /*IN*/, double dFrameRate /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_DEFAULT_OUTPUT_FORMAT( PVOID pDevice /*IN*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_DEFAULT_OUTPUT_FORMAT( PVOID pDevice /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_VERTICAL_ANCILLARY_DATA_GRABBED_LINES( PVOID pDevice /*IN*/, ULONG * pLines /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_VERTICAL_ANCILLARY_DATA_GRABBED_LINES( PVOID pDevice /*IN*/, ULONG nLines /*IN*/ ); // 0 = DISABLE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_DEINTERLACE_TYPE( PVOID pDevice /*IN*/, ULONG * pType /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_DEINTERLACE_TYPE( PVOID pDevice /*IN*/, ULONG nType /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_DEINTERLACE( PVOID pDevice /*IN*/, BOOL * pEnable /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_DEINTERLACE( PVOID pDevice /*IN*/, BOOL bEnable /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_REGION_DISPLAY( PVOID pDevice /*IN*/, ULONG * pCropX /*OUT*/, ULONG * pCropY /*OUT*/, ULONG * pCropW /*OUT*/, ULONG * pCropH /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_REGION_DISPLAY( PVOID pDevice /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_MIRROR( PVOID pDevice /*IN*/, BOOL * pHorizontalMirror /*OUT*/, BOOL * pVerticalMirror /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_MIRROR( PVOID pDevice /*IN*/, BOOL bHorizontalMirror /*IN*/, BOOL bVerticalMirror /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_ASPECT_RATIO( PVOID pDevice /*IN*/, BOOL * pMaintainAspectRatio /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_ASPECT_RATIO( PVOID pDevice /*IN*/, BOOL bMaintainAspectRatio /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_BRIGHTNESS( PVOID pDevice /*IN*/, ULONG * pValue /*OUT*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_BRIGHTNESS( PVOID pDevice /*IN*/, ULONG nValue /*IN*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_CONTRAST( PVOID pDevice /*IN*/, ULONG * pValue /*OUT*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_CONTRAST( PVOID pDevice /*IN*/, ULONG nValue /*IN*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_HUE( PVOID pDevice /*IN*/, ULONG * pValue /*OUT*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_HUE( PVOID pDevice /*IN*/, ULONG nValue /*IN*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SATURATION( PVOID pDevice /*IN*/, ULONG * pValue /*OUT*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SATURATION( PVOID pDevice /*IN*/, ULONG nValue /*IN*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARPNESS( PVOID pDevice /*IN*/, ULONG * pValue /*OUT*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARPNESS( PVOID pDevice /*IN*/, ULONG nValue /*IN*/ /*PHYSICAL VALUE 0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_BRIGHTNESS_EX( PVOID pDevice /*IN*/, ULONG * pPhysicalValue /*OUT*/ /*0 ~ 255*/, ULONG * pDisplayValue /*OUT*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_BRIGHTNESS_EX( PVOID pDevice /*IN*/, ULONG nPhysicalValue /*IN*/ /*0 ~ 255*/, ULONG nDisplayValue /*IN*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_CONTRAST_EX( PVOID pDevice /*IN*/, ULONG * pPhysicalValue /*OUT*/ /*0 ~ 255*/, ULONG * pDisplayValue /*OUT*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_CONTRAST_EX( PVOID pDevice /*IN*/, ULONG nPhysicalValue /*IN*/ /*0 ~ 255*/, ULONG nDisplayValue /*IN*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_HUE_EX( PVOID pDevice /*IN*/, ULONG * pPhysicalValue /*OUT*/ /*0 ~ 255*/, ULONG * pDisplayValue /*OUT*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_HUE_EX( PVOID pDevice /*IN*/, ULONG nPhysicalValue /*IN*/ /*0 ~ 255*/, ULONG nDisplayValue /*IN*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SATURATION_EX( PVOID pDevice /*IN*/, ULONG * pPhysicalValue /*OUT*/ /*0 ~ 255*/, ULONG * pDisplayValue /*OUT*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SATURATION_EX( PVOID pDevice /*IN*/, ULONG nPhysicalValue /*IN*/ /*0 ~ 255*/, ULONG nDisplayValue /*IN*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARPNESS_EX( PVOID pDevice /*IN*/, ULONG * pPhysicalValue /*OUT*/ /*0 ~ 255*/, ULONG * pDisplayValue /*OUT*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARPNESS_EX( PVOID pDevice /*IN*/, ULONG nPhysicalValue /*IN*/ /*0 ~ 255*/, ULONG nDisplayValue /*IN*/ /*0 ~ 255*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_PREVIEW_PROPERTY_EX( PVOID pDevice /*IN*/, ULONG * pDownscaleMode /*OUT*/, ULONG * pPostSkipFrameRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pPostAvgFrameRate /*OUT*/ /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_PREVIEW_PROPERTY_EX( PVOID pDevice /*IN*/, ULONG   nDownscaleMode /*IN*/,  ULONG   nPostSkipFrameRate /*IN*/  /*DEFAULT = 0*/, ULONG   nPostAvgFrameRate /*IN*/  /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_HARDWARE_ENCODER_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, ULONG * pDownscaleMode /*OUT*/, ULONG * pPostSkipFrameRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pPostAvgFrameRate /*OUT*/ /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  ULONG   nDownscaleMode /*IN*/,  ULONG   nPostSkipFrameRate /*IN*/  /*DEFAULT = 0*/, ULONG   nPostAvgFrameRate /*IN*/  /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_HARDWARE_ENCODER_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pRecordProfile /*OUT*/, ULONG * pRecordLevel /*OUT*/, ULONG * pRecordEntropy /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pBFrames /*OUT*/, BOOL * pIsInterleaved /*OUT*/, ULONG * pSlices /*OUT*/, ULONG * pLayers /*OUT*/, ULONG * pSceneCut /*OUT*/, BOOL * pMultiThread /*OUT*/, BOOL * pMBBRC /*OUT*/, BOOL * pExtBRC /*OUT*/, ULONG * pMinQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pMaxQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVMaxRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVBufSize /*OUT*/ /*DEFAULT = 0*/, ULONG * pCBRVariation /*OUT*/ /*DEFAULT = 0*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, ULONG * pCropX /*OUT*/, ULONG * pCropY /*OUT*/, ULONG * pCropW /*OUT*/, ULONG * pCropH /*OUT*/, ULONG * pDstW /*OUT*/, ULONG * pDstH /*OUT*/, ULONG * pPostSkipFrameRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pPostAvgFrameRate /*OUT*/ /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nRecordProfile /*IN*/ , ULONG   nRecordLevel /*IN*/ , ULONG   nRecordEntropy /*IN*/ , ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nBFrames /*IN*/ , BOOL   bIsInterleaved /*IN*/ , ULONG   nSlices /*IN*/ , ULONG   nLayers /*IN*/ , ULONG   nSceneCut /*IN*/,  BOOL   bMultiThread /*IN*/,  BOOL   bMBBRC /*IN*/,  BOOL   bExtBRC /*IN*/,  ULONG   nMinQP /*IN*/  /*DEFAULT = 0*/, ULONG   nMaxQP /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVMaxRate /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVBufSize /*IN*/  /*DEFAULT = 0*/, ULONG   nCBRVariation /*IN*/  /*DEFAULT = 0*/, ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  ULONG   nCropX /*IN*/,  ULONG   nCropY /*IN*/,  ULONG   nCropW /*IN*/,  ULONG   nCropH /*IN*/,  ULONG   nDstW /*IN*/,  ULONG   nDstH /*IN*/,  ULONG   nPostSkipFrameRate /*IN*/  /*DEFAULT = 0*/, ULONG   nPostAvgFrameRate /*IN*/  /*DEFAULT = 0*/ ); // SKIP = -1 (0xFFFFFFFF)
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_HARDWARE_ENCODER_VIDEOCOMPRESSION_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG nProperty /*IN*/, ULONG * pValue /*OUT*/ ); // = AMESDK_GET_VIDEOCOMPRESSION_PROPERTY. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_HARDWARE_ENCODER_VIDEOCOMPRESSION_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG nProperty /*IN*/, ULONG nValue /*IN*/ ); // = AMESDK_SET_VIDEOCOMPRESSION_PROPERTY. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_SOUND_RENDERER( PVOID pDevice /*IN*/, UINT * pSoundNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SOUND_RENDERER( PVOID pDevice /*IN*/, UINT iSoundNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_VOLUME( PVOID pDevice /*IN*/, ULONG * pVolume /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_VOLUME( PVOID pDevice /*IN*/, ULONG nVolume /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_DEVICE_CUSTOM_PROPERTY_PAGE( PVOID pDevice /*IN*/, HWND hAttachedWindow /*IN*/, UINT iPageNum = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_DEVICE_CUSTOM_PROPERTY( PVOID pDevice /*IN*/, ULONG nProperty /*IN*/, ULONG * pValue /*OUT*/ ); // = AMESDK_GET_CUSTOM_PROPERTY. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_DEVICE_CUSTOM_PROPERTY( PVOID pDevice /*IN*/, ULONG nProperty /*IN*/, ULONG nValue /*IN*/ ); // = AMESDK_SET_CUSTOM_PROPERTY. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_DEVICE_CUSTOM_PROPERTY_EX( PVOID pDevice /*IN*/, ULONG nProperty /*IN*/, BYTE * pValue /*OUT*/, ULONG nBytes /*IN*/ ); // = AMESDK_GET_CUSTOM_PROPERTY_EX. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_DEVICE_CUSTOM_PROPERTY_EX( PVOID pDevice /*IN*/, ULONG nProperty /*IN*/, BYTE * pValue /*IN*/, ULONG nBytes /*IN*/ ); // = AMESDK_SET_CUSTOM_PROPERTY_EX. PLS CHECK PRODUCT'S EXTRA PROGRAMMING GUIDE.
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DIAGNOSE_VIDEO_STREAM_STATUS( PVOID pDevice /*IN*/, BOOL * pIsStill /*OUT*/, ULONG nStillThreshold = 64 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DIAGNOSE_AUDIO_STREAM_STATUS( PVOID pDevice /*IN*/, double * pVolumeDB_L /*OUT*/ /*RANGE = -100 ~ 0 (DB)*/, double * pVolumeDB_R /*OUT*/ /*RANGE = -100 ~ 0 (DB)*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_NO_SIGNAL_DETECTED_CALLBACK( PVOID pDevice /*IN*/, PF_NO_SIGNAL_DETECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SIGNAL_REMOVED_CALLBACK( PVOID pDevice /*IN*/, PF_SIGNAL_REMOVED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_FORMAT_CHANGED_CALLBACK( PVOID pDevice /*IN*/, PF_FORMAT_CHANGED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_FORMAT_CHANGED_CALLBACK_EX( PVOID pDevice /*IN*/, PF_FORMAT_CHANGED_CALLBACK_EX pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_VERTICAL_ANCILLARY_DATA_CALLBACK( PVOID pDevice /*IN*/, PF_VIDEO_VERTICAL_ANCILLARY_DATA_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // VANC
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_PREVIEW_CALLBACK( PVOID pDevice /*IN*/, PF_VIDEO_PREVIEW_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_PREVIEW_CALLBACK( PVOID pDevice /*IN*/, PF_AUDIO_PREVIEW_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_HARDWARE_ENCODER_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_VIDEO_HARDWARE_ENCODER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// LOCK/UNLOCK FUNCTIONS (FOR LABVIEW 2010/2012 DEVELOPER) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COPY_VIDEO_PREVIEW_BUFFER( PVOID pDevice /*IN*/, double * pSampleTime /*OUT*/, ULONG nColorSpaceType /*IN*/, VOID * pFrameBuffer /*IN*/, ULONG * pFrameBufferLen /*IN/OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COPY_AUDIO_PREVIEW_BUFFER( PVOID pDevice /*IN*/, double * pSampleTime /*OUT*/, VOID * pFrameBuffer /*IN*/, ULONG * pFrameBufferLen /*IN/OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_LOCK_VIDEO_PREVIEW_BUFFER( PVOID pDevice /*IN*/, double * pSampleTime /*OUT*/, VOID * * ppFrameBuffer /*OUT*/, ULONG * pFrameBufferLen /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_UNLOCK_VIDEO_PREVIEW_BUFFER( PVOID pDevice /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_LOCK_AUDIO_PREVIEW_BUFFER( PVOID pDevice /*IN*/, double * pSampleTime /*OUT*/, VOID * * ppFrameBuffer /*OUT*/, ULONG * pFrameBufferLen /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_UNLOCK_AUDIO_PREVIEW_BUFFER( PVOID pDevice /*IN*/ );
+
+// SNAPSHOT FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_BMP( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_JPG( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_BMP_EX( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_JPG_EX( PVOID pDevice /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SNAPSHOT_DONE_CALLBACK( PVOID pDevice /*IN*/, PF_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SNAPSHOT_STREAM_CALLBACK( PVOID pDevice /*IN*/, PF_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// CHANNEL RECORDING FUNCTIONS (SUPPORT MULTIPLE-STREAMS CHANNEL RECORDING) (RECNUM: 0 ~ 3) /////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_RECORD_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, ULONG * pDownscaleMode /*OUT*/ ); // HARDWARE ENCODER NEED USE QCAP_GET_VIDEO_HARDWARE_ENCODER_PROPERTY
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_RECORD_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  ULONG   nDownscaleMode /*IN*/  ); // HARDWARE ENCODER NEED USE QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_RECORD_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pRecordProfile /*OUT*/ /*DEFAULT = BASELINE*/, ULONG * pRecordLevel /*OUT*/ /*DEFAULT = 41*/, ULONG * pRecordEntropy /*OUT*/ /*DEFAULT = CAVLC*/, ULONG * pRecordComplexity /*OUT*/ /*DEFAULT = 0*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pBFrames /*OUT*/ /*DEFAULT = 0*/, BOOL * pIsInterleaved /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pSlices /*OUT*/ /*DEFAULT = 0*/, ULONG * pLayers /*OUT*/ /*DEFAULT = 0*/, ULONG * pSceneCut /*OUT*/ /*DEFAULT = 0*/, BOOL * pMultiThread /*OUT*/ /*DEFAULT = TRUE*/, BOOL * pMBBRC /*OUT*/ /*DEFAULT = FALSE*/, BOOL * pExtBRC /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pMinQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pMaxQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVMaxRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVBufSize /*OUT*/ /*DEFAULT = 0*/, ULONG * pCBRVariation /*OUT*/ /*DEFAULT = 0*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, ULONG * pCropX /*OUT*/, ULONG * pCropY /*OUT*/, ULONG * pCropW /*OUT*/, ULONG * pCropH /*OUT*/, ULONG * pDstW /*OUT*/, ULONG * pDstH /*OUT*/, ULONG * pPostSkipFrameRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pPostAvgFrameRate /*OUT*/ /*DEFAULT = 0*/ ); // HARDWARE ENCODER NEED USE QCAP_GET_VIDEO_HARDWARE_ENCODER_PROPERTY_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_RECORD_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nRecordProfile /*IN*/  /*DEFAULT = BASELINE*/, ULONG   nRecordLevel /*IN*/  /*DEFAULT = 41*/, ULONG   nRecordEntropy /*IN*/  /*DEFAULT = CAVLC*/, ULONG   nRecordComplexity /*IN*/  /*DEFAULT = 0*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nBFrames /*IN*/  /*DEFAULT = 0*/, BOOL   bIsInterleaved /*IN*/  /*DEFAULT = FALSE*/, ULONG   nSlices /*IN*/  /*DEFAULT = 0*/, ULONG   nLayers /*IN*/  /*DEFAULT = 0*/, ULONG   nSceneCut /*IN*/  /*DEFAULT = 0*/, BOOL   bMultiThread /*IN*/  /*DEFAULT = TRUE*/, BOOL   bMBBRC /*IN*/  /*DEFAULT = FALSE*/, BOOL   bExtBRC /*IN*/  /*DEFAULT = FALSE*/, ULONG   nMinQP /*IN*/  /*DEFAULT = 0*/, ULONG   nMaxQP /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVMaxRate /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVBufSize /*IN*/  /*DEFAULT = 0*/, ULONG   nCBRVariation /*IN*/  /*DEFAULT = 0*/, ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  ULONG   nCropX /*IN*/,  ULONG   nCropY /*IN*/,  ULONG   nCropW /*IN*/,  ULONG   nCropH /*IN*/,  ULONG   nDstW /*IN*/,  ULONG   nDstH /*IN*/,  ULONG   nPostSkipFrameRate /*IN*/  /*DEFAULT = 0*/, ULONG   nPostAvgFrameRate /*IN*/  /*DEFAULT = 0*/ ); // HARDWARE ENCODER NEED USE QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_RECORD_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_RECORD_PROPERTY( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_RECORD_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_RECORD_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_RECORD_DYNAMIC_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_RECORD_DYNAMIC_PROPERTY_EX( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_RECORD_HEADER( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszTitle /*IN*/, CHAR * pszArtist /*IN*/, CHAR * pszComments /*IN*/, CHAR * pszGenre /*IN*/, CHAR * pszComposer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_RECORD_HEADER_W( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, WSTRING pwszTitle /*IN*/, WSTRING pwszArtist /*IN*/, WSTRING pwszComments /*IN*/, WSTRING pwszGenre /*IN*/, WSTRING pwszComposer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_RECORD_DATA_BUFFER( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, BYTE * pDataBuffer /*IN*/, ULONG nDataBufferSize /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_CLONE_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathNameA /*IN*/, CHAR * pszFilePathNameB /*IN*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_TIMESHIFT_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID * ppPhysicalFileWriter /*OUT*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_FAILSAFE_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, UINT iLinkRecNum /*IN*/, PVOID pLinkPhysicalFileWriter /*IN*/, double dPreRecordTime = 0.0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESUME_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_PAUSE_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEGMENT_RECORD( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_RECORD_DONE_CALLBACK(  PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_RECORD_DONE_CALLBACK  pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_RECORD_FAIL_CALLBACK(  PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_RECORD_FAIL_CALLBACK  pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_VIDEO_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_AUDIO_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_MEDIA_RECORD_CALLBACK( PVOID pDevice /*IN*/, UINT iRecNum /*IN*/, PF_MEDIA_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR TS & FLV FILE FORMAT
+
+// CLONE FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_CLONE( PVOID pDevice /*IN*/, HWND hAttachedWindow /*IN*/, PVOID * ppCloneDevice /*OUT*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+// OSD FUNCTIONS (SUPPORT MULTIPLE-LAYERS OSD OBJECTS) (OSDNUM: 0 ~ 511) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MOVE_OSD_OBJECT( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_OSD_TEXT_BOUNDARY( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_OSD_TEXT_BOUNDARY_W( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_TEXT( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_TEXT_W( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_TEXT_EX( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_TEXT_EX_W( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_PICTURE( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_BUFFER( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_BUFFER_EX( PVOID pDevice /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+// MULTIPLE CHANNELS SYNCHRONIZED RECORDING/PLAYBACK FUNCTIONS (SYNCHRONIZED RECORDING/PLAYBACK) ////////////////////////////////////////////////////////////////////////////////
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_SYNCHRONIZED_RECORD( PVOID * ppSyncRecorder /*IN*/, ULONG nFileArgs /*IN*/, CHAR * pszFilePathName1 /*IN*/, PVOID pDevice1 /*IN*/, UINT iRecNum1 /*IN*/, CHAR * pszFilePathName2 /*IN*/, PVOID pDevice2 /*IN*/, UINT iRecNum2 /*IN*/, ... );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_SYNCHRONIZED_TIMESHIFT_RECORD( PVOID pSyncRecorder /*IN*/, PVOID * ppPhysicalFileWriters /*OUT*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/, BOOL bIsAsync /*IN*/, ULONG nMilliseconds /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESUME_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_PAUSE_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEGMENT_SYNCHRONIZED_RECORD( PVOID pSyncRecorder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_OPEN_SYNCHRONIZED_FILE( PVOID * ppFile /*OUT*/, ULONG nFileArgs /*IN*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, CHAR * pszFilePathName1 /*IN*/,  HWND hAttachedWindow1 /*IN*/, BOOL bThumbDraw1 /*IN*/, BOOL bMaintainAspectRatio1 /*IN*/, CHAR * pszFilePathName2 /*IN*/,  HWND hAttachedWindow2 /*IN*/, BOOL bThumbDraw2 /*IN*/, BOOL bMaintainAspectRatio2 /*IN*/, ... );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_SYNCHRONIZED_FILE_INFO( PVOID pFile /*IN*/, UINT iFileNum /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/ );
+
+// SYNCHRONIZED RECORDING EXAMPLE
+//
+// QCAP_CREATE_SYNCHRONIZED_RECORD( &pSyncRecorder, 4, "SR_CH01.MP4", pDevices[ 0 ], 0, 
+//
+//								                       "SR_CH02.MP4", pDevices[ 1 ], 0, 
+//
+//								                       "SR_CH03.MP4", pDevices[ 2 ], 0, 
+//
+//								                       "SR_CH04.MP4", pDevices[ 3 ], 0 );
+//
+// QCAP_START_SYNCHRONIZED_RECORD( pSyncRecorder );
+// 
+// QCAP_STOP_SYNCHRONIZED_RECORD( pSyncRecorder, TRUE, 0 );
+// 
+// QCAP_DESTROY_SYNCHRONIZED_RECORD( pSyncRecorder );
+
+// SYNCHRONIZED PLAYBACK EXAMPLE
+//
+// QCAP_OPEN_SYNCHRONIZED_FILE( &pFile, 4, QCAP_DECODER_TYPE_SOFTWARE, &nVideoEncoderFormat, &nVideoWidth, &nVideoHeight, &dVideoFrameRate, 
+//
+//                                                                     &nAudioEncoderFormat, &nAudioChannels, &nAudioBitsPerSample, &pAudioSampleFrequency, 
+//
+//                                                                     &nTotalDurationTimes, 
+
+//                                                                     "SR_CH01.MP4", hAttachedWindow[ 0 ], BOOL bThumbDraw[ 0 ], BOOL bMaintainAspectRatio[ 0 ],
+//
+//                                                                     "SR_CH02.MP4", hAttachedWindow[ 1 ], BOOL bThumbDraw[ 1 ], BOOL bMaintainAspectRatio[ 1 ],
+//
+//                                                                     "SR_CH03.MP4", hAttachedWindow[ 2 ], BOOL bThumbDraw[ 2 ], BOOL bMaintainAspectRatio[ 2 ],
+//
+//                                                                     "SR_CH04.MP4", hAttachedWindow[ 3 ], BOOL bThumbDraw[ 3 ], BOOL bMaintainAspectRatio[ 3 ] );
+// QCAP_PLAY_FILE( pFile );
+//
+// QCAP_STOP_FILE( pFile );
+//
+// QCAP_DESTROY_FILE( pFile );
+//
+// CAMERA FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CAMERA_ENUMERATION( CHAR * * ppszCameraDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CAMERA_ENUMERATION_W( WSTRING * ppwszCameraDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_DEFAULT_CAMERA( CHAR * pszCameraDevName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_CAMERA_COUNT_OF_SUPPORT_OUTPUT_FORMATS( PVOID pDevice /*IN*/, ULONG * pCount /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_CAMERA_SUPPORT_OUTPUT_FORMAT( PVOID pDevice /*IN*/, UINT iFmtNum /*IN*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, BOOL * pIsInterleaved /*OUT*/, double * pFrameRate /*OUT*/ );
+
+// CAMERA EXAMPLE:
+// 
+// STEP#01 QCAP_CREATE( "CAMERA", 0, hWindow, &pDevice, TRUE );
+// 
+// STEP#03 QCAP_RUN( pDevice );
+// 
+// STEP#04 QCAP_STOP( pDevice );
+// 
+// STEP#05 QCAP_DESTROY( pDevice );
+
+// SOUNCARD FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SOUNDCARD_ENUMERATION( CHAR * * ppszSoundCardDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SOUNDCARD_ENUMERATION_W( WSTRING * ppwszSoundCardDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_DEFAULT_SOUNDCARD( CHAR * pszMicrophoneDevName /*IN*/, CHAR * pszLineInDevName /*IN*/ );
+
+// SOUNCARD EXAMPLE:
+// 
+// STEP#01 QCAP_CREATE( "SOUNDCARD", 0, hWindow, &pDevice, TRUE );
+// 
+// STEP#02 QCAP_SET_AUDIO_INPUT( pDevice, QCAP_INPUT_TYPE_SOUNDCARD_LINE_IN );
+// 
+// STEP#03 QCAP_RUN( pDevice );
+// 
+// STEP#04 QCAP_STOP( pDevice );
+// 
+// STEP#05 QCAP_DESTROY( pDevice );
+
+// SHARE RECORDING FUNCTIONS (SUPPORT MULTIPLE-STREAMS SHARE RECORDING) (RECNUM: 0 ~ 63) ////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_SHARE_RECORD_STATUS( UINT iRecNum /*IN*/, BOOL * pIsValid /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_PROPERTY( UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, HWND * pAttachedWindow = NULL /*OUT*/, BOOL * pThumbDraw = NULL /*OUT*/, BOOL * pMaintainAspectRatio = NULL /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_PROPERTY( UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nColorSpaceType /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  HWND   hAttachedWindow = NULL /*IN*/,  BOOL   bThumbDraw = FALSE /*IN*/, BOOL   bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordProfile /*OUT*/ /*DEFAULT = BASELINE*/, ULONG * pRecordLevel /*OUT*/ /*DEFAULT = 41*/, ULONG * pRecordEntropy /*OUT*/ /*DEFAULT = CAVLC*/, ULONG * pRecordComplexity /*OUT*/ /*DEFAULT = 0*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pBFrames /*OUT*/ /*DEFAULT = 0*/, BOOL * pIsInterleaved /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pSlices /*OUT*/ /*DEFAULT = 0*/, ULONG * pLayers /*OUT*/ /*DEFAULT = 0*/, ULONG * pSceneCut /*OUT*/ /*DEFAULT = 0*/, BOOL * pMultiThread /*OUT*/ /*DEFAULT = TRUE*/, BOOL * pMBBRC /*OUT*/ /*DEFAULT = FALSE*/, BOOL * pExtBRC /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pMinQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pMaxQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVMaxRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVBufSize /*OUT*/ /*DEFAULT = 0*/, ULONG * pCBRVariation /*OUT*/ /*DEFAULT = 0*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, HWND * pAttachedWindow = NULL /*OUT*/, BOOL * pThumbDraw = NULL /*OUT*/, BOOL * pMaintainAspectRatio = NULL /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nColorSpaceType /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordProfile /*IN*/  /*DEFAULT = BASELINE*/, ULONG   nRecordLevel /*IN*/  /*DEFAULT = 41*/, ULONG   nRecordEntropy /*IN*/  /*DEFAULT = CAVLC*/, ULONG   nRecordComplexity /*IN*/  /*DEFAULT = 0*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nBFrames /*IN*/  /*DEFAULT = 0*/, BOOL   bIsInterleaved /*IN*/  /*DEFAULT = FALSE*/, ULONG   nSlices /*IN*/  /*DEFAULT = 0*/, ULONG   nLayers /*IN*/  /*DEFAULT = 0*/, ULONG   nSceneCut /*IN*/  /*DEFAULT = 0*/, BOOL   bMultiThread /*IN*/  /*DEFAULT = TRUE*/, BOOL   bMBBRC /*IN*/  /*DEFAULT = FALSE*/, BOOL   bExtBRC /*IN*/  /*DEFAULT = FALSE*/, ULONG   nMinQP /*IN*/  /*DEFAULT = 0*/, ULONG   nMaxQP /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVMaxRate /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVBufSize /*IN*/  /*DEFAULT = 0*/, ULONG   nCBRVariation /*IN*/  /*DEFAULT = 0*/, ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  HWND   hAttachedWindow = NULL /*IN*/,  BOOL   bThumbDraw = FALSE /*IN*/, BOOL   bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_DYNAMIC_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_DYNAMIC_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_COPP( UINT iRecNum /*IN*/, BOOL * pEnable /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_COPP( UINT iRecNum /*IN*/, BOOL   bEnable /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_BRIGHTNESS( UINT iRecNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_BRIGHTNESS( UINT iRecNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_CONTRAST( UINT iRecNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_CONTRAST( UINT iRecNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_HUE( UINT iRecNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_HUE( UINT iRecNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_SHARE_RECORD_SATURATION( UINT iRecNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_SATURATION( UINT iRecNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_SHARE_RECORD_PROPERTY( UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_PROPERTY( UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_SHARE_RECORD_SOUND_RENDERER( UINT iRecNum /*IN*/, UINT * pSoundNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_SOUND_RENDERER( UINT iRecNum /*IN*/, UINT   iSoundNum /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_SHARE_RECORD_VOLUME( UINT iRecNum /*IN*/, ULONG * pVolume /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_VOLUME( UINT iRecNum /*IN*/, ULONG   nVolume /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, BOOL bForceKeyFrame = FALSE /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_SHARE_RECORD_COMPRESSION_BUFFER( UINT iRecNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, ULONG bIsKeyFrame /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_SHARE_RECORD_COMPRESSION_BUFFER( UINT iRecNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_SHARE_RECORD_HEADER( UINT iRecNum /*IN*/, CHAR * pszTitle /*IN*/, CHAR * pszArtist /*IN*/, CHAR * pszComments /*IN*/, CHAR * pszGenre /*IN*/, CHAR * pszComposer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_SHARE_RECORD_HEADER_W( UINT iRecNum /*IN*/, WSTRING pwszTitle /*IN*/, WSTRING pwszArtist /*IN*/, WSTRING pwszComments /*IN*/, WSTRING pwszGenre /*IN*/, WSTRING pwszComposer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_METADATA_SHARE_RECORD_DATA_BUFFER( UINT iRecNum /*IN*/, BYTE * pDataBuffer /*IN*/, ULONG nDataBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_TIMESHIFT_SHARE_RECORD( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID * ppPhysicalFileWriter /*OUT*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_SHARE_RECORD( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, DWORD dwFlags = QCAP_RECORD_FLAG_FULL /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_SHARE_RECORD( UINT iRecNum /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESUME_SHARE_RECORD( UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_PAUSE_SHARE_RECORD( UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEGMENT_SHARE_RECORD( UINT iRecNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_SHARE_RECORD_BMP( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_SHARE_RECORD_JPG( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_SHARE_RECORD_BMP_EX( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_SHARE_RECORD_JPG_EX( UINT iRecNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MOVE_OSD_SHARE_RECORD_OBJECT( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_OSD_SHARE_RECORD_TEXT_BOUNDARY( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_OSD_SHARE_RECORD_TEXT_BOUNDARY_W( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_TEXT( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_TEXT_W( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_TEXT_EX( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_TEXT_EX_W( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_PICTURE( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_BUFFER( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_OSD_SHARE_RECORD_BUFFER_EX( UINT iRecNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_DONE_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_FAIL_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_FAIL_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_SNAPSHOT_DONE_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SHARE_RECORD_SNAPSHOT_STREAM_CALLBACK( UINT iRecNum /*IN*/, PF_SHARE_RECORD_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_MEDIA_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_MEDIA_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR TS & FLV FILE FORMAT
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_DECODER_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_DECODER_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DECODER_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DECODER_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_DISPLAY_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_DISPLAY_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DISPLAY_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DISPLAY_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_VIDEO_SHARE_RECORD_MEDIA_TIMER_CALLBACK( UINT iRecNum /*IN*/, PF_VIDEO_SHARE_RECORD_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_SHARE_RECORD_MEDIA_TIMER_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_SHARE_RECORD_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// VIDEO 3D SHARE RECORDING FUNCTIONS (SUPPORT MULTIPLE-STREAMS SHARE RECORDING) (RECNUM: 0 ~ 63) ///////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_STEREO_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nStereoBufferType = QCAP_3D_STEREO_BUFFER_SIDE_BY_SIDE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_STEREO_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, ULONG nStereoBufferType = QCAP_3D_STEREO_BUFFER_SIDE_BY_SIDE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_L_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_L_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_R_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_R_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_3D_SHARE_RECORD_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, ULONG nStereoDisplayMode = QCAP_3D_STEREO_DISPLAY_MODE_LINE_BY_LINE /*IN*/, BOOL bLeftRightSwap = FALSE /*IN*/, BOOL bForceKeyFrame = FALSE /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+// AUDIO MIXING/TRACKS SHARE RECORDING FUNCTIONS (SUPPORT MULTIPLE-STREAMS SHARE RECORDING) (RECNUM: 0 ~ 63) (TRACKNUM: 0 ~ 3) //////////////////////////////////////////////////////////////////////
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_MX_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG * pTracks /*OUT*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_MX_SHARE_RECORD_PROPERTY_EX( UINT iRecNum /*IN*/, ULONG   nTracks /*IN*/,  ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_MX_SHARE_RECORD_MIXING_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, UINT iMixNum /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_MX_SHARE_RECORD_MIXING_UNCOMPRESSION_BUFFER_EX( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, UINT iMixNum /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_MX_SHARE_RECORD_UNCOMPRESSION_BUFFER( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime = 0.0 /*IN*/, BOOL bEnableSyncMixer = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_AUDIO_MX_SHARE_RECORD_COMPRESSION_BUFFER( UINT iRecNum /*IN*/, UINT iTrackNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_MX_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_MX_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_AUDIO_DECODER_MX_SHARE_RECORD_CALLBACK( UINT iRecNum /*IN*/, PF_AUDIO_DECODER_MX_SHARE_RECORD_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # BROADCASTING SERVER FUNCTIONS (RTSP/RTMP/HLS/TS/MMS) (2D/3D)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_SERVER_GET_CUSTOM_PROPERTY_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*OUT*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_SERVER_SET_CUSTOM_PROPERTY_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_SERVER_SNAPSHOT_DONE_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_SERVER_SNAPSHOT_STREAM_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, BOOL bIsKeyFrame /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_MX_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_MX_BROADCAST_SERVER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, double dDelayTime /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK)( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, double dDelayTime /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_BROADCAST_SERVER_STATUS( UINT iSvrNum /*IN*/ /*0 ~ 63*/, BOOL * pIsValid /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |2D|3D|  |*/ QCAP_CREATE_BROADCAST_RTSP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nNetworkPort_RTSP = 554 /*IN*/, ULONG nNetworkPort_RTSPOverHTTP = 0 /*IN*/ /*DEFAULT = TURN OFF*/, BOOL bEnableMulticasting = FALSE /*IN*/, BOOL bEnableUltraLowLatency = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |2D|3D|  |*/ QCAP_CREATE_BROADCAST_RTSP_RAW_UDP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nNetworkPort_RTSP = 554 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |HLS|  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_HLS_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszWebServerRootFolderPath /*IN*/, CHAR * pszSubFolderPath /*IN*/, ULONG nSegmentDuration = 1000 /*IN*/, BOOL bResumeSegmentNum = FALSE /*IN*/, ULONG nSegmentPlaylistCount = 3 /*IN*/, BOOL bSegmentPreserveAll = FALSE /*IN*/, CHAR * pszWebServerIP = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_RTMP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nNetworkPort_RTMP = 1935 /*IN*/, ULONG nNetworkPort_RTMPOverHTTP = 0 /*IN*/ /*DEFAULT = TURN OFF*/, CHAR * pszServerName = NULL /*IN*/ /*DEFAULT = "flvplayback"*/, CHAR * pszMediaFolderPath = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_RTMP_SERVER_EX( UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nNetworkPort_RTMP = 1935 /*IN*/, ULONG nNetworkPort_RTMPOverHTTP = 0 /*IN*/ /*DEFAULT = TURN OFF*/, CHAR * pszServerName = NULL /*IN*/ /*DEFAULT = "flvplayback"*/, CHAR * pszMediaFolderPath = NULL /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_RTMP_WEB_PORTAL_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_RTMP_WEB_PORTAL_SERVER_EX( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/, CHAR * pszEncryptKey = NULL /*IN*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_FACEBOOK_RTMP_WEB_PORTAL_SERVER( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_FACEBOOK_RTMP_WEB_PORTAL_SERVER_EX( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_YOUTUBE_RTMP_WEB_PORTAL_SERVER( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_YOUTUBE_RTMP_WEB_PORTAL_SERVER_EX( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TWITCH_RTMP_WEB_PORTAL_SERVER( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |RTMP|   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TWITCH_RTMP_WEB_PORTAL_SERVER_EX( UINT iSvrNum /*IN*/, CHAR * pszAccount /*IN*/, CHAR * pszPassword /*IN*/, PVOID * ppServer /*OUT*/, ULONG nConnectionTimeout = 10000 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |  |MMS|2D|  |  |*/ QCAP_CREATE_BROADCAST_MMS_WEB_PORTAL_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszAccount = NULL /*IN*/, CHAR * pszPassword = NULL /*IN*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_RTP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, BOOL bEnableCBRMode = TRUE /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_UDP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, BOOL bEnableCBRMode = TRUE /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_TCP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, PVOID * ppServer /*OUT*/, ULONG nNetworkPort_TCP = 1234 /*IN*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_HTTP_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, PVOID * ppServer /*OUT*/, ULONG nNetworkPort_HTTP = 8888 /*IN*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_SRT_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, PVOID * ppServer /*OUT*/, ULONG nNetworkPort_SRT = 1234 /*IN*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |TS|   |2D|  |  |*/ QCAP_CREATE_BROADCAST_TS_OVER_TCP_PASSIVE_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppServer /*OUT*/, ULONG nServiceID = 1 /*IN*/, CHAR * pszServiceName = NULL /*IN*/, CHAR * pszServiceProviderName = NULL /*IN*/, ULONG nTransferBitRate = 0 /*IN*/ /*0 = FREE*/, ULONG nOriginalNetworkID = 1 /*IN*/, ULONG nTransportStreamID = 1 /*IN*/, ULONG nPMT_PID = 4096 /*IN*/, ULONG nPCR_PID = 4097 /*IN*/, ULONG nVideo_PID = 256 /*IN*/, ULONG nAudio_PID = 257 /*IN*/, ULONG nVideo_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nAudio_CodecID = 0 /*IN*/ /*0 = AUTO*/, ULONG nPCRInterval = 0 /*IN*/ /*ms*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |   |  |   |2D|  |  |*/ QCAP_CREATE_BROADCAST_NDI_SERVER( UINT iSvrNum /*IN*/ /*0 ~ 63*/, CHAR * pszNDIName /*IN*/, CHAR * pszGroupName /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszConnectionMetadata  = NULL /*IN*/ /*XML*/ ); // TOTOAL SESSION = 1
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_DESTROY_BROADCAST_SERVER( PVOID pServer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_START_BROADCAST_SERVER( PVOID pServer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_STOP_BROADCAST_SERVER( PVOID pServer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|  |  |*/ QCAP_SET_SESSION_BROADCAST_SERVER_SOURCE( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PVOID pDevice /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|  |  |*/ QCAP_SET_SESSION_BROADCAST_SERVER_SOURCE_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PVOID pDevice /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_SESSION_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * * ppszSessionName /*OUT*/, ULONG * pVideoDelayLiveDuration /*OUT*/ /*ms*/, ULONG * pAudioDelayLiveDuration /*OUT*/ /*ms*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_SESSION_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszSessionName /*IN*/ /*DEFAULT = "session%d.mpg"*/, ULONG nVideoDelayLiveDuration /*IN*/ /*ms*/, ULONG nAudioDelayLiveDuration /*IN*/ /*ms*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_VIDEO_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, HWND * pAttachedWindow = NULL /*OUT*/, BOOL * pThumbDraw = NULL /*OUT*/, BOOL * pMaintainAspectRatio = NULL /*OUT*/, DWORD * pFlags = NULL /*OUT*/                    );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nColorSpaceType /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  HWND   hAttachedWindow = NULL /*IN*/,  BOOL   bThumbDraw = FALSE /*IN*/, BOOL   bMaintainAspectRatio = FALSE /*IN*/, DWORD  dwFlags = QCAP_BROADCAST_FLAG_FULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_VIDEO_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordProfile /*OUT*/ /*DEFAULT = BASELINE*/, ULONG * pRecordLevel /*OUT*/ /*DEFAULT = 41*/, ULONG * pRecordEntropy /*OUT*/ /*DEFAULT = CAVLC*/, ULONG * pRecordComplexity /*OUT*/ /*DEFAULT = 0*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pBFrames /*OUT*/ /*DEFAULT = 0*/, BOOL * pIsInterleaved /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pSlices /*OUT*/ /*DEFAULT = 0*/, ULONG * pLayers /*OUT*/ /*DEFAULT = 0*/, ULONG * pSceneCut /*OUT*/ /*DEFAULT = 0*/, BOOL * pMultiThread /*OUT*/ /*DEFAULT = TRUE*/, BOOL * pMBBRC /*OUT*/ /*DEFAULT = FALSE*/, BOOL * pExtBRC /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pMinQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pMaxQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVMaxRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVBufSize /*OUT*/ /*DEFAULT = 0*/, ULONG * pCBRVariation /*OUT*/ /*DEFAULT = 0*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/, HWND * pAttachedWindow = NULL /*OUT*/, BOOL * pThumbDraw = NULL /*OUT*/, BOOL * pMaintainAspectRatio = NULL /*OUT*/, DWORD * pFlags = NULL /*OUT*/                    );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nColorSpaceType /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordProfile /*IN*/  /*DEFAULT = BASELINE*/, ULONG   nRecordLevel /*IN*/  /*DEFAULT = 41*/, ULONG   nRecordEntropy /*IN*/  /*DEFAULT = CAVLC*/, ULONG   nRecordComplexity /*IN*/  /*DEFAULT = 0*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nBFrames /*IN*/  /*DEFAULT = 0*/, BOOL   bIsInterleaved /*IN*/  /*DEFAULT = FALSE*/, ULONG   nSlices /*IN*/  /*DEFAULT = 0*/, ULONG   nLayers /*IN*/  /*DEFAULT = 0*/, ULONG   nSceneCut /*IN*/  /*DEFAULT = 0*/, BOOL   bMultiThread /*IN*/  /*DEFAULT = TRUE*/, BOOL   bMBBRC /*IN*/  /*DEFAULT = FALSE*/, BOOL   bExtBRC /*IN*/  /*DEFAULT = FALSE*/, ULONG   nMinQP /*IN*/  /*DEFAULT = 0*/, ULONG   nMaxQP /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVMaxRate /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVBufSize /*IN*/  /*DEFAULT = 0*/, ULONG   nCBRVariation /*IN*/  /*DEFAULT = 0*/, ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/,  HWND   hAttachedWindow = NULL /*IN*/,  BOOL   bThumbDraw = FALSE /*IN*/, BOOL   bMaintainAspectRatio = FALSE /*IN*/, DWORD  dwFlags = QCAP_BROADCAST_FLAG_FULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_VIDEO_BROADCAST_SERVER_DYNAMIC_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_DYNAMIC_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_AUDIO_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_AUDIO_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_GET_AUDIO_MX_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pTracks /*OUT*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_SET_AUDIO_MX_BROADCAST_SERVER_PROPERTY_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nTracks /*IN*/,  ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_AUDIO_BROADCAST_SERVER_SOUND_RENDERER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT * pSoundNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_SOUND_RENDERER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT   iSoundNum /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_AUDIO_BROADCAST_SERVER_VOLUME( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG * pVolume /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_VOLUME( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG   nVolume /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_VIDEO_BROADCAST_SERVER_NETWORK_QOS_STATUS( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BOOL * pIsTransferBusy /*OUT*/, ULONG * pQueueFrames /*OUT*/, ULONG * pQueueBytes /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_AUDIO_BROADCAST_SERVER_NETWORK_QOS_STATUS( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BOOL * pIsTransferBusy /*OUT*/, ULONG * pQueueFrames /*OUT*/, ULONG * pQueueBytes /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, BOOL bForceKeyFrame = FALSE /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_VIDEO_BROADCAST_SERVER_COMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, ULONG bIsKeyFrame /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_AUDIO_BROADCAST_SERVER_COMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_STEREO_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nStereoBufferType = QCAP_3D_STEREO_BUFFER_SIDE_BY_SIDE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_STEREO_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, ULONG nStereoBufferType = QCAP_3D_STEREO_BUFFER_SIDE_BY_SIDE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_L_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_L_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_R_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_R_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |  |3D|  |*/ QCAP_SET_VIDEO_3D_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, ULONG nStereoDisplayMode = QCAP_3D_STEREO_DISPLAY_MODE_LINE_BY_LINE /*IN*/, BOOL bLeftRightSwap = FALSE /*IN*/, BOOL bForceKeyFrame = FALSE /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_SET_AUDIO_MX_BROADCAST_SERVER_MIXING_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, UINT iMixNum /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_SET_AUDIO_MX_BROADCAST_SERVER_MIXING_UNCOMPRESSION_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, UINT iMixNum /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_SET_AUDIO_MX_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/, BOOL bEnableSyncMixer = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_SET_AUDIO_MX_BROADCAST_SERVER_COMPRESSION_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_CLEAR_VIDEO_BROADCAST_SERVER_DELAY_LIVE_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BOOL bEnableClear /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, ULONG bIsKeyFrame /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_CLEAR_AUDIO_BROADCAST_SERVER_DELAY_LIVE_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, BOOL bEnableClear /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_CLEAR_AUDIO_MX_BROADCAST_SERVER_DELAY_LIVE_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iTrackNum /*IN*/, BOOL bEnableClear /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ /*HLS NEED IT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SNAPSHOT_BROADCAST_SERVER_BMP( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SNAPSHOT_BROADCAST_SERVER_JPG( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SNAPSHOT_BROADCAST_SERVER_BMP_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SNAPSHOT_BROADCAST_SERVER_JPG_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_MOVE_OSD_BROADCAST_SERVER_OBJECT( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_OSD_BROADCAST_SERVER_TEXT_BOUNDARY( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_GET_OSD_BROADCAST_SERVER_TEXT_BOUNDARY_W( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_TEXT( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_TEXT_W( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_TEXT_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_TEXT_EX_W( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_PICTURE( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_BUFFER( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_SET_OSD_BROADCAST_SERVER_BUFFER_EX( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |2D|3D|  |*/ QCAP_REGISTER_BROADCAST_SERVER_GET_CUSTOM_PROPERTY_CALLBACK( PVOID pServer /*IN*/, PF_BROADCAST_SERVER_GET_CUSTOM_PROPERTY_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |   |  |   |2D|3D|  |*/ QCAP_REGISTER_BROADCAST_SERVER_SET_CUSTOM_PROPERTY_CALLBACK( PVOID pServer /*IN*/, PF_BROADCAST_SERVER_SET_CUSTOM_PROPERTY_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_BROADCAST_SERVER_SNAPSHOT_DONE_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_BROADCAST_SERVER_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_BROADCAST_SERVER_SNAPSHOT_STREAM_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_BROADCAST_SERVER_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_VIDEO_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_VIDEO_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_AUDIO_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_AUDIO_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_VIDEO_DECODER_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_VIDEO_DECODER_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_AUDIO_DECODER_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_AUDIO_DECODER_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_REGISTER_AUDIO_MX_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_AUDIO_MX_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|MX|*/ QCAP_REGISTER_AUDIO_DECODER_MX_BROADCAST_SERVER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_AUDIO_DECODER_MX_BROADCAST_SERVER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_VIDEO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_VIDEO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|HLS|TS|MMS|2D|3D|  |*/ QCAP_REGISTER_AUDIO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK( PVOID pServer /*IN*/, UINT iSessionNum /*IN*/, PF_AUDIO_BROADCAST_SERVER_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// BROADCASTING RTSP SERVER EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_BROADCAST_RTSP_SERVER( 0, 4 /*4 CHANNELS*/, &pServer, "root", "root", 554 );
+//
+//         CH01 URL -> rtsp://root:root@127.0.0.1:554/session0.mpg
+//
+//         CH02 URL -> rtsp://root:root@127.0.0.1:554/session1.mpg
+//
+//         CH03 URL -> rtsp://root:root@127.0.0.1:554/session2.mpg
+//
+//         CH04 URL -> rtsp://root:root@127.0.0.1:554/session3.mpg
+// 
+// STEP#02 QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY( pServer, 0 /*CH01*/, QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK, QCAP_ENCODER_FORMAT_H264, QCAP_COLORSPACE_TYPE_YUY2, 480, 270, 30, QCAP_RECORD_MODE_CBR, 8000, 1000000, 30, 0, 0, NULL, FALSE, QCAP_BROADCAST_FLAG_NETWORK | QCAP_BROADCAST_FLAG_ENCODE );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY( pServer, 1 /*CH02*/, QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK, QCAP_ENCODER_FORMAT_H264, QCAP_COLORSPACE_TYPE_YUY2, 480, 270, 30, QCAP_RECORD_MODE_CBR, 8000, 1000000, 30, 0, 0, NULL, FALSE, QCAP_BROADCAST_FLAG_NETWORK | QCAP_BROADCAST_FLAG_ENCODE );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY( pServer, 2 /*CH03*/, QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK, QCAP_ENCODER_FORMAT_H264, QCAP_COLORSPACE_TYPE_YUY2, 480, 270, 30, QCAP_RECORD_MODE_CBR, 8000, 1000000, 30, 0, 0, NULL, FALSE, QCAP_BROADCAST_FLAG_NETWORK | QCAP_BROADCAST_FLAG_ENCODE );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_PROPERTY( pServer, 3 /*CH04*/, QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK, QCAP_ENCODER_FORMAT_H264, QCAP_COLORSPACE_TYPE_YUY2, 480, 270, 30, QCAP_RECORD_MODE_CBR, 8000, 1000000, 30, 0, 0, NULL, FALSE, QCAP_BROADCAST_FLAG_NETWORK | QCAP_BROADCAST_FLAG_ENCODE );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY( pServer, 0 /*CH01*/, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC, 2, 16, 48000, 0 );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY( pServer, 1 /*CH02*/, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC, 2, 16, 48000, 0 );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY( pServer, 2 /*CH03*/, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC, 2, 16, 48000, 0 );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_PROPERTY( pServer, 3 /*CH04*/, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC, 2, 16, 48000, 0 );
+//
+// STEP#03 QCAP_START_BROADCAST_SERVER( pServer );
+//
+// STEP#04 QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 0 /*CH01*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferA, nFrameBufferLenA );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 1 /*CH02*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferB, nFrameBufferLenB );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 2 /*CH03*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferC, nFrameBufferLenC );
+//
+//         QCAP_SET_VIDEO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 3 /*CH04*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferD, nFrameBufferLenD );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 0 /*CH01*/, pFrameBufferA, nFrameBufferLenA );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 1 /*CH02*/, pFrameBufferB, nFrameBufferLenB );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 2 /*CH03*/, pFrameBufferC, nFrameBufferLenC );
+//
+//         QCAP_SET_AUDIO_BROADCAST_SERVER_UNCOMPRESSION_BUFFER( pServer, 3 /*CH04*/, pFrameBufferD, nFrameBufferLenD );
+//
+// STEP#05 QCAP_STOP_BROADCAST_SERVER( pServer );
+//
+// STEP#06 QCAP_DRSTROY_BROADCAST_SERVER( pServer );
+
+// BROADCASTING RTMP SERVER EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_BROADCAST_RTMP_SERVER( 0, 4 /*4 CHANNELS*/, &pServer, NULL, NULL, 1935 );
+//
+//         CH01 URL -> rtmp://xxx.xxx.xxx.xxx:1935/flvplayback/session0.mpg (HERE, xxx.xxx.xxx.xxx IS YOUR WEB SERVER ADDRESS)
+//
+//         CH02 URL -> rtmp://xxx.xxx.xxx.xxx:1935/flvplayback/session1.mpg
+//
+//         CH03 URL -> rtmp://xxx.xxx.xxx.xxx:1935/flvplayback/session2.mpg
+//
+//         CH04 URL -> rtmp://xxx.xxx.xxx.xxx:1935/flvplayback/session3.mpg
+
+// BROADCASTING HLS SERVER EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_BROADCAST_HLS_SERVER( 0, 4 /*4 CHANNELS*/, &pServer, "C:\\AppServ\\www\\", "hls\\", 3000 ); // HERE, C:\\AppServ\\www\\ IS YOUR WEB SERVER ROOT FOLDER, hls\\ is SUB FOLDER TO SAVE HLS FILES
+//
+//         CH01 URL -> http://xxx.xxx.xxx.xxx/hls/session0.m3u8 (HERE, xxx.xxx.xxx.xxx IS YOUR WEB SERVER ADDRESS)
+//
+//         CH02 URL -> http://xxx.xxx.xxx.xxx/hls/session1.m3u8
+//
+//         CH03 URL -> http://xxx.xxx.xxx.xxx/hls/session2.m3u8
+//
+//         CH04 URL -> http://xxx.xxx.xxx.xxx/hls/session3.m3u8
+
+// BROADCASTING UDP SERVER EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_BROADCAST_TS_OVER_UDP_SERVER( 0, "udp://xxx.xxx.xxx.xxx:xxx", &pServer );
+
+// ##########################################################################################################################################################################################
+// #
+// # BROADCASTING CLIENT FUNCTIONS (RTSP/RTMP/TS) (2D/3D)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_MEDIAINFO_CALLBACK)( PVOID pClient /*IN*/, ULONG nTotalStreams /*IN*/, UINT iStreamNum /*IN*/, ULONG nStream_PID /*IN*/, ULONG nProgram_PID /*IN*/, ULONG nVideoWidth /*IN*/, ULONG nVideoHeight /*IN*/, BOOL bVideoIsInterleaved /*IN*/, double dVideoFrameRate /*IN*/, ULONG nAudioChannels /*IN*/, ULONG nAudioBitsPerSample /*IN*/, ULONG nAudioSampleFrequency /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_CONNECTED_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nVideoWidth /*IN*/, ULONG nVideoHeight /*IN*/, BOOL bVideoIsInterleaved /*IN*/, double dVideoFrameRate /*IN*/, ULONG nAudioChannels /*IN*/, ULONG nAudioBitsPerSample /*IN*/, ULONG nAudioSampleFrequency /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_FAIL_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, QRESULT nErrorStatus /*IN*/, DWORD nErrorCode /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_RECORD_DONE_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_RECORD_FAIL_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, QRESULT nErrorStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_SNAPSHOT_DONE_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_BROADCAST_CLIENT_SNAPSHOT_STREAM_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_BROADCAST_CLIENT_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, BOOL bIsKeyFrame /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_BROADCAST_CLIENT_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_BROADCAST_CLIENT_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_BROADCAST_CLIENT_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_3D_BROADCAST_CLIENT_CALLBACK)( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iChNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |  |    |NDI|  |  |*/ QCAP_BROADCAST_NDI_CLIENT_ENUMERATION( CHAR * * ppszNDIName /*OUT*/, CHAR * * ppszGroupName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|   |2D|  |*/ QCAP_CREATE_BROADCAST_CLIENT( UINT iCliNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, HWND hAttachedWindow = NULL /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|   |2D|  |*/ QCAP_CREATE_BROADCAST_CLIENT_EX( UINT iCliNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, HWND hAttachedWindow = NULL /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |  |3D|*/ QCAP_CREATE_3D_BROADCAST_CLIENT( UINT iCliNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, HWND hAttachedWindowL = NULL /*IN*/, BOOL bThumbDrawL = FALSE /*IN*/, BOOL bMaintainAspectRatioL = FALSE /*IN*/, HWND hAttachedWindowR = NULL /*IN*/, BOOL bThumbDrawR = FALSE /*IN*/, BOOL bMaintainAspectRatioR = FALSE /*IN*/ ); // ONLY FOR RTSP
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |  |3D|*/ QCAP_CREATE_3D_BROADCAST_CLIENT_EX( UINT iCliNum /*IN*/ /*0 ~ 63*/, CHAR * pszURL /*IN*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/, HWND hAttachedWindowL = NULL /*IN*/, BOOL bThumbDrawL = FALSE /*IN*/, BOOL bMaintainAspectRatioL = FALSE /*IN*/, HWND hAttachedWindowR = NULL /*IN*/, BOOL bThumbDrawR = FALSE /*IN*/, BOOL bMaintainAspectRatioR = FALSE /*IN*/ ); // ONLY FOR RTSP
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |  |    |NDI|2D|  |*/ QCAP_CREATE_BROADCAST_NDI_CLIENT( UINT iCliNum /*IN*/ /*0 ~ 63*/, CHAR * pszNDIName /*IN*/, CHAR * pszGroupName /*IN*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, HWND hAttachedWindow = NULL /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_DESTROY_BROADCAST_CLIENT( PVOID pClient /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_START_BROADCAST_CLIENT( PVOID pClient /*IN*/, ULONG nProtocol = QCAP_BROADCAST_PROTOCOL_TCP /*IN*/ /*FOR RTSP ONLY*/, ULONG nReconnectionTimeout = 3000 /*IN*/ /*ms*/, ULONG nDelayQueueDuration = 0 /*IN*/ /*ms*/ ); // BPS >= 12MBPS, SUGGEST TO SUE QCAP_BROADCAST_PROTOCOL_TCP
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_START_BROADCAST_CLIENT_EX( PVOID pClient /*IN*/, ULONG nProtocol = QCAP_BROADCAST_PROTOCOL_TCP /*IN*/ /*FOR RTSP ONLY*/, ULONG nReconnectionTimeout = 3000 /*IN*/ /*ms*/, ULONG nDelayQueueDuration = 0 /*IN*/ /*ms*/, BOOL bEnableUltraLowLatency = FALSE /*IN*/ /*FOR RTSP ONLY*/, ULONG nAnalyzeDuration = 0 /*IN*/ /*FOR TS ONLY, MPTS = 10000*/ /*ms*/, ULONG nProbeDurationSizeKB = 0 /*IN*/ /*FOR TS ONLY, MPTS = 100000 KB*/, CHAR * pszEncryptKey = NULL /*IN*/ /*FOR RTMP ONLY*/ ); // BPS >= 12MBPS, SUGGEST TO SUE QCAP_BROADCAST_PROTOCOL_TCP
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_STOP_BROADCAST_CLIENT( PVOID pClient /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |TS|MPTS|   |2D|  |*/ QCAP_GET_BROADCAST_CLIENT_OUTPUT_STREAMS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pVideoStream_PID /*OUT*/, ULONG * pAudioStream_PID /*OUT*/, HWND * pAttachedWindow = NULL /*OUT*/, BOOL * pThumbDraw = NULL /*OUT*/, BOOL * pMaintainAspectRatio = NULL /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|    |    |TS|MPTS|   |2D|  |*/ QCAP_SET_BROADCAST_CLIENT_OUTPUT_STREAMS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nVideoStream_PID /*IN*/, ULONG nAudioStream_PID /*IN*/, HWND hAttachedWindow = NULL /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_DIAGNOSE_VIDEO_BROADCAST_CLIENT_STREAM_STATUS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL * pIsStill /*OUT*/, ULONG nStillThreshold = 64 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_DIAGNOSE_AUDIO_BROADCAST_CLIENT_STREAM_STATUS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, double * pVolumeDB_L /*OUT*/ /*RANGE = -100 ~ 0 (DB)*/, double * pVolumeDB_R /*OUT*/ /*RANGE = -100 ~ 0 (DB)*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |  |3D|*/ QCAP_GET_VIDEO_3D_BROADCAST_CLIENT_DISPLAY_MODE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pStereoDisplayMode /*OUT*/, BOOL * pLeftRightSwap /*OUT*/ ); 
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |  |3D|*/ QCAP_SET_VIDEO_3D_BROADCAST_CLIENT_DISPLAY_MODE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nStereoDisplayMode = QCAP_3D_STEREO_DISPLAY_MODE_LINE_BY_LINE /*IN*/, BOOL bLeftRightSwap = FALSE /*IN*/ ); 
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_DEINTERLACE_TYPE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pType /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_DEINTERLACE_TYPE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nType /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_DEINTERLACE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL * pEnable /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_DEINTERLACE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL bEnable /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_REGION_DISPLAY( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pCropX /*OUT*/, ULONG * pCropY /*OUT*/, ULONG * pCropW /*OUT*/, ULONG * pCropH /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_REGION_DISPLAY( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_MIRROR( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL * pHorizontalMirror /*OUT*/, BOOL * pVerticalMirror /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_MIRROR( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL bHorizontalMirror /*IN*/, BOOL bVerticalMirror /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_ASPECT_RATIO( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL * pMaintainAspectRatio /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_ASPECT_RATIO( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL bMaintainAspectRatio /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_BRIGHTNESS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_BRIGHTNESS( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_CONTRAST( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_CONTRAST( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_HUE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_HUE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_VIDEO_BROADCAST_CLIENT_SATURATION( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_VIDEO_BROADCAST_CLIENT_SATURATION( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_AUDIO_BROADCAST_CLIENT_SOUND_RENDERER( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT * pSoundNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_AUDIO_BROADCAST_CLIENT_SOUND_RENDERER( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iSoundNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_AUDIO_BROADCAST_CLIENT_VOLUME( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG * pVolume /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_AUDIO_BROADCAST_CLIENT_VOLUME( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, ULONG nVolume /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_START_BROADCAST_CLIENT_CLONE_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathNameA /*IN*/, CHAR * pszFilePathNameB /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_START_BROADCAST_CLIENT_TIMESHIFT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID * ppPhysicalFileWriter /*OUT*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_START_BROADCAST_CLIENT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, double dVideoDelayTime = 0.0 /*IN*/, double dAudioDelayTime = 0.0 /*IN*/, double dSegmentDurationTime = 0.0 /*IN*/, ULONG nSegmentDurationSizeKB = 0 /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_STOP_BROADCAST_CLIENT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_RESUME_BROADCAST_CLIENT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_PAUSE_BROADCAST_CLIENT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SEGMENT_BROADCAST_CLIENT_RECORD( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SNAPSHOT_BROADCAST_CLIENT_BMP( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SNAPSHOT_BROADCAST_CLIENT_JPG( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SNAPSHOT_BROADCAST_CLIENT_BMP_EX( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SNAPSHOT_BROADCAST_CLIENT_JPG_EX( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_MOVE_OSD_BROADCAST_CLIENT_OBJECT( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_OSD_BROADCAST_CLIENT_TEXT_BOUNDARY( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_GET_OSD_BROADCAST_CLIENT_TEXT_BOUNDARY_W( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_TEXT( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_TEXT_W( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_TEXT_EX( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_TEXT_EX_W( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_PICTURE( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_BUFFER( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_SET_OSD_BROADCAST_CLIENT_BUFFER_EX( PVOID pClient /*IN*/, UINT iSessionNum /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |2D|3D|*/ QCAP_GET_BROADCAST_CLIENT_CUSTOM_PROPERTY( PVOID pClient /*IN*/, CHAR * pszProperty /*IN*/, CHAR * * ppszValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |2D|3D|*/ QCAP_SET_BROADCAST_CLIENT_CUSTOM_PROPERTY( PVOID pClient /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_MEDIAINFO_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_MEDIAINFO_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_CONNECTED_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_CONNECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_FAIL_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_FAIL_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_RECORD_DONE_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_RECORD_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_RECORD_FAIL_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_RECORD_FAIL_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_SNAPSHOT_DONE_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_BROADCAST_CLIENT_SNAPSHOT_STREAM_CALLBACK( PVOID pClient /*IN*/, PF_BROADCAST_CLIENT_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_VIDEO_BROADCAST_CLIENT_CALLBACK( PVOID pClient /*IN*/, PF_VIDEO_BROADCAST_CLIENT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_AUDIO_BROADCAST_CLIENT_CALLBACK( PVOID pClient /*IN*/, PF_AUDIO_BROADCAST_CLIENT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_VIDEO_DECODER_BROADCAST_CLIENT_CALLBACK( PVOID pClient /*IN*/, PF_VIDEO_DECODER_BROADCAST_CLIENT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|RTMP|TS|MPTS|NDI|2D|3D|*/ QCAP_REGISTER_AUDIO_DECODER_BROADCAST_CLIENT_CALLBACK( PVOID pClient /*IN*/, PF_AUDIO_DECODER_BROADCAST_CLIENT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|RTSP|    |  |    |   |  |3D|*/ QCAP_REGISTER_VIDEO_DECODER_3D_BROADCAST_CLIENT_CALLBACK( PVOID pClient /*IN*/, PF_VIDEO_DECODER_3D_BROADCAST_CLIENT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// BROADCASTING CLIENT EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_BROADCAST_CLIENT( 0, "rtsp://root:root@127.0.0.1:554/session0.mpg", &pClient, QCAP_DECODER_TYPE_SOFTWARE, hWindow, TRUE );
+//
+// STEP#02 QCAP_REGISTER_VIDEO_BROADCAST_CLIENT_CALLBACK( pClient, on_process_video_stream, this );
+//
+//         QCAP_REGISTER_AUDIO_BROADCAST_CLIENT_CALLBACK( pClient, on_process_audio_stream, this );
+//
+// STEP#03 QCAP_START_BROADCAST_CLIENT( pClient );
+//
+// STEP#04 QCAP_STOP_BROADCAST_CLIENT( pClient );
+//
+// STEP#05 QCAP_DESTROY_BROADCAST_CLIENT( pClient );
+
+// ##########################################################################################################################################################################################
+// #
+// # ONVIF COMMUNICATION FUNCTIONS (SERVER/EMULATOR/CLIENT)
+// #
+// ##########################################################################################################################################################################################
+//
+// COMMUNICATION SERVER FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_SERVER_GET_CUSTOM_PROPERTY_CALLBACK)( PVOID pServer /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*OUT*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_SERVER_SET_CUSTOM_PROPERTY_CALLBACK)( PVOID pServer /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_SERVER_PROFILE_VIDEO_SETUP_CALLBACK)( PVOID pServer /*IN*/, UINT iProNum /*IN*/, ULONG nEncoderFormat /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, ULONG nFrameRate /*IN*/, ULONG nRecordMode /*IN*/, ULONG nQuality /*IN*/, ULONG nBitRate /*IN*/, ULONG nGOP /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_SERVER_PROFILE_AUDIO_SETUP_CALLBACK)( PVOID pServer /*IN*/, UINT iProNum /*IN*/, ULONG nEncoderFormat /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, ULONG nBitRate /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_COMMUNICATION_ONVIF_SERVER( ULONG nTotalVideoSources /*IN*/, ULONG nTotalAudioSources /*IN*/, ULONG nTotalVideoEncoders /*IN*/, ULONG nTotalAudioEncoders /*IN*/, ULONG nTotalProfiles /*IN*/, PVOID * ppServer /*OUT*/, CHAR * pszName = NULL /*IN*/, CHAR * pszLocation = NULL /*IN*/, CHAR * pszManufacturer = NULL /*IN*/, CHAR * pszModel = NULL /*IN*/, CHAR * pszHardwareVersion = NULL /*IN*/, CHAR * pszFirmwareVersion = NULL /*IN*/, CHAR * pszDeviceID = NULL /*IN*/, CHAR * pszRootAccount = NULL /*IN*/, CHAR * pszRootPassword = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_COMMUNICATION_SERVER( PVOID pServer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_COMMUNICATION_SERVER( PVOID pServer /*IN*/, ULONG nNetworkPort = 8001 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_COMMUNICATION_SERVER( PVOID pServer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_SERVER_VIDEO_SOURCE( PVOID pServer /*IN*/, UINT iVidSrcNum /*IN*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, ULONG * pFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_SERVER_VIDEO_SOURCE( PVOID pServer /*IN*/, UINT iVidSrcNum /*IN*/, ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  ULONG   nFrameRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_SERVER_AUDIO_SOURCE( PVOID pServer /*IN*/, UINT iAudSrcNum /*IN*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_SERVER_AUDIO_SOURCE( PVOID pServer /*IN*/, UINT iAudSrcNum /*IN*/, ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_SERVER_VIDEO_ENCODER( PVOID pServer /*IN*/, UINT iVidEncNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, ULONG * pFrameRate_Min /*OUT*/, ULONG * pFrameRate_Max /*OUT*/, ULONG * pFrameRate_Default /*OUT*/, ULONG * pRecordMode_Min /*OUT*/, ULONG * pRecordMode_Max /*OUT*/, ULONG * pRecordMode_Default /*OUT*/, ULONG * pQuality_Min /*OUT*/, ULONG * pQuality_Max /*OUT*/, ULONG * pQuality_Default /*OUT*/, ULONG * pBitRate_Min /*OUT*/, ULONG * pBitRate_Max /*OUT*/, ULONG * pBitRate_Default /*OUT*/, ULONG * pGOP_Min /*OUT*/, ULONG * pGOP_Max /*OUT*/, ULONG * pGOP_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_SERVER_VIDEO_ENCODER( PVOID pServer /*IN*/, UINT iVidEncNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  ULONG   nFrameRate_Min /*IN*/,  ULONG   nFrameRate_Max /*IN*/,  ULONG   nFrameRate_Default /*IN*/,  ULONG   nRecordMode_Min /*IN*/,  ULONG   nRecordMode_Max /*IN*/,  ULONG   nRecordMode_Default /*IN*/,  ULONG   nQuality_Min /*IN*/,  ULONG   nQuality_Max /*IN*/,  ULONG   nQuality_Default /*IN*/,  ULONG   nBitRate_Min /*IN*/,  ULONG   nBitRate_Max /*IN*/,  ULONG   nBitRate_Default /*IN*/,  ULONG   nGOP_Min /*IN*/,  ULONG   nGOP_Max /*IN*/,  ULONG   nGOP_Default /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_SERVER_AUDIO_ENCODER( PVOID pServer /*IN*/, UINT iAudEncNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate_Min /*OUT*/, ULONG * pBitRate_Max /*OUT*/, ULONG * pBitRate_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_SERVER_AUDIO_ENCODER( PVOID pServer /*IN*/, UINT iAudEncNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate_Min /*IN*/,  ULONG   nBitRate_Max /*IN*/,  ULONG   nBitRate_Default /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_SERVER_PROFILE( PVOID pServer /*IN*/, UINT iProNum /*IN*/, CHAR * * ppszURL /*OUT*/, UINT * pVidSrcNum /*OUT*/, UINT * pAudSrcNum /*OUT*/, UINT * pVidEncNum /*OUT*/, UINT * pAudEncNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_SERVER_PROFILE( PVOID pServer /*IN*/, UINT iProNum /*IN*/, CHAR *   pszURL /*IN*/,   UINT   iVidSrcNum /*IN*/,  UINT   iAudSrcNum /*IN*/,  UINT   iVidEncNum /*IN*/,  UINT   iAudEncNum /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_SERVER_GET_CUSTOM_PROPERTY_CALLBACK( PVOID pServer /*IN*/, PF_COMMUNICATION_SERVER_GET_CUSTOM_PROPERTY_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_SERVER_SET_CUSTOM_PROPERTY_CALLBACK( PVOID pServer /*IN*/, PF_COMMUNICATION_SERVER_SET_CUSTOM_PROPERTY_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_SERVER_PROFILE_VIDEO_SETUP_CALLBACK( PVOID pServer /*IN*/, PF_COMMUNICATION_SERVER_PROFILE_VIDEO_SETUP_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_SERVER_PROFILE_AUDIO_SETUP_CALLBACK( PVOID pServer /*IN*/, PF_COMMUNICATION_SERVER_PROFILE_AUDIO_SETUP_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// COMMUNICATION EMULATOR FUNCTIONS /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_EMULATOR_SCAN_DONE_CALLBACK)( PVOID pEmulator /*IN*/, ULONG nTotalServers /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_COMMUNICATION_ONVIF_EMULATOR( PVOID * ppEmulator /*OUT*/, ULONG nEmulatorPort = 3702 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_COMMUNICATION_EMULATOR( PVOID pEmulator /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_COMMUNICATION_EMULATOR( PVOID pEmulator /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_COMMUNICATION_EMULATOR( PVOID pEmulator /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_EMULATOR_SERVER_INFO( PVOID pEmulator /*IN*/, UINT iSvrNum /*IN*/, CHAR * * ppszNetworkIP /*OUT*/, ULONG * pNetworkPort /*OUT*/, CHAR * * ppszNetworkURL /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_EMULATOR_SCAN_DONE_CALLBACK( PVOID pEmulator /*IN*/, PF_COMMUNICATION_EMULATOR_SCAN_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// COMMUNICATION CLIENT FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+typedef QRETURN (QCAP_EXPORT *PF_COMMUNICATION_CLIENT_CONNECTED_CALLBACK)( PVOID pClient /*IN*/, ULONG nTotalVideoSources /*IN*/, ULONG nTotalAudioSources /*IN*/, ULONG nTotalVideoEncoders /*IN*/, ULONG nTotalAudioEncoders /*IN*/, ULONG nTotalProfiles /*IN*/, CHAR * pszName /*IN*/, CHAR * pszLocationr /*IN*/, CHAR * pszManufacturer /*IN*/, CHAR * pszModel /*IN*/, CHAR * pszHardwareVersion /*IN*/, CHAR * pszFirmwareVersion /*IN*/, CHAR * pszDeviceID /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_COMMUNICATION_ONVIF_CLIENT( CHAR * pszNetworkURL /*IN*/, PVOID * ppClient /*OUT*/, CHAR * pszAccount = NULL /*IN*/ /*DEFAULT = "root"*/, CHAR * pszPassword = NULL /*IN*/ /*DEFAULT = "root"*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_COMMUNICATION_CLIENT( PVOID pClient /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_COMMUNICATION_CLIENT( PVOID pClient /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_COMMUNICATION_CLIENT( PVOID pClient /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_VIDEO_SOURCE_INFO( PVOID pClient /*IN*/, UINT iVidSrcNum /*IN*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, ULONG * pFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_AUDIO_SOURCE_INFO( PVOID pClient /*IN*/, UINT iAudSrcNum /*IN*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_VIDEO_ENCODER_INFO( PVOID pClient /*IN*/, UINT iVidEncNum /*IN*/, ULONG * pTotalVidEncOptions /*OUT*/, UINT * pVidEncOptionNum_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_AUDIO_ENCODER_INFO( PVOID pClient /*IN*/, UINT iAudEncNum /*IN*/, ULONG * pTotalAudEncOptions /*OUT*/, UINT * pAudEncOptionNum_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_VIDEO_ENCODER_OPTION_INFO( PVOID pClient /*IN*/, UINT iVidEncNum /*IN*/, UINT iVidEncOptionNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pWidthList /*OUT*/, ULONG * pWidthListSize /*OUT*/, ULONG * pWidth_Default /*OUT*/, ULONG * pHeightList /*OUT*/, ULONG * pHeightListSize /*OUT*/, ULONG * pHeight_Default /*OUT*/, ULONG * pFrameRate_Min /*OUT*/, ULONG * pFrameRate_Max /*OUT*/, ULONG * pFrameRate_Default /*OUT*/, ULONG * pRecordMode_Min /*OUT*/, ULONG * pRecordMode_Max /*OUT*/, ULONG * pRecordMode_Default /*OUT*/, ULONG * pQuality_Min /*OUT*/, ULONG * pQuality_Max /*OUT*/, ULONG * pQuality_Default /*OUT*/, ULONG * pBitRate_Min /*OUT*/, ULONG * pBitRate_Max /*OUT*/, ULONG * pBitRate_Default /*OUT*/, ULONG * pGOP_Min /*OUT*/, ULONG * pGOP_Max /*OUT*/, ULONG * pGOP_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_AUDIO_ENCODER_OPTION_INFO( PVOID pClient /*IN*/, UINT iAudEncNum /*IN*/, UINT iAudEncOptionNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannelsList /*OUT*/, ULONG * pChannelsListSize /*OUT*/, ULONG * pChannels_Default /*OUT*/, ULONG * pBitsPerSampleList /*OUT*/, ULONG * pBitsPerSampleListSize /*OUT*/, ULONG * pBitsPerSample_Default /*OUT*/, ULONG * pSampleFrequencyList /*OUT*/, ULONG * pSampleFrequencyListSize /*OUT*/, ULONG * pSampleFrequency_Default /*OUT*/, ULONG * pBitRate_Min /*OUT*/, ULONG * pBitRate_Max /*OUT*/, ULONG * pBitRate_Default /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_PROFILE_INFO( PVOID pClient /*IN*/, UINT iProNum /*IN*/, CHAR * * ppszURL /*OUT*/, UINT * pVidSrcNum /*OUT*/, UINT * pAudSrcNum /*OUT*/, UINT * pVidEncNum /*OUT*/, UINT * pAudEncNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_PROFILE_VIDEO_PROPERTY( PVOID pClient /*IN*/, UINT iProNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, ULONG * pFrameRate /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_CLIENT_PROFILE_VIDEO_PROPERTY( PVOID pClient /*IN*/, UINT iProNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  ULONG   nFrameRate /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_PROFILE_AUDIO_PROPERTY( PVOID pClient /*IN*/, UINT iProNum /*IN*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/, ULONG * pBitRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_CLIENT_PROFILE_AUDIO_PROPERTY( PVOID pClient /*IN*/, UINT iProNum /*IN*/, ULONG   nEncoderFormat /*IN*/,  ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/,  ULONG   nBitRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_COMMUNICATION_CLIENT_CUSTOM_PROPERTY( PVOID pClient /*IN*/, CHAR * pszProperty /*IN*/, CHAR * * ppszValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_COMMUNICATION_CLIENT_CUSTOM_PROPERTY( PVOID pClient /*IN*/, CHAR * pszProperty /*IN*/, CHAR * pszValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_COMMUNICATION_CLIENT_CONNECTED_CALLBACK( PVOID pClient /*IN*/, PF_COMMUNICATION_CLIENT_CONNECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # DICOM FUNCTIONS (DICOM WORKSTATION <-> PACS SERVER)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_DICOM_DOWNLOAD_OPERATION_CALLBACK)( PVOID pStation /*IN*/, double dPercentageCompleted /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_DICOM_UPLOAD_OPERATION_CALLBACK)( PVOID pStation /*IN*/, double dPercentageCompleted /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_DICOM_WORKSTATION( CHAR * pszServerIP_PACS /*IN*/, ULONG nServerPort_PACS /*IN*/, CHAR * pszServerApplicationEntityTitle /*IN*/, PVOID * ppStation /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_DICOM_WORKSTATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_DICOM_WORKSTATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_DICOM_WORKSTATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_DICOM_OPERATION_CONDITION( PVOID   pStation,                          /*IN*/ 
+
+																	 ULONG   nQueryLevel,                       /*IN*/
+																	 
+																	 WSTRING pwszPatientName,                   /*IN*/ // 患者姓名 [PATIENT]
+
+																	 WSTRING pwszPatientID,                     /*IN*/ // 病歷號碼 [PATIENT]
+
+																	 WSTRING pwszStudyInstanceUID,              /*IN*/ // 檢查序號 [GENERAL STUDY]
+
+																	 WSTRING pwszStudyDate,                     /*IN*/ // 檢查日期 [GENERAL STUDY]
+
+																	 WSTRING pwszStudyTime,                     /*IN*/ // 檢查時間 [GENERAL STUDY]
+
+																	 WSTRING pwszReferringPhysicianName,        /*IN*/ // 咨詢醫師 [GENERAL STUDY]
+
+																	 WSTRING pwszStudyID,                       /*IN*/ // 檢查編號 [GENERAL STUDY]
+
+																	 WSTRING pwszAccessionNumber,               /*IN*/ // 登記號碼 [GENERAL STUDY]
+
+																	 WSTRING pwszStudyDescription,              /*IN*/ // 檢查說明 [GENERAL STUDY]
+
+																	 WSTRING pwszNameOfPhysiciansReadingStudy,  /*IN*/ // 判讀醫生 [GENERAL STUDY]
+
+																	 WSTRING pwszModality,                      /*IN*/ // 圖像設備 [GENERAL SERIES]
+
+																	 WSTRING pwszSeriesInstanceUID,             /*IN*/ // 序列序號 [GENERAL SERIES]
+
+																	 WSTRING pwszPerformingPhysicianName,       /*IN*/ // 執行醫生 [GENERAL SERIES]
+
+																	 WSTRING pwszInstitutionalDepartmentName ); /*IN*/ // 機構名稱 [GENERAL EQUIPMENT]
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_DICOM_QUERY_OPERATION( PVOID pStation /*IN*/, CHAR * pszClientApplicationEntityTitle /*IN*/, ULONG nClientPort /*IN*/, CHAR * pszOutputFolder /*IN*/, CHAR * pszOutputXMLFileName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_DICOM_QUERY_OPERATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_DICOM_DOWNLOAD_OPERATION( PVOID pStation /*IN*/, CHAR * pszClientApplicationEntityTitle /*IN*/, ULONG nClientPort /*IN*/, CHAR * pszDownloadFolder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_DICOM_DOWNLOAD_OPERATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_DICOM_UPLOAD_OPERATION( PVOID pStation /*IN*/, CHAR * pszClientApplicationEntityTitle /*IN*/, ULONG nClientPort /*IN*/, CHAR * pszUploadFolder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_DICOM_UPLOAD_OPERATION( PVOID pStation /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_DICOM_DOWNLOAD_OPERATION_CALLBACK( PVOID pStation /*IN*/, PF_DICOM_DOWNLOAD_OPERATION_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_DICOM_UPLOAD_OPERATION_CALLBACK( PVOID pStation /*IN*/, PF_DICOM_UPLOAD_OPERATION_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # WEBRTC FUNCTIONS (CHATROOM)
+// #
+// ##########################################################################################################################################################################################
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_WEBRTC_CHATROOM( ULONG nNetworkPort /*IN*/, PVOID * ppChatRoom /*OUT*/, CHAR * pszNetworkAdapterIP = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_WEBRTC_CHATROOM( PVOID pChatRoom /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # WEBRTC FUNCTIONS (P2P)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_WEBRTC_CHATROOM_LOGIN_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, CHAR * pszPeerUserName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_WEBRTC_CHATROOM_LOGOUT_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_WEBRTC_PRIVATE_SDP_PROPERTY_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, CHAR * pszType /*IN*/, CHAR * pszSDP /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_WEBRTC_PEER_CONNECTED_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, QRESULT nConnectionStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_WEBRTC_PEER_DISCONNECTED_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_SEND_DATA_DONE_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, QRESULT nSendStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_SEND_FILE_DONE_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, QRESULT nSendStatus /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_RECEIVED_DATA_DONE_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, CHAR * pszData /*IN*/, ULONG nDataSize /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_RECEIVED_FILE_DONE_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, CHAR * pszFileNamePath /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_RECEIVED_FILE_STATUS_CALLBACK)( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, ULONG nRecvSize /*IN*/, ULONG nTotalSize /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN(QCAP_EXPORT *PF_WEBRTC_NETWORK_QOS_STATUS_CALLBACK)( PVOID pChatter /*IN*/, UINT iSessionNum /*IN*/, ULONG nExpectedBitRate /*IN*/, ULONG nExpectedFrameRate /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_WEBRTC_CHATTER( CHAR * pszChatRoomLoginIP /*IN*/, ULONG nChatRoomLoginPort /*IN*/, CHAR * pszUserName /*IN*/, PVOID * ppChatter /*OUT*/, ULONG * pLoginID /*OUT*/, ULONG nConnectionTimeout = 5000 /*IN*/, CHAR * pszIceURL = NULL /*IN*/, CHAR * pszIceUserName = NULL /*IN*/, CHAR * pszIcePassword = NULL /*IN*/, CHAR * pszReceivedFileFolderPath = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_WEBRTC_CHATTER( PVOID pChatter /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_WEBRTC_CHAT( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_WEBRTC_CHAT( PVOID pChatter /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_WEBRTC_SENDER( PVOID pChatter /*IN*/, UINT iSvrNum /*IN*/ /*0 ~ 63*/, ULONG nTotalSessions /*IN*/, PVOID * ppServer /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_WEBRTC_RECEIVER( PVOID pChatter /*IN*/, UINT iCliNum /*IN*/ /*0 ~ 63*/, PVOID * ppClient /*OUT*/, ULONG nDecoderType = QCAP_DECODER_TYPE_SOFTWARE /*IN*/, HWND hAttachedWindow = NULL /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_WEBRTC_PRIVATE_SDP_PROPERTY( PVOID pChatter /*IN*/, ULONG nPeerID /*IN*/, CHAR * pszSDP /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_ENUM_WEBRTC_USER_IN_CHATROOM( PVOID pChatter /*IN*/, ULONG * pPeerID /*OUT*/, CHAR * * ppszPeerUserName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEND_WEBRTC_DATA( PVOID pChatter /*IN*/, CHAR * pszData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEND_WEBRTC_FILE( PVOID pChatter /*IN*/, CHAR * pszFilePathName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_CHATROOM_LOGIN_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_CHATROOM_LOGIN_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_CHATROOM_LOGOUT_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_CHATROOM_LOGOUT_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_PRIVATE_SDP_PROPERTY_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_PRIVATE_SDP_PROPERTY_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_PEER_CONNECTED_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_PEER_CONNECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_PEER_DISCONNECTED_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_PEER_DISCONNECTED_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_SEND_DATA_DONE_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_SEND_DATA_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_SEND_FILE_DONE_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_SEND_FILE_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_RECEIVED_DATA_DONE_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_RECEIVED_DATA_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_RECEIVED_FILE_DONE_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_RECEIVED_FILE_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_RECEIVED_FILE_STATUS_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_RECEIVED_FILE_STATUS_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_WEBRTC_NETWORK_QOS_STATUS_CALLBACK( PVOID pChatter /*IN*/, PF_WEBRTC_NETWORK_QOS_STATUS_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # FILE PLAYBACK FUNCTIONS (PLAYBACK/EDITING/REPAIR/FILE)
+// #
+// ##########################################################################################################################################################################################
+//
+// FILE PLAYBACK FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+typedef QRETURN (QCAP_EXPORT *PF_FILE_SNAPSHOT_DONE_CALLBACK)( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_FILE_SNAPSHOT_STREAM_CALLBACK)( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_FILE_CALLBACK)( PVOID pFile /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_FILE_CALLBACK)( PVOID pFile /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_FILE_CALLBACK_EX)( PVOID pFile /*IN*/, UINT iFrameNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+typedef QRETURN (QCAP_EXPORT *PF_AUDIO_DECODER_FILE_CALLBACK_EX)( PVOID pFile /*IN*/, UINT iFrameNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+typedef QRETURN (QCAP_EXPORT *PF_VIDEO_DECODER_3D_FILE_CALLBACK)( PVOID pFile /*IN*/, UINT iChNum /*IN*/, double dSampleTime /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|   |  |  |   |*/ QCAP_OPEN_FILE( CHAR * pszFileName /*IN*/, PVOID * ppFile /*OUT*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/, HWND hAttachedWindow /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/, BOOL bEnableEditFunction = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |2D+|  |  |   |*/ QCAP_OPEN_FILE_EX( CHAR * pszFileName /*IN*/, PVOID * ppFile /*OUT*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/, HWND hAttachedWindow /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ ); // MP4 ONLY, NOW
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |3D|  |   |*/ QCAP_OPEN_3D_FILE( CHAR * pszFileName /*IN*/, PVOID * ppFile /*OUT*/, BOOL * pIs3D /*OUT*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/, HWND hAttachedWindowL /*IN*/, BOOL bThumbDrawL = FALSE /*IN*/, BOOL bMaintainAspectRatioL = FALSE /*IN*/, HWND hAttachedWindowR = NULL /*IN*/, BOOL bThumbDrawR = FALSE /*IN*/, BOOL bMaintainAspectRatioR = FALSE /*IN*/, BOOL bEnableEditFunction = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |TS|   |*/ QCAP_OPEN_TIMESHIFT_FILE_EX( PVOID pPhysicalFileWriter /*IN*/, PVOID * ppFile /*OUT*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/, HWND hAttachedWindow /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/, CHAR * pszEncryptKey = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_OPEN_SCF_FILE( UINT iChNum /*IN*/, PVOID * ppFile /*OUT*/, ULONG nDecoderType /*IN*/, HWND hAttachedWindow /*IN*/, BOOL bThumbDraw = FALSE /*IN*/, BOOL bMaintainAspectRatio = FALSE /*IN*/, double dStartSampleTime = 0.0 /*IN*/, double dStopSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_DESTROY_FILE( PVOID pFile /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_PLAY_FILE( PVOID pFile /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_PAUSE_FILE( PVOID pFile /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_STOP_FILE( PVOID pFile /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_PLAY_GLOBAL_SCF_FILE();
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_PAUSE_GLOBAL_SCF_FILE();
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_STOP_GLOBAL_SCF_FILE();
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |TS|   |*/ QCAP_REFRESH_TIMESHIFT_FILE_INFO( PVOID pFile /*IN*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/ ); // QCAP_OPEN_TIMESHIFT_FILE_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_SCF_FILE_ENUMERATION( UINT iChNum /*IN*/, double dStartSearchTime /*IN*/, double dStopSearchTime /*IN*/, ULONG * pFileSizeHigh /*OUT*/, ULONG * pFileSizeLow /*OUT*/, double * pFileStartTime /*OUT*/, double * pFileStopTime /*OUT*/, double * pVideoStartTime /*OUT*/, double * pVideoStopTime /*OUT*/, double * pAudioStartTime /*OUT*/, double * pAudioStopTime /*OUT*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_SET_SCF_FILE_TIMER( UINT iChNum /*IN*/, BOOL bEnableGlobalTimer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_FILE_POSITION( PVOID pFile /*IN*/, double * pSampleTime /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_FILE_POSITION( PVOID pFile /*IN*/, double dSampleTime /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |2D+|  |TS|   |*/ QCAP_GET_FILE_POSITION_EX( PVOID pFile /*IN*/, double * pSampleTime /*OUT*/, ULONG nTimeUnit = QCAP_FILE_TIMEUNIT_FRAME /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |2D+|  |TS|   |*/ QCAP_SET_FILE_POSITION_EX( PVOID pFile /*IN*/, double dSampleTime /*IN*/, ULONG nTimeUnit = QCAP_FILE_TIMEUNIT_FRAME /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_GET_GLOBAL_SCF_FILE_POSITION( double * pSampleTime /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |  |  |SCF|*/ QCAP_SET_GLOBAL_SCF_FILE_POSITION( double dSampleTime /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_FILE_PLAYBACK_PROPERTY( PVOID pFile /*IN*/, ULONG * pRepeatTimes /*OUT*/ /*-1 = FOREVER, 0 = DISABLE (DEFAULT)*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_FILE_PLAYBACK_PROPERTY( PVOID pFile /*IN*/, ULONG nRepeatTimes /*IN*/ /*-1 = FOREVER, 0 = DISABLE (DEFAULT)*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_FILE_PLAYBACK_SPEED( PVOID pFile /*IN*/, double * pSpeed /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_FILE_PLAYBACK_SPEED( PVOID pFile /*IN*/, double dSpeed /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_STREAM_BUFFER( PVOID pFile /*IN*/, UINT iFrameNum /*IN*/, BYTE * pStreamBuffer /*OUT*/, ULONG * pStreamBufferLen /*IN/OUT*/, BOOL * pIsKeyFrame /*OUT*/, double * pSampleTime /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_AUDIO_FILE_STREAM_BUFFER( PVOID pFile /*IN*/, UINT iFrameNum /*IN*/, BYTE * pStreamBuffer /*OUT*/, ULONG * pStreamBufferLen /*IN/OUT*/, double * pSampleTime /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_METADATA_FILE_DATA_BUFFER( PVOID pFile /*IN*/, UINT iFrameNum /*IN*/, BYTE * pDataBuffer /*OUT*/, ULONG * pDataBufferLen /*IN/OUT*/, double * pSampleTime /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_METADATA_FILE_HEADER( PVOID pFile /*IN*/, CHAR * * ppszTitle /*OUT*/, CHAR * * ppszArtist /*OUT*/, CHAR * * ppszComments /*OUT*/, CHAR * * ppszGenre /*OUT*/, CHAR * * ppszComposer /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_METADATA_FILE_HEADER_W( PVOID pFile /*IN*/, WSTRING * ppwszTitle /*OUT*/, WSTRING * ppwszArtist /*OUT*/, WSTRING * ppwszComments /*OUT*/, WSTRING * ppwszGenre /*OUT*/, WSTRING * ppwszComposer /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |3D|  |   |*/ QCAP_GET_VIDEO_3D_FILE_DISPLAY_MODE( PVOID pFile /*IN*/, ULONG * pStereoDisplayMode /*OUT*/, BOOL * pLeftRightSwap /*OUT*/ );  // ONLY FOR QCAP_OPEN_3D_FILE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |3D|  |   |*/ QCAP_SET_VIDEO_3D_FILE_DISPLAY_MODE( PVOID pFile /*IN*/, ULONG nStereoDisplayMode = QCAP_3D_STEREO_DISPLAY_MODE_LINE_BY_LINE /*IN*/, BOOL bLeftRightSwap = FALSE /*IN*/ ); // ONLY FOR QCAP_OPEN_3D_FILE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_REGION_DISPLAY( PVOID pFile /*IN*/, ULONG * pCropX /*OUT*/, ULONG * pCropY /*OUT*/, ULONG * pCropW /*OUT*/, ULONG * pCropH /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_REGION_DISPLAY( PVOID pFile /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_MIRROR( PVOID pFile /*IN*/, BOOL * pHorizontalMirror /*OUT*/, BOOL * pVerticalMirror /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_MIRROR( PVOID pFile /*IN*/, BOOL bHorizontalMirror /*IN*/, BOOL bVerticalMirror /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_ASPECT_RATIO( PVOID pFile /*IN*/, BOOL * pMaintainAspectRatio /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_ASPECT_RATIO( PVOID pFile /*IN*/, BOOL bMaintainAspectRatio /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_BRIGHTNESS( PVOID pFile /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_BRIGHTNESS( PVOID pFile /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_CONTRAST( PVOID pFile /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_CONTRAST( PVOID pFile /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_HUE( PVOID pFile /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_HUE( PVOID pFile /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_VIDEO_FILE_SATURATION( PVOID pFile /*IN*/, ULONG * pValue /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_VIDEO_FILE_SATURATION( PVOID pFile /*IN*/, ULONG nValue /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_AUDIO_FILE_SOUND_RENDERER( PVOID pFile /*IN*/, UINT * pSoundNum /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_AUDIO_FILE_SOUND_RENDERER( PVOID pFile /*IN*/, UINT iSoundNum /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_AUDIO_FILE_VOLUME( PVOID pFile /*IN*/, ULONG * pVolume /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_AUDIO_FILE_VOLUME( PVOID pFile /*IN*/, ULONG nVolume /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SNAPSHOT_FILE_BMP( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SNAPSHOT_FILE_JPG( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SNAPSHOT_FILE_BMP_EX( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SNAPSHOT_FILE_JPG_EX( PVOID pFile /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_MOVE_OSD_FILE_OBJECT( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_OSD_FILE_TEXT_BOUNDARY( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_GET_OSD_FILE_TEXT_BOUNDARY_W( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_TEXT( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_TEXT_W( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_TEXT_EX( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_TEXT_EX_W( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_PICTURE( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_BUFFER( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_SET_OSD_FILE_BUFFER_EX( PVOID pFile /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_REGISTER_FILE_SNAPSHOT_DONE_CALLBACK( PVOID pFile /*IN*/, PF_FILE_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_REGISTER_FILE_SNAPSHOT_STREAM_CALLBACK( PVOID pFile /*IN*/, PF_FILE_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_REGISTER_VIDEO_DECODER_FILE_CALLBACK( PVOID pFile /*IN*/, PF_VIDEO_DECODER_FILE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|2D|2D+|3D|TS|SCF|*/ QCAP_REGISTER_AUDIO_DECODER_FILE_CALLBACK( PVOID pFile /*IN*/, PF_AUDIO_DECODER_FILE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |2D+|  |TS|   |*/ QCAP_REGISTER_VIDEO_DECODER_FILE_CALLBACK_EX( PVOID pFile /*IN*/, PF_VIDEO_DECODER_FILE_CALLBACK_EX pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |2D+|  |TS|   |*/ QCAP_REGISTER_AUDIO_DECODER_FILE_CALLBACK_EX( PVOID pFile /*IN*/, PF_AUDIO_DECODER_FILE_CALLBACK_EX pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR QCAP_OPEN_FILE_EX & QCAP_OPEN_TIMESHIFT_FILE_EX
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |   |3D|  |   |*/ QCAP_REGISTER_VIDEO_DECODER_3D_FILE_CALLBACK( PVOID pFile /*IN*/, PF_VIDEO_DECODER_3D_FILE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ ); // ONLY FOR QCAP_OPEN_3D_FILE
+
+// FILE EDITING FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_EXPORT_FILE( PVOID pFile /*IN*/, double dStartSampleTime /*IN*/, double dStopSampleTime /*IN*/, CHAR * pszExportedFileName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_EXPORT_FILE_EX( PVOID pFile /*IN*/, CHAR * pszExportedFileName /*IN*/, ULONG nFileArgs /*IN*/, double dStartSampleTime1 /*IN*/, double dStopSampleTime1 /*IN*/, double dStartSampleTime2 /*IN*/, double dStopSampleTime2 /*IN*/, ... );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_EXPORT_FILE_EX_C( PVOID pFile /*IN*/, CHAR * pszExportedFileName /*IN*/, ULONG nFileArgs /*IN*/, double dStartSampleTimes[ ] /*IN*/, double dStopSampleTimes[ ] /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_EXPORT_FILES_EX( PVOID pFile /*IN*/, ULONG nFileArgs /*IN*/, double dStartSampleTime1 /*IN*/, double dStopSampleTime1 /*IN*/, CHAR * pszExportedFileName1 /*IN*/, double dStartSampleTime2 /*IN*/, double dStopSampleTime2 /*IN*/, CHAR * pszExportedFileName2 /*IN*/, ... );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_EXPORT_FILES_EX_C( PVOID pFile /*IN*/, ULONG nFileArgs /*IN*/, double dStartSampleTimes[ ] /*IN*/, double dStopSampleTimes[ ] /*IN*/, CHAR * pszExportedFileNames[ ] /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MERGE_FILES( CHAR * pszFrontEndFileName /*IN*/, CHAR * pszBackEndFileName /*IN*/, CHAR * pszMergedFileName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MERGE_FILES_EX( CHAR * pszMergedFileName /*IN*/, ULONG nFileArgs /*IN*/, CHAR * pszSourceFileName1 /*IN*/, CHAR * pszSourceFileName2 /*IN*/, ... );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MERGE_FILES_EX_C( CHAR * pszMergedFileName /*IN*/, ULONG nFileArgs /*IN*/, CHAR * pszSourceFileNames[ ] /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MERGE_FILES_BY_EDL( CHAR * pszEDLFileName /*IN*/ ); // PLEASE REFERENCE DOC\MANUALS\13. FILE\MERGE.EDL.EXAMPLE.INI
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_BUILD_VIDEO_ON_DEMAND_FILE( CHAR * pszOriginalFileName /*IN*/, CHAR * pszVideoOnDemandFileName /*IN*/ ); // ONLY FOR MP4 FILE BOXING
+
+// FILE REPAIR FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DIAGNOSE_FILE( CHAR * pszFileName /*IN*/, BOOL * pIsHealthy /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REPAIR_FILE( CHAR * pszBadFileName /*IN*/, CHAR * pszRepairedFileName /*IN*/ );
+
+// FILE TRANSCODING FUNCTIONS ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+typedef QRETURN (QCAP_EXPORT *PF_FILE_TRANSCODER_CALLBACK)( PVOID pFileTranscoder /*IN*/, double dPercentageCompleted /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_FILE_TRANSCODER( CHAR * pszSrcFileName /*IN*/, PVOID * ppFileTranscoder /*OUT*/, ULONG nDecoderType /*IN*/, ULONG * pVideoEncoderFormat /*OUT*/, ULONG * pVideoWidth /*OUT*/, ULONG * pVideoHeight /*OUT*/, double * pVideoFrameRate /*OUT*/, ULONG * pAudioEncoderFormat /*OUT*/, ULONG * pAudioChannels /*OUT*/, ULONG * pAudioBitsPerSample /*OUT*/, ULONG * pAudioSampleFrequency /*OUT*/, double * pTotalDurationTimes /*OUT*/, ULONG * pTotalVideoFrames /*OUT*/, ULONG * pTotalAudioFrames /*OUT*/, ULONG * pTotalMetadataFrames /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_FILE_TRANSCODER( PVOID pFileTranscoder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_FILE_TRANSCODER_PROPERTY( PVOID pFileTranscoder /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_FILE_TRANSCODER_PROPERTY( PVOID pFileTranscoder /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_VIDEO_FILE_TRANSCODER_PROPERTY_EX( PVOID pFileTranscoder /*IN*/, ULONG * pEncoderType /*OUT*/, ULONG * pEncoderFormat /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/, ULONG * pRecordProfile /*OUT*/ /*DEFAULT = BASELINE*/, ULONG * pRecordLevel /*OUT*/ /*DEFAULT = 41*/, ULONG * pRecordEntropy /*OUT*/ /*DEFAULT = CAVLC*/, ULONG * pRecordComplexity /*OUT*/ /*DEFAULT = 0*/, ULONG * pRecordMode /*OUT*/, ULONG * pQuality /*OUT*/, ULONG * pBitRate /*OUT*/, ULONG * pGOP /*OUT*/, ULONG * pBFrames /*OUT*/ /*DEFAULT = 0*/, BOOL * pIsInterleaved /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pSlices /*OUT*/ /*DEFAULT = 0*/, ULONG * pLayers /*OUT*/ /*DEFAULT = 0*/, ULONG * pSceneCut /*OUT*/ /*DEFAULT = 0*/, BOOL * pMultiThread /*OUT*/ /*DEFAULT = TRUE*/, BOOL * pMBBRC /*OUT*/ /*DEFAULT = FALSE*/, BOOL * pExtBRC /*OUT*/ /*DEFAULT = FALSE*/, ULONG * pMinQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pMaxQP /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVMaxRate /*OUT*/ /*DEFAULT = 0*/, ULONG * pVBVBufSize /*OUT*/ /*DEFAULT = 0*/, ULONG * pCBRVariation /*OUT*/ /*DEFAULT = 0*/, ULONG * pAspectRatioX /*OUT*/, ULONG * pAspectRatioY /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_VIDEO_FILE_TRANSCODER_PROPERTY_EX( PVOID pFileTranscoder /*IN*/, ULONG   nEncoderType /*IN*/,  ULONG   nEncoderFormat /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/,  ULONG   nRecordProfile /*IN*/  /*DEFAULT = BASELINE*/, ULONG   nRecordLevel /*IN*/  /*DEFAULT = 41*/, ULONG   nRecordEntropy /*IN*/  /*DEFAULT = CAVLC*/, ULONG   nRecordComplexity /*IN*/  /*DEFAULT = 0*/, ULONG   nRecordMode /*IN*/,  ULONG   nQuality /*IN*/,  ULONG   nBitRate /*IN*/,  ULONG   nGOP /*IN*/,  ULONG   nBFrames /*IN*/  /*DEFAULT = 0*/, BOOL   bIsInterleaved /*IN*/  /*DEFAULT = FALSE*/, ULONG   nSlices /*IN*/  /*DEFAULT = 0*/, ULONG   nLayers /*IN*/  /*DEFAULT = 0*/, ULONG   nSceneCut /*IN*/  /*DEFAULT = 0*/, BOOL   bMultiThread /*IN*/  /*DEFAULT = TRUE*/, BOOL   bMBBRC /*IN*/  /*DEFAULT = FALSE*/, BOOL   bExtBRC /*IN*/  /*DEFAULT = FALSE*/, ULONG   nMinQP /*IN*/  /*DEFAULT = 0*/, ULONG   nMaxQP /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVMaxRate /*IN*/  /*DEFAULT = 0*/, ULONG   nVBVBufSize /*IN*/  /*DEFAULT = 0*/, ULONG   nCBRVariation /*IN*/  /*DEFAULT = 0*/, ULONG   nAspectRatioX /*IN*/,  ULONG   nAspectRatioY /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_FILE_TRANSCODER( PVOID pFileTranscoder /*IN*/, CHAR * pszDstFileName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_FILE_TRANSCODER( PVOID pFileTranscoder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_FILE_TRANSCODER_CALLBACK( PVOID pFileTranscoder /*IN*/, PF_FILE_TRANSCODER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # ANIMATION FUNCTIONS
+// #
+// ##########################################################################################################################################################################################
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_ANIMATION_CLIP( CHAR * pszAniFileName /*IN*/, PVOID * ppClip /*OUT*/, ULONG * pTotalFrames /*OUT*/, ULONG * pTotalSprites /*OUT*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_ANIMATION_CLIP( PVOID pClip /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_ANIMATION_CLIP( PVOID pClip /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_ANIMATION_CLIP( PVOID pClip /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STEP_ANIMATION_CLIP( PVOID pClip /*IN*/, UINT * pFrameNum /*OUT*/, BYTE * * ppFrameBuffer /*OUT*/, ULONG * pFrameBufferLen /*OUT*/, BOOL bClearBackground = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEEK_ANIMATION_CLIP( PVOID pClip /*IN*/, UINT iFrameNum /*IN*/, BYTE * * ppFrameBuffer /*OUT*/, ULONG * pFrameBufferLen /*OUT*/, BOOL bClearBackground = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ANIMATION_CLIP_SPRITE_TRANSFORM_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, UINT iFrameNum /*IN*/, INT * pPositionX /*OUT*/, INT * pPositionY /*OUT*/, INT * pScaleW /*OUT*/, INT * pScaleH /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_TRANSFORM_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, UINT iFrameNum /*IN*/, INT nPositionX /*IN*/, INT nPositionY /*IN*/, INT nScaleW /*IN*/, INT nScaleH /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ANIMATION_CLIP_SPRITE_ALPHA_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, UINT iFrameNum /*IN*/, double * pAlpha /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_ALPHA_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, UINT iFrameNum /*IN*/, double dAlpha /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ANIMATION_CLIP_SPRITE_ZORDER_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, INT * pZOrder /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_ZORDER_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, INT nZOrder /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ANIMATION_CLIP_SPRITE_SCALE_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG * pScaleStyle /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_SCALE_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG nScaleStyle /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ANIMATION_CLIP_SPRITE_BLINDS_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG * pBlindsType /*OUT*/, ULONG * pSlices /*OUT*/, ULONG * pDirection /*OUT*/ /*0 = BOTTOM-TOP, LEFT-RIGHT, 1 = TOP-BOTTOM, RIGHT-LEFT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_BLINDS_PROPERTY( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG nBlindsType /*IN*/, ULONG nSlices /*IN*/, ULONG nDirection /*IN*/ /*0 = BOTTOM-TOP, LEFT-RIGHT, 1 = TOP-BOTTOM, RIGHT-LEFT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_PICTURE( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, CHAR * pszFilePathName /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_BUFFER( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, BOOL bCloneCopy = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_BUFFER_EX( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, BOOL bCloneCopy = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_SOURCE( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, PVOID pDevice /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, BOOL bCloneCopy = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SET_ANIMATION_CLIP_SPRITE_SOURCE_EX( PVOID pClip /*IN*/, UINT iSpriteNum /*IN*/, PVOID pDevice /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, BOOL bCloneCopy = FALSE /*IN*/ );
+
+// ANIMATION EXAMPLE:
+//
+// STEP#01 QCAP_CREATE_ANIMATION_CLIP( "EXAMPLE.FADEOUT.XML", &pClip, &nFrames, &nSprites, &nColorSpaceType, &nWidth, &nHeight );
+//
+// STEP#02 QCAP_START_ANIMATION_CLIP( pClip );
+//
+// STEP#03 QCAP_SET_ANIMATION_CLIP_SPRITE_BUFFER( pClip, 0 /*CH01*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferA, nFrameBufferLenA );
+// 
+//         QCAP_SET_ANIMATION_CLIP_SPRITE_SOURCE( pClip, 1 /*CH02*/, QCAP_COLORSPACE_TYPE_YUY2, 1920, 1080, pFrameBufferB, nFrameBufferLenB );
+//
+// STEP#04 QCAP_STEP_ANIMATION_CLIP( pClip, &iFrameNum, &pFrameBuffer, &nFrameBufferLen, TRUE );
+//
+// STEP#05 QCAP_STOP_ANIMATION_CLIP( pClip );
+//
+// STEP#06 QCAP_DESTROY_ANIMATION_CLIP( pClip );
+
+// ##########################################################################################################################################################################################
+// #
+// # VIRTUAL CAMERA FUNCTIONS
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_VIRTUAL_CAMERA_SNAPSHOT_DONE_CALLBACK)( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, PVOID pUserData /*IN*/ );
+
+typedef QRETURN (QCAP_EXPORT *PF_VIRTUAL_CAMERA_SNAPSHOT_STREAM_CALLBACK)( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_CREATE_VIRTUAL_CAMERA( UINT iCamNum /*IN*/ /*0 ~ 63*/, PVOID * ppCamera /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_DESTROY_VIRTUAL_CAMERA( PVOID pCamera /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_GET_VIDEO_VIRTUAL_CAMERA_PROPERTY( PVOID pCamera /*IN*/, ULONG * pColorSpaceType /*OUT*/, ULONG * pWidth /*OUT*/, ULONG * pHeight /*OUT*/, double * pFrameRate /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_VIDEO_VIRTUAL_CAMERA_PROPERTY( PVOID pCamera /*IN*/, ULONG   nColorSpaceType /*IN*/,  ULONG   nWidth /*IN*/,  ULONG   nHeight /*IN*/,  double   dFrameRate /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_GET_AUDIO_VIRTUAL_CAMERA_PROPERTY( PVOID pCamera /*IN*/, ULONG * pChannels /*OUT*/, ULONG * pBitsPerSample /*OUT*/, ULONG * pSampleFrequency /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_AUDIO_VIRTUAL_CAMERA_PROPERTY( PVOID pCamera /*IN*/, ULONG   nChannels /*IN*/,  ULONG   nBitsPerSample /*IN*/,  ULONG   nSampleFrequency /*IN*/  );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_VIDEO_VIRTUAL_CAMERA_UNCOMPRESSION_BUFFER( PVOID pCamera /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_VIDEO_VIRTUAL_CAMERA_UNCOMPRESSION_BUFFER_EX( PVOID pCamera /*IN*/, ULONG nColorSpaceType /*IN*/, ULONG nWidth /*IN*/, ULONG nHeight /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nScaleStyle = QCAP_SCALE_STYLE_STRETCH /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_AUDIO_VIRTUAL_CAMERA_UNCOMPRESSION_BUFFER( PVOID pCamera /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_AUDIO_VIRTUAL_CAMERA_UNCOMPRESSION_BUFFER_EX( PVOID pCamera /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, double dSampleTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|MX|*/ QCAP_SET_AUDIO_MX_VIRTUAL_CAMERA_MIXING_UNCOMPRESSION_BUFFER( PVOID pCamera /*IN*/, UINT iMixNum /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ ); // ONLY FOR AUDIO MIXING
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|MX|*/ QCAP_SET_AUDIO_MX_VIRTUAL_CAMERA_MIXING_UNCOMPRESSION_BUFFER_EX( PVOID pCamera /*IN*/, UINT iMixNum /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/ ); // ONLY FOR AUDIO MIXING
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|MX|*/ QCAP_SET_AUDIO_MX_VIRTUAL_CAMERA_UNCOMPRESSION_BUFFER( PVOID pCamera /*IN*/, double dSampleTime = 0.0 /*IN*/, BOOL bEnableSyncMixer = TRUE /*IN*/ ); // ONLY FOR AUDIO MIXING
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_START_VIRTUAL_CAMERA( PVOID pCamera /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_STOP_VIRTUAL_CAMERA( PVOID pCamera /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SNAPSHOT_VIRTUAL_CAMERA_BMP( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SNAPSHOT_VIRTUAL_CAMERA_JPG( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SNAPSHOT_VIRTUAL_CAMERA_BMP_EX( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SNAPSHOT_VIRTUAL_CAMERA_JPG_EX( PVOID pCamera /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, ULONG nDstW /*IN*/, ULONG nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_MOVE_OSD_VIRTUAL_CAMERA_OBJECT( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ ); // FOR SCROLLING TEXT/PICTURE
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_GET_OSD_VIRTUAL_CAMERA_TEXT_BOUNDARY( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_GET_OSD_VIRTUAL_CAMERA_TEXT_BOUNDARY_W( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, ULONG * pBoundaryWidth /*OUT*/, ULONG * pBoundaryHeight /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_TEXT( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_TEXT_W( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_TEXT_EX( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszString /*IN*/, CHAR * pszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_TEXT_EX_W( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, WSTRING pwszString /*IN*/, WSTRING pwszFontFamilyName /*IN*/, ULONG nFontStyle /*IN*/, ULONG nFontSize /*IN*/, DWORD dwFontColor /*IN*/, DWORD dwBackgroundColor /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, INT nTextStartPosX = 0 /*IN*/, INT nTextStartPosY = 0 /*IN*/, ULONG nStringAlignmentStyle = QCAP_STRING_ALIGNMENT_STYLE_LEFT /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_PICTURE( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, CHAR * pszFilePathName /*IN*/, ULONG nTransparent /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_BUFFER( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_SET_OSD_VIRTUAL_CAMERA_BUFFER_EX( PVOID pCamera /*IN*/, UINT iOsdNum /*IN*/, INT x /*IN*/, INT y /*IN*/, INT w /*IN*/, INT h /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pFrameBuffer /*IN*/, ULONG nFrameWidth /*IN*/, ULONG nFrameHeight /*IN*/, ULONG nFramePitch /*IN*/, ULONG nCropX /*IN*/, ULONG nCropY /*IN*/, ULONG nCropW /*IN*/, ULONG nCropH /*IN*/, DWORD dwBorderColor /*IN*/, ULONG nBorderWidth /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/, BYTE * pMaskBuffer = NULL /*IN*/, ULONG nSequenceStyle = QCAP_SEQUENCE_STYLE_FOREMOST /*IN*/, double dLifeTime = 0.0 /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_REGISTER_VIRTUAL_CAMERA_SNAPSHOT_DONE_CALLBACK( PVOID pCamera /*IN*/, PF_VIRTUAL_CAMERA_SNAPSHOT_DONE_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT /*|  |*/ QCAP_REGISTER_VIRTUAL_CAMERA_SNAPSHOT_STREAM_CALLBACK( PVOID pCamera /*IN*/, PF_VIRTUAL_CAMERA_SNAPSHOT_STREAM_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # SERIAL PORT I/O FUNCTIONS (RS232/RS485)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_SERIAL_PORT_RECEIVED_DATA_CALLBACK)( PVOID pPort /*IN*/, UINT iPortNum /*IN*/, BYTE * pDataBuffer /*IN*/, ULONG nDataBufferLen /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SERIAL_PORT_ENUMERATION( UINT * pAvailablePortNum /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_SERIAL_PORT( UINT iPortNum /*IN*/, PVOID * ppPort /*OUT*/, ULONG nBaudRate = 9600 /*IN*/, ULONG nDataBits = 8 /*IN*/, ULONG nParityCheck = QCAP_SERIAL_PORT_PARITY_CHECK_NONE /*IN*/, ULONG nStopBits = QCAP_SERIAL_PORT_STOP_BITS_ONE /*IN*/, ULONG nFlowControl = QCAP_SERIAL_PORT_FLOW_CONTROL_NONE /*IN*/, BOOL bAsynchronousIO = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_SERIAL_PORT( PVOID pPort /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_SERIAL_PORT( PVOID pPort /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_SERIAL_PORT( PVOID pPort /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEND_SERIAL_PORT_SIGNAL( PVOID pPort /*IN*/, ULONG nSignalType /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SEND_SERIAL_PORT_DATA( PVOID pPort /*IN*/, BYTE * pDataBuffer /*IN*/, ULONG nDataBufferLen /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_SERIAL_PORT_RECEIVED_DATA_CALLBACK( PVOID pPort /*IN*/, PF_SERIAL_PORT_RECEIVED_DATA_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # DISC BURNING FUNCTIONS
+// #
+// ##########################################################################################################################################################################################
+//
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_BURNING_DRIVE( CHAR cDriveName /*IN*/, CHAR * pVolumeName /*IN*/, PVOID * ppDrive /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_BURNING_DRIVE( PVOID pDrive /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_BURNING_DRIVE( PVOID pDrive /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_BURNING_DRIVE( PVOID pDrive /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_UNLOAD_DISC( PVOID pDrive /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_LOAD_DISC( PVOID pDrive /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_DISC_INFO( PVOID pDrive /*IN*/, BOOL * pIsDiscBlank /*OUT*/, BOOL * pIsDiscWriteable /*OUT*/, DWORD * pDiscType /*OUT*/, ULONGLONG * pDiscRemainCapability /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_ERASE_DISC( PVOID pDrive /*IN*/ );
+
+// BURNING EXAMPLE:
+// 
+// STEP#01 QCAP_CREATE_BURNING_DRIVE( 'E', "TEST", &pDrive );
+//
+// STEP#02 QCAP_START_BURNING_DRIVE( pDrive );
+// 
+// STEP#03 QCAP_START_RECORD( pDevice, 0, "E:\\CH01.TS" );
+// 
+// STEP#04 QCAP_STOP_RECORD( pDevice, 0, FALSE, INFINE ); // NOTE!! WAITIING FILE CLOSE
+// 
+// STEP#05 QCAP_STOP_BURNING_DRIVE( pDrive );
+// 
+// STEP#06 QCAP_UNLOAD_DISC( pDrive );
+// 
+// STEP#07 QCAP_DESTROY_BURNING_DRIVE( pDrive );
+
+// ##########################################################################################################################################################################################
+// #
+// # MEDIA TIMER FUNCTIONS (HIGH PRECISION)
+// #
+// ##########################################################################################################################################################################################
+//
+typedef QRETURN (QCAP_EXPORT *PF_MEDIA_TIMER_CALLBACK)( PVOID pTimer /*IN*/, double dSampleTime /*IN*/, double dDelayTime /*IN*/, PVOID pUserData /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CREATE_MEDIA_TIMER( ULONG nElapseTimeNum /*IN*/, ULONG nElapseTimeDeno /*IN*/, PVOID * ppTimer /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_DESTROY_MEDIA_TIMER( PVOID pTimer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_START_MEDIA_TIMER( PVOID pTimer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_STOP_MEDIA_TIMER( PVOID pTimer /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_REGISTER_MEDIA_TIMER_CALLBACK( PVOID pTimer /*IN*/, PF_MEDIA_TIMER_CALLBACK pCB /*IN*/, PVOID pUserData /*IN*/ );
+
+// ##########################################################################################################################################################################################
+// #
+// # HELPER FUNCTIONS (ENCODER/VIDEO/AUDIO/DEVELOPER)
+// #
+// ##########################################################################################################################################################################################
+//
+// HELPER FUNCTIONS PART.1 (FOR ENCODER) ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_H264_BUFFER_LAYER_ID( BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, ULONG * pLayerID /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_H264_BUFFER_COLOR_INFO( BYTE * pStreamBuffer /*IN*/, ULONG nStreamBufferLen /*IN*/, ULONG * pColorRangeType /*OUT*/ );
+
+// HELPER FUNCTIONS PART.2 (FOR VIDEO) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YUY2_TO_ABGR32( BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BYTE bAlpah = 0x00 /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YV12_TO_ABGR32( BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BYTE bAlpah = 0x00 /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YUY2_TO_ARGB32( BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BYTE bAlpah = 0x00 /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YV12_TO_ARGB32( BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BYTE bAlpah = 0x00 /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YUY2_TO_BGR24(  BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YV12_TO_BGR24(  BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YUY2_TO_RGB24(  BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YV12_TO_RGB24(  BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YUY2_TO_YV12(   BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_COLORSPACE_YV12_TO_YUY2(   BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bHorizontalMirror = FALSE /*IN*/, BOOL bVerticalMirror = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_BUFFER_TO_BMP_EX( CHAR * pszFilePathName /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, UINT nCropX /*IN*/, UINT nCropY /*IN*/, UINT nCropW /*IN*/, UINT nCropH /*IN*/, UINT nDstW /*IN*/, UINT nDstH /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/, BYTE * pszDstStreamBuffer = NULL /*OUT*/, ULONG * pDstStreamBufferSize = NULL /*IN/OUT*/, PF_SNAPSHOT_DONE_CALLBACK pCB = NULL /*IN*/, PVOID pUserData = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SNAPSHOT_BUFFER_TO_JPG_EX( CHAR * pszFilePathName /*IN*/, ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, UINT nCropX /*IN*/, UINT nCropY /*IN*/, UINT nCropW /*IN*/, UINT nCropH /*IN*/, UINT nDstW /*IN*/, UINT nDstH /*IN*/, ULONG nQuality /*IN*/, BOOL bIsAsync = TRUE /*IN*/, ULONG nMilliseconds = 0 /*IN*/, BYTE * pszDstStreamBuffer = NULL /*OUT*/, ULONG * pDstStreamBufferSize = NULL /*IN/OUT*/, PF_SNAPSHOT_DONE_CALLBACK pCB = NULL /*IN*/, PVOID pUserData = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CONVERT_3D_STEREO_BUFFER( ULONG nColorSpaceType /*IN*/, ULONG nSrcStereoDisplayMode /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, ULONG nDstStereoDisplayMode /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, BOOL bLeftRightSwap = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESIZE_VIDEO_BUFFER( ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_ROTATE_VIDEO_BUFFER_BOUNDARY( ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG * pDstWidth /*OUT*/, ULONG * pDstHeight /*OUT*/, double dAngle /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_ROTATE_VIDEO_BUFFER( ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, double dAngle /*IN*/, BYTE * pSrcTempFrameBuffer = NULL /*IN*/, BYTE * pDstTempFrameBuffer = NULL /*IN*/, BOOL bClearBackground = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_WARP_VIDEO_BUFFER( ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, LONG nWarpDstX1 /*IN*/, LONG nWarpDstY1 /*IN*/, LONG nWarpDstX2 /*IN*/, LONG nWarpDstY2 /*IN*/, LONG nWarpDstX3 /*IN*/, LONG nWarpDstY3 /*IN*/, LONG nWarpDstX4 /*IN*/, LONG nWarpDstY4 /*IN*/, BYTE * pSrcTempFrameBuffer = NULL /*IN*/, BYTE * pDstTempFrameBuffer = NULL /*IN*/, BOOL bClearBackground = TRUE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_LOAD_PICTURE_BUFFER( CHAR * pszFilePathName /*IN*/, ULONG * pColorSpaceType /*OUT*/, BYTE * pFrameBuffer /*OUT*/, ULONG * pFrameBufferSize /*IN/OUT*/, ULONG * pFrameWidth /*OUT*/, ULONG * pFrameHeight /*OUT*/, ULONG * pFramePitch /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_CALCULATE_CHROMAKEY( ULONG nColorSpaceType /*IN*/, BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcWidth /*IN*/, ULONG nSrcHeight /*IN*/, ULONG nSrcPitch /*IN*/, ULONG nSrcCropX /*IN*/, ULONG nSrcCropY /*IN*/, ULONG nSrcCropW /*IN*/, ULONG nSrcCropH /*IN*/, BYTE * pDstAlpahBuffer /*OUT*/, BYTE * pDstYBuffer /*OUT*/, BYTE * pDstCbBuffer /*OUT*/, BYTE * pDstCrBuffer /*OUT*/, BYTE * pDstABGRBuffer /*OUT*/, ULONG nDstWidth /*IN*/, ULONG nDstHeight /*IN*/, ULONG nDstPitch /*IN*/, ULONG nTransparent /*IN*/, DWORD dwKeyColor = 0xFFFFFFFF /*IN*/ /*0xFFFFFFFF (OFF) / 0x00FF0000 (BLUE) / 0x0000FF00 (GREEN)*/, ULONG nKeyColorThreshold = 25 /*IN*/ /*0 ~ 128*/, ULONG nKeyColorBlurLevel = 2 /*IN*/ /*0 ~ 2*/, BOOL bKeyColorSpillSuppress = TRUE /*IN*/, ULONG nKeyColorSpillSuppressThreshold = 22 /*IN*/ );
+
+// HELPER FUNCTIONS PART.3 (FOR AUDIO) //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_BUFFER_VOLUME_DB( BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, UINT iChNum /*IN*/, double * pVolumeDB /*OUT*/ /*RANGE = -100 ~ 0 (DB)*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_GET_AUDIO_BUFFER_FAST_FOURIER_TRANSFORM_DATA( BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, UINT iChNum /*IN*/, double * pPeakFrq /*OUT*/, double * pPeakFrqAmp /*OUT*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESAMPLE_AUDIO_BUFFER( BYTE * pSrcFrameBuffer /*IN*/, ULONG nSrcFrameBufferLen /*IN*/, ULONG nSrcChannels /*IN*/, ULONG nSrcBitsPerSample /*IN*/, ULONG nSrcSampleFrequency /*IN*/, BYTE * pDstFrameBuffer /*OUT*/, ULONG * pDstFrameBufferLen /*IN/OUT*/, ULONG nDstChannels /*IN*/, ULONG nDstBitsPerSample /*IN*/, ULONG nDstSampleFrequency /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_RESCALE_AUDIO_BUFFER( BYTE * pFrameBuffer /*IN*/, ULONG nFrameBufferLen /*IN*/, ULONG nChannels /*IN*/, ULONG nBitsPerSample /*IN*/, ULONG nSampleFrequency /*IN*/, ULONG nVolume /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SOUNDRENDERER_ENUMERATION( CHAR * * ppszSoundRendererDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SOUNDRENDERER_ENUMERATION_W( WSTRING * ppwszSoundRendererDevName /*OUT*/, BOOL bNext = FALSE /*IN*/ );
+
+// HELPER FUNCTIONS PART.4 (FOR SYSTEM) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SYSTEM_ENABLE_HARDWARE_DEVICE( DWORD dwVendorID /*IN*/, DWORD dwProductID /*IN*/, CHAR * pszDevicePath = NULL /*IN*/ );
+
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_SYSTEM_DISABLE_HARDWARE_DEVICE( DWORD dwVendorID /*IN*/, DWORD dwProductID /*IN*/, CHAR * pszDevicePath = NULL /*IN*/ );
+
+// HELPER FUNCTIONS PART.5 (FOR MATRIX) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API QRESULT QCAP_EXPORT QCAP_MATRIX_QUAD_MAPPING( double * pMatrixA /*IN*/ /*(x1, y1) ~ (x4, y4)*/, double * pMatrixB /*IN*/ /*(X1, Y1) ~ (X4, Y4)*/, double * pSrcA /*IN*/ /*(x, y)*/, double * pDstB /*OUT*/ /*(X, Y)*/ );
+
+// HELPER FUNCTIONS PART.6 (FOR .NET DEVELOPER) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 
+QCAP_EXT_API ULONGLONG QCAP_EXPORT QCAP_HELPER_OBJPTR( PVOID pObj /*IN*/ );
+
+#endif // QCAP_H
+

BIN
VideoCapture/VideoCapture/QCAP.X86.LIB


+ 178 - 0
VideoCapture/VideoCapture/Resource.h

@@ -0,0 +1,178 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ 生成的包含文件。
+// 供 VideoCapture.rc 使用
+//
+#define IDD_ABOUTBOX                    100
+#define IDP_OLE_INIT_FAILED             100
+#define IDB_WRITESMALL                  110
+#define IDB_WRITELARGE                  111
+#define IDB_MAIN                        112
+#define IDB_BUTTONS                     113
+#define IDB_FILELARGE                   114
+#define IDB_FILESMALL                   115
+#define IDR_POPUP_EDIT                  119
+#define ID_STATUSBAR_PANE1              120
+#define ID_STATUSBAR_PANE2              121
+#define IDS_STATUS_PANE1                122
+#define IDS_STATUS_PANE2                123
+#define IDR_MAINFRAME                   128
+#define IDR_MAINFRAME_256               129
+#define IDR_VideoCaptureTYPE            130
+#define ID_WINDOW_MANAGER               131
+#define ID_VIEW_FILEVIEW                133
+#define ID_VIEW_CLASSVIEW               134
+#define ID_PROPERTIES                   135
+#define ID_OPEN                         136
+#define ID_OPEN_WITH                    137
+#define ID_DUMMY_COMPILE                138
+#define ID_CLASS_ADD_MEMBER_FUNCTION    139
+#define ID_CLASS_ADD_MEMBER_VARIABLE    140
+#define ID_CLASS_DEFINITION             141
+#define ID_CLASS_PROPERTIES             142
+#define ID_NEW_FOLDER                   143
+#define ID_SORT_MENU                    144
+#define ID_SORTING_GROUPBYTYPE          145
+#define ID_SORTING_SORTALPHABETIC       146
+#define ID_SORTING_SORTBYTYPE           147
+#define ID_SORTING_SORTBYACCESS         148
+#define ID_VIEW_OUTPUTWND               149
+#define ID_VIEW_PROPERTIESWND           150
+#define IDR_PASTE_MENU                  151
+#define ID_SORTPROPERTIES               151
+#define IDR_WINDOWS_MENU                152
+#define ID_PROPERTIES1                  152
+#define ID_PROPERTIES2                  153
+#define ID_EXPAND_ALL                   154
+#define IDS_FILE_VIEW                   155
+#define IDS_CLASS_VIEW                  156
+#define IDS_OUTPUT_WND                  157
+#define IDS_PROPERTIES_WND              158
+#define IDI_FILE_VIEW                   161
+#define IDI_FILE_VIEW_HC                162
+#define IDI_CLASS_VIEW                  163
+#define IDI_CLASS_VIEW_HC               164
+#define IDI_OUTPUT_WND                  165
+#define IDI_OUTPUT_WND_HC               166
+#define IDI_PROPERTIES_WND              167
+#define IDI_PROPERTIES_WND_HC           168
+#define IDR_EXPLORER                    169
+#define IDB_EXPLORER_24                 170
+#define IDR_SORT                        171
+#define IDB_SORT_24                     172
+#define IDR_POPUP_SORT                  173
+#define IDR_POPUP_EXPLORER              174
+#define IDB_FILE_VIEW                   175
+#define IDB_FILE_VIEW_24                176
+#define IDB_CLASS_VIEW                  177
+#define IDB_CLASS_VIEW_24               178
+#define IDR_MENU_IMAGES                 179
+#define IDB_MENU_IMAGES_24              180
+#define ID_TOOLS_MACRO                  181
+#define IDR_OUTPUT_POPUP                182
+#define IDR_PROPERTIES                  183
+#define IDB_PROPERTIES_HC               184
+#define ID_VIEW_NAVIGATION              185
+#define IDB_NAVIGATION_LARGE            186
+#define IDB_NAVIGATION_LARGE_HC         187
+#define IDB_PAGES                       188
+#define IDB_PAGES_HC                    189
+#define IDB_PAGES_SMALL                 190
+#define IDB_PAGES_SMALL_HC              191
+#define IDR_THEME_MENU                  200
+#define ID_SET_STYLE                    201
+#define ID_VIEW_APPLOOK_WIN_2000        205
+#define ID_VIEW_APPLOOK_OFF_XP          206
+#define ID_VIEW_APPLOOK_WIN_XP          207
+#define ID_VIEW_APPLOOK_OFF_2003        208
+#define ID_VIEW_APPLOOK_VS_2005         209
+#define ID_VIEW_APPLOOK_VS_2008         210
+#define ID_VIEW_APPLOOK_OFF_2007_BLUE   215
+#define ID_VIEW_APPLOOK_OFF_2007_BLACK  216
+#define ID_VIEW_APPLOOK_OFF_2007_SILVER 217
+#define ID_VIEW_APPLOOK_OFF_2007_AQUA   218
+#define ID_VIEW_APPLOOK_WINDOWS_7       219
+#define ID_TOOLS_OPTIONS                220
+#define ID_VIEW_CAPTION_BAR             221
+#define IDB_INFO                        230
+#define IDS_CAPTION_BUTTON              231
+#define IDS_CAPTION_BUTTON_TIP          232
+#define IDS_CAPTION_TEXT                233
+#define IDS_CAPTION_IMAGE_TIP           234
+#define IDS_CAPTION_IMAGE_TEXT          235
+#define IDS_MYCALENDARS                 250
+#define IDS_CALENDAR                    251
+#define IDS_SHORTCUTS                   252
+#define IDS_FOLDERS                     253
+#define IDS_OUTLOOKBAR                  258
+#define IDS_BUILD_TAB                   300
+#define IDS_DEBUG_TAB                   301
+#define IDS_FIND_TAB                    302
+#define IDS_EXPLORER                    305
+#define IDS_EDIT_MENU                   306
+#define IDR_RIBBON                      307
+#define IDD_DLG_IRCONTROL               311
+#define IDC_STATIC_VER                  1000
+#define IDC_BUTTON1                     1001
+#define IDC_BUTTON2                     1002
+#define IDC_BUTTON3                     1003
+#define IDC_BUTTON4                     1004
+#define IDC_BUTTON5                     1005
+#define IDC_BUTTON6                     1006
+#define IDC_BUTTON7                     1007
+#define IDC_BUTTON8                     1008
+#define IDC_BUTTON9                     1009
+#define IDC_BUTTON10                    1010
+#define IDC_BUTTON11                    1011
+#define IDC_BUTTON12                    1012
+#define IDC_BUTTON13                    1013
+#define IDC_BUTTON14                    1014
+#define IDC_BUTTON15                    1015
+#define IDC_BUTTON16                    1016
+#define IDC_BUTTON17                    1017
+#define IDC_BUTTON18                    1018
+#define IDC_BUTTON19                    1019
+#define IDC_BUTTON20                    1020
+#define IDC_BUTTON21                    1021
+#define IDC_BUTTON22                    1022
+#define IDC_BUTTON23                    1023
+#define IDC_BUTTON24                    1024
+#define ID_WRITE_PASTEASHYPERLINK       32770
+#define ID_CHECK_HDMI                   32771
+#define ID_CHECK_DVID                   32772
+#define ID_CHECK_YCBCR                  32773
+#define ID_CHECK_DVIA                   32774
+#define ID_CHECK_COMPOSITE              32775
+#define ID_CHECK_SVIDEO                 32776
+#define ID_CHECK_SDI                    32777
+#define ID_CHECK_AUTO                   32778
+#define ID_CHECK2                       32779
+#define ID_CHECK3                       32780
+#define ID_SLIDER1                      32781
+#define ID_SLIDER2                      32782
+#define ID_CHECK_FORMAT_MP4             32786
+#define ID_BUTTON4                      32787
+#define ID_CUT_BMP                      32790
+#define ID_CUT_JPG                      32791
+#define ID_START_RECORD                 32792
+#define ID_STOP_RECORD                  32793
+#define ID_TRAYMENU_32794               32794
+#define ID_TRAYMENU_EXIT                32795
+#define ID_CHECK_VERTICALLY             32796
+#define ID_CHECK_HORIONTAL              32797
+#define ID_TRAYMENU_32799               32799
+#define ID_TRAYMENU_RECONNECT           32800
+#define ID_BUTTON2                      32802
+#define ID_BUTTON3                      32803
+#define ID_CHECK_SUPORT_GPU             32804
+#define ID_CHECK_FORMAT_AVI             32805
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        313
+#define _APS_NEXT_COMMAND_VALUE         32806
+#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_SYMED_VALUE           310
+#endif
+#endif

+ 1290 - 0
VideoCapture/VideoCapture/SpreadSheet.cpp

@@ -0,0 +1,1290 @@
+// Class to read and write to Excel and text delimited spreadsheet
+//
+// Created by Yap Chun Wei
+// December 2001
+// 
+// Version 1.1
+// Updates: Fix bug in ReadRow() which prevent reading of single column spreadsheet
+// Modified by jingzhou xu
+#include "stdafx.h"
+#include "SpreadSheet.h"
+
+// Open spreadsheet for reading and writing
+CSpreadSheet::CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup) :
+m_Database(NULL), m_rSheet(NULL), m_sFile(File),
+m_dTotalRows(0), m_dTotalColumns(0), m_dCurrentRow(1),
+m_bAppend(false), m_bBackup(Backup), m_bTransaction(false)
+{
+	// Detect whether file is an Excel spreadsheet or a text delimited file
+	m_stempString = m_sFile.Right(4);
+	m_stempString.MakeLower();
+	if (m_stempString == ".xls") // File is an Excel spreadsheet
+	{
+		m_bExcel = true;
+		m_sSheetName = SheetOrSeparator;
+		m_sSeparator = ",;.?";
+	}
+	else // File is a text delimited file
+	{
+		m_bExcel = false;
+		m_sSeparator = SheetOrSeparator;
+	}
+
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		m_Database = new CDatabase;
+		GetExcelDriver();
+		m_sDsn.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=\"%s\";DBQ=%s", m_sExcelDriver, m_sFile, m_sFile);
+
+		if (Open())
+		{
+			if (m_bBackup)
+			{
+				if ((m_bBackup) && (m_bAppend))
+				{
+					CString tempSheetName = m_sSheetName;
+					m_sSheetName = "CSpreadSheetBackup";
+					m_bAppend = false;
+					if (!Commit())
+					{
+						m_bBackup = false;
+					}
+					m_bAppend = true;
+					m_sSheetName = tempSheetName;
+					m_dCurrentRow = 1;
+				}
+			}
+		}
+	}
+	else // if file is a text delimited file
+	{
+		if (Open())
+		{
+			if ((m_bBackup) && (m_bAppend))
+			{
+				m_stempString = m_sFile;
+				m_stempSql.Format("%s.bak", m_sFile);
+				m_sFile = m_stempSql;
+				if (!Commit())
+				{
+					m_bBackup = false;
+				}
+				m_sFile = m_stempString;
+			}
+		}
+	}
+}
+
+// Perform some cleanup functions
+CSpreadSheet::~CSpreadSheet()
+{
+	if (m_Database != NULL)
+	{
+		m_Database->Close();
+		delete m_Database;
+	}
+}
+
+// Add header row to spreadsheet
+bool CSpreadSheet::AddHeaders(CStringArray &FieldNames, bool replace)
+{
+	if (m_bAppend) // Append to old Sheet
+	{
+		if (replace) // Replacing header row rather than adding new columns
+		{
+			if (!AddRow(FieldNames, 1, true))
+			{
+				return false;
+			}
+			else
+			{
+				return true;
+			}
+		}
+
+		if (ReadRow(m_atempArray, 1)) // Add new columns
+		{
+			if (m_bExcel)
+			{
+				// Check for duplicate header row field
+				for (int i = 0; i < FieldNames.GetSize(); i++)
+				{
+					for (int j = 0; j < m_atempArray.GetSize(); j++)
+					{
+						if (FieldNames.GetAt(i) == m_atempArray.GetAt(j))
+						{
+							m_sLastError.Format("Duplicate header row field:%s\n", FieldNames.GetAt(i));
+							return false;
+						}
+					}
+				}	
+			}
+
+			m_atempArray.Append(FieldNames);
+			if (!AddRow(m_atempArray, 1, true))
+			{
+				m_sLastError = "Problems with adding headers\n";
+				return false;
+			}
+
+			// Update largest number of columns if necessary
+			if (m_atempArray.GetSize() > m_dTotalColumns)
+			{
+				m_dTotalColumns = m_atempArray.GetSize();
+			}
+			return true;
+		}
+		return false;				
+	}
+	else // New Sheet
+	{
+		m_dTotalColumns = FieldNames.GetSize();
+		if (!AddRow(FieldNames, 1, true))
+		{
+			return false;
+		}
+		else
+		{
+			m_dTotalRows = 1;
+			return true;
+		}
+	}
+}
+
+// Clear text delimited file content
+bool CSpreadSheet::DeleteSheet()
+{
+	if (m_bExcel)
+	{
+		if (DeleteSheet(m_sSheetName))
+		{
+			return true;
+		}
+		else
+		{
+			m_sLastError = "Error deleting sheet\n";
+			return false;
+		}
+	}
+	else
+	{
+		m_aRows.RemoveAll();
+		m_aFieldNames.RemoveAll();
+		m_dTotalColumns = 0;
+		m_dTotalRows = 0;
+		if (!m_bTransaction)
+		{
+			Commit();			
+		}
+		m_bAppend = false; // Set flag to new sheet
+		return true;		
+	}
+}
+
+// Clear entire Excel spreadsheet content. The sheet itself is not deleted
+bool CSpreadSheet::DeleteSheet(CString SheetName)
+{
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		// Delete sheet
+		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
+		SheetName = "[" + SheetName + "$A1:IV65536]";
+		m_stempSql.Format("DROP TABLE %s", SheetName);
+		try
+		{
+			m_Database->ExecuteSQL(m_stempSql);
+			m_Database->Close();
+			m_aRows.RemoveAll();
+			m_aFieldNames.RemoveAll();
+			m_dTotalColumns = 0;
+			m_dTotalRows = 0;
+		}
+		catch(CDBException *e)
+		{
+			m_sLastError = e->m_strError;
+			m_Database->Close();
+			return false;
+		}
+		return true;
+	}
+	else // if file is a text delimited file
+	{
+		return DeleteSheet();
+	}
+}
+
+// Insert or replace a row into spreadsheet. 
+// Default is add new row.
+bool CSpreadSheet::AddRow(CStringArray &RowValues, long row, bool replace)
+{
+	long tempRow;
+	
+	if (row == 1)
+	{
+		if (m_bExcel) 
+		{
+			// Check for duplicate header row field for Excel spreadsheet
+			for (int i = 0; i < RowValues.GetSize(); i++)
+			{
+				for (int j = 0; j < RowValues.GetSize(); j++)
+				{
+					if ((i != j) && (RowValues.GetAt(i) == RowValues.GetAt(j)))
+					{
+						m_sLastError.Format("Duplicate header row field:%s\n", RowValues.GetAt(i));
+						return false;
+					}
+				}
+			}
+			
+			// Check for reduced header row columns
+			if (RowValues.GetSize() < m_dTotalColumns)
+			{
+				m_sLastError = "Number of columns in new header row cannot be less than the number of columns in previous header row";
+				return false;
+			}
+			m_dTotalColumns = RowValues.GetSize();
+		}
+
+		// Update header row
+		m_aFieldNames.RemoveAll();
+		m_aFieldNames.Copy(RowValues);
+	}
+	else
+	{
+		if (m_bExcel)
+		{
+			if (m_dTotalColumns == 0)
+			{
+				m_sLastError = "No header row. Add header row first\n";
+				return false;
+			}
+		}
+	}
+
+	if (m_bExcel) // For Excel spreadsheet
+	{
+		if (RowValues.GetSize() > m_aFieldNames.GetSize())
+		{
+			m_sLastError = "Number of columns to be added cannot be greater than the number of fields\n";
+			return false;
+		}
+	}
+	else // For text delimited spreadsheet
+	{
+		// Update largest number of columns if necessary
+		if (RowValues.GetSize() > m_dTotalColumns)
+		{
+			m_dTotalColumns = RowValues.GetSize();
+		}
+	}
+
+	// Convert row values
+	m_stempString.Empty();
+	for (int i = 0; i < RowValues.GetSize(); i++)
+	{
+		if (i != RowValues.GetSize()-1) // Not last column
+		{
+			m_stempSql.Format("\"%s\"%s", RowValues.GetAt(i), m_sSeparator);
+			m_stempString += m_stempSql;
+		}
+		else // Last column
+		{
+			m_stempSql.Format("\"%s\"", RowValues.GetAt(i));
+			m_stempString += m_stempSql;
+		}
+	}
+	
+	if (row)
+	{
+		if (row <= m_dTotalRows) // Not adding new rows
+		{
+			if (replace) // Replacing row
+			{
+				m_aRows.SetAt(row-1, m_stempString);
+			}
+			else // Inserting row
+			{
+				m_aRows.InsertAt(row-1, m_stempString);
+				m_dTotalRows++;
+			}
+
+			if (!m_bTransaction)
+			{
+				Commit();
+			}
+			return true;
+		}
+		else // Adding new rows
+		{
+			// Insert null rows until specified row
+			m_dCurrentRow = m_dTotalRows;
+			m_stempSql.Empty();
+			CString nullString;
+			for (int i = 1; i <= m_dTotalColumns; i++)
+			{
+				if (i != m_dTotalColumns)
+				{
+					if (m_bExcel)
+					{
+						nullString.Format("\" \"%s", m_sSeparator);
+					}
+					else
+					{
+						nullString.Format("\"\"%s", m_sSeparator);
+					}
+					m_stempSql += nullString;
+				}
+				else
+				{
+					if (m_bExcel)
+					{
+						m_stempSql += "\" \"";
+					}
+					else
+					{
+						m_stempSql += "\"\"";
+					}
+				}
+			}
+			for (int j = m_dTotalRows + 1; j < row; j++)
+			{
+				m_dCurrentRow++;
+				m_aRows.Add(m_stempSql);
+			}
+		}
+	}
+	else
+	{
+		tempRow = m_dCurrentRow;
+		m_dCurrentRow = m_dTotalRows;
+	}
+
+	// Insert new row
+	m_dCurrentRow++;
+	m_aRows.Add(m_stempString);
+	
+	if (row > m_dTotalRows)
+	{
+		m_dTotalRows = row;
+	}
+	else if (!row)
+	{
+		m_dTotalRows = m_dCurrentRow;
+		m_dCurrentRow = tempRow;
+	}
+	if (!m_bTransaction)
+	{
+		Commit();
+	}
+	return true;
+}
+
+// Replace or add a cell into Excel spreadsheet using header row or column alphabet. 
+// Default is add cell into new row.
+// Set Auto to false if want to force column to be used as header name
+bool CSpreadSheet::AddCell(CString CellValue, CString column, long row, bool Auto)
+{
+	short columnIndex = CalculateColumnNumber(column, Auto);
+	if (columnIndex == 0)
+	{
+		return false;
+	}
+
+	if (AddCell(CellValue, columnIndex, row))
+	{
+		return true;
+	}
+	return false;
+}
+
+// Replace or add a cell into spreadsheet using column number
+// Default is add cell into new row.
+bool CSpreadSheet::AddCell(CString CellValue, short column, long row)
+{
+	if (column == 0)
+	{
+		m_sLastError = "Column cannot be zero\n";
+		return false;
+	}
+
+	long tempRow;
+
+	if (m_bExcel) // For Excel spreadsheet
+	{
+		if (column > m_aFieldNames.GetSize() + 1)
+		{
+			m_sLastError = "Cell column to be added cannot be greater than the number of fields\n";
+			return false;
+		}
+	}
+	else // For text delimited spreadsheet
+	{
+		// Update largest number of columns if necessary
+		if (column > m_dTotalColumns)
+		{
+			m_dTotalColumns = column;
+		}
+	}
+
+	if (row)
+	{
+		if (row <= m_dTotalRows)
+		{
+			ReadRow(m_atempArray, row);
+	
+			// Change desired row
+			m_atempArray.SetAtGrow(column-1, CellValue);
+
+			if (row == 1)
+			{
+				if (m_bExcel) // Check for duplicate header row field
+				{										
+					for (int i = 0; i < m_atempArray.GetSize(); i++)
+					{
+						for (int j = 0; j < m_atempArray.GetSize(); j++)
+						{
+							if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))
+							{
+								m_sLastError.Format("Duplicate header row field:%s\n", m_atempArray.GetAt(i));
+								return false;
+							}
+						}
+					}
+				}
+
+				// Update header row
+				m_aFieldNames.RemoveAll();
+				m_aFieldNames.Copy(m_atempArray);
+			}	
+
+			if (!AddRow(m_atempArray, row, true))
+			{
+				return false;
+			}
+
+			if (!m_bTransaction)
+			{
+				Commit();
+			}
+			return true;
+		}
+		else
+		{
+			// Insert null rows until specified row
+			m_dCurrentRow = m_dTotalRows;
+			m_stempSql.Empty();
+			CString nullString;
+			for (int i = 1; i <= m_dTotalColumns; i++)
+			{
+				if (i != m_dTotalColumns)
+				{
+					if (m_bExcel)
+					{
+						nullString.Format("\" \"%s", m_sSeparator);
+					}
+					else
+					{
+						nullString.Format("\"\"%s", m_sSeparator);
+					}
+					m_stempSql += nullString;
+				}
+				else
+				{
+					if (m_bExcel)
+					{
+						m_stempSql += "\" \"";
+					}
+					else
+					{
+						m_stempSql += "\"\"";
+					}
+				}
+			}
+			for (int j = m_dTotalRows + 1; j < row; j++)
+			{
+				m_dCurrentRow++;
+				m_aRows.Add(m_stempSql);
+			}
+		}
+	}
+	else
+	{
+		tempRow = m_dCurrentRow;
+		m_dCurrentRow = m_dTotalRows;
+	}
+
+	// Insert cell
+	m_dCurrentRow++;
+	m_stempString.Empty();
+	for (int j = 1; j <= m_dTotalColumns; j++)
+	{
+		if (j != m_dTotalColumns) // Not last column
+		{
+			if (j != column)
+			{
+				if (m_bExcel)
+				{
+					m_stempSql.Format("\" \"%s", m_sSeparator);
+				}
+				else
+				{
+					m_stempSql.Format("\"\"%s", m_sSeparator);
+				}
+				m_stempString += m_stempSql;
+			}
+			else
+			{
+				m_stempSql.Format("\"%s\"%s", CellValue, m_sSeparator);
+				m_stempString += m_stempSql;
+			}
+		}
+		else // Last column
+		{
+			if (j != column)
+			{
+				if (m_bExcel)
+				{
+					m_stempString += "\" \"";
+				}
+				else
+				{
+					m_stempString += "\"\"";
+				}
+			}
+			else
+			{
+				m_stempSql.Format("\"%s\"", CellValue);
+				m_stempString += m_stempSql;
+			}
+		}
+	}	
+
+	m_aRows.Add(m_stempString);
+	
+	if (row > m_dTotalRows)
+	{
+		m_dTotalRows = row;
+	}
+	else if (!row)
+	{
+		m_dTotalRows = m_dCurrentRow;
+		m_dCurrentRow = tempRow;
+	}
+	if (!m_bTransaction)
+	{
+		Commit();
+	}
+	return true;
+}
+
+// Search and replace rows in Excel spreadsheet
+bool CSpreadSheet::ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues)
+{
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
+		m_stempSql.Format("UPDATE [%s] SET ", m_sSheetName);
+		for (int i = 0; i < NewRowValues.GetSize(); i++)
+		{
+			m_stempString.Format("[%s]='%s', ", m_aFieldNames.GetAt(i), NewRowValues.GetAt(i));
+			m_stempSql = m_stempSql + m_stempString;
+		}
+		m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
+		m_stempSql = m_stempSql + " WHERE (";
+		for (int j = 0; j < OldRowValues.GetSize()-1; j++)
+		{
+			m_stempString.Format("[%s]='%s' AND ", m_aFieldNames.GetAt(j), OldRowValues.GetAt(j));
+			m_stempSql = m_stempSql + m_stempString;
+		}
+		m_stempSql.Delete(m_stempSql.GetLength()-4, 5);
+		m_stempSql += ")";
+
+		try
+		{
+			m_Database->ExecuteSQL(m_stempSql);
+			m_Database->Close();
+			Open();
+			return true;
+		}
+		catch(CDBException *e)
+		{
+			m_sLastError = e->m_strError;
+			m_Database->Close();
+			return false;
+		}
+	}
+	else // if file is a text delimited file
+	{
+		m_sLastError = "Function not available for text delimited file\n";
+		return false;
+	}
+}
+
+// Read a row from spreadsheet. 
+// Default is read the next row
+bool CSpreadSheet::ReadRow(CStringArray &RowValues, long row)
+{
+	// Check if row entered is more than number of rows in sheet
+	if (row <= m_aRows.GetSize())
+	{
+		if (row != 0)
+		{
+			m_dCurrentRow = row;
+		}
+		else if (m_dCurrentRow > m_aRows.GetSize())
+		{
+			return false;
+		}
+		// Read the desired row
+		RowValues.RemoveAll();
+		m_stempString = m_aRows.GetAt(m_dCurrentRow-1);
+		m_dCurrentRow++;
+
+		// Search for separator to split row
+		int separatorPosition;
+		m_stempSql.Format("\"%s\"", m_sSeparator);
+		separatorPosition = m_stempString.Find(m_stempSql); // If separator is "?"
+		if (separatorPosition != -1)
+		{
+			// Save columns
+			int nCount = 0;
+			int stringStartingPosition = 0;
+			while (separatorPosition != -1)
+			{
+				nCount = separatorPosition - stringStartingPosition;
+				RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
+				stringStartingPosition = separatorPosition + m_stempSql.GetLength();
+				separatorPosition = m_stempString.Find(m_stempSql, stringStartingPosition);
+			}
+			nCount = m_stempString.GetLength() - stringStartingPosition;
+			RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
+
+			// Remove quotes from first column
+			m_stempString = RowValues.GetAt(0);
+			m_stempString.Delete(0, 1);
+			RowValues.SetAt(0, m_stempString);
+			
+			// Remove quotes from last column
+			m_stempString = RowValues.GetAt(RowValues.GetSize()-1);
+			m_stempString.Delete(m_stempString.GetLength()-1, 1);
+			RowValues.SetAt(RowValues.GetSize()-1, m_stempString);
+
+			return true;
+		}
+		else
+		{
+			// Save columns
+			separatorPosition = m_stempString.Find(m_sSeparator); // if separator is ?
+			if (separatorPosition != -1)
+			{
+				int nCount = 0;
+				int stringStartingPosition = 0;
+				while (separatorPosition != -1)
+				{
+					nCount = separatorPosition - stringStartingPosition;
+					RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
+					stringStartingPosition = separatorPosition + m_sSeparator.GetLength();
+					separatorPosition = m_stempString.Find(m_sSeparator, stringStartingPosition);
+				}
+				nCount = m_stempString.GetLength() - stringStartingPosition;
+				RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));
+				return true;
+			}
+			else	// Treat spreadsheet as having one column
+			{
+				// Remove opening and ending quotes if any
+				int quoteBegPos = m_stempString.Find('\"');
+				int quoteEndPos = m_stempString.ReverseFind('\"');
+				if ((quoteBegPos == 0) && (quoteEndPos == m_stempString.GetLength()-1))
+				{
+					m_stempString.Delete(0, 1);
+					m_stempString.Delete(m_stempString.GetLength()-1, 1);
+				}
+
+				RowValues.Add(m_stempString);
+			}
+		}
+	}
+	m_sLastError = "Desired row is greater than total number of rows in spreadsheet\n";
+	return false;
+}
+
+// Read a column from Excel spreadsheet using header row or column alphabet. 
+// Set Auto to false if want to force column to be used as header name
+bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, CString column, bool Auto)
+{
+	short columnIndex = CalculateColumnNumber(column, Auto);
+	if (columnIndex == 0)
+	{
+		return false;
+	}
+
+	if (ReadColumn(ColumnValues, columnIndex))
+	{
+		return true;
+	}
+	return false;
+}
+
+// Read a column from spreadsheet using column number
+bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, short column)
+{
+	if (column == 0)
+	{
+		m_sLastError = "Column cannot be zero\n";
+		return false;
+	}
+
+	int tempRow = m_dCurrentRow;
+	m_dCurrentRow = 1;
+	ColumnValues.RemoveAll();
+	for (int i = 1; i <= m_aRows.GetSize(); i++)
+	{
+		// Read each row
+		if (ReadRow(m_atempArray, i))
+		{
+			// Get value of cell in desired column
+			if (column <= m_atempArray.GetSize())
+			{
+				ColumnValues.Add(m_atempArray.GetAt(column-1));
+			}
+			else
+			{
+				ColumnValues.Add("");
+			}
+		}
+		else
+		{
+			m_dCurrentRow = tempRow;
+			m_sLastError = "Error reading row\n";
+			return false;
+		}
+	}
+	m_dCurrentRow = tempRow;
+	return true;
+}
+
+// Read a cell from Excel spreadsheet using header row or column alphabet. 
+// Default is read the next cell in next row. 
+// Set Auto to false if want to force column to be used as header name
+bool CSpreadSheet::ReadCell (CString &CellValue, CString column, long row, bool Auto)
+{
+	short columnIndex = CalculateColumnNumber(column, Auto);
+	if (columnIndex == 0)
+	{
+		return false;
+	}
+
+	if (ReadCell(CellValue, columnIndex, row))
+	{
+		return true;
+	}
+	return false;
+}
+
+// Read a cell from spreadsheet using column number. 
+// Default is read the next cell in next row.
+bool CSpreadSheet::ReadCell (CString &CellValue, short column, long row)
+{
+	if (column == 0)
+	{
+		m_sLastError = "Column cannot be zero\n";
+		return false;
+	}
+
+	int tempRow = m_dCurrentRow;
+	if (row)
+	{
+		m_dCurrentRow = row;
+	}
+	if (ReadRow(m_atempArray, m_dCurrentRow))
+	{
+		// Get value of cell in desired column
+		if (column <= m_atempArray.GetSize())
+		{
+			CellValue = m_atempArray.GetAt(column-1);
+		}
+		else
+		{
+			CellValue.Empty();
+			m_dCurrentRow = tempRow;
+			return false;
+		}
+		m_dCurrentRow = tempRow;
+		return true;
+	}
+	m_dCurrentRow = tempRow;
+	m_sLastError = "Error reading row\n";
+	return false;
+}
+
+// Begin transaction
+void CSpreadSheet::BeginTransaction()
+{
+	m_bTransaction = true;
+}
+
+// Save changes to spreadsheet
+bool CSpreadSheet::Commit()
+{
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
+
+		if (m_bAppend)
+		{
+			// Delete old sheet if it exists
+			m_stempString= "[" + m_sSheetName + "$A1:IV65536]";
+			m_stempSql.Format("DROP TABLE %s", m_stempString);
+			try
+			{
+				m_Database->ExecuteSQL(m_stempSql);
+			}
+			catch(CDBException *e)
+			{
+				m_sLastError = e->m_strError;
+				m_Database->Close();
+				return false;
+			}
+			
+			// Create new sheet
+			m_stempSql.Format("CREATE TABLE [%s$A1:IV65536] (", m_sSheetName);
+			for (int j = 0; j < m_aFieldNames.GetSize(); j++)
+			{
+				m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(j) +"]" + " char(255), ";
+			}
+			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
+			m_stempSql += ")";
+		}
+		else
+		{
+			// Create new sheet
+			m_stempSql.Format("CREATE TABLE [%s] (", m_sSheetName);
+			for (int i = 0; i < m_aFieldNames.GetSize(); i++)
+			{
+				m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(i) +"]" + " char(255), ";
+			}
+			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
+			m_stempSql += ")";
+		}
+
+		try
+		{
+			m_Database->ExecuteSQL(m_stempSql);
+			if (!m_bAppend)
+			{
+				m_dTotalColumns = m_aFieldNames.GetSize();
+				m_bAppend = true;
+			}
+		}
+		catch(CDBException *e)
+		{
+			m_sLastError = e->m_strError;
+			m_Database->Close();
+			return false;
+		}
+
+		// Save changed data
+		for (int k = 1; k < m_dTotalRows; k++)
+		{
+			ReadRow(m_atempArray, k+1);
+
+			// Create Insert SQL
+			m_stempSql.Format("INSERT INTO [%s$A1:IV%d] (", m_sSheetName, k);
+			for (int i = 0; i < m_atempArray.GetSize(); i++)
+			{
+				m_stempString.Format("[%s], ", m_aFieldNames.GetAt(i));
+				m_stempSql = m_stempSql + m_stempString;
+			}
+			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
+			m_stempSql += ") VALUES (";
+			for (int j = 0; j < m_atempArray.GetSize(); j++)
+			{
+				m_stempString.Format("'%s', ", m_atempArray.GetAt(j));
+				m_stempSql = m_stempSql + m_stempString;
+			}
+			m_stempSql.Delete(m_stempSql.GetLength()-2, 2);
+			m_stempSql += ")";
+
+			// Add row
+			try
+			{
+				m_Database->ExecuteSQL(m_stempSql);
+			}
+			catch(CDBException *e)
+			{
+				m_sLastError = e->m_strError;
+				m_Database->Close();
+				return false;
+			}
+		}
+		m_Database->Close();
+		m_bTransaction = false;
+		return true;
+	}
+	else // if file is a text delimited file
+	{
+		try
+		{
+			CFile *File = NULL;
+			File = new CFile(m_sFile, CFile::modeCreate | CFile::modeWrite  | CFile::shareDenyNone);
+			if (File != NULL)
+			{
+				CArchive *Archive = NULL;
+				Archive = new CArchive(File, CArchive::store);
+				if (Archive != NULL)
+				{
+					for (int i = 0; i < m_aRows.GetSize(); i++)
+					{
+						Archive->WriteString(m_aRows.GetAt(i));
+						Archive->WriteString("\r\n");
+					}
+					delete Archive;
+					delete File;
+					m_bTransaction = false;
+					return true;
+				}
+				delete File;
+			}
+		}
+		catch(...)
+		{
+		}
+		m_sLastError = "Error writing file\n";
+		return false;
+	}
+}
+
+// Undo changes to spreadsheet
+bool CSpreadSheet::RollBack()
+{
+	if (Open())
+	{
+		m_bTransaction = false;
+		return true;
+	}
+	m_sLastError = "Error in returning to previous state\n";
+	return false;
+}
+
+bool CSpreadSheet::Convert(CString SheetOrSeparator)
+{
+	// Prepare file
+	m_stempString = m_sFile;
+	m_stempString.Delete(m_stempString.GetLength()-4, 4);
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		m_stempString += ".csv";
+		CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);
+		
+		// Stop convert if text delimited file exists
+		if (tempSheet.GetTotalColumns() != 0)
+		{
+			return false;
+		}
+
+		tempSheet.BeginTransaction();
+
+		for (int i = 1; i <= m_dTotalRows; i++)
+		{
+			if (!ReadRow(m_atempArray, i))
+			{
+				return false;
+			}
+			if (!tempSheet.AddRow(m_atempArray, i))
+			{
+				return false;
+			}
+		}
+		if (!tempSheet.Commit())
+		{
+			return false;
+		}
+		return true;
+	}
+	else // if file is a text delimited file
+	{
+		m_stempString += ".xls";
+		CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);
+
+		// Stop convert if Excel file exists
+		if (tempSheet.GetTotalColumns() != 0)
+		{
+			return false;
+		}
+
+		GetFieldNames(m_atempArray);
+
+		// Check for duplicate header row field
+		bool duplicate = false;
+		for (int i = 0; i < m_atempArray.GetSize(); i++)
+		{
+			for (int j = 0; j < m_atempArray.GetSize(); j++)
+			{
+				if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))
+				{
+					m_sLastError.Format("Duplicate header row field:%s\n", m_atempArray.GetAt(i));
+					duplicate = true;
+				}
+			}
+		}
+
+		if (duplicate) // Create dummy header row
+		{
+			m_atempArray.RemoveAll();
+			for (int k = 1; k <= m_dTotalColumns; k++)
+			{
+				m_stempString.Format("%d", k);
+				m_atempArray.Add(m_stempString);
+			}
+
+			if (!tempSheet.AddHeaders(m_atempArray))
+			{
+				return false;
+			}
+
+			for (int l = 1; l <= m_dTotalRows; l++)
+			{
+				if (!ReadRow(m_atempArray, l))
+				{
+					return false;
+				}
+				if (!tempSheet.AddRow(m_atempArray, l+1))
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+		else
+		{
+			if (!tempSheet.AddHeaders(m_atempArray))
+			{
+				return false;
+			}
+
+			for (int l = 2; l <= m_dTotalRows; l++)
+			{
+				if (!ReadRow(m_atempArray, l))
+				{
+					return false;
+				}
+				if (!tempSheet.AddRow(m_atempArray, l))
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+	}
+}
+
+// Open a text delimited file for reading or writing
+bool CSpreadSheet::Open()
+{
+	if (m_bExcel) // If file is an Excel spreadsheet
+	{
+		m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);
+
+		// Open Sheet
+		m_rSheet = new CRecordset( m_Database );
+		m_sSql.Format("SELECT * FROM [%s$A1:IV65536]", m_sSheetName);
+		try
+		{
+			m_rSheet->Open(CRecordset::forwardOnly, m_sSql, CRecordset::readOnly);
+		}
+		catch(...)
+		{
+			delete m_rSheet;
+			m_rSheet = NULL;
+			m_Database->Close();
+			return false;
+		}
+
+		// Get number of columns
+		m_dTotalColumns = m_rSheet->m_nResultCols;
+
+		if (m_dTotalColumns != 0)
+		{
+			m_aRows.RemoveAll();
+			m_stempString.Empty();
+			m_bAppend = true;
+			m_dTotalRows++; // Keep count of total number of rows
+			
+			// Get field names i.e header row
+			for (int i = 0; i < m_dTotalColumns; i++)
+			{
+				m_stempSql = m_rSheet->m_rgODBCFieldInfos[i].m_strName;
+				m_aFieldNames.Add(m_stempSql);
+
+				// Join up all the columns into a string
+				if (i != m_dTotalColumns-1) // Not last column
+				{
+					m_stempString = m_stempString + "\"" + m_stempSql + "\"" + m_sSeparator;
+				}
+				else // Last column
+				{	
+					m_stempString = m_stempString + "\"" + m_stempSql + "\"";
+				}				
+			}
+			
+			// Store the header row as the first row in memory
+			m_aRows.Add(m_stempString);
+
+			// Read and store the rest of the rows in memory
+			while (!m_rSheet->IsEOF())
+			{
+				m_dTotalRows++; // Keep count of total number of rows
+				try
+				{
+					// Get all the columns in a row
+					m_stempString.Empty();
+					for (short column = 0; column < m_dTotalColumns; column++)
+					{
+						m_rSheet->GetFieldValue(column, m_stempSql);
+
+						// Join up all the columns into a string
+						if (column != m_dTotalColumns-1) // Not last column
+						{
+							m_stempString = m_stempString + "\"" + m_stempSql + "\"" + m_sSeparator;
+						}
+						else // Last column
+						{	
+							m_stempString = m_stempString + "\"" + m_stempSql + "\"";
+						}
+					}
+
+					// Store the obtained row in memory
+					m_aRows.Add(m_stempString);
+					m_rSheet->MoveNext();
+				}
+				catch (...)
+				{
+					m_sLastError = "Error reading row\n";
+					delete m_rSheet;
+					m_rSheet = NULL;
+					m_Database->Close();
+					return false;
+				}
+			}		
+		}
+		
+		m_rSheet->Close();
+		delete m_rSheet;
+		m_rSheet = NULL;
+		m_Database->Close();
+		m_dCurrentRow = 1;
+		return true;
+	}
+	else // if file is a text delimited file
+	{
+		try
+		{
+			CFile *File = NULL;
+			File = new CFile(m_sFile, CFile::modeRead | CFile::shareDenyNone);
+			if (File != NULL)
+			{
+				CArchive *Archive = NULL;
+				Archive = new CArchive(File, CArchive::load);
+				if (Archive != NULL)
+				{
+					m_aRows.RemoveAll();
+					// Read and store all rows in memory
+					while(Archive->ReadString(m_stempString))
+					{
+						m_aRows.Add(m_stempString);
+					}
+					ReadRow(m_aFieldNames, 1); // Get field names i.e header row
+					delete Archive;
+					delete File;
+
+					// Get total number of rows
+					m_dTotalRows = m_aRows.GetSize();
+
+					// Get the largest number of columns
+					for (int i = 0; i < m_aRows.GetSize(); i++)
+					{
+						ReadRow(m_atempArray, i);
+						if (m_atempArray.GetSize() > m_dTotalColumns)
+						{
+							m_dTotalColumns = m_atempArray.GetSize();
+						}
+					}
+
+					if (m_dTotalColumns != 0)
+					{
+						m_bAppend = true;
+					}
+					return true;
+				}
+				delete File;
+			}
+		}
+		catch(...)
+		{
+		}
+		m_sLastError = "Error in opening file\n";
+		return false;
+	}
+}
+
+// Convert Excel column in alphabet into column number
+short CSpreadSheet::CalculateColumnNumber(CString column, bool Auto)
+{
+	if (Auto)
+	{
+		int firstLetter, secondLetter;
+		column.MakeUpper();
+
+		if (column.GetLength() == 1)
+		{
+			firstLetter = column.GetAt(0);
+			return (firstLetter - 65 + 1); // 65 is A in ascii
+		}
+		else if (column.GetLength() == 2)
+		{
+			firstLetter = column.GetAt(0);
+			secondLetter = column.GetAt(1);
+			return ((firstLetter - 65 + 1)*26 + (secondLetter - 65 + 1)); // 65 is A in ascii
+		}
+	}
+
+	// Check if it is a valid field name
+	for (int i = 0; i < m_aFieldNames.GetSize(); i++)
+	{
+		if (!column.Compare(m_aFieldNames.GetAt(i)))
+		{
+			return (i + 1);
+		}
+	}
+	m_sLastError = "Invalid field name or column alphabet\n";
+	return 0;	
+}
+
+// Get the name of the Excel-ODBC driver
+void CSpreadSheet::GetExcelDriver()
+{
+	char szBuf[2001];
+	WORD cbBufMax = 2000;
+	WORD cbBufOut;
+	char *pszBuf = szBuf;
+
+	// Get the names of the installed drivers ("odbcinst.h" has to be included )
+	if(!SQLGetInstalledDrivers(szBuf,cbBufMax,& cbBufOut))
+	{
+		m_sExcelDriver = "";
+	}
+	
+	// Search for the driver...
+	do
+	{
+		if( strstr( pszBuf, "Excel" ) != 0 )
+		{
+			// Found !
+			m_sExcelDriver = CString( pszBuf );
+			break;
+		}
+		pszBuf = strchr( pszBuf, '\0' ) + 1;
+	}
+	while( pszBuf[1] != '\0' );
+}

+ 78 - 0
VideoCapture/VideoCapture/SpreadSheet.h

@@ -0,0 +1,78 @@
+// Class to read and write to Excel and text delimited spreadsheet
+//
+// Created by Yap Chun Wei
+// December 2001
+// 
+// Version 1.1
+// Updates: Fix bug in ReadRow() which prevent reading of single column spreadsheet
+// Modified by jingzhou xu
+
+#ifndef CSPREADSHEET_H
+#define CSPREADSHEET_H
+
+#include <odbcinst.h>
+#include <afxdb.h>
+
+class CSpreadSheet
+{
+public:
+	CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup = true); // Open spreadsheet for reading and writing
+	~CSpreadSheet(); // Perform some cleanup functions
+	
+	bool AddHeaders(CStringArray &FieldNames, bool replace = false); // Add header row to spreadsheet
+	bool DeleteSheet(); // Clear text delimited file content
+	bool DeleteSheet(CString SheetName); // Clear entire Excel spreadsheet content. The sheet itself is not deleted
+	bool AddRow(CStringArray &RowValues, long row = 0, bool replace = false); // Insert or replace a row into spreadsheet. Default is add new row. 
+	bool AddCell(CString CellValue, CString column, long row = 0, bool Auto = true); // Replace or add a cell into Excel spreadsheet using header row or column alphabet. Default is add cell into new row. Set Auto to false if want to force column to be used as header name
+	bool AddCell(CString CellValue, short column, long row = 0); // Replace or add a cell into spreadsheet using column number. Default is add cell into new row. 
+	bool ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues); // Search and replace rows in Excel spreadsheet
+	bool ReadRow(CStringArray &RowValues, long row = 0); // Read a row from spreadsheet. Default is read the next row
+	bool ReadColumn(CStringArray &ColumnValues, CString column, bool Auto = true); // Read a column from Excel spreadsheet using header row or column alphabet. Set Auto to false if want to force column to be used as header name
+	bool ReadColumn(CStringArray &ColumnValues, short column); // Read a column from spreadsheet using column number
+	bool ReadCell (CString &CellValue, CString column, long row = 0, bool Auto = true); // Read a cell from Excel spreadsheet using header row or column alphabet. Default is read the next cell in next row. Set Auto to false if want to force column to be used as header name
+	bool ReadCell (CString &CellValue, short column, long row = 0); // Read a cell from spreadsheet using column number. Default is read the next cell in next row.
+	void BeginTransaction(); // Begin transaction
+	bool Commit(); // Save changes to spreadsheet
+	bool RollBack(); // Undo changes to spreadsheet
+	bool Convert(CString SheetOrSeparator);
+	inline void GetFieldNames (CStringArray &FieldNames) {FieldNames.RemoveAll(); FieldNames.Copy(m_aFieldNames);} // Get the header row from spreadsheet
+	inline long GetTotalRows() {return m_dTotalRows;} // Get total number of rows in  spreadsheet
+	inline short GetTotalColumns() {return m_dTotalColumns;} // Get total number of columns in  spreadsheet
+	inline long GetCurrentRow() {return m_dCurrentRow;} // Get the currently selected row in  spreadsheet
+	inline bool GetBackupStatus() {return m_bBackup;} // Get status of backup. True if backup is successful, False if spreadsheet is not backup
+	inline bool GetTransactionStatus() {return m_bTransaction;} // Get status of Transaction. True if Transaction is started, False if Transaction is not started or has error in starting
+	inline CString GetLastError() {return m_sLastError;} // Get last error message
+
+private:
+	bool Open(); // Open a text delimited file for reading or writing
+	void GetExcelDriver(); // Get the name of the Excel-ODBC driver
+	short CalculateColumnNumber(CString column, bool Auto); // Convert Excel column in alphabet into column number
+
+	bool m_bAppend; // Internal flag to denote newly created spreadsheet or previously created spreadsheet
+	bool m_bBackup; // Internal flag to denote status of Backup
+	bool m_bExcel; // Internal flag to denote whether file is Excel spreadsheet or text delimited spreadsheet
+	bool m_bTransaction; // Internal flag to denote status of Transaction
+
+	long m_dCurrentRow; // Index of current row, starting from 1
+	long m_dTotalRows; // Total number of rows in spreadsheet
+	short m_dTotalColumns; // Total number of columns in Excel spreadsheet. Largest number of columns in text delimited spreadsheet
+
+	CString m_sSql; // SQL statement to open Excel spreadsheet for reading
+	CString m_sDsn; // DSN string to open Excel spreadsheet for reading and writing
+	CString m_stempSql; // Temporary string for SQL statements or for use by functions
+	CString m_stempString; // Temporary string for use by functions
+	CString m_sSheetName; // Sheet name of Excel spreadsheet
+	CString m_sExcelDriver; // Name of Excel Driver
+	CString m_sFile; // Spreadsheet file name
+	CString m_sSeparator; // Separator in text delimited spreadsheet
+	CString m_sLastError; // Last error message
+
+	CStringArray m_atempArray; // Temporary array for use by functions
+	CStringArray m_aFieldNames; // Header row in spreadsheet
+	CStringArray m_aRows; // Content of all the rows in spreadsheet
+
+	CDatabase *m_Database; // Database variable for Excel spreadsheet
+	CRecordset *m_rSheet; // Recordset for Excel spreadsheet
+};
+
+#endif

+ 471 - 0
VideoCapture/VideoCapture/TrayIcon.cpp

@@ -0,0 +1,471 @@
+#include "stdafx.h"
+#include "trayicon.h"
+#include <strsafe.h>
+#include <afxpriv.h>		// for AfxLoadString
+
+IMPLEMENT_DYNAMIC(ITrayIcon, CCmdTarget)
+typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 
+
+ITrayIcon::ITrayIcon(UINT uID)
+{
+	// Initialize NOTIFYICONDATA
+	memset(&m_nid, 0 , sizeof(m_nid));
+	m_nid.cbSize = sizeof(m_nid);
+	m_nid.uID = uID;	// never changes after construction
+	OpendThread();
+	
+	bShowMinibox = FALSE;
+	//m_pWnd = AfxGetMainWnd();
+	// Use resource string as tip if there is one
+	AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip));
+}
+
+ITrayIcon::~ITrayIcon()
+{
+	SetIcon(0); // remove icon from system tray
+	TerminalThread();
+}
+
+//////////////////
+// Set notification window. It must created already.
+//
+void ITrayIcon::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg)
+{
+	// If the following assert fails, you're probably
+	// calling me before you created your window. Oops.
+	ASSERT(pNotifyWnd==NULL || ::IsWindow(pNotifyWnd->GetSafeHwnd()));
+	m_nid.hWnd = pNotifyWnd->GetSafeHwnd();
+
+	ASSERT(uCbMsg==0 || uCbMsg>=WM_USER);
+	m_nid.uCallbackMessage = uCbMsg;
+}
+
+//////////////////
+// This is the main variant for setting the icon.
+// Sets both the icon and tooltip from resource ID
+// To remove the icon, call SetIcon(0)
+//
+BOOL ITrayIcon::SetIcon(UINT uID)
+{
+	HICON hicon=NULL;
+	if (uID) 
+		hicon = AfxGetApp()->LoadIcon(uID);
+
+	UINT msg;
+	m_nid.uFlags = 0;
+
+	// Set the icon
+	if (hicon) 
+	{
+		// Add or replace icon in system tray
+		msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD;
+		m_nid.hIcon = hicon;
+		m_nid.uFlags |= NIF_ICON;
+	}
+	else 
+	{ // remove icon from tray
+		if (m_nid.hIcon==NULL)
+			return TRUE;		// already deleted
+		msg = NIM_DELETE;
+	}
+
+	// Use callback if any
+	if (m_nid.uCallbackMessage && m_nid.hWnd)
+		m_nid.uFlags |= NIF_MESSAGE;
+
+	// Do it
+	BOOL bRet = Shell_NotifyIcon(msg, &m_nid);
+	if (msg==NIM_DELETE || !bRet)
+		m_nid.hIcon = NULL;	// failed
+	return bRet;
+}
+
+BOOL ITrayIcon::SetIcon(UINT uID, LPCTSTR lpTip)
+{ 
+	HICON hicon=NULL;
+	if (uID) 
+	{
+		AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip));
+		hicon = AfxGetApp()->LoadIcon(uID);
+	}
+
+	return SetIcon(hicon, lpTip ? lpTip:NULL); 
+}
+
+//////////////////
+// Common SetIcon for all overloads. 
+//
+BOOL ITrayIcon::SetIcon(HICON hicon, LPCTSTR lpTip)
+{
+	UINT msg;
+	m_nid.uFlags = 0;
+
+	// Set the icon
+	if (hicon) 
+	{
+		// Add or replace icon in system tray
+		msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD;
+		m_nid.hIcon = hicon;
+		m_nid.uFlags |= NIF_ICON;
+	} 
+	else 
+	{ // remove icon from tray
+		if (m_nid.hIcon==NULL)
+			return TRUE;		// already deleted
+		msg = NIM_DELETE;
+	}
+
+	// Use the tip, if any
+	if (lpTip)
+		//strncpy(m_nid.szTip, lpTip, sizeof(m_nid.szTip));
+		StringCchCopy(m_nid.szTip, sizeof(m_nid.szTip),lpTip);
+	if (m_nid.szTip[0])
+		m_nid.uFlags |= NIF_TIP;
+
+	// Use callback if any
+	if (m_nid.uCallbackMessage && m_nid.hWnd)
+		m_nid.uFlags |= NIF_MESSAGE;
+
+	// Do it
+	BOOL bRet = Shell_NotifyIcon(msg, &m_nid);
+	if (msg==NIM_DELETE || !bRet)
+		m_nid.hIcon = NULL;	// failed
+	return bRet;
+}
+
+BOOL ITrayIcon::SetTip(LPCTSTR lpTip) 
+{
+	UINT msg;
+	m_nid.uFlags = 0;
+
+	if (m_nid.hIcon == NULL)
+		return TRUE;		// already deleted
+
+	msg = NIM_MODIFY;
+
+	// Use the tip, if any
+	//if (lpTip)
+	//strncpy(m_nid.szTip, lpTip, sizeof(m_nid.szTip));
+	StringCchCopy(m_nid.szTip, sizeof(m_nid.szTip), lpTip);
+	if (m_nid.szTip[0])
+		m_nid.uFlags |= NIF_TIP;
+
+	// Use callback if any
+	if (m_nid.uCallbackMessage && m_nid.hWnd)
+		m_nid.uFlags |= NIF_MESSAGE;
+
+	return Shell_NotifyIcon(msg, &m_nid);
+}
+
+BOOL ITrayIcon::SetTipTitle(LPCTSTR lpTipTitle)
+{
+	UINT msg;
+	m_nid.uFlags = 0;
+
+	if (m_nid.hIcon == NULL)
+		return TRUE;		// already deleted
+
+	msg = NIM_MODIFY;
+	StringCchCopy(m_nid.szInfo, sizeof(m_nid.szInfo), _lpTip);
+	if ( lpTipTitle != NULL)
+	{
+		StringCchCopy(m_nid.szInfoTitle, sizeof(m_nid.szInfoTitle), lpTipTitle);
+		m_nid.uFlags |= NIF_INFO|NIIF_INFO;
+		m_nid.uTimeout = 1000;
+	}
+	else
+	{
+		m_nid.uFlags |= NIF_INFO;
+	}
+
+	// Use callback if any
+	if (m_nid.uCallbackMessage && m_nid.hWnd)
+		m_nid.uFlags |= NIF_MESSAGE;
+
+	return Shell_NotifyIcon(msg, &m_nid);
+}
+
+//BOOL ITrayIcon::SetInfo(LPCSTR lpInof, LPCSTR lpInfoTitle) 
+BOOL ITrayIcon::SetInfo(LPCTSTR lpInof, LPCTSTR lpInfoTitle)
+{
+	UINT msg;
+	m_nid.uFlags = 0;
+
+	if (m_nid.hIcon == NULL)
+		return TRUE;		// already deleted
+
+	msg = NIM_MODIFY;
+	//strncpy(m_nid.szInfo, lpInof, sizeof(m_nid.szInfo));
+	StringCchCopy(m_nid.szInfo, sizeof(m_nid.szInfo),lpInof);
+	if ( lpInfoTitle != NULL)
+	{
+		StringCchCopy(m_nid.szInfoTitle, sizeof(m_nid.szInfoTitle), lpInfoTitle);
+		m_nid.uFlags |= NIF_INFO|NIIF_INFO;
+		m_nid.uTimeout = 1000;
+	}
+	else
+	{
+		m_nid.uFlags |= NIF_INFO;
+	}
+
+	// Use callback if any
+	if (m_nid.uCallbackMessage && m_nid.hWnd)
+		m_nid.uFlags |= NIF_MESSAGE;
+
+	return Shell_NotifyIcon(msg, &m_nid);
+}
+
+/////////////////
+// Default event handler handles right-menu and doubleclick.
+// Call this function from your own notification handler.
+//
+LRESULT ITrayIcon::OnTrayNotification(WPARAM wID, LPARAM lEvent)
+{
+	if (wID!=m_nid.uID || (lEvent!=WM_RBUTTONUP && lEvent!=WM_LBUTTONDBLCLK))
+		return 0;
+
+	// If there's a resource menu with the same ID as the icon, use it as 
+	// the right-button popup menu. CTrayIcon will interprets the first
+	// item in the menu as the default command for WM_LBUTTONDBLCLK
+	// 
+#if 0
+	CMenu menu;
+	if (!menu.LoadMenu(m_nid.uID))
+		return 0;
+	CMenu* pSubMenu = menu.GetSubMenu(0);
+	if (!pSubMenu) 
+		return 0;
+
+	if (lEvent==WM_RBUTTONUP) 
+	{
+
+		// Make first menu item the default (bold font)
+		::SetMenuDefaultItem(pSubMenu->m_hMenu, 0, TRUE);
+
+		// Display the menu at the current mouse location. There's a "bug"
+		// (Microsoft calls it a feature) in Windows 95 that requires calling
+		// SetForegroundWindow. To find out more, search for Q135788 in MSDN.
+		//
+		CPoint mouse;
+		GetCursorPos(&mouse);
+		::SetForegroundWindow(m_nid.hWnd);	
+		::TrackPopupMenu(pSubMenu->m_hMenu, 0, mouse.x, mouse.y, 0,
+			m_nid.hWnd, NULL);
+
+	} else  // double click: execute first menu item
+		::SendMessage(m_nid.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
+#endif
+	return 1; // handled
+}
+
+// ------------------------------- [5/30/2013 Z.t]
+BOOL ITrayIcon::IsWow64()  
+{  
+	BOOL bIsWow64 = FALSE;  
+
+	LPFN_ISWOW64PROCESS  fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(_T("kernel32")),"IsWow64Process");  
+
+	if (NULL != fnIsWow64Process)  
+	{  
+		if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))  
+		{  
+			// handle error   
+		}  
+	}  
+	return bIsWow64;  
+}
+
+/************************************************************************/
+/* 
+	函数:GetTrayRect,获取托盘图标区域;(有待完善,添加各种错误判断)
+	参数:None;
+	返回:返回指定托盘图标的区域;
+
+	注意:函数的功能有些太复杂,暂时没办法使用更简单的方法获取图标区域;
+*/
+/************************************************************************/
+void ITrayIcon::GetTrayRect(RECT &rc)
+{
+	HWND hWnd,hWndPaper;
+	long ret;
+	
+	LPVOID lngAddress;
+//	long lngTextAdr; //,lngHwndAdr,lngHwnd,lngButtonID;
+	TCHAR strBuff[1024]={0};
+
+	TBBUTTON btnData={0};
+
+	hWnd = FindWindow(_T("Shell_TrayWnd"), NULL);				// 获取任务栏句柄 [5/31/2013 Z.t]
+	hWnd = FindWindowEx(hWnd, 0, _T("TrayNotifyWnd"), NULL);	// 获取托盘区域句柄 [5/31/2013 Z.t]
+	hWndPaper = FindWindowEx(hWnd, 0, _T("SysPager"), NULL);	// 获取系统页句柄 [5/31/2013 Z.t]
+
+	if(!hWndPaper)
+		hWnd = FindWindowEx(hWnd, 0, _T("ToolbarWindow32"), NULL);
+	else
+		hWnd = FindWindowEx(hWndPaper, 0, _T("ToolbarWindow32"), NULL);
+
+	DWORD dwProcessId = 0; 
+	GetWindowThreadProcessId(hWnd, &dwProcessId);//LOG4C_NO_FILENUM((LOG_NOTICE,"进程ID%d",dwProcessId));进程其实就是explorer.exe
+	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS|PROCESS_VM_OPERATION|PROCESS_VM_READ|PROCESS_VM_WRITE,0,dwProcessId);
+	if ( hProcess == NULL )
+	{
+		//LOG4C_NO_FILENUM((LOG_NOTICE,"hProcess == NULL--"));
+		return ;
+	}
+	
+	lngAddress = VirtualAllocEx(hProcess,0, 0x4096, MEM_COMMIT, PAGE_READWRITE); 
+	if( lngAddress == NULL) 
+	{
+		//LOG4C_NO_FILENUM((LOG_NOTICE,"lngAddress == NULL--"));
+		return;
+	}
+
+	DWORD lTextAdr = 0;
+	BYTE buff[1024] = {0};
+	CString strFilePath;
+	CString strTile;
+	HWND hMainWnd = NULL;
+	int nDataOffset = sizeof(TBBUTTON) - sizeof(INT_PTR) - sizeof(DWORD_PTR);
+	int nStrOffset = 18; 
+	if ( IsWow64() )
+	{
+		nDataOffset+=4;
+		nStrOffset+=6;
+	}
+
+	 // 获取托盘区域的所有图标数量 [5/31/2013 Z.t]      
+	int ibtnCount = SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0);               
+	LPVOID lngRect = VirtualAllocEx(hProcess,0,sizeof(RECT), MEM_COMMIT, PAGE_READWRITE);
+	
+	CRect rect;
+	for(int i=0 ;i< ibtnCount;i++)
+	{
+		int j = i;
+		ret = SendMessage(hWnd,TB_GETBUTTON,j, (LPARAM)(lngAddress));
+		// 读文本地址;
+		ret = ReadProcessMemory(hProcess, LPVOID(long(lngAddress) + nDataOffset),&lTextAdr,4,0);
+		if(lTextAdr != -1)
+		{
+			// 读文本;
+			ret = ReadProcessMemory(hProcess, LPVOID(lTextAdr),buff,1024,0);
+
+			hMainWnd = (HWND)(*((DWORD*)buff));
+			strFilePath = (WCHAR *)buff + nStrOffset;			// 获取托盘图标进程路径 [5/31/2013 Z.t]
+			strTile = (WCHAR *)buff + nStrOffset + MAX_PATH;	// 获取托盘图标tip标题 [5/31/2013 Z.t]
+			//_tprintf(_T("%s %s\n"),strTile,strFilePath);
+
+			if (strTile.Compare(m_nid.szTip) == 0)
+			{
+				::SendMessage(hWnd,TB_GETITEMRECT,(WPARAM)j,(LPARAM)lngRect);
+				ReadProcessMemory(hProcess,lngRect,&rc, sizeof(rc),0);			// 获取托盘图标区域;
+				CWnd::FromHandle(hWnd)->ClientToScreen(&rc);
+			}
+		}
+	}
+	VirtualFreeEx( hProcess, lngAddress, 0x4096, MEM_DECOMMIT);
+	VirtualFreeEx( hProcess, lngAddress, 0, MEM_RELEASE);
+	VirtualFreeEx( hProcess, lngRect, sizeof(RECT), MEM_DECOMMIT);
+	VirtualFreeEx( hProcess, lngRect, 0, MEM_RELEASE);
+	CloseHandle(hProcess);
+}
+
+int ITrayIcon::OpendThread()
+{
+	//LOG4C_NO_FILENUM((LOG_NOTICE,"创建TrayIcon"));
+	m_hThreadCtrl = CreateEvent(NULL,TRUE,FALSE,NULL);	// 无信号事件;
+	if ( m_hThreadCtrl == NULL )
+	{
+		//LOG4C_NO_FILENUM((LOG_NOTICE,"创建TrayIcon事件失败"));
+		return -1;
+	}
+
+	m_hThreadObj = CreateThread(NULL,0,FlashingThread,this,CREATE_SUSPENDED,&m_dwThreadID);
+	if ( m_hThreadObj == NULL )
+	{
+		//LOG4C_NO_FILENUM((LOG_NOTICE,"创建TrayIcon线程失败"));
+		return -1;
+	}
+	bSuspending = true;
+	return 0;
+}
+
+void ITrayIcon::TerminalThread()
+{
+	if ( m_hThreadCtrl )
+	{
+		SetEvent( m_hThreadCtrl );
+	}
+
+	if (WaitForSingleObject(m_hThreadCtrl,INFINITE) != WAIT_TIMEOUT)
+	{
+		CloseHandle(m_hThreadObj);
+		m_hThreadObj = NULL;
+	}
+
+	CloseHandle( m_hThreadCtrl );
+	m_hThreadCtrl = NULL;
+
+	bSuspending = false;
+}
+
+BOOL ITrayIcon::StartFlashing()
+{
+	if ( !bSuspending ) return FALSE;
+	if(::ResumeThread(m_hThreadObj) == 0xFFFFFFFF)
+		return FALSE;
+	
+	bSuspending = false;
+	SetInfo(_T("环境监控系统产生新警报,请及时处理!"),_T("警报提示"));
+	return TRUE;
+}
+
+BOOL ITrayIcon::StopFlashing()
+{
+	if ( bSuspending ) return FALSE;
+
+	if(::SuspendThread(m_hThreadObj) == 0xFFFFFFFF)
+		return FALSE;
+	
+	bSuspending = true;
+	SetIcon(_utIcon[0]);
+	return TRUE;
+}
+
+/************************************************************************/
+/* 
+	线程函数:闪烁线程;
+*/
+/************************************************************************/
+DWORD WINAPI ITrayIcon::FlashingThread(LPVOID lpVoid)
+{
+	ITrayIcon *pTrayIcon = (ITrayIcon*)lpVoid;
+
+	CPoint pt; 
+	CRect IconRect;
+	bool bChange = FALSE;
+	do 
+	{
+		if ( bChange)
+		{
+			pTrayIcon->SetIcon(pTrayIcon->_utIcon[1]); 
+			bChange = FALSE;
+		}
+		else
+		{
+			pTrayIcon->SetIcon(pTrayIcon->_utIcon[2]);
+			bChange = TRUE;
+		}
+
+		if( pTrayIcon->bShowMinibox )
+		{
+			GetCursorPos(&pt); 
+			pTrayIcon->GetTrayRect(IconRect);
+			if ( IconRect.PtInRect( pt) ) 
+				::PostMessage(pTrayIcon->m_nid.hWnd,MYWM_SHOWMINBOX,1,0);
+			else
+				::PostMessage(pTrayIcon->m_nid.hWnd,MYWM_SHOWMINBOX,0,0);
+		}
+	}while (WaitForSingleObject(pTrayIcon->m_hThreadCtrl,300) == WAIT_TIMEOUT);
+
+	return 0;
+}

+ 84 - 0
VideoCapture/VideoCapture/TrayIcon.h

@@ -0,0 +1,84 @@
+#ifndef _ZEROT_TRAYICON_H
+#define _ZEROT_TRAYICON_H
+
+////////////////
+#define MYWM_SHOWMINBOX WM_USER + 2  // 自定义消息,显示迷你对话框;
+
+
+class ITrayIcon : public CCmdTarget 
+{
+protected:
+	DECLARE_DYNAMIC(ITrayIcon)
+	NOTIFYICONDATA m_nid;			// struct for Shell_NotifyIcon args
+
+public:
+	ITrayIcon(UINT uID);
+	~ITrayIcon();
+
+	// Call this to receive tray notifications
+	void SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg);
+
+	// SetIcon functions. To remove icon, call SetIcon(0)
+	BOOL SetIcon(UINT uID); // only set the icon,but without tip zt.
+	BOOL SetIcon(HICON hicon, LPCTSTR lpTip);
+	BOOL SetIcon(UINT uID, LPCTSTR lpTip);
+	BOOL SetIcon(LPCTSTR lpResName, LPCTSTR lpTip)
+	{ 
+		return SetIcon(lpResName ? 	AfxGetApp()->LoadIcon(lpResName) : NULL, lpTip); 
+	}
+
+	// 设置提示(设置提示时,是否也要同时设置图标???);
+	BOOL SetTip(LPCTSTR lpTip);
+	BOOL SetTipTitle(LPCTSTR lpTipTitle);
+	//BOOL SetInfo(LPCSTR lpInfo,LPCSTR lpInfoTitle = _T(""));	// NIF_INFO
+	BOOL SetInfo(LPCTSTR lpInfo, LPCTSTR lpInfoTitle = NULL);	// NIF_INFO
+
+	BOOL SetStandardIcon(LPCTSTR lpszIconName, LPCTSTR lpTip)
+	{ 
+		return SetIcon(::LoadIcon(NULL, lpszIconName), lpTip); 
+	}
+
+	virtual LRESULT OnTrayNotification(WPARAM uID, LPARAM lEvent);
+
+	// -------------------------------以下是托盘闪烁实现------------------------------- [5/30/2013 Z.t]
+public:
+	bool IsFlashing(){return bSuspending;}						// 外部调用,判断是否在闪烁;
+	void SetMiniShow(BOOL bSet){bShowMinibox = bSet;}
+
+	BOOL StartFlashing();
+	BOOL StopFlashing();
+	inline void SetIconInfos(const UINT &u1,const UINT &u2,const UINT &u3);
+	inline void SetDefaultTip(LPCTSTR lpTip){_lpTip=lpTip;}
+protected:
+	bool bSuspending;			// 线程运行标识;
+	
+	LPCTSTR _lpTip;				// 默认的提示;
+	UINT _utIcon[3];			// 1.停止闪烁时的默认图标;2.闪烁时的报警图标;3.闪烁时的盘里背景图标;
+
+	DWORD  m_dwThreadID;		// 线程ID; 
+	HANDLE m_hThreadCtrl;		// 线程控件事件;
+	HANDLE m_hThreadObj;		// 线程本身;
+
+	BOOL bShowMinibox;			// 闪烁期间,是否对窗口发送消息;
+	void GetTrayRect(RECT &rc);
+	BOOL IsWow64();
+
+	// 托盘闪烁线程;
+	int OpendThread();
+	void TerminalThread();
+	static DWORD WINAPI FlashingThread(LPVOID pVoid);
+
+};
+
+inline void ITrayIcon::SetIconInfos(const UINT &u1,const UINT &u2,const UINT &u3)
+{
+	_utIcon[0] = u1;
+	_utIcon[1] = u2;
+	_utIcon[2] = u3;
+}
+
+#endif
+
+// 未处理的BUG:
+// 1.在任务管理器中结束进程,托盘图标未能清除;
+// SetIcon(0)代表着清除托盘图标(NIF_DELETE);

+ 272 - 0
VideoCapture/VideoCapture/VideoCapture.cpp

@@ -0,0 +1,272 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCapture.cpp: 定义应用程序的类行为。
+//
+
+#include "stdafx.h"
+#include "framework.h"
+#include "afxwinappex.h"
+#include "afxdialogex.h"
+#include "VideoCapture.h"
+#include "MainFrm.h"
+
+#include "VideoCaptureDoc.h"
+#include "VideoCaptureView.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// CVideoCaptureApp
+
+BEGIN_MESSAGE_MAP(CVideoCaptureApp, CWinAppEx)
+	ON_COMMAND(ID_APP_ABOUT, &CVideoCaptureApp::OnAppAbout)
+	// 基于文件的标准文档命令
+	ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew)
+	ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
+	// 标准打印设置命令
+	ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup)
+END_MESSAGE_MAP()
+
+
+// CVideoCaptureApp 构造
+
+HANDLE g_hMutex = NULL;	// 全局互斥量;
+ULONG_PTR CVideoCaptureApp::m_gdiplusToken = 0;
+
+CVideoCaptureApp::CVideoCaptureApp() noexcept
+{
+	m_bHiColorIcons = TRUE;
+
+	// 支持重新启动管理器
+	m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_ALL_ASPECTS;
+#ifdef _MANAGED
+	// 如果应用程序是利用公共语言运行时支持(/clr)构建的,则: 
+	//     1) 必须有此附加设置,“重新启动管理器”支持才能正常工作。
+	//     2) 在您的项目中,您必须按照生成顺序向 System.Windows.Forms 添加引用。
+	System::Windows::Forms::Application::SetUnhandledExceptionMode(System::Windows::Forms::UnhandledExceptionMode::ThrowException);
+#endif
+
+	// TODO: 将以下应用程序 ID 字符串替换为唯一的 ID 字符串;建议的字符串格式
+	//为 CompanyName.ProductName.SubProduct.VersionInformation
+	SetAppID(_T("VideoCapture.AppID.NoVersion"));
+
+	// TODO:  在此处添加构造代码,
+	// 将所有重要的初始化放置在 InitInstance 中
+}
+
+// 唯一的 CVideoCaptureApp 对象
+
+CVideoCaptureApp theApp;
+
+
+// CVideoCaptureApp 初始化
+
+BOOL CVideoCaptureApp::InitInstance()
+{
+	// 如果一个运行在 Windows XP 上的应用程序清单指定要
+	// 使用 ComCtl32.dll 版本 6 或更高版本来启用可视化方式,
+	//则需要 InitCommonControlsEx()。  否则,将无法创建窗口。
+	INITCOMMONCONTROLSEX InitCtrls;
+	InitCtrls.dwSize = sizeof(InitCtrls);
+	// 将它设置为包括所有要在应用程序中使用的
+	// 公共控件类。
+	InitCtrls.dwICC = ICC_WIN95_CLASSES;
+	InitCommonControlsEx(&InitCtrls);
+
+	CWinAppEx::InitInstance();
+
+#if 1
+	g_hMutex = ::CreateMutex(NULL, FALSE, _T("UB530"));
+	if (GetLastError() == ERROR_ALREADY_EXISTS)
+	{
+		::MessageBox(NULL, _T("UB530采集卡程序已经打开!"), _T("温馨提示"), MB_ICONINFORMATION);
+		return FALSE;
+	}
+
+	GdiplusStartupInput gdiplusStartupInput;
+	GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
+
+	// 获取模块的目录;
+	TCHAR szDrive[MAX_PATH] = { 0 };
+	TCHAR szDir[MAX_PATH] = { 0 };
+	TCHAR szExt[MAX_PATH] = { 0 };
+	::GetModuleFileName(NULL, Global::g_szCurModulePath, sizeof(Global::g_szCurModulePath) / sizeof(TCHAR));
+	_tsplitpath_s(Global::g_szCurModulePath, szDrive, szDir, Global::g_szFna, szExt);
+	_tcscpy_s(Global::g_szCurModuleDir, szDrive);
+	_tcscat_s(Global::g_szCurModuleDir, szDir);
+#endif
+
+	Global::WriteTextLog("程序启动");
+
+	// 初始化 OLE 库
+	if (!AfxOleInit())
+	{
+		AfxMessageBox(IDP_OLE_INIT_FAILED);
+		return FALSE;
+	}
+
+	AfxEnableControlContainer();
+
+	EnableTaskbarInteraction(FALSE);
+
+	// 使用 RichEdit 控件需要 AfxInitRichEdit2()
+	// AfxInitRichEdit2();
+
+	// 标准初始化
+	// 如果未使用这些功能并希望减小
+	// 最终可执行文件的大小,则应移除下列
+	// 不需要的特定初始化例程
+	// 更改用于存储设置的注册表项
+	// TODO: 应适当修改该字符串,
+	// 例如修改为公司或组织名
+	SetRegistryKey(_T("应用程序向导生成的本地应用程序"));
+	LoadStdProfileSettings(4);  // 加载标准 INI 文件选项(包括 MRU)
+
+
+	InitContextMenuManager();
+	InitShellManager();
+
+	InitKeyboardManager();
+
+	InitTooltipManager();
+	CMFCToolTipInfo ttParams;
+	ttParams.m_bVislManagerTheme = TRUE;
+	theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
+		RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
+
+	// 注册应用程序的文档模板。  文档模板
+	// 将用作文档、框架窗口和视图之间的连接
+	CSingleDocTemplate* pDocTemplate;
+	pDocTemplate = new CSingleDocTemplate(
+		IDR_MAINFRAME,
+		RUNTIME_CLASS(CVideoCaptureDoc),
+		RUNTIME_CLASS(CMainFrame),       // 主 SDI 框架窗口
+		RUNTIME_CLASS(CVideoCaptureView));
+	if (!pDocTemplate)
+		return FALSE;
+	AddDocTemplate(pDocTemplate);
+
+
+	// 分析标准 shell 命令、DDE、打开文件操作的命令行
+	CCommandLineInfo cmdInfo;
+	ParseCommandLine(cmdInfo);
+
+
+
+	// 调度在命令行中指定的命令。  如果
+	// 用 /RegServer、/Register、/Unregserver 或 /Unregister 启动应用程序,则返回 FALSE。
+	if (!ProcessShellCommand(cmdInfo))
+		return FALSE;
+
+	// 唯一的一个窗口已初始化,因此显示它并对其进行更新
+	m_pMainWnd->ShowWindow(SW_SHOW);
+	m_pMainWnd->UpdateWindow();
+	return TRUE;
+}
+
+int CVideoCaptureApp::ExitInstance()
+{
+	//TODO: 处理可能已添加的附加资源
+	AfxOleTerm(FALSE);
+	Gdiplus::GdiplusShutdown(m_gdiplusToken);
+	return CWinAppEx::ExitInstance();
+}
+
+// CVideoCaptureApp 消息处理程序
+
+
+// 用于应用程序“关于”菜单项的 CAboutDlg 对话框
+
+class CAboutDlg : public CDialogEx
+{
+public:
+	CAboutDlg() noexcept;
+
+// 对话框数据
+#ifdef AFX_DESIGN_TIME
+	enum { IDD = IDD_ABOUTBOX };
+#endif
+
+protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
+
+// 实现
+protected:
+	DECLARE_MESSAGE_MAP()
+public:
+	virtual BOOL OnInitDialog();
+};
+
+CAboutDlg::CAboutDlg() noexcept : CDialogEx(IDD_ABOUTBOX)
+{
+}
+
+void CAboutDlg::DoDataExchange(CDataExchange* pDX)
+{
+	CDialogEx::DoDataExchange(pDX);
+}
+
+BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
+END_MESSAGE_MAP()
+
+// 用于运行对话框的应用程序命令
+void CVideoCaptureApp::OnAppAbout()
+{
+	CAboutDlg aboutDlg;
+	aboutDlg.DoModal();
+}
+
+// CVideoCaptureApp 自定义加载/保存方法
+
+void CVideoCaptureApp::PreLoadState()
+{
+	BOOL bNameValid;
+	CString strName;
+	bNameValid = strName.LoadString(IDS_EDIT_MENU);
+	ASSERT(bNameValid);
+	GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EDIT);
+	bNameValid = strName.LoadString(IDS_EXPLORER);
+	ASSERT(bNameValid);
+	GetContextMenuManager()->AddMenu(strName, IDR_POPUP_EXPLORER);
+}
+
+void CVideoCaptureApp::LoadCustomState()
+{
+}
+
+void CVideoCaptureApp::SaveCustomState()
+{
+}
+
+// CVideoCaptureApp 消息处理程序
+
+
+
+
+
+BOOL CAboutDlg::OnInitDialog()
+{
+	CDialogEx::OnInitDialog();
+
+	// TODO:  在此添加额外的初始化
+	// 当前文件版本号、产品版本号;
+	WORD sFileVersion[4] = { 0 };
+	WORD sProductVerion[4] = { 0 };
+	Global::GetVersion(sFileVersion, sProductVerion);
+	CString strVer;
+	strVer.Format(_T("VideoCapture,版本: %d.%d.%d.%d"), sFileVersion[0], sFileVersion[1], sFileVersion[2], sFileVersion[3]);
+	SetDlgItemText(IDC_STATIC_VER, strVer);
+	return TRUE;  // return TRUE unless you set the focus to a control
+				  // 异常: OCX 属性页应返回 FALSE
+}

+ 51 - 0
VideoCapture/VideoCapture/VideoCapture.h

@@ -0,0 +1,51 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCapture.h: VideoCapture 应用程序的主头文件
+//
+#pragma once
+
+#ifndef __AFXWIN_H__
+	#error "在包含此文件之前包含 'pch.h' 以生成 PCH"
+#endif
+
+#include "resource.h"       // 主符号
+
+
+// CVideoCaptureApp:
+// 有关此类的实现,请参阅 VideoCapture.cpp
+//
+
+class CVideoCaptureApp : public CWinAppEx
+{
+public:
+	CVideoCaptureApp() noexcept;
+
+
+// 重写
+public:
+	virtual BOOL InitInstance();
+	virtual int ExitInstance();
+	static ULONG_PTR m_gdiplusToken;
+
+// 实现
+	UINT  m_nAppLook;
+	BOOL  m_bHiColorIcons;
+
+	virtual void PreLoadState();
+	virtual void LoadCustomState();
+	virtual void SaveCustomState();
+
+	afx_msg void OnAppAbout();
+	DECLARE_MESSAGE_MAP()
+};
+
+extern CVideoCaptureApp theApp;

BIN
VideoCapture/VideoCapture/VideoCapture.rc


+ 336 - 0
VideoCapture/VideoCapture/VideoCapture.vcxproj

@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <VCProjectVersion>16.0</VCProjectVersion>
+    <ProjectGuid>{97596051-DEC7-464E-95A9-CF7E550CD56F}</ProjectGuid>
+    <Keyword>MFCProj</Keyword>
+    <RootNamespace>VideoCapture</RootNamespace>
+    <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v142</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>Unicode</CharacterSet>
+    <UseOfMfc>Dynamic</UseOfMfc>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="Shared">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <OutDir>..\..\..\..\bin\$(ProjectName)\</OutDir>
+    <IntDir>$(OutDir)$(Configuration)\</IntDir>
+    <TargetName>$(ProjectName)_D</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <OutDir>..\..\..\..\bin\$(ProjectName)\</OutDir>
+    <IntDir>$(OutDir)$(Configuration)\</IntDir>
+    <TargetName>$(ProjectName)</TargetName>
+    <CustomBuildBeforeTargets>
+    </CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>StdAfx.h</PrecompiledHeaderFile>
+      <AdditionalIncludeDirectories>..\UI</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <AdditionalDependencies>QCAP.X86.lib;VFW32.LIB;legacy_stdio_definitions.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <PostBuildEvent>
+      <Command>copy "$(SolutionDir)QCAP.DLL" "$(TargetDir)QCAP.dll" /y/a
+copy "$(SolutionDir)QCAP.X86.DLL" "$(TargetDir)QCAP.X86.dll" /y/a
+copy "$(SolutionDir)AMESDK.DLL" "$(TargetDir)AMESDK.dll" /y/a</Command>
+    </PostBuildEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>StdAfx.h</PrecompiledHeaderFile>
+      <AdditionalIncludeDirectories>..\UI</AdditionalIncludeDirectories>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>QCAP.X86.lib;VFW32.LIB;legacy_stdio_definitions.lib</AdditionalDependencies>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <PostBuildEvent>
+      <Command>copy "$(SolutionDir)QCAP.DLL" "$(TargetDir)QCAP.dll" /y/a</Command>
+    </PostBuildEvent>
+    <CustomBuildStep>
+      <Command>
+      </Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>
+      </Outputs>
+    </CustomBuildStep>
+    <PreBuildEvent>
+      <Command>subwcrev.exe $(SolutionDir) $(ProjectDir)$(ProjectName).rc $(ProjectDir)$(ProjectName).rc_</Command>
+    </PreBuildEvent>
+    <PreLinkEvent>
+      <Command>rc.exe /l 0x409 /fo "$(IntDir)\$(ProjectName).res" /d "_AUTOVERSION_" /d "_AFXDLL" "$(ProjectDir)$(ProjectName).rc_"</Command>
+    </PreLinkEvent>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <PrecompiledHeader>Use</PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <SDLCheck>true</SDLCheck>
+      <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+    <Midl>
+      <MkTypLibCompatible>false</MkTypLibCompatible>
+      <ValidateAllParameters>true</ValidateAllParameters>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </Midl>
+    <ResourceCompile>
+      <Culture>0x0804</Culture>
+      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="..\UI\BCMenu.h" />
+    <ClInclude Include="..\UI\BtnST.h" />
+    <ClInclude Include="..\UI\ComboTreeCtrl.h" />
+    <ClInclude Include="..\UI\FontSize.h" />
+    <ClInclude Include="..\UI\PictureEx.h" />
+    <ClInclude Include="..\UI\SubLabel.h" />
+    <ClInclude Include="..\UI\TreeComboBox.h" />
+    <ClInclude Include="..\UI\XColorStatic.h" />
+    <ClInclude Include="calendarbar.h" />
+    <ClInclude Include="ClassView.h" />
+    <ClInclude Include="DlgIRControl.h" />
+    <ClInclude Include="FileView.h" />
+    <ClInclude Include="framework.h" />
+    <ClInclude Include="Global.h" />
+    <ClInclude Include="IRControlWnd.h" />
+    <ClInclude Include="MainFrm.h" />
+    <ClInclude Include="MemoryClient.h" />
+    <ClInclude Include="MemoryComm.h" />
+    <ClInclude Include="MemoryDef.h" />
+    <ClInclude Include="OutputWnd.h" />
+    <ClInclude Include="PropertiesWnd.h" />
+    <ClInclude Include="QCAP.H" />
+    <ClInclude Include="Resource.h" />
+    <ClInclude Include="SpreadSheet.h" />
+    <ClInclude Include="stdafx.h" />
+    <ClInclude Include="targetver.h" />
+    <ClInclude Include="TrayIcon.h" />
+    <ClInclude Include="VideoCapture.h" />
+    <ClInclude Include="VideoCaptureDoc.h" />
+    <ClInclude Include="VideoCaptureView.h" />
+    <ClInclude Include="ViewTree.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\UI\BCMenu.cpp" />
+    <ClCompile Include="..\UI\BtnST.cpp" />
+    <ClCompile Include="..\UI\ComboTreeCtrl.cpp" />
+    <ClCompile Include="..\UI\FontSize.cpp" />
+    <ClCompile Include="..\UI\PictureEx.cpp" />
+    <ClCompile Include="..\UI\SubLabel.cpp" />
+    <ClCompile Include="..\UI\TreeComboBox.cpp" />
+    <ClCompile Include="..\UI\XColorStatic.cpp" />
+    <ClCompile Include="calendarbar.cpp" />
+    <ClCompile Include="ClassView.cpp" />
+    <ClCompile Include="DlgIRControl.cpp" />
+    <ClCompile Include="FileView.cpp" />
+    <ClCompile Include="Global.cpp" />
+    <ClCompile Include="IRControlWnd.cpp" />
+    <ClCompile Include="MainFrm.cpp" />
+    <ClCompile Include="MemoryClient.cpp" />
+    <ClCompile Include="MemoryComm.cpp" />
+    <ClCompile Include="OutputWnd.cpp" />
+    <ClCompile Include="PropertiesWnd.cpp" />
+    <ClCompile Include="SpreadSheet.cpp" />
+    <ClCompile Include="stdafx.cpp">
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+    </ClCompile>
+    <ClCompile Include="TrayIcon.cpp" />
+    <ClCompile Include="VideoCapture.cpp" />
+    <ClCompile Include="VideoCaptureDoc.cpp" />
+    <ClCompile Include="VideoCaptureView.cpp" />
+    <ClCompile Include="ViewTree.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="VideoCapture.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\buttons.bmp" />
+    <Image Include="res\classview.bmp" />
+    <Image Include="res\classview_hc.bmp" />
+    <Image Include="res\class_view.ico" />
+    <Image Include="res\class_view_hc.ico" />
+    <Image Include="res\explorer.bmp" />
+    <Image Include="res\explorer_hc.bmp" />
+    <Image Include="res\filelarge.bmp" />
+    <Image Include="res\filesmall.bmp" />
+    <Image Include="res\fileview.bmp" />
+    <Image Include="res\fileview_hc.bmp" />
+    <Image Include="res\file_view.ico" />
+    <Image Include="res\file_view_hc.ico" />
+    <Image Include="res\info.bmp" />
+    <Image Include="res\main.bmp" />
+    <Image Include="res\menuimages.bmp" />
+    <Image Include="res\menuimages_hc.bmp" />
+    <Image Include="res\nav_large.bmp" />
+    <Image Include="res\nav_large_hc.bmp" />
+    <Image Include="res\output_wnd.ico" />
+    <Image Include="res\output_wnd_hc.ico" />
+    <Image Include="res\pages.bmp" />
+    <Image Include="res\pages_hc.bmp" />
+    <Image Include="res\pages_small.bmp" />
+    <Image Include="res\pages_small_hc.bmp" />
+    <Image Include="res\properties.bmp" />
+    <Image Include="res\properties_hc.bmp" />
+    <Image Include="res\properties_wnd.ico" />
+    <Image Include="res\properties_wnd_hc.ico" />
+    <Image Include="res\sort.bmp" />
+    <Image Include="res\sort_hc.bmp" />
+    <Image Include="res\Toolbar.bmp" />
+    <Image Include="res\Toolbar256.bmp" />
+    <Image Include="res\VideoCapture.ico" />
+    <Image Include="res\VideoCaptureDoc.ico" />
+    <Image Include="res\writelarge.bmp" />
+    <Image Include="res\writesmall.bmp" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\ribbon.mfcribbon-ms" />
+    <None Include="res\VideoCapture.rc2" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 324 - 0
VideoCapture/VideoCapture/VideoCapture.vcxproj.filters

@@ -0,0 +1,324 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="源文件">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="头文件">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
+    </Filter>
+    <Filter Include="资源文件">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+    <Filter Include="DockPane">
+      <UniqueIdentifier>{5202c702-fe38-467f-ab4c-49c343f91f1e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="UI">
+      <UniqueIdentifier>{3d45edde-5892-4d23-95fb-1ab695bc5995}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="VideoCapture.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="framework.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="targetver.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="MainFrm.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="VideoCaptureDoc.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="VideoCaptureView.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Resource.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="QCAP.H">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="Global.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="TrayIcon.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="MemoryDef.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="MemoryClient.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="MemoryComm.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="ViewTree.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="stdafx.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="SpreadSheet.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="calendarbar.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="ClassView.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="FileView.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="IRControlWnd.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="OutputWnd.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="PropertiesWnd.h">
+      <Filter>DockPane</Filter>
+    </ClInclude>
+    <ClInclude Include="DlgIRControl.h">
+      <Filter>头文件</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\BCMenu.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\BtnST.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\ComboTreeCtrl.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\FontSize.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\PictureEx.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\SubLabel.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\TreeComboBox.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+    <ClInclude Include="..\UI\XColorStatic.h">
+      <Filter>UI</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="VideoCapture.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="MainFrm.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="VideoCaptureDoc.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="VideoCaptureView.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="Global.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="TrayIcon.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="MemoryClient.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="MemoryComm.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="ViewTree.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="stdafx.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="SpreadSheet.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="calendarbar.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="ClassView.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="FileView.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="IRControlWnd.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="OutputWnd.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="PropertiesWnd.cpp">
+      <Filter>DockPane</Filter>
+    </ClCompile>
+    <ClCompile Include="DlgIRControl.cpp">
+      <Filter>源文件</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\BCMenu.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\BtnST.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\ComboTreeCtrl.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\FontSize.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\PictureEx.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\SubLabel.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\TreeComboBox.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+    <ClCompile Include="..\UI\XColorStatic.cpp">
+      <Filter>UI</Filter>
+    </ClCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="VideoCapture.rc">
+      <Filter>资源文件</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <Image Include="res\file_view.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\file_view_hc.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\class_view.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\class_view_hc.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\fileview.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\fileview_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\classview.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\classview_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\explorer.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\explorer_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\sort.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\sort_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\menuimages.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\menuimages_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\output_wnd.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\output_wnd_hc.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\properties_wnd.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\properties_wnd_hc.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\properties.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\properties_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\nav_large.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\nav_large_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\pages.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\pages_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\pages_small.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\pages_small_hc.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\info.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\buttons.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\filelarge.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\filesmall.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\main.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\writelarge.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\writesmall.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\VideoCaptureDoc.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\VideoCapture.ico">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\Toolbar.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+    <Image Include="res\Toolbar256.bmp">
+      <Filter>资源文件</Filter>
+    </Image>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="res\ribbon.mfcribbon-ms">
+      <Filter>资源文件</Filter>
+    </None>
+    <None Include="res\VideoCapture.rc2">
+      <Filter>资源文件</Filter>
+    </None>
+  </ItemGroup>
+</Project>

+ 148 - 0
VideoCapture/VideoCapture/VideoCaptureDoc.cpp

@@ -0,0 +1,148 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCaptureDoc.cpp: CVideoCaptureDoc 类的实现
+//
+
+#include "stdafx.h"
+#include "framework.h"
+// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
+// ATL 项目中进行定义,并允许与该项目共享文档代码。
+#ifndef SHARED_HANDLERS
+#include "VideoCapture.h"
+#endif
+
+#include "VideoCaptureDoc.h"
+
+#include <propkey.h>
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+// CVideoCaptureDoc
+
+IMPLEMENT_DYNCREATE(CVideoCaptureDoc, CDocument)
+
+BEGIN_MESSAGE_MAP(CVideoCaptureDoc, CDocument)
+END_MESSAGE_MAP()
+
+
+// CVideoCaptureDoc 构造/析构
+
+CVideoCaptureDoc::CVideoCaptureDoc() noexcept
+{
+	// TODO: 在此添加一次性构造代码
+
+}
+
+CVideoCaptureDoc::~CVideoCaptureDoc()
+{
+}
+
+BOOL CVideoCaptureDoc::OnNewDocument()
+{
+	if (!CDocument::OnNewDocument())
+		return FALSE;
+
+	// TODO: 在此添加重新初始化代码
+	// (SDI 文档将重用该文档)
+
+	return TRUE;
+}
+
+
+
+
+// CVideoCaptureDoc 序列化
+
+void CVideoCaptureDoc::Serialize(CArchive& ar)
+{
+	if (ar.IsStoring())
+	{
+		// TODO:  在此添加存储代码
+	}
+	else
+	{
+		// TODO:  在此添加加载代码
+	}
+}
+
+#ifdef SHARED_HANDLERS
+
+// 缩略图的支持
+void CVideoCaptureDoc::OnDrawThumbnail(CDC& dc, LPRECT lprcBounds)
+{
+	// 修改此代码以绘制文档数据
+	dc.FillSolidRect(lprcBounds, RGB(255, 255, 255));
+
+	CString strText = _T("TODO: implement thumbnail drawing here");
+	LOGFONT lf;
+
+	CFont* pDefaultGUIFont = CFont::FromHandle((HFONT) GetStockObject(DEFAULT_GUI_FONT));
+	pDefaultGUIFont->GetLogFont(&lf);
+	lf.lfHeight = 36;
+
+	CFont fontDraw;
+	fontDraw.CreateFontIndirect(&lf);
+
+	CFont* pOldFont = dc.SelectObject(&fontDraw);
+	dc.DrawText(strText, lprcBounds, DT_CENTER | DT_WORDBREAK);
+	dc.SelectObject(pOldFont);
+}
+
+// 搜索处理程序的支持
+void CVideoCaptureDoc::InitializeSearchContent()
+{
+	CString strSearchContent;
+	// 从文档数据设置搜索内容。
+	// 内容部分应由“;”分隔
+
+	// 例如:     strSearchContent = _T("point;rectangle;circle;ole object;");
+	SetSearchContent(strSearchContent);
+}
+
+void CVideoCaptureDoc::SetSearchContent(const CString& value)
+{
+	if (value.IsEmpty())
+	{
+		RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
+	}
+	else
+	{
+		CMFCFilterChunkValueImpl *pChunk = nullptr;
+		ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
+		if (pChunk != nullptr)
+		{
+			pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
+			SetChunkValue(pChunk);
+		}
+	}
+}
+
+#endif // SHARED_HANDLERS
+
+// CVideoCaptureDoc 诊断
+
+#ifdef _DEBUG
+void CVideoCaptureDoc::AssertValid() const
+{
+	CDocument::AssertValid();
+}
+
+void CVideoCaptureDoc::Dump(CDumpContext& dc) const
+{
+	CDocument::Dump(dc);
+}
+#endif //_DEBUG
+
+
+// CVideoCaptureDoc 命令

+ 58 - 0
VideoCapture/VideoCapture/VideoCaptureDoc.h

@@ -0,0 +1,58 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCaptureDoc.h: CVideoCaptureDoc 类的接口
+//
+
+
+#pragma once
+
+
+class CVideoCaptureDoc : public CDocument
+{
+protected: // 仅从序列化创建
+	CVideoCaptureDoc() noexcept;
+	DECLARE_DYNCREATE(CVideoCaptureDoc)
+
+// 特性
+public:
+
+// 操作
+public:
+
+// 重写
+public:
+	virtual BOOL OnNewDocument();
+	virtual void Serialize(CArchive& ar);
+#ifdef SHARED_HANDLERS
+	virtual void InitializeSearchContent();
+	virtual void OnDrawThumbnail(CDC& dc, LPRECT lprcBounds);
+#endif // SHARED_HANDLERS
+
+// 实现
+public:
+	virtual ~CVideoCaptureDoc();
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+
+protected:
+
+// 生成的消息映射函数
+protected:
+	DECLARE_MESSAGE_MAP()
+
+#ifdef SHARED_HANDLERS
+	// 用于为搜索处理程序设置搜索内容的 Helper 函数
+	void SetSearchContent(const CString& value);
+#endif // SHARED_HANDLERS
+};

+ 1221 - 0
VideoCapture/VideoCapture/VideoCaptureView.cpp

@@ -0,0 +1,1221 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCaptureView.cpp: CVideoCaptureView 类的实现
+//
+
+#include "stdafx.h"
+#include "framework.h"
+// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
+// ATL 项目中进行定义,并允许与该项目共享文档代码。
+#ifndef SHARED_HANDLERS
+#include "VideoCapture.h"
+#endif
+
+#include "VideoCaptureDoc.h"
+#include "VideoCaptureView.h"
+#include "MainFrm.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+CMemoryClient g_ub530;
+static CMainFrame* g_pMainFrame = NULL;
+
+VOID Dbg(CHAR* pszStr, ...)
+{
+	char szData[MAX_PATH] = "[SC] ";
+	va_list args;
+	va_start(args, pszStr);
+	_vsnprintf_s(szData + 5, MAX_PATH - 5, MAX_PATH - 6, pszStr, args);
+	va_end(args);
+	strcat_s(szData, "\n");
+	OutputDebugStringA(szData);
+}
+
+//  FORMAT CHANGED CALLBACK FUNCTION
+//
+QRETURN on_process_format_changed(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, ULONG nVideoWidth, ULONG nVideoHeight, BOOL bVideoIsInterleaved, double dVideoFrameRate, ULONG nAudioChannels, ULONG nAudioBitsPerSample, ULONG nAudioSampleFrequency, PVOID pUserData)
+{
+	//Dbg("format changed Detected  \n");
+	CVideoCaptureView* pView = (CVideoCaptureView*)pUserData;
+	if (pView == NULL) { return QCAP_RT_OK; }
+	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
+
+	pView->m_nVideoWidth = nVideoWidth;
+	pView->m_nVideoHeight = nVideoHeight;
+	pView->m_bVideoIsInterleaved = bVideoIsInterleaved;
+	pView->m_dVideoFrameRate = dVideoFrameRate;
+	pView->m_nAudioChannels = nAudioChannels;
+	pView->m_nAudioBitsPerSample = nAudioBitsPerSample;
+	pView->m_nAudioSampleFrequency = nAudioSampleFrequency;
+	// OUTPUT FORMAT CHANGED MESSAGE
+	//
+	CHAR strVideoInput[MAX_PATH] = { 0 };
+	CHAR strAudioInput[MAX_PATH] = { 0 };
+	CHAR strFrameType[MAX_PATH] = { 0 };
+	UINT nVH = 0;
+
+	if (nVideoInput == 0) { sprintf_s(strVideoInput, "COMPOSITE"); }
+	if (nVideoInput == 1) { sprintf_s(strVideoInput, "SVIDEO"); }
+	if (nVideoInput == 2) { sprintf_s(strVideoInput, "HDMI"); }
+	if (nVideoInput == 3) { sprintf_s(strVideoInput, "DVI_D"); }
+	if (nVideoInput == 4) { sprintf_s(strVideoInput, "COMPONENTS (YCBCR)"); }
+	if (nVideoInput == 5) { sprintf_s(strVideoInput, "DVI_A (RGB / VGA)"); }
+	if (nVideoInput == 6) { sprintf_s(strVideoInput, "SDI"); }
+	if (nVideoInput == 7) { sprintf_s(strVideoInput, "AUTO"); }
+	if (nAudioInput == 0) { sprintf_s(strAudioInput, "EMBEDDED_AUDIO"); }
+	if (nAudioInput == 1) { sprintf_s(strAudioInput, "LINE_IN"); }
+
+	if (bVideoIsInterleaved == TRUE) { nVH = nVideoHeight / 2; }
+	else { nVH = nVideoHeight; }
+
+	if (bVideoIsInterleaved == TRUE) { sprintf_s(strFrameType, " I "); }
+	else { sprintf_s(strFrameType, " P "); }
+
+	pView->m_strFormatChangedOutput.Format(
+		_T("INFO : %d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ ,  VIDEO INPUT : %s ,  AUDIO INPUT : %s"),
+		nVideoWidth,
+		nVH,
+		strFrameType,
+		dVideoFrameRate,
+		nAudioChannels,
+		nAudioBitsPerSample,
+		nAudioSampleFrequency,
+		strVideoInput,
+		strAudioInput
+	);
+	Global::WriteTextLog(_T("采集卡格式变更:%d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ ,  视频输入源 : %s ,  音频输入源 : %s"),
+		nVideoWidth,
+		nVH,
+		strFrameType,
+		dVideoFrameRate,
+		nAudioChannels,
+		nAudioBitsPerSample,
+		nAudioSampleFrequency,
+		strVideoInput,
+		strAudioInput);
+
+	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)& pView->m_strFormatChangedOutput, ID_STATUSBAR_PANE1);
+
+	// NO SOURCE
+	//
+	if (nVideoWidth == 0 &&
+		nVideoHeight == 0 &&
+		dVideoFrameRate == 0.0 &&
+		nAudioChannels == 0 &&
+		nAudioBitsPerSample == 0 &&
+		nAudioSampleFrequency == 0)
+	{
+		pView->m_bNoSignal = TRUE;
+	}
+	else
+	{
+		pView->m_bNoSignal = FALSE;
+	}
+
+	pView->SetTimer(0x00000000, 1, NULL);
+
+	return QCAP_RT_OK;
+}
+
+// NO SIGNAL DETEACTED CALLBACK FUNCTION
+//
+QRETURN on_process_no_signal_detected(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
+{
+	AFX_MANAGE_STATE(AfxGetStaticModuleState());
+	CVideoCaptureView* pView = (CVideoCaptureView*)pUserData;
+
+	//Dbg("No Signal Detected  \n");
+	if (pView == NULL) { return QCAP_RT_OK; }
+	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
+
+	//pView->SetRibbonStatusBarText("当前采集卡无信号。", ID_STATUSBAR_PANE1);
+	Global::WriteTextLog(_T("当前采集卡无信号"));
+	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)& CString("当前采集卡无信号"), ID_STATUSBAR_PANE1);
+
+	pView->m_bNoSignal = TRUE;
+	pView->SetTimer(0x00000000, 1, NULL);
+
+	return QCAP_RT_OK;
+}
+
+// SIGNAL REMOVED CALLBACK FUNCTION
+//
+QRETURN on_process_signal_removed(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
+{
+	AFX_MANAGE_STATE(AfxGetStaticModuleState());
+	CVideoCaptureView* pView = (CVideoCaptureView*)pUserData;
+	if (pView == NULL) { return QCAP_RT_OK; }
+	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
+
+	//pView->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
+	Global::WriteTextLog(_T("当前采集卡信号被移除"));
+	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)& CString("当前采集卡信号被移除"), ID_STATUSBAR_PANE1);
+
+	pView->m_bNoSignal = TRUE;
+	pView->SetTimer(0x00000000, 1, NULL);
+
+	return QCAP_RT_OK;
+}
+
+// PREVIEW VIDEO CALLBACK FUNCTION
+//
+QRETURN on_process_preview_video_buffer(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
+{
+	CVideoCaptureView* pView = (CVideoCaptureView*)pUserData;
+	if (pView)
+	{
+		// 尝试加锁;
+		if (!pView->m_mut_cpature.try_lock())
+		{
+#ifdef DEBUG
+			OutputDebugStringA("!pView->m_mut_cpature.try_lock()\n");
+#endif
+			return QCAP_RT_OK;
+		}
+
+		// 是否触发截图;
+		if (pView->m_bCaptureImage)
+		{
+			// 加锁;
+			std::lock_guard<std::mutex> lk(pView->m_mut_thread);
+			// 复制数据;
+			pView->m_dwBufferLen = nFrameBufferLen;
+			pView->m_pBuffer = new BYTE[nFrameBufferLen];
+			memcpy(pView->m_pBuffer, pFrameBuffer, nFrameBufferLen);
+			// 通知线程保存图片;
+			pView->m_thread_cond.notify_one();
+			// 恢复截图标记,防止重复截图;
+			pView->m_bCaptureImage = FALSE;
+#ifdef DEBUG
+			OutputDebugStringA("preview_video_buffer:pView->m_bCaptureImage\n");
+#endif
+		}
+
+		// 解锁;
+		pView->m_mut_cpature.unlock();
+	}
+
+	return QCAP_RT_OK;
+}
+
+// PREVIEW AUDIO CALLBACK FUNCTION
+//
+QRETURN on_process_preview_audio_buffer(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
+{
+	return QCAP_RT_OK;
+}
+
+// VIDEO HARDARE ENCODER CALLBACK FUNCTION
+//
+QRETURN on_process_hardware_encoder_video_buffer(PVOID pDevice, UINT iRecNum, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, BOOL bIsKeyFrame, PVOID pUserData)
+{
+	return QCAP_RT_OK;
+}
+
+QRETURN on_process_snapshot_done(PVOID pDevice, CHAR* pszFilePathName, PVOID pUserData)
+{
+	return QCAP_RT_OK;
+}
+
+QRETURN on_process_snapshot_stream(PVOID pDevice, CHAR* pszFilePathName, BYTE* pStreamBuffer, ULONG nStreamBufferLen, PVOID pUserData)
+{
+	// 注意:在调用本回调函数前,已经保存了图片!
+	CVideoCaptureView* pView = (CVideoCaptureView*)pUserData;
+	if (pView->m_bHoriontal || pView->m_bVertically)
+		Global::SaveImgByRotate(pszFilePathName, pStreamBuffer, nStreamBufferLen, pView->m_bHoriontal, pView->m_bVertically);
+
+	return QCAP_RT_OK;
+}
+
+// CVideoCaptureView
+
+IMPLEMENT_DYNCREATE(CVideoCaptureView, CView)
+
+BEGIN_MESSAGE_MAP(CVideoCaptureView, CView)
+	// 标准打印命令
+	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
+	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
+	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CVideoCaptureView::OnFilePrintPreview)
+	ON_WM_CONTEXTMENU()
+	ON_WM_RBUTTONUP()
+	ON_WM_CREATE()
+	ON_WM_TIMER()
+	ON_COMMAND(ID_CUT_BMP, &CVideoCaptureView::OnCutBmp)
+	ON_COMMAND(ID_CUT_JPG, &CVideoCaptureView::OnCutJpg)
+	ON_COMMAND(ID_START_RECORD, &CVideoCaptureView::OnStartRecord)
+	ON_COMMAND(ID_STOP_RECORD, &CVideoCaptureView::OnStopRecord)
+	ON_COMMAND(ID_CHECK_VERTICALLY, &CVideoCaptureView::OnCheckVertically)
+	ON_COMMAND(ID_CHECK_HORIONTAL, &CVideoCaptureView::OnCheckHoriontal)
+	ON_UPDATE_COMMAND_UI(ID_CHECK_VERTICALLY, &CVideoCaptureView::OnUpdateCheckVertically)
+	ON_UPDATE_COMMAND_UI(ID_CHECK_HORIONTAL, &CVideoCaptureView::OnUpdateCheckHoriontal)
+	ON_COMMAND(ID_TRAYMENU_RECONNECT, &CVideoCaptureView::OnTraymenuReconnect)
+	ON_COMMAND(ID_CHECK_SUPORT_GPU, &CVideoCaptureView::OnCheckSuportGpu)
+	ON_COMMAND(ID_CHECK_FORMAT_MP4, &CVideoCaptureView::OnCheckFormatMp4)
+	ON_COMMAND(ID_CHECK_FORMAT_AVI, &CVideoCaptureView::OnCheckFormatAvi)
+	ON_UPDATE_COMMAND_UI(ID_CHECK_SUPORT_GPU, &CVideoCaptureView::OnUpdateCheckSuportGpu)
+	ON_UPDATE_COMMAND_UI(ID_CHECK_FORMAT_MP4, &CVideoCaptureView::OnUpdateCheckFormatMp4)
+	ON_UPDATE_COMMAND_UI(ID_CHECK_FORMAT_AVI, &CVideoCaptureView::OnUpdateCheckFormatAvi)
+	ON_UPDATE_COMMAND_UI(ID_START_RECORD, &CVideoCaptureView::OnUpdateStartRecord)
+	ON_UPDATE_COMMAND_UI(ID_STOP_RECORD, &CVideoCaptureView::OnUpdateStopRecord)
+END_MESSAGE_MAP()
+
+// CVideoCaptureView 构造/析构
+
+CVideoCaptureView::CVideoCaptureView() noexcept
+{
+	// TODO: 在此处添加构造代码
+	m_hVideoDevice = NULL;
+	m_bIsRecord = FALSE;
+	m_bNoSignal = FALSE;
+	m_bVertically = FALSE;
+	m_bHoriontal = FALSE;
+	m_bAppQuit = FALSE;
+	m_pBuffer = NULL;
+	m_bCaptureImage = FALSE;
+	m_dwBufferLen = 0;
+	m_bIsMp4 = TRUE;
+	m_bSupportGPU = FALSE;
+}
+
+CVideoCaptureView::~CVideoCaptureView()
+{
+	g_ub530.EndOfThread();
+	m_bAppQuit = TRUE;
+	HwUninitialize();
+}
+
+BOOL CVideoCaptureView::PreCreateWindow(CREATESTRUCT& cs)
+{
+	// TODO: 在此处通过修改
+	//  CREATESTRUCT cs 来修改窗口类或样式
+
+	return CView::PreCreateWindow(cs);
+}
+
+// CVideoCaptureView 绘图
+
+void CVideoCaptureView::OnDraw(CDC* pDC)
+{
+	CVideoCaptureDoc* pDoc = GetDocument();
+	ASSERT_VALID(pDoc);
+	if (!pDoc)
+		return;
+
+	// TO FILL IN THE TEXT 
+	//
+	if (m_hVideoDevice == 0 || m_bNoSignal) {
+
+		CFont font;
+		ULONG nFontSize = 300;
+		font.CreatePointFont(nFontSize, TEXT("Arial"), NULL);
+		HFONT hOldFont = (HFONT)pDC->SelectObject(&font);
+		pDC->SetBkMode(TRANSPARENT);
+		pDC->SetTextColor(RGB(255, 255, 255));
+
+		CRect rect_client;
+		GetClientRect(&rect_client);
+
+		CString string = _T("");
+		if (m_hVideoDevice == 0)
+		{
+			CBrush brush_fill_rect(RGB(0, 0, 0));
+			pDC->FillRect(&rect_client, &brush_fill_rect);
+			string = TEXT("No Device");
+			//g_pMainFrame->SetRibbonStatusBarText("当前采集卡设备被移除。", ID_STATUSBAR_PANE1);
+		}
+		else if(m_bNoSignal)
+		{
+			CBrush brush_fill_rect(RGB(0, 0, 255));
+			pDC->FillRect(&rect_client, &brush_fill_rect);
+			string = TEXT("No Source");
+			//g_pMainFrame->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
+		}
+		pDC->DrawText(string, &rect_client, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
+
+		pDC->SelectObject(&hOldFont);
+		font.DeleteObject();
+	}
+
+	// TODO: 在此处为本机数据添加绘制代码
+}
+
+
+// CVideoCaptureView 打印
+
+
+BOOL CVideoCaptureView::HwInitialize()
+{
+	if (m_hVideoDevice != NULL)
+		return TRUE;
+
+	// CALLBACK FUNCTION       
+	PF_FORMAT_CHANGED_CALLBACK pFormatChangedCB = { 0 };
+	PF_VIDEO_PREVIEW_CALLBACK  pPreviewVideoCB = { 0 };
+	PF_AUDIO_PREVIEW_CALLBACK pPreviewAudioCB = { 0 };
+	PF_VIDEO_HARDWARE_ENCODER_CALLBACK pHardwareEncoderVideoCB = { 0 };
+	PF_NO_SIGNAL_DETECTED_CALLBACK pNoSignalDetectedCB = { 0 };
+	PF_SIGNAL_REMOVED_CALLBACK pSignalRemovedCB = { 0 };
+	PF_SNAPSHOT_DONE_CALLBACK pSnapShotDoneCB = { 0 };
+	PF_SNAPSHOT_STREAM_CALLBACK pSnapShotStreamCB = { 0 };
+	// CREATE CAPTURE DEVICE
+	//
+	if (m_hVideoDevice == NULL)
+		QCAP_CREATE("CY3014 USB", 0, m_hWnd, &m_hVideoDevice, 1);
+
+	if (m_hVideoDevice == NULL) {
+		return FALSE;
+	}
+
+	// REGISTER FORMAT CHANGED CALLBACK FUNCTION
+	pFormatChangedCB = on_process_format_changed;
+	QCAP_REGISTER_FORMAT_CHANGED_CALLBACK(m_hVideoDevice, pFormatChangedCB, this);
+
+	// REGISTER PREVIEW VIDEO CALLBACK FUNCTION
+	pPreviewVideoCB = on_process_preview_video_buffer;
+	QCAP_REGISTER_VIDEO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewVideoCB, this);
+
+	// REGISTER PREVIEW AUDIO CALLBACK FUNCTION
+	//pPreviewAudioCB = on_process_preview_audio_buffer;
+	//QCAP_REGISTER_AUDIO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewAudioCB, this);
+
+	// REGISTER HARDWARE ENCODER VIDEO CALLBACK FUNCTION
+	//pHardwareEncoderVideoCB = on_process_hardware_encoder_video_buffer;
+	//QCAP_REGISTER_VIDEO_HARDWARE_ENCODER_CALLBACK(m_hVideoDevice, 0, pHardwareEncoderVideoCB, this);
+
+	// REGISTER NO SIGNAL DETECTED CALLBACK FUNCTION
+	pNoSignalDetectedCB = on_process_no_signal_detected;
+	QCAP_REGISTER_NO_SIGNAL_DETECTED_CALLBACK(m_hVideoDevice, pNoSignalDetectedCB, this);
+
+	// REGISTER SIGNAL REMOVED CALLBACK FUNCTION
+	pSignalRemovedCB = on_process_signal_removed;
+	QCAP_REGISTER_SIGNAL_REMOVED_CALLBACK(m_hVideoDevice, pSignalRemovedCB, this);
+
+#if 1
+	// 
+	pSnapShotDoneCB = on_process_snapshot_done;
+	QCAP_REGISTER_SNAPSHOT_DONE_CALLBACK(m_hVideoDevice, pSnapShotDoneCB, this);
+
+	// 
+	pSnapShotStreamCB = on_process_snapshot_stream;
+	QCAP_REGISTER_SNAPSHOT_STREAM_CALLBACK(m_hVideoDevice, pSnapShotStreamCB, this);
+#endif
+
+	QCAP_SET_VIDEO_DEINTERLACE_TYPE(m_hVideoDevice, QCAP_SOFTWARE_DEINTERLACE_TYPE_BLENDING);
+
+	QCAP_SET_VIDEO_DEINTERLACE(m_hVideoDevice, 0);
+	QCAP_SET_AUDIO_VOLUME(m_hVideoDevice, 100);
+	QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_FORMAT_H264, QCAP_RECORD_MODE_CBR, 8000, 12 * 1024 * 1024, 30, 0, 0, QCAP_DOWNSCALE_MODE_OFF, 0, 0);
+
+	QCAP_SET_VIDEO_INPUT(m_hVideoDevice, QCAP_INPUT_TYPE_AUTO);
+	QCAP_RUN(m_hVideoDevice);
+
+	// 刷新区域;
+	Invalidate();
+
+	// UPDATE USER INTERFACE RESOURCE
+	if (m_hVideoDevice == 0) {
+		/*m_oSetupDialog.m_btnVideoInput.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnVideoQuality.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnAudioInput.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
+		m_oSetupDialog.m_checkGPU_1_2.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
+		m_oSetupDialog.m_checkGPU_1_3.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
+		m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
+	}
+	else {
+		/*m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(TRUE);
+		m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(TRUE);
+		m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(TRUE);
+		m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(TRUE);
+		m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
+		m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(TRUE);
+		m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
+		m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
+		m_oSetupDialog.m_checkGPU_1_2.EnableWindow(TRUE);
+		m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
+		m_oSetupDialog.m_checkGPU_1_3.EnableWindow(TRUE);
+		m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
+		m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(TRUE);
+		m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
+	}
+
+	return TRUE;
+}
+
+BOOL CVideoCaptureView::HwUninitialize()
+{
+	if (m_hVideoDevice != 0) {
+		QCAP_STOP(m_hVideoDevice);
+		QCAP_DESTROY(m_hVideoDevice);
+		m_hVideoDevice = NULL;
+	}
+
+	return TRUE;
+}
+
+void CVideoCaptureView::CaptureSingleImage(LPTSTR lpszFileName, BOOL bIsJPG)
+{
+	if (m_hVideoDevice != NULL)
+	{
+		if (bIsJPG)
+		{
+			QCAP_SNAPSHOT_JPG(m_hVideoDevice, lpszFileName, 100, FALSE, 5000); //参数4:是否异步;
+		}
+		else
+		{
+			QCAP_SNAPSHOT_BMP(m_hVideoDevice, lpszFileName, FALSE, 5000);
+		}
+#ifdef _DEBUG
+		Global::WriteTextLog("完成:CaptureSingleImage");
+#endif
+	}
+}
+
+std::string CVideoCaptureView::CaptureSingleImageAutoName(LPCTSTR lpszDir, BOOL bIsJPG)
+{
+	if (m_hVideoDevice != NULL)
+	{
+		TCHAR szPath[MAX_PATH] = { 0 };
+		// 毫秒级;
+		time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
+		auto tt = std::chrono::system_clock::to_time_t(tp);
+		std::tm now = { 0 };
+		localtime_s(&now, &tt); // 时间戳转成本地时间;
+		int msc = tp.time_since_epoch().count() % 1000;
+		if (bIsJPG)
+		{
+			_stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
+				lpszDir ? lpszDir : Global::g_szCurModuleDir,
+				now.tm_year + 1990,
+				now.tm_mon + 1,
+				now.tm_mday,
+				now.tm_hour,
+				now.tm_min,
+				now.tm_sec,
+				msc);
+			QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, FALSE, 5000);
+		}
+		else
+		{
+			_stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
+				lpszDir ? lpszDir : Global::g_szCurModuleDir,
+				now.tm_year + 1990,
+				now.tm_mon + 1,
+				now.tm_mday,
+				now.tm_hour,
+				now.tm_min,
+				now.tm_sec,
+				msc);
+			QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, FALSE, 5000);
+		}
+#ifdef _DEBUG
+		Global::WriteTextLog("完成:CaptureSingleImageAutoName");
+#endif
+		return std::string(szPath);
+	}
+
+	return std::string();
+}
+
+void CVideoCaptureView::CaptureMultiImage(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
+{
+	std::thread t([&](CVideoCaptureView* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
+		// 连续截图;
+		TCHAR szDir[MAX_PATH] = { 0 };
+		TCHAR szPath[MAX_PATH] = { 0 };
+
+		_stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
+			lpszDir ? lpszDir : Global::g_szCurModuleDir,
+			lpszPrefix ? lpszPrefix : _T(""));
+
+		auto start = system_clock::now();
+		while (true)
+		{
+			// C++11获取当前时间;
+			time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
+			if (bIsJPG)
+			{
+				_stprintf_s(szPath, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
+				QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, TRUE);
+				// 等待磁盘完成写入;
+				//Sleep(20);
+			}
+			else
+			{
+				_stprintf_s(szPath, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
+				QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, TRUE);
+				// 等待磁盘完成写入;
+				//Sleep(530);
+			}
+
+			auto duration = duration_cast<milliseconds>(system_clock::now() - start);
+			if (duration.count() >= nDurationTime)
+				break;
+		}
+		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
+	t.detach();
+}
+
+void CVideoCaptureView::CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG)
+{
+	{
+		// 加锁;
+		std::lock_guard<std::mutex> lk(m_mut_cpature);
+		// 标记截图;
+		m_bCaptureImage = TRUE;
+		// 初始化数据;
+		ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
+		m_CaptureInfo.bIsJPG = bIsJPG;
+		m_CaptureInfo.bSingle = TRUE;
+		m_CaptureInfo.IsAutoName = FALSE;
+		m_CaptureInfo.nCaputerCount = 0;
+		m_CaptureInfo.nKeepTime = 0;
+		memset(m_CaptureInfo.szPrefix, 0, 64);
+		//_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s"), lpszFileName);
+		_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s"), lpszFileName);
+		//m_strCaptureName = lpszFileName;
+	}
+
+	// 等待截图完成;
+	{
+		// 加锁;
+		std::unique_lock<std::mutex> lk(m_mut_cpature);
+		m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
+		// 解锁;
+		lk.unlock();
+	}
+}
+
+std::string CVideoCaptureView::CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJPG)
+{
+	{
+		// 加锁;
+		std::lock_guard<std::mutex> lk(m_mut_cpature);
+		// 标记截图;
+		m_bCaptureImage = TRUE;
+		// 初始化数据;
+		ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
+		m_CaptureInfo.bIsJPG = bIsJPG;
+		m_CaptureInfo.bSingle = TRUE;
+		m_CaptureInfo.IsAutoName = FALSE;
+		m_CaptureInfo.nCaputerCount = 0;
+		m_CaptureInfo.nKeepTime = 0;
+		memset(m_CaptureInfo.szPrefix, 0, 64);
+		memset(m_CaptureInfo.szSaveDir, 0, MAX_PATH);
+
+		// 毫秒级;
+		time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
+		auto tt = std::chrono::system_clock::to_time_t(tp);
+		std::tm now = { 0 };
+		localtime_s(&now, &tt); // 时间戳转成本地时间;
+		int msc = tp.time_since_epoch().count() % 1000;
+		if (bIsJPG)
+		{
+			_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
+				lpszDir ? lpszDir : Global::g_szCurModuleDir,
+				now.tm_year + 1990,
+				now.tm_mon + 1,
+				now.tm_mday,
+				now.tm_hour,
+				now.tm_min,
+				now.tm_sec,
+				msc);
+		}
+		else
+		{
+			_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
+				lpszDir ? lpszDir : Global::g_szCurModuleDir,
+				now.tm_year + 1990,
+				now.tm_mon + 1,
+				now.tm_mday,
+				now.tm_hour,
+				now.tm_min,
+				now.tm_sec,
+				msc);
+		}
+
+#ifdef DEBUG
+		OutputDebugStringA(m_CaptureInfo.szSaveDir);
+		OutputDebugStringA("\tCVideoCaptureView::CaptureSingleImageAutoNameEx\n");
+#endif // DEBUG
+	}
+
+	// 等待截图完成;
+	{
+		// 加锁;
+		std::unique_lock<std::mutex> lk(m_mut_cpature);
+		m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
+		// 解锁;
+		lk.unlock();
+	}
+
+	return std::string(m_CaptureInfo.szSaveDir);
+}
+
+void CVideoCaptureView::CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
+{
+	std::thread t([&](CVideoCaptureView* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
+		// 连续截图;
+		TCHAR szDir[MAX_PATH] = { 0 };
+		_stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
+			lpszDir ? lpszDir : Global::g_szCurModuleDir,
+			lpszPrefix ? lpszPrefix : _T(""));
+
+		auto start = system_clock::now();
+		while (true)
+		{
+			// C++11获取当前时间;
+			time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
+
+			{
+				// 加锁;
+				std::lock_guard<std::mutex> lk(m_mut_cpature);
+				// 标记截图;
+				m_bCaptureImage = TRUE;
+				// 初始化数据;
+				ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
+				m_CaptureInfo.bIsJPG = bIsJPG;
+				m_CaptureInfo.bSingle = FALSE;
+				m_CaptureInfo.IsAutoName = TRUE;
+				m_CaptureInfo.nCaputerCount = 0;
+				m_CaptureInfo.nKeepTime = nDurationTime;
+				_stprintf_s(m_CaptureInfo.szPrefix, _T("%s"), lpszPrefix);
+				if (bIsJPG)
+				{
+					_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
+				}
+				else
+				{
+					_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
+				}
+			}
+
+			// 等待截图完成;
+			{
+				// 加锁;
+				std::unique_lock<std::mutex> lk(m_mut_cpature);
+				m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
+				// 解锁;
+				lk.unlock();
+			}
+
+			auto duration = duration_cast<milliseconds>(system_clock::now() - start);
+			if (duration.count() >= nDurationTime)
+				break;
+		}
+		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
+	t.detach();
+}
+
+BOOL CVideoCaptureView::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
+{
+	if (m_pBuffer == NULL)
+	{
+		return FALSE;
+	}
+
+	BOOL bRet = FALSE;
+	// 保存截图;
+	HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, m_nVideoWidth * m_nVideoHeight * 4);
+	if (hMemery != NULL)
+	{
+		BYTE* pDstFrameBuffer = NULL;
+		pDstFrameBuffer = (BYTE*)GlobalLock(hMemery);
+		if (pDstFrameBuffer != NULL)
+		{
+			QRESULT QRet = QCAP_COLORSPACE_YUY2_TO_ABGR32(m_pBuffer,
+				m_nVideoWidth,
+				m_nVideoHeight,
+				0,
+				pDstFrameBuffer,
+				m_nVideoWidth,
+				m_nVideoHeight,
+				0);
+
+			Status stat = GenericError;
+			Bitmap* pImg = ::new Bitmap(
+				m_nVideoWidth,
+				m_nVideoHeight,
+				m_nVideoWidth * 4,
+				PixelFormat32bppRGB,
+				pDstFrameBuffer);
+
+			if (m_bHoriontal && !m_bVertically)
+				pImg->RotateFlip(RotateNoneFlipX);// 水平翻转;
+			else if (m_bHoriontal && m_bVertically)
+				pImg->RotateFlip(Rotate180FlipNone);// 270度;
+			else if (!m_bHoriontal && m_bVertically)
+				pImg->RotateFlip(Rotate180FlipX);// 垂直翻转;
+
+			CLSID encoderClsid = { 0 };
+			CString strFileName = m_CaptureInfo.szSaveDir;
+			// 需要判断路径是否存在,不存在创建目录;
+			int nIndex = strFileName.ReverseFind(_T('\\'));
+			if (nIndex != -1) 
+			{
+				if (!PathFileExists(strFileName.Left(nIndex)))
+				{
+					// 如果文件夹不存在,创建;
+					SHCreateDirectoryEx(NULL, strFileName.Left(nIndex), NULL);
+				}
+			}
+
+			BSTR newfile = strFileName.AllocSysString();
+			if (!capInfo.bIsJPG)
+			{
+				Global::GetEncoderClsid(L"image/bmp", &encoderClsid);
+				stat = pImg->Save(newfile, &encoderClsid, NULL);
+			}
+			else
+			{
+				Global::GetEncoderClsid(L"image/jpeg", &encoderClsid);
+				EncoderParameters encoderParameters;
+				encoderParameters.Count = 1;
+				encoderParameters.Parameter[0].Guid = EncoderQuality;
+				encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
+				encoderParameters.Parameter[0].NumberOfValues = 1;
+				// Save the image as a JPEG with quality level 100.
+				ULONG uQuality = 100;
+				encoderParameters.Parameter[0].Value = &uQuality;
+				stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
+			}
+
+			if (pImg)
+				::delete pImg;
+			pImg = NULL;
+			SysFreeString(newfile);
+
+			bRet = (stat == 0 ? TRUE : FALSE);
+#ifdef DEBUG
+			if (bRet)
+			{
+				OutputDebugStringA(strFileName);
+				OutputDebugStringA("\tSave Image::Ok\n");
+			}
+#endif
+		}
+#ifdef DEBUG
+		else
+		{
+			OutputDebugStringA("pDstFrameBuffer == NULL\n");
+		}
+#endif
+
+		GlobalUnlock(hMemery);
+	}
+#ifdef DEBUG
+	else
+	{
+		DWORD dwError = GetLastError();
+		CString strError = _T("");
+		strError.Format(_T("hMemery == NULL分配内存出错:%ld\n"), dwError);
+		OutputDebugStringA(strError);
+	}
+#endif
+
+	if (m_pBuffer)
+		delete[]m_pBuffer;
+	m_pBuffer = NULL;
+
+	// 必须调用GlobalFree释放;
+	GlobalFree(hMemery);
+
+	return bRet;
+}
+
+void CVideoCaptureView::CaptureImageThread(CVideoCaptureView* pView)
+{
+	CString strFileName = _T("");
+	while (!pView->m_bAppQuit)
+	{
+		std::unique_lock<std::mutex> lk(pView->m_mut_thread);   // 这里使用unique_lock是为了后面方便解锁
+#if 1	// 避免线程虚假唤醒;
+		pView->m_thread_cond.wait(lk, [&]() {return pView->m_pBuffer; });
+#else
+		while (!pView->m_pBuffer)
+			pView->m_data_cond.wait(lk);
+#endif
+		// 保存截图;
+		pView->SaveImageByCaptureInfo(pView->m_CaptureInfo);
+		// 通知截图完成;
+		pView->m_capture_cond.notify_one();
+
+		// 解锁;
+		lk.unlock();
+
+		// sleep 10ms;
+		//this_thread::sleep_for(chrono::milliseconds(10));
+	}
+}
+
+void CVideoCaptureView::StartRecord(DWORD dwDuration, LPCTSTR lpSavePath)
+{
+	QRESULT QRet = QCAP_RS_SUCCESSFUL;
+	if (!m_bIsMp4) // 音频格式;
+	{
+		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_PCM);
+		//_tcscat_s(szPath, _T(".avi"));
+	}
+	else
+	{
+		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC);
+		//_tcscat_s(szPath, _T(".mp4"));
+	}
+
+	// 设置视频属性;
+	QRet = QCAP_SET_VIDEO_RECORD_PROPERTY(
+		m_hVideoDevice,
+		0,
+		m_bSupportGPU ? QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK : QCAP_ENCODER_TYPE_SOFTWARE,
+		QCAP_ENCODER_FORMAT_H264,
+		QCAP_RECORD_MODE_CBR,
+		8000,
+		16 * 1024 * 1024, // 16最高质量;
+		30, // 每秒多少帧
+		0,
+		0,
+		QCAP_DOWNSCALE_MODE_OFF);
+
+	// 开始录屏;
+	QRet = QCAP_START_RECORD(m_hVideoDevice, 0, const_cast<CHAR*>(lpSavePath), QCAP_RECORD_FLAG_FULL, 0.0, 0.0, 0.0, 0, NULL);
+
+	m_bIsRecord = TRUE;
+}
+
+void CVideoCaptureView::StopRecord()
+{
+	QCAP_STOP_RECORD(m_hVideoDevice, 0);
+	m_bIsRecord = FALSE;
+}
+
+void CVideoCaptureView::OnFilePrintPreview()
+{
+#ifndef SHARED_HANDLERS
+	AFXPrintPreview(this);
+#endif
+}
+
+BOOL CVideoCaptureView::OnPreparePrinting(CPrintInfo* pInfo)
+{
+	// 默认准备
+	return DoPreparePrinting(pInfo);
+}
+
+void CVideoCaptureView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
+{
+	// TODO: 添加额外的打印前进行的初始化过程
+}
+
+void CVideoCaptureView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
+{
+	// TODO: 添加打印后进行的清理过程
+}
+
+void CVideoCaptureView::OnRButtonUp(UINT /* nFlags */, CPoint point)
+{
+	ClientToScreen(&point);
+	OnContextMenu(this, point);
+}
+
+void CVideoCaptureView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
+{
+#ifndef SHARED_HANDLERS
+	theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
+#endif
+}
+
+
+// CVideoCaptureView 诊断
+
+#ifdef _DEBUG
+void CVideoCaptureView::AssertValid() const
+{
+	CView::AssertValid();
+}
+
+void CVideoCaptureView::Dump(CDumpContext& dc) const
+{
+	CView::Dump(dc);
+}
+
+CVideoCaptureDoc* CVideoCaptureView::GetDocument() const // 非调试版本是内联的
+{
+	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVideoCaptureDoc)));
+	return (CVideoCaptureDoc*)m_pDocument;
+}
+#endif //_DEBUG
+
+
+// CVideoCaptureView 消息处理程序
+
+
+void CVideoCaptureView::SetRibbonStatusBarText(CString strText, int uId)
+{
+	if ( g_pMainFrame )
+	{
+		g_pMainFrame->SetRibbonStatusBarText(strText, uId);
+	}
+}
+
+int CVideoCaptureView::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CView::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	// 初始化共享内存;
+	CMemoryClient::m_pView = this;
+	g_ub530.InitMemery();
+	g_ub530.StartThread();
+
+	g_pMainFrame = (CMainFrame*)this->GetParent();
+
+	// TODO:  在此添加您专用的创建代码
+	// 创建视频流,并关联指定显示窗口;
+	HwInitialize();
+
+	// 创建截图线程;
+	std::thread t(CaptureImageThread, this);
+	t.detach();
+
+	return 0;
+}
+
+
+void CVideoCaptureView::OnTimer(UINT_PTR nIDEvent)
+{
+	// TODO: 在此添加消息处理程序代码和/或调用默认值
+	if (nIDEvent == 0)
+	{
+		KillTimer(0);
+
+		if (m_bNoSignal)
+		{
+			if (m_bIsRecord)
+			{
+				QCAP_STOP_RECORD(m_hVideoDevice, 0);
+				m_bIsRecord = FALSE;
+			}
+		}
+		else
+		{
+
+		}
+	}
+
+	CView::OnTimer(nIDEvent);
+}
+
+
+void CVideoCaptureView::OnCutBmp()
+{
+	// TODO: 在此添加命令处理程序代码
+	CaptureSingleImageAutoName(NULL, FALSE);
+}
+
+
+void CVideoCaptureView::OnCutJpg()
+{
+	// TODO: 在此添加命令处理程序代码
+	CaptureSingleImageAutoName(NULL, TRUE);
+}
+
+
+void CVideoCaptureView::OnStartRecord()
+{
+	// TODO: 在此添加命令处理程序代码
+	TCHAR szPath[MAX_PATH] = { 0 };
+	// 毫秒级;
+	time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
+	auto tt = std::chrono::system_clock::to_time_t(tp);
+	std::tm now = { 0 };
+	localtime_s(&now, &tt); // 时间戳转成本地时间;
+	int msc = tp.time_since_epoch().count() % 1000;
+
+	_stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d"),
+#ifdef _DEBUG
+		_T("D:\\bin\\VideoCapture\\"),
+#else
+		Global::g_szCurModuleDir,
+#endif
+		now.tm_year + 1990,
+		now.tm_mon + 1,
+		now.tm_mday,
+		now.tm_hour,
+		now.tm_min,
+		now.tm_sec,
+		msc);
+
+	QRESULT QRet = QCAP_RS_SUCCESSFUL;
+	if (!m_bIsMp4) // 音频格式;
+	{
+		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_PCM);
+		_tcscat_s(szPath, _T(".avi"));
+	}
+	else
+	{
+		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC);
+		_tcscat_s(szPath, _T(".mp4"));
+	}
+	
+	// 设置视频属性;
+	QRet = QCAP_SET_VIDEO_RECORD_PROPERTY(
+		m_hVideoDevice,
+		0,
+		m_bSupportGPU ? QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK : QCAP_ENCODER_TYPE_SOFTWARE,
+		QCAP_ENCODER_FORMAT_H264,
+		QCAP_RECORD_MODE_CBR,
+		8000,
+		16*1024*1024, // 16最高质量;
+		30, // 每秒多少帧
+		0, 
+		0,
+		QCAP_DOWNSCALE_MODE_OFF);
+	
+
+	// 开始录屏;
+	QRet = QCAP_START_RECORD(m_hVideoDevice, 0, szPath, QCAP_RECORD_FLAG_FULL, 0.0, 0.0, 0.0, 0, NULL);
+
+	m_bIsRecord = TRUE;
+}
+
+
+void CVideoCaptureView::OnStopRecord()
+{
+	// TODO: 在此添加命令处理程序代码
+	QCAP_STOP_RECORD(m_hVideoDevice, 0);
+	m_bIsRecord = FALSE;
+}
+
+
+void CVideoCaptureView::OnCheckVertically()
+{
+	// TODO: 在此添加命令处理程序代码
+	CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
+	CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_VERTICALLY);
+	m_bVertically = !pCheckbox->IsChecked();
+	if (m_hVideoDevice)
+	{
+		QCAP_SET_VIDEO_MIRROR(m_hVideoDevice, m_bHoriontal, m_bVertically);
+	}
+}
+
+
+void CVideoCaptureView::OnCheckHoriontal()
+{
+	// TODO: 在此添加命令处理程序代码
+	CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
+	CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_HORIONTAL);
+	m_bHoriontal = !pCheckbox->IsChecked();
+	if (m_hVideoDevice)
+	{
+		QCAP_SET_VIDEO_MIRROR(m_hVideoDevice, m_bHoriontal, m_bVertically);
+	}
+}
+
+
+void CVideoCaptureView::OnUpdateCheckVertically(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->SetCheck(m_bVertically);
+}
+
+
+void CVideoCaptureView::OnUpdateCheckHoriontal(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->SetCheck(m_bHoriontal);
+}
+
+
+void CVideoCaptureView::OnTraymenuReconnect()
+{
+	// TODO: 在此添加命令处理程序代码
+	HwUninitialize();// 断开;
+	Invalidate();
+	HwInitialize();// 重连;
+}
+
+
+void CVideoCaptureView::OnCheckSuportGpu()
+{
+	// TODO: 在此添加命令处理程序代码
+	CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
+	CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_SUPORT_GPU);
+	m_bSupportGPU = !pCheckbox->IsChecked();
+}
+
+
+void CVideoCaptureView::OnCheckFormatMp4()
+{
+	CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
+	CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_FORMAT_MP4);
+	m_bIsMp4 = !pCheckbox->IsChecked();
+}
+
+
+void CVideoCaptureView::OnCheckFormatAvi()
+{
+	CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
+	CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_FORMAT_AVI);
+	m_bIsMp4 = pCheckbox->IsChecked();
+}
+
+
+void CVideoCaptureView::OnUpdateCheckSuportGpu(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->SetCheck(m_bSupportGPU);
+}
+
+
+void CVideoCaptureView::OnUpdateCheckFormatMp4(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->SetCheck(m_bIsMp4);
+}
+
+
+void CVideoCaptureView::OnUpdateCheckFormatAvi(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->SetCheck(!m_bIsMp4);
+}
+
+
+void CVideoCaptureView::OnUpdateStartRecord(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->Enable(!m_bIsRecord);
+}
+
+
+void CVideoCaptureView::OnUpdateStopRecord(CCmdUI* pCmdUI)
+{
+	// TODO: 在此添加命令更新用户界面处理程序代码
+	pCmdUI->Enable(m_bIsRecord);
+}

+ 199 - 0
VideoCapture/VideoCapture/VideoCaptureView.h

@@ -0,0 +1,199 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+// VideoCaptureView.h: CVideoCaptureView 类的接口
+//
+
+#pragma once
+#include "VideoCaptureDoc.h"
+#include "MemoryClient.h"
+
+typedef struct __CAPTURE_INFO__ 
+{
+	// 是否是jpg;
+	BOOL bIsJPG;
+	// 持续时间;
+	int nKeepTime;
+	// 每秒抓取张数;
+	int nCaputerCount;
+	// 保存路径;
+	TCHAR szSaveDir[MAX_PATH];
+	// 文件名前缀;
+	TCHAR szPrefix[64];
+	// 是否自动命名;
+	BOOL IsAutoName;
+	// 是否单张截图;
+	BOOL bSingle;
+}CaptureInfo, *pCaptureInfo;
+
+class CVideoCaptureView : public CView
+{
+protected: // 仅从序列化创建
+	CVideoCaptureView() noexcept;
+	DECLARE_DYNCREATE(CVideoCaptureView)
+
+// 特性
+public:
+	CVideoCaptureDoc* GetDocument() const;
+
+// 操作
+public:
+
+// 重写
+public:
+	virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图
+	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
+protected:
+	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
+	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
+	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
+
+// 实现
+public:
+	virtual ~CVideoCaptureView();
+#ifdef _DEBUG
+	virtual void AssertValid() const;
+	virtual void Dump(CDumpContext& dc) const;
+#endif
+
+public:
+	// 设备句柄;
+	PVOID 				m_hVideoDevice;
+	// 是否有信号;
+	BOOL				m_bNoSignal;
+	// 是否在录频;
+	BOOL				m_bIsRecord;
+	// 录频格式;
+	BOOL				m_bIsMp4; // FALSE= AVI
+	//////////////////////////////////////////////////////////////////////////
+	// VIDEO PROPERTIES
+	// 是否支持GPU;
+	BOOL				m_bSupportGPU;
+	// 视频流宽度;
+	ULONG				m_nVideoWidth;
+	// 视频流高度;
+	ULONG				m_nVideoHeight;
+
+	BOOL				m_bVideoIsInterleaved;
+
+	double				m_dVideoFrameRate;
+
+	BOOL				m_bVideoDeinterlaceEnable;
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// AUDIO PROPERTIES
+
+	ULONG				m_nAudioChannels;
+
+	ULONG				m_nAudioBitsPerSample;
+
+	ULONG				m_nAudioSampleFrequency;
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QUALITY PROPERTIES
+
+	ULONG				m_nSharpness;
+
+	ULONG				m_nSaturation;
+
+	ULONG				m_nHue;
+
+	ULONG				m_nConstrast;
+
+	ULONG				m_nBrightness;
+
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// RECORD & FILE PROPERTIES
+
+	// 截图路径;
+	CString				m_strSnapshotPath;
+	//
+	CString				m_strFormatChangedOutput;
+	// 垂直镜像;
+	BOOL				m_bVertically;
+	// 水平镜像;
+	BOOL				m_bHoriontal;
+
+	// 程序退出;
+	BOOL				m_bAppQuit;
+
+public:
+	// 初始化设备;
+	BOOL HwInitialize();
+	// 释放设备;
+	BOOL HwUninitialize();
+
+	// 单次截图;
+	void CaptureSingleImage(LPTSTR lpszFileName, BOOL bIsJPG = TRUE);
+	// 单次截图并自动命名;
+	std::string CaptureSingleImageAutoName(LPCTSTR lpszDir, BOOL bIsJPG = TRUE);
+	// 连续截图;//默认持续1000ms;
+	void CaptureMultiImage(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime = 1000);
+
+	//////////////////////////////////////////////////////////////////////////
+	// ->预览截图;
+	CaptureInfo m_CaptureInfo;
+	BOOL m_bCaptureImage;
+	std::mutex m_mut_cpature;
+	std::condition_variable m_capture_cond;
+	// 单次截图;
+	void CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG = TRUE);
+	// 单次截图并自动命名;
+	std::string CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJPG = TRUE);
+	// 连续截图;//默认持续1000ms;
+	void CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime = 1000);
+	// 截图;
+	BOOL SaveImageByCaptureInfo(const CaptureInfo &capInfo);
+	
+	// 截图线程;
+	BYTE* m_pBuffer;
+	DWORD m_dwBufferLen;
+
+	std::mutex m_mut_thread;
+	std::condition_variable m_thread_cond; //使用std::condition_variable等待数据
+	static void CaptureImageThread(CVideoCaptureView *pView);
+
+	// 录屏;
+	void StartRecord(DWORD dwDuration, LPCTSTR lpSavePath);
+	void StopRecord();
+protected:
+
+// 生成的消息映射函数
+protected:
+	afx_msg void OnFilePrintPreview();
+	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
+	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
+	DECLARE_MESSAGE_MAP()
+public:
+	void SetRibbonStatusBarText(CString strText, int uId);
+	friend class CMemoryClient;
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg void OnTimer(UINT_PTR nIDEvent);
+	afx_msg void OnCutBmp();
+	afx_msg void OnCutJpg();
+	afx_msg void OnStartRecord();
+	afx_msg void OnStopRecord();
+	afx_msg void OnCheckVertically();
+	afx_msg void OnCheckHoriontal();
+	afx_msg void OnUpdateCheckVertically(CCmdUI* pCmdUI);
+	afx_msg void OnUpdateCheckHoriontal(CCmdUI* pCmdUI);
+	afx_msg void OnTraymenuReconnect();
+	afx_msg void OnCheckSuportGpu();
+	afx_msg void OnCheckFormatMp4();
+	afx_msg void OnCheckFormatAvi();
+	afx_msg void OnUpdateCheckSuportGpu(CCmdUI* pCmdUI);
+	afx_msg void OnUpdateCheckFormatMp4(CCmdUI* pCmdUI);
+	afx_msg void OnUpdateCheckFormatAvi(CCmdUI* pCmdUI);
+	afx_msg void OnUpdateStartRecord(CCmdUI* pCmdUI);
+	afx_msg void OnUpdateStopRecord(CCmdUI* pCmdUI);
+};
+
+#ifndef _DEBUG  // VideoCaptureView.cpp 中的调试版本
+inline CVideoCaptureDoc* CVideoCaptureView::GetDocument() const
+   { return reinterpret_cast<CVideoCaptureDoc*>(m_pDocument); }
+#endif
+

+ 52 - 0
VideoCapture/VideoCapture/ViewTree.cpp

@@ -0,0 +1,52 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+#include "ViewTree.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CViewTree
+
+CViewTree::CViewTree() noexcept
+{
+}
+
+CViewTree::~CViewTree()
+{
+}
+
+BEGIN_MESSAGE_MAP(CViewTree, CTreeCtrl)
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CViewTree 消息处理程序
+
+BOOL CViewTree::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
+{
+	BOOL bRes = CTreeCtrl::OnNotify(wParam, lParam, pResult);
+
+	NMHDR* pNMHDR = (NMHDR*)lParam;
+	ASSERT(pNMHDR != nullptr);
+
+	if (pNMHDR && pNMHDR->code == TTN_SHOW && GetToolTips() != nullptr)
+	{
+		GetToolTips()->SetWindowPos(&wndTop, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
+	}
+
+	return bRes;
+}

+ 33 - 0
VideoCapture/VideoCapture/ViewTree.h

@@ -0,0 +1,33 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// CViewTree 窗口
+
+class CViewTree : public CTreeCtrl
+{
+// 构造
+public:
+	CViewTree() noexcept;
+
+// 重写
+protected:
+	virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult);
+
+// 实现
+public:
+	virtual ~CViewTree();
+
+protected:
+	DECLARE_MESSAGE_MAP()
+};

+ 172 - 0
VideoCapture/VideoCapture/calendarbar.cpp

@@ -0,0 +1,172 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#include "stdafx.h"
+#include "framework.h"
+#include "CalendarBar.h"
+#include "VideoCapture.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+const int nBorderSize = 10;
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalendarBar
+
+CCalendarBar::CCalendarBar()
+{
+	m_nMyCalendarsY = 0;
+}
+
+CCalendarBar::~CCalendarBar()
+{
+}
+
+BEGIN_MESSAGE_MAP(CCalendarBar, CWnd)
+	ON_WM_CREATE()
+	ON_WM_ERASEBKGND()
+	ON_WM_SIZE()
+	ON_WM_PAINT()
+	ON_WM_SETFOCUS()
+	ON_WM_SETTINGCHANGE()
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalendarBar 消息处理程序
+
+int CCalendarBar::OnCreate(LPCREATESTRUCT lpCreateStruct)
+{
+	if (CWnd::OnCreate(lpCreateStruct) == -1)
+		return -1;
+
+	CRect rectDummy(0, 0, 0, 0);
+	m_wndCalendar.Create(WS_CHILD | WS_VISIBLE, rectDummy, this, 1);
+
+	CBitmap bmp;
+	bmp.LoadBitmap(IDB_PAGES_SMALL_HC);
+
+	m_Images.Create(16, 16, ILC_COLOR24 | ILC_MASK, 0, 0);
+	m_Images.Add(&bmp, RGB(255, 0, 255));
+
+	return 0;
+}
+
+BOOL CCalendarBar::PreTranslateMessage(MSG *pMsg)
+{
+	if (pMsg->message == WM_LBUTTONDOWN)
+	{
+		// 确保将键盘焦点设置到日历上
+		m_wndCalendar.SetFocus();
+	}
+
+	return CWnd::PreTranslateMessage(pMsg);
+}
+
+BOOL CCalendarBar::OnEraseBkgnd(CDC* /*pDC*/)
+{
+	return TRUE;
+}
+
+void CCalendarBar::OnSetFocus(CWnd *pOldWnd)
+{
+	CWnd::OnSetFocus(pOldWnd);
+	m_wndCalendar.SetFocus();
+}
+
+void CCalendarBar::OnSize(UINT nType, int cx, int cy)
+{
+	CWnd::OnSize(nType, cx, cy);
+
+	int nMyCalendarsHeight = 70;
+
+	if (m_wndCalendar.GetSafeHwnd() != nullptr)
+	{
+		m_wndCalendar.SetWindowPos(nullptr, nBorderSize, nBorderSize, cx - 2 * nBorderSize, cy - 2 * nBorderSize - nMyCalendarsHeight - 10, SWP_NOZORDER | SWP_NOACTIVATE);
+	}
+
+	m_nMyCalendarsY = cy - nMyCalendarsHeight;
+}
+
+BOOL CCalendarBar::Create(const RECT& rect, CWnd* pParentWnd, UINT nID)
+{
+	return CWnd::Create(nullptr, _T(""), WS_CHILD | WS_VISIBLE, rect, pParentWnd, nID);
+}
+
+void CCalendarBar::OnPaint()
+{
+	CPaintDC dc(this); // 用于绘制的设备上下文
+
+	CRect rectClient;
+	GetClientRect(rectClient);
+
+	dc.FillRect(rectClient, &afxGlobalData.brWindow);
+
+	if (rectClient.bottom - m_nMyCalendarsY > 0)
+	{
+		CRect rectMyCalendarsCaption = rectClient;
+		rectMyCalendarsCaption.top = m_nMyCalendarsY;
+		rectMyCalendarsCaption.bottom = rectMyCalendarsCaption.top + afxGlobalData.GetTextHeight(TRUE) * 3 / 2;
+
+		COLORREF clrText = CMFCVisualManager::GetInstance()->OnDrawPaneCaption(&dc, nullptr, FALSE, rectMyCalendarsCaption, CRect(0, 0, 0, 0));
+
+		CPen* pOldPen = dc.SelectObject(&afxGlobalData.penBarShadow);
+
+		dc.MoveTo(rectMyCalendarsCaption.left - 1, rectMyCalendarsCaption.top);
+		dc.LineTo(rectMyCalendarsCaption.right, rectMyCalendarsCaption.top);
+
+		dc.SelectStockObject(BLACK_PEN);
+
+		dc.MoveTo(rectMyCalendarsCaption.left - 1, rectMyCalendarsCaption.bottom);
+		dc.LineTo(rectMyCalendarsCaption.right, rectMyCalendarsCaption.bottom);
+
+		dc.SelectObject(pOldPen);
+
+		CRect rectText = rectMyCalendarsCaption;
+		rectText.DeflateRect(10, 0);
+
+		dc.SetBkMode(TRANSPARENT);
+		dc.SetTextColor(clrText);
+
+		CFont* pOldFont = dc.SelectObject(&afxGlobalData.fontRegular);
+
+		BOOL bNameValid;
+		CString str;
+
+		bNameValid = str.LoadString(IDS_MYCALENDARS);
+		ASSERT(bNameValid);
+		dc.DrawText(str, rectText, DT_VCENTER | DT_LEFT | DT_SINGLELINE);
+
+		CRect rectCalendar = rectClient;
+		rectCalendar.top = rectMyCalendarsCaption.bottom + 5;
+		rectCalendar.bottom = rectCalendar.top + afxGlobalData.GetTextHeight(TRUE) * 3 / 2 - 5;
+
+		dc.FillSolidRect(rectCalendar, RGB(255, 255, 213));
+
+		rectCalendar.DeflateRect(20, 0);
+		m_Images.Draw(&dc, 3, rectCalendar.TopLeft(), 0);
+
+		rectCalendar.left += 20;
+
+		bNameValid = str.LoadString(IDS_CALENDAR);
+		ASSERT(bNameValid);
+
+		dc.SetTextColor(afxGlobalData.clrHotLinkNormalText);
+		dc.DrawText(str, rectCalendar, DT_VCENTER | DT_LEFT | DT_SINGLELINE);
+
+		dc.SelectObject(pOldFont);
+	}
+}
+
+

+ 46 - 0
VideoCapture/VideoCapture/calendarbar.h

@@ -0,0 +1,46 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和 
+// MFC C++ 库软件随附的相关电子文档。  
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。  
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问 
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+/////////////////////////////////////////////////////////////////////////////
+// CCalendarBar 窗口
+
+class CCalendarBar : public CWnd
+{
+// 构造
+public:
+	CCalendarBar();
+
+// 特性
+protected:
+	CMonthCalCtrl m_wndCalendar;
+	int m_nMyCalendarsY;
+	CImageList m_Images;
+
+// 重写
+public:
+	virtual BOOL Create(const RECT& rect, CWnd* pParentWnd, UINT nID = (UINT)-1);
+	virtual BOOL PreTranslateMessage(MSG *pMsg);
+
+// 实现
+public:
+	virtual ~CCalendarBar();
+
+protected:
+	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
+	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
+	afx_msg void OnSize(UINT nType, int cx, int cy);
+	afx_msg void OnPaint();
+	afx_msg void OnSetFocus(CWnd *pOldWnd);
+
+	DECLARE_MESSAGE_MAP()
+};

+ 59 - 0
VideoCapture/VideoCapture/framework.h

@@ -0,0 +1,59 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include "targetver.h"
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+// 关闭 MFC 的一些常见且经常可放心忽略的隐藏警告消息
+#define _AFX_ALL_WARNINGS
+
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+
+
+#include <afxdisp.h>        // MFC 自动化类
+
+
+
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>             // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <afxcontrolbars.h>     // MFC 支持功能区和控制条
+
+
+
+
+
+
+
+
+#ifdef _UNICODE
+#if defined _M_IX86
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#elif defined _M_X64
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#else
+#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+#endif
+#endif
+
+

BIN
VideoCapture/VideoCapture/res/Toolbar.bmp


BIN
VideoCapture/VideoCapture/res/Toolbar256.bmp


BIN
VideoCapture/VideoCapture/res/VideoCapture.ico


BIN
VideoCapture/VideoCapture/res/VideoCapture.rc2


BIN
VideoCapture/VideoCapture/res/VideoCaptureDoc.ico


BIN
VideoCapture/VideoCapture/res/buttons.bmp


BIN
VideoCapture/VideoCapture/res/class_view.ico


BIN
VideoCapture/VideoCapture/res/class_view_hc.ico


BIN
VideoCapture/VideoCapture/res/classview.bmp


BIN
VideoCapture/VideoCapture/res/classview_hc.bmp


BIN
VideoCapture/VideoCapture/res/explorer.bmp


BIN
VideoCapture/VideoCapture/res/explorer_hc.bmp


BIN
VideoCapture/VideoCapture/res/file_view.ico


BIN
VideoCapture/VideoCapture/res/file_view_hc.ico


BIN
VideoCapture/VideoCapture/res/filelarge.bmp


BIN
VideoCapture/VideoCapture/res/filesmall.bmp


BIN
VideoCapture/VideoCapture/res/fileview.bmp


BIN
VideoCapture/VideoCapture/res/fileview_hc.bmp


BIN
VideoCapture/VideoCapture/res/info.bmp


BIN
VideoCapture/VideoCapture/res/main.bmp


BIN
VideoCapture/VideoCapture/res/menuimages.bmp


BIN
VideoCapture/VideoCapture/res/menuimages_hc.bmp


BIN
VideoCapture/VideoCapture/res/nav_large.bmp


BIN
VideoCapture/VideoCapture/res/nav_large_hc.bmp


BIN
VideoCapture/VideoCapture/res/output_wnd.ico


BIN
VideoCapture/VideoCapture/res/output_wnd_hc.ico


BIN
VideoCapture/VideoCapture/res/pages.bmp


BIN
VideoCapture/VideoCapture/res/pages_hc.bmp


BIN
VideoCapture/VideoCapture/res/pages_small.bmp


BIN
VideoCapture/VideoCapture/res/pages_small_hc.bmp


BIN
VideoCapture/VideoCapture/res/properties.bmp


BIN
VideoCapture/VideoCapture/res/properties_hc.bmp


BIN
VideoCapture/VideoCapture/res/properties_wnd.ico


BIN
VideoCapture/VideoCapture/res/properties_wnd_hc.ico


+ 790 - 0
VideoCapture/VideoCapture/res/ribbon.mfcribbon-ms

@@ -0,0 +1,790 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<AFX_RIBBON>
+    <HEADER>
+        <VERSION>1</VERSION>
+    </HEADER>
+    <RIBBON_BAR>
+        <ELEMENT_NAME>RibbonBar</ELEMENT_NAME>
+        <ENABLE_TOOLTIPS>TRUE</ENABLE_TOOLTIPS>
+        <ENABLE_TOOLTIPS_DESCRIPTION>TRUE</ENABLE_TOOLTIPS_DESCRIPTION>
+        <ENABLE_KEYS>TRUE</ENABLE_KEYS>
+        <ENABLE_PRINTPREVIEW>TRUE</ENABLE_PRINTPREVIEW>
+        <ENABLE_DRAWUSINGFONT>FALSE</ENABLE_DRAWUSINGFONT>
+        <IMAGE>
+            <ID>
+                <NAME>IDB_BUTTONS</NAME>
+                <VALUE>113</VALUE>
+            </ID>
+        </IMAGE>
+        <BUTTON_MAIN>
+            <ELEMENT_NAME>Button_Main</ELEMENT_NAME>
+            <KEYS>F</KEYS>
+            <PALETTE_TOP>FALSE</PALETTE_TOP>
+            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+            <INDEX_SMALL>-1</INDEX_SMALL>
+            <INDEX_LARGE>-1</INDEX_LARGE>
+            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+            <IMAGE>
+                <ID>
+                    <NAME>IDB_MAIN</NAME>
+                    <VALUE>112</VALUE>
+                </ID>
+            </IMAGE>
+        </BUTTON_MAIN>
+        <CATEGORY_MAIN>
+            <ELEMENT_NAME>Category_Main</ELEMENT_NAME>
+            <NAME>文件</NAME>
+            <IMAGE_SMALL>
+                <ID>
+                    <NAME>IDB_FILESMALL</NAME>
+                    <VALUE>115</VALUE>
+                </ID>
+            </IMAGE_SMALL>
+            <IMAGE_LARGE>
+                <ID>
+                    <NAME>IDB_FILELARGE</NAME>
+                    <VALUE>114</VALUE>
+                </ID>
+            </IMAGE_LARGE>
+            <ELEMENTS>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button</ELEMENT_NAME>
+                    <ID>
+                        <NAME>ID_TRAYMENU_RECONNECT</NAME>
+                        <VALUE>32800</VALUE>
+                    </ID>
+                    <TEXT>重连(&amp;C)</TEXT>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>8</INDEX_SMALL>
+                    <INDEX_LARGE>8</INDEX_LARGE>
+                    <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                    <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                </ELEMENT>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button</ELEMENT_NAME>
+                    <ID>
+                        <NAME>ID_FILE_PRINT</NAME>
+                        <VALUE>57607</VALUE>
+                    </ID>
+                    <TEXT>打印</TEXT>
+                    <KEYS>P</KEYS>
+                    <KEYS_MENU>W</KEYS_MENU>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>4</INDEX_SMALL>
+                    <INDEX_LARGE>4</INDEX_LARGE>
+                    <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                    <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                    <ELEMENTS>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Label</ELEMENT_NAME>
+                            <TEXT>预览并打印文档</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_FILE_PRINT_DIRECT</NAME>
+                                <VALUE>57608</VALUE>
+                            </ID>
+                            <TEXT>快速打印(&amp;Q)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>5</INDEX_SMALL>
+                            <INDEX_LARGE>5</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>TRUE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_FILE_PRINT_PREVIEW</NAME>
+                                <VALUE>57609</VALUE>
+                            </ID>
+                            <TEXT>打印预览(&amp;V)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>6</INDEX_SMALL>
+                            <INDEX_LARGE>6</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>TRUE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_FILE_PRINT_SETUP</NAME>
+                                <VALUE>57606</VALUE>
+                            </ID>
+                            <TEXT>打印设置(&amp;U)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>7</INDEX_SMALL>
+                            <INDEX_LARGE>7</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>TRUE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                    </ELEMENTS>
+                </ELEMENT>
+                <ELEMENT>
+                    <ELEMENT_NAME>Separator</ELEMENT_NAME>
+                    <HORIZ>TRUE</HORIZ>
+                </ELEMENT>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button</ELEMENT_NAME>
+                    <ID>
+                        <NAME>ID_FILE_CLOSE</NAME>
+                        <VALUE>57602</VALUE>
+                    </ID>
+                    <TEXT>关闭(&amp;C)</TEXT>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>8</INDEX_SMALL>
+                    <INDEX_LARGE>8</INDEX_LARGE>
+                    <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                    <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                </ELEMENT>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button_Main_Panel</ELEMENT_NAME>
+                    <ID>
+                        <NAME>ID_APP_EXIT</NAME>
+                        <VALUE>57665</VALUE>
+                    </ID>
+                    <TEXT>退出(&amp;X)</TEXT>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>10</INDEX_SMALL>
+                    <INDEX_LARGE>-1</INDEX_LARGE>
+                    <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                </ELEMENT>
+            </ELEMENTS>
+            <RECENT_FILE_LIST>
+                <ENABLE>FALSE</ENABLE>
+                <WIDTH>300</WIDTH>
+            </RECENT_FILE_LIST>
+        </CATEGORY_MAIN>
+        <QAT_ELEMENTS>
+            <ELEMENT_NAME>QAT</ELEMENT_NAME>
+            <QAT_TOP>TRUE</QAT_TOP>
+            <ITEMS>
+                <ITEM>
+                    <ID>
+                        <NAME>ID_FILE_NEW</NAME>
+                        <VALUE>57600</VALUE>
+                    </ID>
+                    <VISIBLE>TRUE</VISIBLE>
+                </ITEM>
+                <ITEM>
+                    <ID>
+                        <NAME>ID_FILE_OPEN</NAME>
+                        <VALUE>57601</VALUE>
+                    </ID>
+                    <VISIBLE>TRUE</VISIBLE>
+                </ITEM>
+                <ITEM>
+                    <ID>
+                        <NAME>ID_FILE_SAVE</NAME>
+                        <VALUE>57603</VALUE>
+                    </ID>
+                    <VISIBLE>TRUE</VISIBLE>
+                </ITEM>
+                <ITEM>
+                    <ID>
+                        <NAME>ID_FILE_PRINT_DIRECT</NAME>
+                        <VALUE>57608</VALUE>
+                    </ID>
+                    <VISIBLE>TRUE</VISIBLE>
+                </ITEM>
+            </ITEMS>
+        </QAT_ELEMENTS>
+        <TAB_ELEMENTS>
+            <ELEMENT_NAME>Group</ELEMENT_NAME>
+            <ELEMENTS>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button</ELEMENT_NAME>
+                    <TEXT>样式</TEXT>
+                    <KEYS>S</KEYS>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>-1</INDEX_SMALL>
+                    <INDEX_LARGE>-1</INDEX_LARGE>
+                    <DEFAULT_COMMAND>FALSE</DEFAULT_COMMAND>
+                    <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                    <ELEMENTS>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_VIEW_APPLOOK_OFF_2007_BLUE</NAME>
+                                <VALUE>215</VALUE>
+                            </ID>
+                            <TEXT>Office 2007 (蓝色样式)(&amp;B)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_VIEW_APPLOOK_OFF_2007_BLACK</NAME>
+                                <VALUE>216</VALUE>
+                            </ID>
+                            <TEXT>Office 2007 (黑色样式)(&amp;L)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_VIEW_APPLOOK_OFF_2007_SILVER</NAME>
+                                <VALUE>217</VALUE>
+                            </ID>
+                            <TEXT>Office 2007 (银色样式)(&amp;S)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_VIEW_APPLOOK_OFF_2007_AQUA</NAME>
+                                <VALUE>218</VALUE>
+                            </ID>
+                            <TEXT>Office 2007 (水绿色样式)(&amp;A)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                        <ELEMENT>
+                            <ELEMENT_NAME>Button</ELEMENT_NAME>
+                            <ID>
+                                <NAME>ID_VIEW_APPLOOK_WINDOWS_7</NAME>
+                                <VALUE>219</VALUE>
+                            </ID>
+                            <TEXT>Windows 7(&amp;D)</TEXT>
+                            <PALETTE_TOP>FALSE</PALETTE_TOP>
+                            <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                            <INDEX_SMALL>-1</INDEX_SMALL>
+                            <INDEX_LARGE>-1</INDEX_LARGE>
+                            <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                        </ELEMENT>
+                    </ELEMENTS>
+                </ELEMENT>
+                <ELEMENT>
+                    <ELEMENT_NAME>Button</ELEMENT_NAME>
+                    <ID>
+                        <NAME>ID_APP_ABOUT</NAME>
+                        <VALUE>57664</VALUE>
+                    </ID>
+                    <KEYS>A</KEYS>
+                    <PALETTE_TOP>FALSE</PALETTE_TOP>
+                    <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                    <INDEX_SMALL>0</INDEX_SMALL>
+                    <INDEX_LARGE>-1</INDEX_LARGE>
+                    <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                    <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                </ELEMENT>
+            </ELEMENTS>
+        </TAB_ELEMENTS>
+        <CATEGORIES>
+            <CATEGORY>
+                <ELEMENT_NAME>Category</ELEMENT_NAME>
+                <NAME>主页</NAME>
+                <KEYS>H</KEYS>
+                <IMAGE_SMALL>
+                    <ID>
+                        <NAME>IDB_WRITESMALL</NAME>
+                        <VALUE>110</VALUE>
+                    </ID>
+                </IMAGE_SMALL>
+                <IMAGE_LARGE>
+                    <ID>
+                        <NAME>IDB_WRITELARGE</NAME>
+                        <VALUE>111</VALUE>
+                    </ID>
+                </IMAGE_LARGE>
+                <PANELS>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>截图</NAME>
+                        <KEYS>F</KEYS>
+                        <INDEX>3</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CUT_BMP</NAME>
+                                    <VALUE>32790</VALUE>
+                                </ID>
+                                <TEXT>截图BMP</TEXT>
+                                <KEYS>F</KEYS>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>5</INDEX_SMALL>
+                                <INDEX_LARGE>2</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CUT_JPG</NAME>
+                                    <VALUE>32791</VALUE>
+                                </ID>
+                                <TEXT>截图JPG</TEXT>
+                                <KEYS>F</KEYS>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>5</INDEX_SMALL>
+                                <INDEX_LARGE>2</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>录屏</NAME>
+                        <INDEX>-1</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_START_RECORD</NAME>
+                                    <VALUE>32792</VALUE>
+                                </ID>
+                                <TEXT>开始录频</TEXT>
+                                <KEYS>N</KEYS>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>6</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_STOP_RECORD</NAME>
+                                    <VALUE>32793</VALUE>
+                                </ID>
+                                <TEXT>停止录频</TEXT>
+                                <KEYS>R</KEYS>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>7</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                <ALWAYS_DESCRIPTION>FALSE</ALWAYS_DESCRIPTION>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Separator</ELEMENT_NAME>
+                                <HORIZ>FALSE</HORIZ>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_SUPORT_GPU</NAME>
+                                    <VALUE>32804</VALUE>
+                                </ID>
+                                <TEXT>GPU支持</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_FORMAT_MP4</NAME>
+                                    <VALUE>32786</VALUE>
+                                </ID>
+                                <TEXT>MP4格式</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_FORMAT_AVI</NAME>
+                                    <VALUE>32805</VALUE>
+                                </ID>
+                                <TEXT>AVI格式</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>其他</NAME>
+                        <KEYS>W</KEYS>
+                        <INDEX>4</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_VERTICALLY</NAME>
+                                    <VALUE>32796</VALUE>
+                                </ID>
+                                <TEXT>垂直镜像</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_HORIONTAL</NAME>
+                                    <VALUE>32797</VALUE>
+                                </ID>
+                                <TEXT>水平镜像</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>Video Input</NAME>
+                        <KEYS>D</KEYS>
+                        <INDEX>1</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_AUTO</NAME>
+                                    <VALUE>32778</VALUE>
+                                </ID>
+                                <TEXT>AUTO</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_HDMI</NAME>
+                                    <VALUE>32771</VALUE>
+                                </ID>
+                                <TEXT>HDMI</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_DVID</NAME>
+                                    <VALUE>32772</VALUE>
+                                </ID>
+                                <TEXT>DVI-D</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_YCBCR</NAME>
+                                    <VALUE>32773</VALUE>
+                                </ID>
+                                <TEXT>YCBCR</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_DVIA</NAME>
+                                    <VALUE>32774</VALUE>
+                                </ID>
+                                <TEXT>DVI-A</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_SDI</NAME>
+                                    <VALUE>32777</VALUE>
+                                </ID>
+                                <TEXT>SDI</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_COMPOSITE</NAME>
+                                    <VALUE>32775</VALUE>
+                                </ID>
+                                <TEXT>COMPOSITE</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK_SVIDEO</NAME>
+                                    <VALUE>32776</VALUE>
+                                </ID>
+                                <TEXT>SVIDEO</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>Audio Input</NAME>
+                        <KEYS>I</KEYS>
+                        <INDEX>-1</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK2</NAME>
+                                    <VALUE>32779</VALUE>
+                                </ID>
+                                <TEXT>Embedded Audio</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Button_Check</ELEMENT_NAME>
+                                <ID>
+                                    <NAME>ID_CHECK3</NAME>
+                                    <VALUE>32780</VALUE>
+                                </ID>
+                                <TEXT>Line-IN</TEXT>
+                                <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                <INDEX_SMALL>-1</INDEX_SMALL>
+                                <INDEX_LARGE>-1</INDEX_LARGE>
+                                <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                    <PANEL>
+                        <ELEMENT_NAME>Panel</ELEMENT_NAME>
+                        <NAME>Video Quality</NAME>
+                        <INDEX>2</INDEX>
+                        <JUSTIFY_COLUMNS>FALSE</JUSTIFY_COLUMNS>
+                        <CENTER_COLUMN_VERT>FALSE</CENTER_COLUMN_VERT>
+                        <ELEMENTS>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Group</ELEMENT_NAME>
+                                <ELEMENTS>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Label</ELEMENT_NAME>
+                                        <TEXT>亮度:</TEXT>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <INDEX_SMALL>-1</INDEX_SMALL>
+                                        <INDEX_LARGE>-1</INDEX_LARGE>
+                                        <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                    </ELEMENT>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Slider</ELEMENT_NAME>
+                                        <ID>
+                                            <NAME>ID_SLIDER1</NAME>
+                                            <VALUE>32781</VALUE>
+                                        </ID>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <STYLE>0</STYLE>
+                                        <WIDTH>80</WIDTH>
+                                        <MIN>0</MIN>
+                                        <MAX>128</MAX>
+                                        <POS>0</POS>
+                                        <ZOOM_BUTTONS>FALSE</ZOOM_BUTTONS>
+                                    </ELEMENT>
+                                </ELEMENTS>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Group</ELEMENT_NAME>
+                                <ELEMENTS>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Label</ELEMENT_NAME>
+                                        <TEXT>对比度:</TEXT>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <INDEX_SMALL>-1</INDEX_SMALL>
+                                        <INDEX_LARGE>-1</INDEX_LARGE>
+                                        <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                    </ELEMENT>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Slider</ELEMENT_NAME>
+                                        <ID>
+                                            <NAME>ID_SLIDER2</NAME>
+                                            <VALUE>32782</VALUE>
+                                        </ID>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <STYLE>0</STYLE>
+                                        <WIDTH>80</WIDTH>
+                                        <MIN>0</MIN>
+                                        <MAX>128</MAX>
+                                        <POS>0</POS>
+                                        <ZOOM_BUTTONS>FALSE</ZOOM_BUTTONS>
+                                    </ELEMENT>
+                                </ELEMENTS>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Group</ELEMENT_NAME>
+                                <ELEMENTS>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Label</ELEMENT_NAME>
+                                        <TEXT>色调:</TEXT>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <INDEX_SMALL>-1</INDEX_SMALL>
+                                        <INDEX_LARGE>-1</INDEX_LARGE>
+                                        <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                    </ELEMENT>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Slider</ELEMENT_NAME>
+                                        <ID>
+                                            <NAME>32783</NAME>
+                                            <VALUE>32783</VALUE>
+                                        </ID>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <STYLE>0</STYLE>
+                                        <WIDTH>80</WIDTH>
+                                        <MIN>0</MIN>
+                                        <MAX>128</MAX>
+                                        <POS>0</POS>
+                                        <ZOOM_BUTTONS>FALSE</ZOOM_BUTTONS>
+                                    </ELEMENT>
+                                </ELEMENTS>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Group</ELEMENT_NAME>
+                                <ELEMENTS>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Label</ELEMENT_NAME>
+                                        <TEXT>饱和度:</TEXT>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <INDEX_SMALL>-1</INDEX_SMALL>
+                                        <INDEX_LARGE>-1</INDEX_LARGE>
+                                        <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                    </ELEMENT>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Slider</ELEMENT_NAME>
+                                        <ID>
+                                            <NAME>32784</NAME>
+                                            <VALUE>32784</VALUE>
+                                        </ID>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <STYLE>0</STYLE>
+                                        <WIDTH>80</WIDTH>
+                                        <MIN>0</MIN>
+                                        <MAX>128</MAX>
+                                        <POS>0</POS>
+                                        <ZOOM_BUTTONS>FALSE</ZOOM_BUTTONS>
+                                    </ELEMENT>
+                                </ELEMENTS>
+                            </ELEMENT>
+                            <ELEMENT>
+                                <ELEMENT_NAME>Group</ELEMENT_NAME>
+                                <ELEMENTS>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Label</ELEMENT_NAME>
+                                        <TEXT>锐度:</TEXT>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <INDEX_SMALL>-1</INDEX_SMALL>
+                                        <INDEX_LARGE>-1</INDEX_LARGE>
+                                        <DEFAULT_COMMAND>TRUE</DEFAULT_COMMAND>
+                                    </ELEMENT>
+                                    <ELEMENT>
+                                        <ELEMENT_NAME>Slider</ELEMENT_NAME>
+                                        <ID>
+                                            <NAME>32785</NAME>
+                                            <VALUE>32785</VALUE>
+                                        </ID>
+                                        <PALETTE_TOP>FALSE</PALETTE_TOP>
+                                        <ALWAYS_LARGE>FALSE</ALWAYS_LARGE>
+                                        <STYLE>0</STYLE>
+                                        <WIDTH>80</WIDTH>
+                                        <MIN>0</MIN>
+                                        <MAX>128</MAX>
+                                        <POS>0</POS>
+                                        <ZOOM_BUTTONS>FALSE</ZOOM_BUTTONS>
+                                    </ELEMENT>
+                                </ELEMENTS>
+                            </ELEMENT>
+                        </ELEMENTS>
+                    </PANEL>
+                </PANELS>
+            </CATEGORY>
+        </CATEGORIES>
+    </RIBBON_BAR>
+</AFX_RIBBON>

BIN
VideoCapture/VideoCapture/res/sort.bmp


BIN
VideoCapture/VideoCapture/res/sort_hc.bmp


BIN
VideoCapture/VideoCapture/res/writelarge.bmp


BIN
VideoCapture/VideoCapture/res/writesmall.bmp


+ 5 - 0
VideoCapture/VideoCapture/stdafx.cpp

@@ -0,0 +1,5 @@
+// pch.cpp: 与预编译标头对应的源文件
+
+#include "stdafx.h"
+
+// 当使用预编译的头时,需要使用此源文件,编译才能成功。

+ 51 - 0
VideoCapture/VideoCapture/stdafx.h

@@ -0,0 +1,51 @@
+// pch.h: 这是预编译标头文件。
+// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
+// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
+// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
+// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。
+
+#ifndef PCH_H
+#define PCH_H
+
+// 添加要在此处预编译的标头
+#include "framework.h"
+
+#include <thread>
+#include <future>               // std::async, std::future
+#include <chrono>   
+#include <mutex>
+#include <condition_variable>
+using namespace std;
+using namespace chrono;
+
+// 启停停靠窗口;
+#define __DOCKINGBAR__ 1
+// 启停导航栏;
+#define __OUTLOOKBAR__ 0
+// 启停标题栏;
+#define __CAPTIONBAR__ 0
+// 快速访问工具栏
+#define __QUICKACCESS_COMMAND__ 0
+
+
+//////////////////////////////////////////////////////////////////////////
+// START;
+#include <VFW.H>
+//#include "AMESDK.H"
+#include "QCAP.H"
+#define FREE( p ) { if( p ) { free( p ); p = NULL; } }	
+
+// SET INITIAL PARAMETER VALUES
+// CY3014 USB
+#define	SC_DEFAULT_STANDARD                 0		// 0 = NTSC / 1 = PALB
+#define SC_DEFAULT_INPUT_SUPPORT			0x00000000	// HDMI
+#define DEFAULT_PRODUCT						"StreamCatcher QCAP - UB658G"
+#define DEFAULT_PRODUCT_VERSION				""
+// END
+//////////////////////////////////////////////////////////////////////////
+
+#include "Global.h"
+#include <afxcontrolbars.h>
+
+
+#endif //PCH_H

+ 19 - 0
VideoCapture/VideoCapture/targetver.h

@@ -0,0 +1,19 @@
+// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面
+// (“Fluent UI”)。该示例仅供参考,
+// 用以补充《Microsoft 基础类参考》和
+// MFC C++ 库软件随附的相关电子文档。
+// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
+// 若要了解有关 Fluent UI 许可计划的详细信息,请访问
+// https://go.microsoft.com/fwlink/?LinkId=238214.
+//
+// 版权所有(C) Microsoft Corporation
+// 保留所有权利。
+
+#pragma once
+
+// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。
+
+// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将
+// 将 _WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。
+
+#include <SDKDDKVer.h>

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff