diff --git a/CMakeLists.txt b/CMakeLists.txt
index d53b4aa..5a75bbf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories(external/TinyThread/source)
if (WIN32)
include_directories(external/zlib/)
+include_directories(external/win32cpp/include)
endif()
add_subdirectory(src)
diff --git a/external/win32cpp/3rd Party Software/ADO Class/About.TXT b/external/win32cpp/3rd Party Software/ADO Class/About.TXT
new file mode 100644
index 0000000..9272cae
--- /dev/null
+++ b/external/win32cpp/3rd Party Software/ADO Class/About.TXT
@@ -0,0 +1,6 @@
+This software provides a simple database catalog access using a set of ADOX classes.
+It was written by Carlos Antollini. It was downloaded from CodeProject at:
+http://www.codeproject.com/KB/database/caaadoxclass.aspx
+
+This software remains the property of Carlos Antollini. Refer to the original download
+site to ensure your use of the software is consistant with any copyright or license.
diff --git a/external/win32cpp/3rd Party Software/ADO Class/AdoxClass_src.zip b/external/win32cpp/3rd Party Software/ADO Class/AdoxClass_src.zip
new file mode 100644
index 0000000..ea9e2cb
Binary files /dev/null and b/external/win32cpp/3rd Party Software/ADO Class/AdoxClass_src.zip differ
diff --git a/external/win32cpp/3rd Party Software/About this folder.TXT b/external/win32cpp/3rd Party Software/About this folder.TXT
new file mode 100644
index 0000000..990ef1a
--- /dev/null
+++ b/external/win32cpp/3rd Party Software/About this folder.TXT
@@ -0,0 +1,10 @@
+This folder contains a collection software written by other authors.
+They are included here in the hope that they might prove a useful addition for
+Win32++ users.
+
+The original authors retain all rights over their software. Each folder contains information
+regarding where the software was download from. Refer to the original download sites to
+ensure your use of the software is consistant with any copyright or license.
+
+
+
diff --git a/external/win32cpp/3rd Party Software/GridControl/About.TXT b/external/win32cpp/3rd Party Software/GridControl/About.TXT
new file mode 100644
index 0000000..6c8a2b7
--- /dev/null
+++ b/external/win32cpp/3rd Party Software/GridControl/About.TXT
@@ -0,0 +1,7 @@
+This software provides a DataGrid control.
+It was written by Darkoman. It was downloaded from CodeProject at:
+http://www.codeproject.com/KB/miscctrl/DataGridControl.aspx
+
+This software remains the property of the author (Darkoman). Refer to the
+original download site to ensure your use of the software is consistant
+with any copyright or license.
diff --git a/external/win32cpp/3rd Party Software/GridControl/DataGridTest.zip b/external/win32cpp/3rd Party Software/GridControl/DataGridTest.zip
new file mode 100644
index 0000000..cc1ce34
Binary files /dev/null and b/external/win32cpp/3rd Party Software/GridControl/DataGridTest.zip differ
diff --git a/external/win32cpp/3rd Party Software/GridControl/Sample/About.TXT b/external/win32cpp/3rd Party Software/GridControl/Sample/About.TXT
new file mode 100644
index 0000000..505509c
--- /dev/null
+++ b/external/win32cpp/3rd Party Software/GridControl/Sample/About.TXT
@@ -0,0 +1 @@
+This sample was kindly provided by Jianjun Wang.
\ No newline at end of file
diff --git a/external/win32cpp/3rd Party Software/GridControl/Sample/GridSample.zip b/external/win32cpp/3rd Party Software/GridControl/Sample/GridSample.zip
new file mode 100644
index 0000000..e627b1d
Binary files /dev/null and b/external/win32cpp/3rd Party Software/GridControl/Sample/GridSample.zip differ
diff --git a/external/win32cpp/About these folders.txt b/external/win32cpp/About these folders.txt
new file mode 100644
index 0000000..8c4ba4d
--- /dev/null
+++ b/external/win32cpp/About these folders.txt
@@ -0,0 +1,13 @@
+The contents of the folders within Win32++
+==========================================
+3rd Party Software Contains software devloped by other authors
+help Contains the documentation of Win32++.
+include Contains the set of files that make up the Win32++ library.
+new projects A set of projects to be used in your new projects.
+output A directory which contains the output of some tools.
+samples A set of sample projects that demonstrate the various features of Win32++.
+tools A set of useful batch files for Win32++.
+tutorials The code for the tutorials described in the Win32++ documentation.
+WCE samples A set of sample projects that demonstrate using Win32++ on WinCE.
+
+
diff --git a/external/win32cpp/WCE samples/Clean.bat b/external/win32cpp/WCE samples/Clean.bat
new file mode 100644
index 0000000..b6bda82
--- /dev/null
+++ b/external/win32cpp/WCE samples/Clean.bat
@@ -0,0 +1,30 @@
+
+::A batch file to remove unnecessary files from
+:: each Visual Studio project
+
+::Remove directories
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\emulatorDbg
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\emulatorRel
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\ARMV4Dbg
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\ARMV4Rel
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\X86Dbg
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\X86Rel
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\_UpgradeReport_Files
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\"Pocket PC 2003 (ARMV4)"
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\"Smartphone 2003 (ARMV4)"
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\"Windows Mobile 5.0 Pocket PC SDK (ARMV4I)"
+FOR /D %%f IN ("*.") DO RMDIR /S /Q %%f\"Windows Mobile 5.0 Smartphone SDK (ARMV4I)"
+
+::Remove files
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.vcb"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.vcl"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.vco"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.aps"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.XML"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.user"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.ncb"
+FOR /D %%f IN ("*.") DO DEL /Q %%f\"*.bak"
+FOR /D %%f IN ("*.") DO DEL /Q /AH %%f\"*.suo"
+
+
+
diff --git a/external/win32cpp/WCE samples/Dialog/Dialog.sln b/external/win32cpp/WCE samples/Dialog/Dialog.sln
new file mode 100644
index 0000000..39e752d
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/Dialog.sln
@@ -0,0 +1,30 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Dialog", "Dialog.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/Dialog/Dialog.vcp b/external/win32cpp/WCE samples/Dialog/Dialog.vcp
new file mode 100644
index 0000000..7a6fb8b
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/Dialog.vcp
@@ -0,0 +1,178 @@
+# Microsoft eMbedded Visual Tools Project File - Name="Dialog" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=Dialog - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Dialog.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Dialog.vcn" CFG="Dialog - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Dialog - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "Dialog - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Dialog - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "Dialog - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ENDIF
+
+# Begin Target
+
+# Name "Dialog - Win32 (WCE emulator) Release"
+# Name "Dialog - Win32 (WCE emulator) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\DialogApp.cpp
+DEP_CPP_DIALO=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\DialogApp.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+DEP_CPP_MAIN_=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\DialogApp.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.cpp
+DEP_CPP_MYDIA=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\DialogApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\star.ico
+# End Source File
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\include\Dialog.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/Dialog/Dialog.vcproj b/external/win32cpp/WCE samples/Dialog/Dialog.vcproj
new file mode 100644
index 0000000..1098856
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/Dialog.vcproj
@@ -0,0 +1,767 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/Dialog/Dialog.vcw b/external/win32cpp/WCE samples/Dialog/Dialog.vcw
new file mode 100644
index 0000000..3689b14
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/Dialog.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Dialog"=".\Dialog.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/Dialog/DialogApp.cpp b/external/win32cpp/WCE samples/Dialog/DialogApp.cpp
new file mode 100644
index 0000000..4b4e544
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/DialogApp.cpp
@@ -0,0 +1,27 @@
+/////////////////////////////////////////////////
+//App.cpp - Definitions for the CDialogApp class
+
+#include "dialog.h"
+#include "resource.h"
+#include "DialogApp.h"
+
+
+CDialogApp::CDialogApp() : MyDialog(IDD_DIALOG)
+{
+}
+
+BOOL CDialogApp::InitInstance()
+{
+ //Display the Modal Dialog
+ MyDialog.DoModal();
+
+ //End the program
+ ::PostQuitMessage(0);
+
+ return TRUE;
+}
+
+CDialogApp::~CDialogApp()
+{
+}
+
diff --git a/external/win32cpp/WCE samples/Dialog/DialogApp.h b/external/win32cpp/WCE samples/Dialog/DialogApp.h
new file mode 100644
index 0000000..d30dce2
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/DialogApp.h
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////
+// DialogApp.h
+// Declaration of the CDialogApp class
+
+#ifndef DIALOGAPP_H
+#define DIALOGAPP_H
+
+
+#include "dialog.h"
+#include "MyDialog.h"
+
+
+class CDialogApp : public CWinApp
+{
+public:
+ CDialogApp();
+ virtual ~CDialogApp();
+ virtual BOOL InitInstance();
+ CMyDialog& GetDialog() { return MyDialog; }
+
+private:
+ CMyDialog MyDialog;
+};
+
+
+// returns a reference to the CDialogApp object
+inline CDialogApp& GetDlgApp() { return *((CDialogApp*)GetApp()); }
+
+
+#endif // define DIALOGAPP_H
+
diff --git a/external/win32cpp/WCE samples/Dialog/MyDialog.cpp b/external/win32cpp/WCE samples/Dialog/MyDialog.cpp
new file mode 100644
index 0000000..6072d60
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/MyDialog.cpp
@@ -0,0 +1,49 @@
+
+#include "MyDialog.h"
+#include "resource.h"
+
+
+
+CMyDialog::CMyDialog(UINT nResID, CWnd* pParent)
+ : CDialog(nResID, pParent)
+{
+}
+
+CMyDialog::~CMyDialog()
+{
+}
+
+
+BOOL CMyDialog::OnInitDialog()
+{
+ // This function is called before the dialog is displayed.
+
+
+ //Set the Icon
+ SetIconLarge(IDW_MAIN);
+ SetIconSmall(IDW_MAIN);
+
+ return true;
+}
+
+void CMyDialog::OnOK()
+{
+ ::MessageBox(NULL, TEXT("DONE Button Pressed. Program will exit now."), TEXT("Button"), MB_OK);
+ CDialog::OnOK();
+}
+
+INT_PTR CMyDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+// Add any messages to be handled inside the switch statement
+
+
+// switch (uMsg)
+// {
+//
+// } // switch(uMsg)
+
+ return DialogProcDefault(uMsg, wParam, lParam);
+
+} // INT_PTR CALLBACK DialogProc(...)
+
+
diff --git a/external/win32cpp/WCE samples/Dialog/MyDialog.h b/external/win32cpp/WCE samples/Dialog/MyDialog.h
new file mode 100644
index 0000000..0b2cb79
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/MyDialog.h
@@ -0,0 +1,23 @@
+#ifndef MYDIALOG_H
+#define MYDIALOG_H
+
+
+#include "dialog.h"
+#include "resource.h"
+
+
+class CMyDialog : public CDialog
+{
+public:
+ CMyDialog(UINT nResID, CWnd* pParent = NULL);
+ virtual ~CMyDialog();
+
+
+protected:
+ virtual BOOL OnInitDialog();
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnOK();
+
+};
+
+#endif //MYDIALOG_H
diff --git a/external/win32cpp/WCE samples/Dialog/main.cpp b/external/win32cpp/WCE samples/Dialog/main.cpp
new file mode 100644
index 0000000..8e086b7
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/main.cpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "DialogApp.h"
+
+
+INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int iCmdShow)
+{
+ TCHAR szBuf[MAX_STRING_SIZE];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, MAX_STRING_SIZE -1);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ // The one and only CDialogApp object
+ CDialogApp theApp;
+
+ //Process the window messages
+ return theApp.Run();
+}
+
diff --git a/external/win32cpp/WCE samples/Dialog/res/star.ico b/external/win32cpp/WCE samples/Dialog/res/star.ico
new file mode 100644
index 0000000..4de93a1
Binary files /dev/null and b/external/win32cpp/WCE samples/Dialog/res/star.ico differ
diff --git a/external/win32cpp/WCE samples/Dialog/resource.h b/external/win32cpp/WCE samples/Dialog/resource.h
new file mode 100644
index 0000000..ff8ebed
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/resource.h
@@ -0,0 +1,9 @@
+//This file contains the resource ID definitions.
+
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+
+//Resource IDs for the dialog
+#define IDD_DIALOG 100
diff --git a/external/win32cpp/WCE samples/Dialog/resource.rc b/external/win32cpp/WCE samples/Dialog/resource.rc
new file mode 100644
index 0000000..9c33bcf
--- /dev/null
+++ b/external/win32cpp/WCE samples/Dialog/resource.rc
@@ -0,0 +1,41 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+#include "windows.h"
+#include "commctrl.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON DISCARDABLE "res\\star.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG DIALOG DISCARDABLE 0, 0, 160, 180
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE
+FONT 8, "Tahoma"
+BEGIN
+ PUSHBUTTON "Done",IDOK,54,118,50,14
+ CTEXT "Dialog Application",IDC_STATIC,33,63,90,13
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "Dialog Application"
+END
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogApp.cpp b/external/win32cpp/WCE samples/DialogDemo/DialogApp.cpp
new file mode 100644
index 0000000..700be65
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogApp.cpp
@@ -0,0 +1,27 @@
+/////////////////////////////////////////////////
+//App.cpp - Definitions for the CDialogApp class
+
+#include "dialog.h"
+#include "resource.h"
+#include "DialogApp.h"
+
+
+CDialogApp::CDialogApp() : MyDialog(IDD_COMCTLS)
+{
+}
+
+BOOL CDialogApp::InitInstance()
+{
+ //Display the Modal Dialog
+ MyDialog.DoModal();
+
+ //End the program
+ ::PostQuitMessage(0);
+
+ return TRUE;
+}
+
+CDialogApp::~CDialogApp()
+{
+}
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogApp.h b/external/win32cpp/WCE samples/DialogDemo/DialogApp.h
new file mode 100644
index 0000000..f2929a0
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogApp.h
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////
+// DialogApp.h
+// Declaration of the CDialogApp class
+
+#ifndef DIALOGAPP_H
+#define DIALOGAPP_H
+
+
+#include "dialog.h"
+#include "MyDialog.h"
+
+
+class CDialogApp : public CWinApp
+{
+public:
+ CDialogApp();
+ virtual ~CDialogApp();
+ virtual BOOL InitInstance();
+ CMyDialog& GetDlg() { return MyDialog; }
+
+private:
+ CMyDialog MyDialog;
+};
+
+
+// returns a reference to the CDialogApp object
+inline CDialogApp& GetDlgApp() { return *((CDialogApp*)GetApp()); }
+
+
+#endif // define DIALOGAPP_H
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogDemo.sln b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.sln
new file mode 100644
index 0000000..36b9197
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DialogDemo", "DialogDemo.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcp b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcp
new file mode 100644
index 0000000..483fc82
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcp
@@ -0,0 +1,193 @@
+# Microsoft eMbedded Visual Tools Project File - Name="DialogDemo" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=DialogDemo - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "DialogDemo.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "DialogDemo.vcn" CFG="DialogDemo - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "DialogDemo - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "DialogDemo - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "DialogDemo - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "DialogDemo - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ENDIF
+
+# Begin Target
+
+# Name "DialogDemo - Win32 (WCE emulator) Release"
+# Name "DialogDemo - Win32 (WCE emulator) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\DialogApp.cpp
+DEP_CPP_DIALO=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\dialog.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\DialogApp.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_DIALO=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+DEP_CPP_MAIN_=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\dialog.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\DialogApp.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.cpp
+DEP_CPP_MYDIA=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\dialog.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_MYDIA=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\DialogApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\star.ico
+# End Source File
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\include\DialogDemo.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcproj b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcproj
new file mode 100644
index 0000000..abef3fe
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcproj
@@ -0,0 +1,747 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcw b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcw
new file mode 100644
index 0000000..12308bf
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/DialogDemo.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "DialogDemo"=".\DialogDemo.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/MyDialog.cpp b/external/win32cpp/WCE samples/DialogDemo/MyDialog.cpp
new file mode 100644
index 0000000..e0e0178
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/MyDialog.cpp
@@ -0,0 +1,149 @@
+
+#include "MyDialog.h"
+#include "resource.h"
+#include "windowsx.h"
+
+
+CMyDialog::CMyDialog(UINT nResID, CWnd* pParent)
+ : CDialog(nResID, pParent), m_nCounter(0)
+{
+}
+
+CMyDialog::~CMyDialog()
+{
+}
+
+void CMyDialog::AddToButton()
+{
+ //get the control window
+ HWND hwButton = ::GetDlgItem(m_hWnd, IDC_BUTTON1);
+
+ //set text to show in control
+ TCHAR szBufW[16];
+ wsprintf(szBufW, L"Button %d", m_nCounter);
+ ::Button_SetText(hwButton, szBufW);
+ return;
+}
+
+void CMyDialog::AddToComboBox()
+{
+ //get the control window
+ HWND hwComboBox = ::GetDlgItem(m_hWnd, IDC_COMBO1);
+
+ //set text to show in control
+ TCHAR szBufW[16];
+ wsprintf(szBufW, L"ComboBox %d", m_nCounter);
+ if (m_nCounter)
+ {
+ ComboBox_AddString(hwComboBox, szBufW);
+ ::ComboBox_SetText(hwComboBox, szBufW);
+ ComboBox_SetCurSel(hwComboBox, m_nCounter-1);
+ }
+ else
+ {
+ ComboBox_ResetContent(hwComboBox);
+ ComboBox_ShowDropdown(hwComboBox, FALSE);
+ }
+}
+
+void CMyDialog::AddToEdit()
+{
+ //get the control window
+ HWND hwEdit = ::GetDlgItem(m_hWnd, IDC_EDIT1 );
+
+ //set text to show in control
+ TCHAR szBufW[16];
+ wsprintf(szBufW, L"Edit %d\r\n", m_nCounter);
+ if (m_nCounter)
+ Edit_ReplaceSel(hwEdit, szBufW);
+ else
+ ::SetWindowText(hwEdit, L"");
+}
+
+void CMyDialog::AddToListBox()
+{
+ //get the control window
+ HWND hwListBox = ::GetDlgItem(m_hWnd, IDC_LIST1 );
+
+ //set text to show in control
+ TCHAR szBufW[16];
+ wsprintf(szBufW, L"ListBox %d", m_nCounter);
+ if (m_nCounter)
+ ListBox_AddString(hwListBox, szBufW);
+ else
+ ListBox_ResetContent(hwListBox);
+}
+
+void CMyDialog::AddToProgressBar()
+{
+ //get the control window
+ HWND hwProgressBar = ::GetDlgItem(m_hWnd, IDC_PROGRESS1);
+
+ //set progress bar position
+ SendMessage(hwProgressBar, PBM_SETPOS, (WPARAM)m_nCounter * 10, 0L);
+}
+
+void CMyDialog::AddToScrollBars()
+{
+ //get the control window
+ HWND hwScrollBarH = ::GetDlgItem(m_hWnd, IDC_SCROLLBAR1);
+ HWND hwScrollBarV = ::GetDlgItem(m_hWnd, IDC_SCROLLBAR2);
+
+ //set scroll bar range
+ ScrollBar_SetRange(hwScrollBarH, 0, 10, FALSE);
+ ScrollBar_SetRange(hwScrollBarV, 0, 10, FALSE);
+
+ //set scroll bar position
+ ScrollBar_SetPos(hwScrollBarH, m_nCounter, TRUE);
+ ScrollBar_SetPos(hwScrollBarV, m_nCounter, TRUE);
+}
+
+void CMyDialog::AddToSlider()
+{
+ //get the control window
+ HWND hwSlider = ::GetDlgItem(m_hWnd, IDC_SLIDER1);
+
+ //set slider position
+ SendMessage(hwSlider, TBM_SETPOS, TRUE, (WPARAM)m_nCounter * 10);
+}
+
+BOOL CMyDialog::OnInitDialog()
+{
+ //Set the Icon
+ SetIconLarge(IDW_MAIN);
+ SetIconSmall(IDW_MAIN);
+
+ // Set a timer to animate the controls on the dialog window
+ SetTimer(ID_TIMER, 500, NULL);
+
+ return true;
+}
+
+void CMyDialog::OnOK()
+{
+ ::MessageBox(NULL, TEXT("DONE Button Pressed. Program will exit now."), TEXT("Button"), MB_OK);
+ CDialog::OnOK();
+}
+
+INT_PTR CMyDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_TIMER:
+ m_nCounter > 9 ? m_nCounter = 0 : m_nCounter++;
+ AddToEdit();
+ AddToListBox();
+ AddToScrollBars();
+ AddToProgressBar();
+ AddToSlider();
+ AddToComboBox();
+ AddToButton();
+ break;
+
+ } // switch(uMsg)
+
+ return DialogProcDefault(uMsg, wParam, lParam);
+
+} // INT_PTR CALLBACK DialogProc(...)
+
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/MyDialog.h b/external/win32cpp/WCE samples/DialogDemo/MyDialog.h
new file mode 100644
index 0000000..73bc34c
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/MyDialog.h
@@ -0,0 +1,30 @@
+#ifndef MYDIALOG_H
+#define MYDIALOG_H
+
+
+#include "dialog.h"
+#include "resource.h"
+
+
+class CMyDialog : public CDialog
+{
+public:
+ CMyDialog(UINT nResID, CWnd* pParent = NULL);
+ virtual ~CMyDialog();
+ void AddToEdit();
+ void AddToListBox();
+ void AddToProgressBar();
+ void AddToScrollBars();
+ void AddToSlider();
+ void AddToComboBox();
+ void AddToButton();
+
+private:
+ virtual BOOL OnInitDialog();
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnOK();
+
+ int m_nCounter;
+};
+
+#endif //MYDIALOG_H
diff --git a/external/win32cpp/WCE samples/DialogDemo/main.cpp b/external/win32cpp/WCE samples/DialogDemo/main.cpp
new file mode 100644
index 0000000..8e086b7
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/main.cpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "DialogApp.h"
+
+
+INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int iCmdShow)
+{
+ TCHAR szBuf[MAX_STRING_SIZE];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, MAX_STRING_SIZE -1);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ // The one and only CDialogApp object
+ CDialogApp theApp;
+
+ //Process the window messages
+ return theApp.Run();
+}
+
diff --git a/external/win32cpp/WCE samples/DialogDemo/res/star.ico b/external/win32cpp/WCE samples/DialogDemo/res/star.ico
new file mode 100644
index 0000000..4de93a1
Binary files /dev/null and b/external/win32cpp/WCE samples/DialogDemo/res/star.ico differ
diff --git a/external/win32cpp/WCE samples/DialogDemo/resource.h b/external/win32cpp/WCE samples/DialogDemo/resource.h
new file mode 100644
index 0000000..41cc211
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/resource.h
@@ -0,0 +1,20 @@
+//This file contains the resource ID definitions.
+
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+
+//Resource IDs for the dialog
+#define IDD_COMCTLS 100
+#define IDC_EDIT1 101
+#define IDC_BUTTON1 102
+#define IDC_COMBO1 103
+#define IDC_LIST1 104
+#define IDC_SCROLLBAR1 105
+#define IDC_SCROLLBAR2 106
+#define IDC_SPIN1 107
+#define IDC_SLIDER1 108
+#define IDC_PROGRESS1 109
+
+#define ID_TIMER 120
diff --git a/external/win32cpp/WCE samples/DialogDemo/resource.rc b/external/win32cpp/WCE samples/DialogDemo/resource.rc
new file mode 100644
index 0000000..2cc83e2
--- /dev/null
+++ b/external/win32cpp/WCE samples/DialogDemo/resource.rc
@@ -0,0 +1,62 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+#include "windows.h"
+#include "commctrl.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON DISCARDABLE "res\\star.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_COMCTLS DIALOG DISCARDABLE 0, 0, 160, 180
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE
+FONT 8, "Tahoma"
+BEGIN
+ LTEXT "Static Text",IDC_STATIC,2,2,48,8
+ CTEXT "Boxed Static Text",IDC_STATIC,56,2,66,12,WS_BORDER
+ EDITTEXT IDC_EDIT1,4,22,58,54,ES_MULTILINE | ES_AUTOVSCROLL |
+ ES_WANTRETURN | WS_VSCROLL
+ PUSHBUTTON "Button1",IDC_BUTTON1,66,22,46,14
+ COMBOBOX IDC_COMBO1,66,52,64,53,CBS_DROPDOWN | CBS_SORT |
+ CBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ LISTBOX IDC_LIST1,4,88,58,42,LBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Edit",IDC_STATIC,2,12,48,8
+ LTEXT "Combo box",IDC_STATIC,66,40,48,11
+ LTEXT "List box",IDC_STATIC,2,78,48,8
+ SCROLLBAR IDC_SCROLLBAR1,138,46,10,56,SBS_VERT
+ SCROLLBAR IDC_SCROLLBAR2,66,108,86,8
+ CONTROL "Spin1",IDC_SPIN1,"msctls_updown32",UDS_ARROWKEYS,140,2,
+ 11,18
+ CONTROL "Slider1",IDC_SLIDER1,"msctls_trackbar32",TBS_BOTH |
+ WS_TABSTOP,78,134,72,26
+ CONTROL "Progress1",IDC_PROGRESS1,"msctls_progress32",WS_BORDER,
+ 2,140,72,12
+ LTEXT "Slider",IDC_STATIC,78,124,48,8
+ LTEXT "Progress Bar",IDC_STATIC,4,132,48,8
+ LTEXT "Vert and Horz Scrollbars",IDC_STATIC,80,82,48,20
+ PUSHBUTTON "Done",IDOK,54,162,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "Dialog Application"
+END
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/Button.cpp b/external/win32cpp/WCE samples/DlgSubclass/Button.cpp
new file mode 100644
index 0000000..f7bf997
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/Button.cpp
@@ -0,0 +1,36 @@
+/////////////////////////////
+// Button.cpp
+
+#include "DlgSubclassApp.h"
+#include "Button.h"
+
+LRESULT CButton::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ CMyDialog& dialog = ((CDlgSubclassApp*) GetApp())->GetDialog();
+ switch (uMsg)
+ {
+ case WM_MOUSEMOVE:
+ TRACE(TEXT("CButton::WndProc - WM_MOUSEMOVE Message\n"));
+ dialog.SetStatic(TEXT("WM_MOUSEMOVE"));
+ break;
+ case WM_SETCURSOR:
+ TRACE(TEXT("CButton::WndProc - WM_SETCURSOR Message\n"));
+ dialog.SetStatic(TEXT("WM_SETCURSOR"));
+ break;
+ case WM_LBUTTONDOWN:
+ TRACE(TEXT("CButton::WndProc - WM_LBUTTONDOWN Message\n"));
+ dialog.SetStatic(TEXT("WM_LBUTTONDOWN"));
+ break;
+ case WM_LBUTTONUP:
+ TRACE(TEXT("CButton::WndProc - WM_LBUTTONUP Message\n"));
+ dialog.SetStatic(TEXT("WM_LBUTTONUP"));
+ break;
+
+ default:
+ TRACE(TEXT("CButton::WndProc - Unspecified Message\n"));
+ break;
+ }
+
+ // Pass unhandled messages on for default processing
+ return WndProcDefault(uMsg, wParam, lParam);
+}
diff --git a/external/win32cpp/WCE samples/DlgSubclass/Button.h b/external/win32cpp/WCE samples/DlgSubclass/Button.h
new file mode 100644
index 0000000..694957d
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/Button.h
@@ -0,0 +1,26 @@
+/////////////////////////////
+// Button.h
+
+
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#include "wincore.h"
+
+
+class CButton : public CWnd
+{
+public:
+ CButton() {}
+ virtual ~CButton() {}
+
+protected:
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+};
+
+
+
+#endif //BUTTON_H
+
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.sln b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.sln
new file mode 100644
index 0000000..5d998df
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DlgSubclass", "DlgSubclass.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcp b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcp
new file mode 100644
index 0000000..28739d1
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcp
@@ -0,0 +1,536 @@
+# Microsoft eMbedded Visual Tools Project File - Name="DlgSubclass" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=DlgSubclass - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "DlgSubclass.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "DlgSubclass.vcn" CFG="DlgSubclass - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "DlgSubclass - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "DlgSubclass - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "DlgSubclass - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "DlgSubclass - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Gs8192 /F0x0 /GF /O2 /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Gs8192 /GF /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 $(CEx86Corelibc) commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ARMV4Rel"
+# PROP BASE Intermediate_Dir "ARMV4Rel"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ARMV4Rel"
+# PROP Intermediate_Dir "ARMV4Rel"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /O2 /M$(CECrtMT) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ARMV4Dbg"
+# PROP BASE Intermediate_Dir "ARMV4Dbg"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "ARMV4Dbg"
+# PROP Intermediate_Dir "ARMV4Dbg"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /M$(CECrtMTDebug) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ENDIF
+
+# Begin Target
+
+# Name "DlgSubclass - Win32 (WCE emulator) Release"
+# Name "DlgSubclass - Win32 (WCE emulator) Debug"
+# Name "DlgSubclass - Win32 (WCE ARMV4) Release"
+# Name "DlgSubclass - Win32 (WCE ARMV4) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Button.cpp
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+DEP_CPP_BUTTO=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_BUTTO=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+DEP_CPP_BUTTO=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_BUTTO=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_BUTTO=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_BUTTO=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\DlgSubclassApp.cpp
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+DEP_CPP_DLGSU=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_DLGSU=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+DEP_CPP_DLGSU=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_DLGSU=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_DLGSU=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_DLGSU=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Hyperlink.cpp
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+DEP_CPP_HYPER=\
+ ".\Hyperlink.h"\
+
+NODEP_CPP_HYPER=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+DEP_CPP_HYPER=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\WinCore.h"\
+ ".\Hyperlink.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_HYPER=\
+ ".\Hyperlink.h"\
+
+NODEP_CPP_HYPER=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_HYPER=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\WinCore.h"\
+ ".\Hyperlink.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+DEP_CPP_MAIN_=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MAIN_=\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\DlgSubclassApp.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.cpp
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+DEP_CPP_MYDIA=\
+ ".\Button.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_MYDIA=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MYDIA=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MYDIA=\
+ ".\Button.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+NODEP_CPP_MYDIA=\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\WinCore.h"\
+
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MYDIA=\
+ "..\..\include\Default_Resource.h"\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\Hyperlink.h"\
+ ".\MyDialog.h"\
+ ".\resource.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.rc
+
+!IF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Release"
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE emulator) Debug"
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Release"
+
+!ELSEIF "$(CFG)" == "DlgSubclass - Win32 (WCE ARMV4) Debug"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Button.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DlgSubclassApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Hyperlink.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MyDialog.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\res\Dialog.ico
+# End Source File
+# Begin Source File
+
+SOURCE=".\res\Win32++.manifest"
+# End Source File
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\include\Default_Resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\Dialog.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcproj b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcproj
new file mode 100644
index 0000000..eead477
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcproj
@@ -0,0 +1,763 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcw b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcw
new file mode 100644
index 0000000..41560cf
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclass.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "DlgSubclass"=".\DlgSubclass.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.cpp b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.cpp
new file mode 100644
index 0000000..b1fae5f
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.cpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////
+// DlgSubclassApp.cpp
+
+#include "resource.h"
+#include "DlgSubclassApp.h"
+
+
+// Definitions for the CDialogApp class
+CDlgSubclassApp::CDlgSubclassApp() : m_MyDialog(IDD_DIALOG1)
+{
+}
+
+BOOL CDlgSubclassApp::InitInstance()
+{
+ //Display the Modal Dialog
+ m_MyDialog.DoModal();
+
+ //End the program
+ ::PostQuitMessage(0);
+
+ return TRUE;
+}
+
+CDlgSubclassApp::~CDlgSubclassApp()
+{
+}
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.h b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.h
new file mode 100644
index 0000000..d435526
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/DlgSubclassApp.h
@@ -0,0 +1,29 @@
+///////////////////////////////////////
+// DlgSubclassApp.h
+
+#ifndef DLGSUBCLASSAPP_H
+#define DLGSUBCLASSAPP_H
+
+#include "MyDialog.h"
+
+
+// Declaration of the CDialogApp class
+class CDlgSubclassApp : public CWinApp
+{
+public:
+ CDlgSubclassApp();
+ virtual ~CDlgSubclassApp();
+ virtual BOOL InitInstance();
+ CMyDialog& GetDialog() {return m_MyDialog;}
+
+private:
+ CMyDialog m_MyDialog;
+};
+
+
+// returns a reference to the CDlgSubclassApp object
+inline CDlgSubclassApp& GetSubApp() { return *((CDlgSubclassApp*)GetApp()); }
+
+
+#endif // define DLGSUBCLASSAPP_H
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.cpp b/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.cpp
new file mode 100644
index 0000000..39e6a0e
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.cpp
@@ -0,0 +1,116 @@
+/////////////////////////////
+// Hyperlink.cpp
+
+#include "Hyperlink.h"
+
+CHyperlink::CHyperlink() : m_bUrlVisited(FALSE), m_bClicked(FALSE), m_crVisited(RGB(128, 0, 128)),
+ m_crNotVisited(RGB(0,0,255)), m_hUrlFont(NULL)
+{
+ // Create the cursor
+ m_hCursor = ::LoadCursor(NULL, IDC_HAND);
+
+ // IDC_HAND is not available on Win95, so load a reasonable alternative
+ if( !m_hCursor )
+ m_hCursor = ::LoadCursor(NULL, IDC_ARROW);
+}
+
+CHyperlink::~CHyperlink()
+{
+ if (m_hUrlFont) ::DeleteObject(m_hUrlFont);
+}
+
+BOOL CHyperlink::AttachDlgItem(UINT nID, CWnd* pParent)
+{
+ BOOL bSuccess = CWnd::AttachDlgItem(nID, pParent);;
+
+ LOGFONT lf;
+ m_hUrlFont = (HFONT)::SendMessage( m_hWnd, WM_GETFONT, 0L, 0L);
+ ::GetObject(m_hUrlFont, sizeof(LOGFONT), &lf);
+ lf.lfUnderline = TRUE;
+ m_hUrlFont = ::CreateFontIndirect(&lf);
+
+ return bSuccess;
+}
+
+void CHyperlink::OnLButtonDown()
+{
+ SetCapture();
+ m_bClicked = TRUE;
+}
+
+void CHyperlink::OnLButtonUp(LPARAM lParam)
+{
+ ReleaseCapture();
+ if(m_bClicked)
+ {
+ m_bClicked = FALSE;
+ POINT pt;
+ RECT rc;
+ pt.x = (short)LOWORD(lParam);
+ pt.y = (short)HIWORD(lParam);
+ ::ClientToScreen(m_hWnd, &pt);
+ ::GetWindowRect(m_hWnd, &rc);
+
+ if(PtInRect(&rc, pt))
+ OpenUrl();
+ }
+}
+
+void CHyperlink::OpenUrl()
+{
+ SHELLEXECUTEINFO ExecInfo = {0};;
+ ExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+ ExecInfo.lpVerb = TEXT("open");
+ ExecInfo.lpFile = TEXT("iexplore.exe");
+ ExecInfo.lpParameters = GetWindowText();
+
+ if (ShellExecuteEx(&ExecInfo))
+
+ {
+ m_bUrlVisited = TRUE;
+
+ // redraw the window to update the color
+ Invalidate();
+ }
+ else
+ TRACE(_T("ShellExecuteEx Failed"));
+}
+
+LRESULT CHyperlink::OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ // Messages such as WM_CTLCOLORSTATIC are reflected back to the CWnd object that created them.
+ if (uMsg == WM_CTLCOLORSTATIC)
+ {
+ HDC hDC = (HDC)wParam;
+
+ ::SetTextColor(hDC, m_bUrlVisited? m_crVisited : m_crNotVisited);
+ ::SetBkMode(hDC, TRANSPARENT);
+ ::SelectObject(hDC, m_hUrlFont);
+ return (LRESULT)::GetSysColorBrush(COLOR_BTNFACE);
+ }
+ return 0L;
+}
+
+LRESULT CHyperlink::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_LBUTTONDOWN:
+ OnLButtonDown();
+ break;
+
+ case WM_LBUTTONUP:
+ OnLButtonUp(lParam);
+ break;
+
+ case WM_SETCURSOR:
+ ::SetCursor(m_hCursor);
+ return 1L;
+
+ }
+
+ // Pass unhandled messages on for default processing
+ return WndProcDefault( uMsg, wParam, lParam );
+}
+
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.h b/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.h
new file mode 100644
index 0000000..8b94a0e
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/Hyperlink.h
@@ -0,0 +1,37 @@
+/////////////////////////////
+// Hyperlink.h
+
+#ifndef HYPERLINK_H
+#define HYPERLINK_H
+
+#include "wincore.h"
+
+#ifndef IDC_HAND
+#define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+class CHyperlink : public CWnd
+{
+public:
+ CHyperlink();
+ virtual ~CHyperlink();
+ virtual BOOL AttachDlgItem(UINT nID, CWnd* pParent);
+ void OnLButtonDown();
+ void OnLButtonUp(LPARAM lParam);
+
+protected:
+ virtual void OpenUrl();
+ virtual LRESULT OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+private:
+ BOOL m_bUrlVisited;
+ BOOL m_bClicked;
+ COLORREF m_crVisited;
+ COLORREF m_crNotVisited;
+ HCURSOR m_hCursor;
+ HFONT m_hUrlFont;
+};
+
+#endif // HYPERLINK_H
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/MyDialog.cpp b/external/win32cpp/WCE samples/DlgSubclass/MyDialog.cpp
new file mode 100644
index 0000000..bea498c
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/MyDialog.cpp
@@ -0,0 +1,76 @@
+///////////////////////////////////////
+// MyDialog.cpp
+
+#include "MyDialog.h"
+#include "Hyperlink.h"
+#include "resource.h"
+
+
+// Definitions for the CMyDialog class
+CMyDialog::CMyDialog(UINT nResID, CWnd* pParent)
+ : CDialog(nResID, pParent)
+{
+}
+
+CMyDialog::CMyDialog(LPCTSTR lpszResName, CWnd* pParent)
+ : CDialog(lpszResName, pParent)
+{
+}
+
+CMyDialog::~CMyDialog()
+{
+}
+
+INT_PTR CMyDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+// switch (uMsg)
+// {
+ //Additional messages to be handled go here
+// }
+
+
+ //Use the dialogframe default message handling for remaining messages
+ return DialogProcDefault(uMsg, wParam, lParam);
+}
+
+BOOL CMyDialog::OnCommand(UINT nID)
+{
+// switch (nID)
+// {
+
+// } //switch (nID)
+
+ return TRUE;
+}
+
+BOOL CMyDialog::OnInitDialog()
+{
+ // Set the Icon
+ SetIconLarge(IDW_MAIN);
+ SetIconSmall(IDW_MAIN);
+
+ // Put some text in the edit boxes
+ ::SetDlgItemText(GetHwnd(), IDC_EDIT1, TEXT("Edit Control"));
+
+ // Turn our button into a MyButton object
+ m_Button.AttachDlgItem(IDC_BUTTON2, this);
+
+ // Turn our static control into a hyperlink
+ m_Hyperlink.AttachDlgItem(IDC_STATIC4, this);
+
+ return true;
+}
+
+void CMyDialog::OnOK()
+{
+ ::MessageBox(NULL, TEXT("OK Button Pressed. Program will exit now."), TEXT("Button"), MB_OK);
+ CDialog::OnOK();
+}
+
+
+
+void CMyDialog::SetStatic(LPCTSTR szString)
+{
+ ::SetDlgItemText(GetHwnd(), IDC_EDIT1, szString);
+}
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/MyDialog.h b/external/win32cpp/WCE samples/DlgSubclass/MyDialog.h
new file mode 100644
index 0000000..ced6a4f
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/MyDialog.h
@@ -0,0 +1,33 @@
+///////////////////////////////////////
+// MyDialog.h
+
+#ifndef MYDIALOG_H
+#define MYDIALOG_H
+
+#include "dialog.h"
+#include "resource.h"
+#include "Button.h"
+#include "Hyperlink.h"
+
+
+// Declaration of the CMyDialog class
+class CMyDialog : public CDialog
+{
+public:
+ CMyDialog(UINT nResID, CWnd* pParent = NULL);
+ CMyDialog(LPCTSTR lpszResName, CWnd* pParent = NULL);
+ void SetStatic(LPCTSTR szString);
+ virtual ~CMyDialog();
+
+protected:
+ virtual BOOL OnInitDialog();
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual BOOL OnCommand(UINT nID);
+ virtual void OnOK();
+
+private:
+ CButton m_Button;
+ CHyperlink m_Hyperlink;
+};
+
+#endif //MYDIALOG_H
diff --git a/external/win32cpp/WCE samples/DlgSubclass/main.cpp b/external/win32cpp/WCE samples/DlgSubclass/main.cpp
new file mode 100644
index 0000000..2f2bcc6
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/main.cpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "DlgSubclassApp.h"
+
+
+INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
+{
+ TCHAR szBuf[MAX_STRING_SIZE];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, MAX_STRING_SIZE -1);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ // Start Win32++
+ CDlgSubclassApp theApp;
+
+ // Process the window messages
+ return theApp.Run();
+}
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/res/Dialog.ico b/external/win32cpp/WCE samples/DlgSubclass/res/Dialog.ico
new file mode 100644
index 0000000..e1cb5c1
Binary files /dev/null and b/external/win32cpp/WCE samples/DlgSubclass/res/Dialog.ico differ
diff --git a/external/win32cpp/WCE samples/DlgSubclass/res/Toolbar.bmp b/external/win32cpp/WCE samples/DlgSubclass/res/Toolbar.bmp
new file mode 100644
index 0000000..ca1824c
Binary files /dev/null and b/external/win32cpp/WCE samples/DlgSubclass/res/Toolbar.bmp differ
diff --git a/external/win32cpp/WCE samples/DlgSubclass/res/Zapotec.bmp b/external/win32cpp/WCE samples/DlgSubclass/res/Zapotec.bmp
new file mode 100644
index 0000000..9c5f34e
Binary files /dev/null and b/external/win32cpp/WCE samples/DlgSubclass/res/Zapotec.bmp differ
diff --git a/external/win32cpp/WCE samples/DlgSubclass/resource.h b/external/win32cpp/WCE samples/DlgSubclass/resource.h
new file mode 100644
index 0000000..41c8559
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/resource.h
@@ -0,0 +1,29 @@
+///////////////////////////////////////////////////
+// resource.h
+// This file contains the resource ID definitions.
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+//Resource IDs for the dialog
+#define IDD_DIALOG1 101
+#define IDC_RADIO1 110
+#define IDC_RADIO2 111
+#define IDC_RADIO3 112
+#define IDC_CHECK1 113
+#define IDC_CHECK2 114
+#define IDC_CHECK3 115
+#define IDC_EDIT1 120
+#define IDC_LIST1 121
+#define IDC_BUTTON1 122
+#define IDC_BUTTON2 123
+#define IDC_RICHEDIT1 124
+#define IDC_STATIC1 130
+#define IDC_STATIC2 131
+#define IDC_STATIC3 132
+#define IDC_STATIC4 133
+#define IDC_HOTKEY1 140
+#define IDB_BITMAP1 150
+
+
+
diff --git a/external/win32cpp/WCE samples/DlgSubclass/resource.rc b/external/win32cpp/WCE samples/DlgSubclass/resource.rc
new file mode 100644
index 0000000..9be7e79
--- /dev/null
+++ b/external/win32cpp/WCE samples/DlgSubclass/resource.rc
@@ -0,0 +1,40 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "windows.h"
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+ID_MAIN ICON DISCARDABLE "res\\Dialog.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+ID_MAIN BITMAP MOVEABLE PURE "res\\toolbar.bmp"
+IDB_BITMAP1 BITMAP MOVEABLE PURE "res\\Zapotec.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 160, 166
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
+CAPTION "Hyperlink and Subclassed Button"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,52,111,50,16
+ PUSHBUTTON "Subclassed Button",IDC_BUTTON2,39,9,81,45
+ LTEXT "https://sourceforge.net/projects/win32-framework",IDC_STATIC4,
+ 11,149,136,11
+ EDITTEXT IDC_EDIT1,21,73,114,15,ES_AUTOHSCROLL
+END
+
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.cpp b/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.cpp
new file mode 100644
index 0000000..c701666
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.cpp
@@ -0,0 +1,13 @@
+#include "FrameApp.h"
+
+CWceFrameApp::CWceFrameApp()
+{
+}
+
+BOOL CWceFrameApp::InitInstance()
+{
+ //Create the Window
+ m_Frame.Create();
+
+ return TRUE;
+}
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.h b/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.h
new file mode 100644
index 0000000..0bc525d
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/FrameApp.h
@@ -0,0 +1,26 @@
+#ifndef SIMPLEAPP_H
+#define SIMPLEAPP_H
+
+#include "wincore.h"
+#include "MainFrm.h"
+
+
+class CWceFrameApp : public CWinApp
+{
+public:
+ CWceFrameApp();
+ virtual ~CWceFrameApp() {}
+ virtual BOOL InitInstance();
+ CMainFrame& GetMainFrame() { return m_Frame; }
+
+private:
+ CMainFrame m_Frame;
+};
+
+
+// returns a reference to the CWceFrameApp object
+inline CWceFrameApp& GetFrameApp() { return *((CWceFrameApp*)GetApp()); }
+
+
+#endif //SIMPLEAPP_H
+
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.cpp b/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.cpp
new file mode 100644
index 0000000..4a74ebf
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.cpp
@@ -0,0 +1,86 @@
+#include "MainFrm.h"
+#include "resource.h"
+
+
+CMainFrame::CMainFrame()
+{
+ // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_BOLD );
+ AddToolBarButton( IDM_ITALIC);
+ AddToolBarButton( IDM_UNDERLINE);
+}
+
+CMainFrame::~CMainFrame()
+{
+}
+
+BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam)
+{
+ // Respond to menu and toolbar selections
+ switch (LOWORD(wParam))
+ {
+ // Respond to menu items
+ case IDM_EDIT_CUT:
+ TRACE(TEXT("Cut ... Menu item\n"));
+ return TRUE;
+ case IDM_EDIT_COPY:
+ TRACE(TEXT("Copy ... Menu item\n"));
+ return TRUE;
+ case IDM_EDIT_PASTE:
+ TRACE(TEXT("PASTE ... Menu item\n"));
+ return TRUE;
+ case IDM_EDIT_CLEAR:
+ TRACE(TEXT("CLEAR ... Menu item\n"));
+ return TRUE;
+ case IDM_HELP_ABOUT:
+ {
+ CDialog HelpDialog(IDW_ABOUT, this);
+ HelpDialog.DoModal();
+ }
+ return TRUE;
+
+ // Respond to ToolBar buttons
+ case IDM_BOLD:
+ TRACE(TEXT("Bold button pressed\n"));
+ return TRUE;
+ case IDM_ITALIC:
+ TRACE(TEXT("Italic button pressed\n"));
+ return TRUE;
+ case IDM_UNDERLINE:
+ TRACE(TEXT("Underline button pressed\n"));
+ return TRUE;
+
+ // Respond to the accelerator key
+ case IDW_QUIT:
+ SendMessage(WM_CLOSE, 0L, 0L);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CMainFrame::OnDraw(CDC* pDC)
+{
+ CRect rc = GetViewRect();
+ tString tsHello = LoadString(IDS_HELLO);
+ pDC->DrawText(tsHello.c_str(), tsHello.length(), rc, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
+}
+
+
+void CMainFrame::OnInitialUpdate()
+{
+ // Startup code goes here
+ TRACE(TEXT("Frame Created\n"));
+}
+
+LRESULT CMainFrame::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+// switch (uMsg)
+// {
+//
+// }
+
+ // Pass unhandled messages on for default processing
+ return WndProcDefault(uMsg, wParam, lParam);
+}
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.h b/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.h
new file mode 100644
index 0000000..b76ca01
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/MainFrm.h
@@ -0,0 +1,21 @@
+#ifndef MAINFRM_H
+#define MAINFRM_H
+
+
+#include "wincore.h"
+#include "wceframe.h"
+#include "dialog.h"
+
+
+class CMainFrame : public CWceFrame
+{
+public:
+ CMainFrame();
+ virtual ~CMainFrame();
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnDraw(CDC* pDC);
+ virtual void OnInitialUpdate();
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+};
+
+#endif // MAINFRM_H
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcp b/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcp
new file mode 100644
index 0000000..bf3df1e
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcp
@@ -0,0 +1,471 @@
+# Microsoft eMbedded Visual Tools Project File - Name="PocketFrame" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=PocketFrame - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "PocketFrame.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "PocketFrame.vcn" CFG="PocketFrame - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "PocketFrame - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "PocketFrame - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "PocketFrame - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "PocketFrame - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+
+!IF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /FR /Gs8192 /GF /O2 /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /FR /Gs8192 /GF /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ARMV4Rel"
+# PROP BASE Intermediate_Dir "ARMV4Rel"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ARMV4Rel"
+# PROP Intermediate_Dir "ARMV4Rel"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /O2 /M$(CECrtMT) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ARMV4Dbg"
+# PROP BASE Intermediate_Dir "ARMV4Dbg"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "ARMV4Dbg"
+# PROP Intermediate_Dir "ARMV4Dbg"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /M$(CECrtMTDebug) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ENDIF
+
+# Begin Target
+
+# Name "PocketFrame - Win32 (WCE emulator) Release"
+# Name "PocketFrame - Win32 (WCE emulator) Debug"
+# Name "PocketFrame - Win32 (WCE ARMV4) Release"
+# Name "PocketFrame - Win32 (WCE ARMV4) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\FrameApp.cpp
+
+!IF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Release"
+
+DEP_CPP_FRAME=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Debug"
+
+DEP_CPP_FRAME=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_FRAME=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_FRAME=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+
+!IF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Release"
+
+DEP_CPP_MAIN_=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MAIN_=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+
+!IF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Release"
+
+DEP_CPP_MAINF=\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MAINF=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MAINF=\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MAINF=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\FrameApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\newres.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Default.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Default.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.rc
+
+!IF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Release"
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE emulator) Debug"
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Release"
+
+!ELSEIF "$(CFG)" == "PocketFrame - Win32 (WCE ARMV4) Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\toolbar.bmp
+# End Source File
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\include\Default_Resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\Dialog.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEframe.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEstddef.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcw b/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcw
new file mode 100644
index 0000000..dab2b76
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/PocketFrame.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "PocketFrame"=".\PocketFrame.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.sln b/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.sln
new file mode 100644
index 0000000..7cb7c91
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PocketPCFrame", "PocketPCFrame.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.vcproj b/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.vcproj
new file mode 100644
index 0000000..59cba39
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/PocketPCFrame.vcproj
@@ -0,0 +1,757 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/main.cpp b/external/win32cpp/WCE samples/PocketPCFrame/main.cpp
new file mode 100644
index 0000000..4a3dbe2
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/main.cpp
@@ -0,0 +1,30 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "wincore.h"
+#include "resource.h"
+#include "FrameApp.h"
+
+
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
+{
+ TCHAR szBuf[100];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, 100);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ //Start the framework
+ CWceFrameApp MyApp;
+
+ //Process the window messages
+ return MyApp.Run();
+}
+
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/newres.h b/external/win32cpp/WCE samples/PocketPCFrame/newres.h
new file mode 100644
index 0000000..e88ad5d
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/newres.h
@@ -0,0 +1,41 @@
+#ifndef __NEWRES_H__
+#define __NEWRES_H__
+
+#if !defined(UNDER_CE)
+#define UNDER_CE _WIN32_WCE
+#endif
+
+#if defined(_WIN32_WCE)
+ #if !defined(WCEOLE_ENABLE_DIALOGEX)
+ #define DIALOGEX DIALOG DISCARDABLE
+ #endif
+ #include
+ #define SHMENUBAR RCDATA
+ #if defined(WIN32_PLATFORM_PSPC) && (_WIN32_WCE >= 300)
+ #include
+ #define AFXCE_IDR_SCRATCH_SHMENU 28700
+ #else
+ #define I_IMAGENONE (-2)
+ #define NOMENU 0xFFFF
+ #define IDS_SHNEW 1
+
+ #define IDM_SHAREDNEW 10
+ #define IDM_SHAREDNEWDEFAULT 11
+ #endif // _WIN32_WCE_PSPC
+ #define AFXCE_IDD_SAVEMODIFIEDDLG 28701
+#endif // _WIN32_WCE
+
+#ifdef RC_INVOKED
+#ifndef _INC_WINDOWS
+#define _INC_WINDOWS
+ #include "winuser.h" // extract from windows header
+// #include "winver.h"
+#endif
+#endif
+
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+#endif //__NEWRES_H__
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/res/Default.ico b/external/win32cpp/WCE samples/PocketPCFrame/res/Default.ico
new file mode 100644
index 0000000..83b3014
Binary files /dev/null and b/external/win32cpp/WCE samples/PocketPCFrame/res/Default.ico differ
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/res/toolbar.bmp b/external/win32cpp/WCE samples/PocketPCFrame/res/toolbar.bmp
new file mode 100644
index 0000000..1238f44
Binary files /dev/null and b/external/win32cpp/WCE samples/PocketPCFrame/res/toolbar.bmp differ
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/resource.h b/external/win32cpp/WCE samples/PocketPCFrame/resource.h
new file mode 100644
index 0000000..b565177
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/resource.h
@@ -0,0 +1,38 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+//
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+// String resource ID
+#define IDS_HELLO 100
+
+// Button resource IDs
+#define IDM_BOLD 110
+#define IDM_ITALIC 111
+#define IDM_UNDERLINE 112
+
+// Menu resource IDs
+#define IDM_MAIN_COMMAND1 120
+#define IDM_MAIN_COMMAND2 121
+#define IDM_MAIN_COMMAND3 122
+#define IDM_NEW 120 // Same as IDM_MAIN_COMMAND1
+#define IDM_EDIT 140
+#define IDM_EDIT_CUT 141
+#define IDM_EDIT_COPY 142
+#define IDM_EDIT_PASTE 143
+#define IDM_EDIT_CLEAR 144
+#define IDM_TOOLS 150
+#define IDM_HELP_ABOUT 151
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 201
+#endif
+#endif
diff --git a/external/win32cpp/WCE samples/PocketPCFrame/resource.rc b/external/win32cpp/WCE samples/PocketPCFrame/resource.rc
new file mode 100644
index 0000000..c34311b
--- /dev/null
+++ b/external/win32cpp/WCE samples/PocketPCFrame/resource.rc
@@ -0,0 +1,117 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+#include "newres.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON DISCARDABLE "res\\Default.ICO"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Data
+//
+
+IDW_MAIN SHMENUBAR MOVEABLE PURE
+BEGIN
+ IDW_MAIN, 3,
+ I_IMAGENONE, IDM_MAIN_COMMAND1, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE,
+ IDM_NEW, 0, NOMENU,
+ I_IMAGENONE, IDM_MAIN_COMMAND2, TBSTATE_ENABLED,
+ TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDM_EDIT, 0, 1,
+ I_IMAGENONE, IDM_MAIN_COMMAND3, TBSTATE_ENABLED,
+ TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDM_TOOLS, 0, 2,
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menubar
+//
+
+IDW_MAIN MENU DISCARDABLE
+BEGIN
+ MENUITEM "New", IDM_NEW
+ POPUP "Edit"
+ BEGIN
+ MENUITEM "Cut", IDM_EDIT_CUT
+ MENUITEM "Copy", IDM_EDIT_COPY
+ MENUITEM "Paste", IDM_EDIT_PASTE
+ MENUITEM "Clear", IDM_EDIT_CLEAR
+ END
+ POPUP "Tools"
+ BEGIN
+ MENUITEM "About", IDM_HELP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDW_ABOUT DIALOG DISCARDABLE 0, 0, 140, 57
+STYLE WS_POPUP | WS_CAPTION
+EXSTYLE 0x80000000L
+CAPTION "About Default"
+BEGIN
+ ICON IDW_MAIN,IDC_STATIC,11,17,20,20
+ LTEXT "Default Version 1.0",IDC_STATIC,40,10,70,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 2007",IDC_STATIC,40,25,70,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDW_MAIN ACCELERATORS DISCARDABLE
+BEGIN
+ "A", IDM_HELP_ABOUT, VIRTKEY, CONTROL, NOINVERT
+ "Q", IDW_QUIT, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDW_MAIN BITMAP DISCARDABLE "res\\toolbar.bmp"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "Pocket PC Frame"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_HELLO "Hello World!"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDM_NEW "New"
+ IDM_EDIT "Edit"
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDM_TOOLS "Tools"
+END
+
diff --git a/external/win32cpp/WCE samples/Scribble/FrameApp.cpp b/external/win32cpp/WCE samples/Scribble/FrameApp.cpp
new file mode 100644
index 0000000..38c052a
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/FrameApp.cpp
@@ -0,0 +1,14 @@
+#include "FrameApp.h"
+
+CWceFrameApp::CWceFrameApp()
+{
+}
+
+BOOL CWceFrameApp::InitInstance()
+{
+ //Create the Window
+ m_Frame.Create();
+
+ return TRUE;
+}
+
diff --git a/external/win32cpp/WCE samples/Scribble/FrameApp.h b/external/win32cpp/WCE samples/Scribble/FrameApp.h
new file mode 100644
index 0000000..0bc525d
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/FrameApp.h
@@ -0,0 +1,26 @@
+#ifndef SIMPLEAPP_H
+#define SIMPLEAPP_H
+
+#include "wincore.h"
+#include "MainFrm.h"
+
+
+class CWceFrameApp : public CWinApp
+{
+public:
+ CWceFrameApp();
+ virtual ~CWceFrameApp() {}
+ virtual BOOL InitInstance();
+ CMainFrame& GetMainFrame() { return m_Frame; }
+
+private:
+ CMainFrame m_Frame;
+};
+
+
+// returns a reference to the CWceFrameApp object
+inline CWceFrameApp& GetFrameApp() { return *((CWceFrameApp*)GetApp()); }
+
+
+#endif //SIMPLEAPP_H
+
diff --git a/external/win32cpp/WCE samples/Scribble/MainFrm.cpp b/external/win32cpp/WCE samples/Scribble/MainFrm.cpp
new file mode 100644
index 0000000..7387fb0
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/MainFrm.cpp
@@ -0,0 +1,161 @@
+#include "MainFrm.h"
+#include "resource.h"
+
+
+
+CMainFrame::CMainFrame() : m_PenColor(RGB(0,0,0))
+{
+ // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_RED );
+ AddToolBarButton( IDM_BLUE );
+ AddToolBarButton( IDM_GREEN );
+ AddToolBarButton( IDM_BLACK );
+}
+
+void CMainFrame::DrawLine(short x, short y)
+{
+ CDC* pDC = GetDC();
+ pDC->CreatePen(PS_SOLID, 1, m_points.back().color);
+ pDC->MoveTo(m_points.back().x, m_points.back().y);
+ pDC->LineTo(x, y);
+}
+
+BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM /*lParam*/)
+{
+ // Respond to menu and toolbar selections
+ switch (LOWORD(wParam))
+ {
+ // Respond to menu items
+ case IDM_NEW:
+ m_points.clear();
+ Invalidate();
+ return TRUE;
+ case IDM_HELP_ABOUT:
+ {
+ CDialog HelpDialog(IDW_ABOUT, this);
+ HelpDialog.DoModal();
+ }
+ return TRUE;
+
+ // Respond to ToolBar buttons
+ case IDM_RED:
+ m_PenColor = RGB(255, 0, 0);
+ TRACE(_T("Red Pen Selected \n"));
+ return TRUE;
+ case IDM_BLUE:
+ m_PenColor = RGB(0, 0, 255);
+ TRACE(_T("Blue Pen Selected \n"));
+ return TRUE;
+ case IDM_GREEN:
+ m_PenColor = RGB(0, 191, 0);
+ TRACE(_T("Green Pen Selected \n"));
+ return TRUE;
+ case IDM_BLACK:
+ m_PenColor = RGB(0, 0, 0);
+ TRACE(_T("Black Pen Selected \n"));
+ return TRUE;
+
+ // Respond to the accelerator key
+ case IDW_QUIT:
+ SendMessage(WM_CLOSE, 0L, 0L);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void CMainFrame::OnDraw(CDC* pDC)
+{
+ // Redraw our client area
+ if (m_points.size() > 0)
+ {
+ bool bDraw = false; //Start with the pen up
+ for (unsigned int i = 0 ; i < m_points.size(); i++)
+ {
+ pDC->CreatePen(PS_SOLID, 1, m_points[i].color);
+ if (bDraw)
+ pDC->LineTo(m_points[i].x, m_points[i].y);
+ else
+ pDC->MoveTo(m_points[i].x, m_points[i].y);
+
+ bDraw = m_points[i].PenDown;
+ }
+ }
+}
+
+void CMainFrame::OnInitialUpdate()
+{
+ // Startup code goes here
+}
+
+void CMainFrame::OnLButtonDown(WPARAM /*wParam*/, LPARAM lParam)
+{
+ // Capture mouse input.
+ SetCapture();
+
+ StorePoint(LOWORD(lParam), HIWORD(lParam), true);
+}
+
+void CMainFrame::OnLButtonUp(WPARAM /*wParam*/, LPARAM lParam)
+{
+ //Release the capture on the mouse
+ ReleaseCapture();
+
+ StorePoint(LOWORD(lParam), HIWORD(lParam), false);
+}
+
+void CMainFrame::OnMouseMove(WPARAM wParam, LPARAM lParam)
+{
+ // hold down the left mouse button and move mouse to draw lines.
+ if (wParam & MK_LBUTTON)
+ {
+ TCHAR str[80];
+ ::wsprintf(str, TEXT("Draw Point: %hd, %hd\n"), LOWORD(lParam), HIWORD(lParam));
+ TRACE(str);
+
+ DrawLine(LOWORD(lParam), HIWORD(lParam));
+ StorePoint(LOWORD(lParam), HIWORD(lParam), true);
+ }
+}
+
+void CMainFrame::SetPen(COLORREF color)
+{
+ m_PenColor = color;
+}
+
+void CMainFrame::StorePoint(int x, int y, bool PenDown)
+{
+ PlotPoint P1;
+ P1.x = x;
+ P1.y = y;
+ P1.PenDown = PenDown;
+ P1.color = m_PenColor;
+
+ m_points.push_back(P1); //Add the point to the vector
+}
+
+LRESULT CMainFrame::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ // handle left mouse button up/down and mouse move messages
+ // a seperate function for each case keeps the code tidy.
+ switch (uMsg)
+ {
+ case WM_LBUTTONDOWN:
+ OnLButtonDown(wParam, lParam);
+ break;
+
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+
+ case WM_LBUTTONUP:
+ OnLButtonUp(wParam, lParam);
+ break;
+ }
+
+ // Pass unhandled messages on to WndProcDefault
+ return WndProcDefault(uMsg, wParam, lParam);
+}
+
+
diff --git a/external/win32cpp/WCE samples/Scribble/MainFrm.h b/external/win32cpp/WCE samples/Scribble/MainFrm.h
new file mode 100644
index 0000000..cdcd094
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/MainFrm.h
@@ -0,0 +1,42 @@
+#ifndef VIEW_H
+#define VIEW_H
+
+
+#include "wincore.h"
+#include "wceframe.h"
+#include "dialog.h"
+#include
+
+
+class CMainFrame : public CWceFrame
+{
+public:
+ CMainFrame();
+ virtual ~CMainFrame() {}
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnInitialUpdate();
+ virtual void SetPen(COLORREF Color);
+
+protected:
+ virtual void DrawLine(short x, short y);
+ virtual void OnDraw(CDC* pDC);
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual void StorePoint(int x, int y, bool PenDown);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+private:
+ struct PlotPoint
+ {
+ short x;
+ short y;
+ bool PenDown;
+ COLORREF color;
+ };
+
+ std::vector m_points; // Points of lines to draw
+ COLORREF m_PenColor;
+};
+
+#endif //VIEW_H
diff --git a/external/win32cpp/WCE samples/Scribble/Scribble.sln b/external/win32cpp/WCE samples/Scribble/Scribble.sln
new file mode 100644
index 0000000..64cd221
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/Scribble.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Scribble", "Scribble.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/Scribble/Scribble.vcp b/external/win32cpp/WCE samples/Scribble/Scribble.vcp
new file mode 100644
index 0000000..4942d90
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/Scribble.vcp
@@ -0,0 +1,471 @@
+# Microsoft eMbedded Visual Tools Project File - Name="Scribble" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE ARMV4) Application" 0xa301
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=Scribble - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Scribble.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Scribble.vcn" CFG="Scribble - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Scribble - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "Scribble - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "Scribble - Win32 (WCE ARMV4) Release" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE "Scribble - Win32 (WCE ARMV4) Debug" (based on "Win32 (WCE ARMV4) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+
+!IF "$(CFG)" == "Scribble - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /Yu"stdafx.h" /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /FR /Gs8192 /GF /O2 /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /Yu"stdafx.h" /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /FR /Gs8192 /GF /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "ARMV4Rel"
+# PROP BASE Intermediate_Dir "ARMV4Rel"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "ARMV4Rel"
+# PROP Intermediate_Dir "ARMV4Rel"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "NDEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /Yu"stdafx.h" /O2 /M$(CECrtMT) /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D "UNICODE" /D "_UNICODE" /D "NDEBUG" /O2 /M$(CECrtMT) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "ARMV4Dbg"
+# PROP BASE Intermediate_Dir "ARMV4Dbg"
+# PROP BASE CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "ARMV4Dbg"
+# PROP Intermediate_Dir "ARMV4Dbg"
+# PROP CPU_ID "{ECBEA43D-CD7B-4852-AD55-D4227B5D624B}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "DEBUG" /d "UNICODE" /d "_UNICODE" /d "$(CePlatform)" /d "ARM" /d "_ARM_" /d "ARMV4" /r
+CPP=clarm.exe
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /Yu"stdafx.h" /M$(CECrtMTDebug) /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "DEBUG" /D "ARM" /D "_ARM_" /D "ARMV4" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "UNICODE" /D "_UNICODE" /M$(CECrtMTDebug) /c
+MTL=midl.exe
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib aygshell.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+# ADD LINK32 commctrl.lib coredll.lib /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"$(CENoDefaultLib)" /subsystem:$(CESubsystem) /align:"4096" /MACHINE:ARM
+
+!ENDIF
+
+# Begin Target
+
+# Name "Scribble - Win32 (WCE emulator) Release"
+# Name "Scribble - Win32 (WCE emulator) Debug"
+# Name "Scribble - Win32 (WCE ARMV4) Release"
+# Name "Scribble - Win32 (WCE ARMV4) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\FrameApp.cpp
+
+!IF "$(CFG)" == "Scribble - Win32 (WCE emulator) Release"
+
+DEP_CPP_FRAME=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE emulator) Debug"
+
+DEP_CPP_FRAME=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_FRAME=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_FRAME=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_FRAME=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+
+!IF "$(CFG)" == "Scribble - Win32 (WCE emulator) Release"
+
+DEP_CPP_MAIN_=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MAIN_=\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MAIN_=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\FrameApp.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.cpp
+
+!IF "$(CFG)" == "Scribble - Win32 (WCE emulator) Release"
+
+DEP_CPP_MAINF=\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\WinCE++\Cmdbar.h"\
+ "..\WinCE++\Default_Resource.h"\
+ "..\WinCE++\Dialog.h"\
+ "..\WinCE++\SHMenubar.h"\
+ "..\WinCE++\WinCore.h"\
+ ".\hellsdk.h"\
+ ".\hsdkstc.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE emulator) Debug"
+
+DEP_CPP_MAINF=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\emulator\vibrate.h"\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Release"
+
+DEP_CPP_MAINF=\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce420\POCKET PC 2003\Include\ARMV4\vibrate.h"\
+ "..\..\include\WCEControls.h"\
+ "..\..\include\WinCore.h"\
+ ".\inuserm.h"\
+ ".\ipapi.h"\
+ ".\ygshell.h"\
+
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Debug"
+
+DEP_CPP_MAINF=\
+ "..\..\include\Dialog.h"\
+ "..\..\include\WCEframe.h"\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\MainFrm.h"\
+
+NODEP_CPP_MAINF=\
+ "..\..\include\DeviceResolutionAware.h"\
+ ".\econfig.h"\
+
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\FrameApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainFrm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\newres.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\Default.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\res\Default.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.rc
+
+!IF "$(CFG)" == "Scribble - Win32 (WCE emulator) Release"
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE emulator) Debug"
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Release"
+
+!ELSEIF "$(CFG)" == "Scribble - Win32 (WCE ARMV4) Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\toolbar.bmp
+# End Source File
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\include\Default_Resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\Dialog.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEframe.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEstddef.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/Scribble/Scribble.vcproj b/external/win32cpp/WCE samples/Scribble/Scribble.vcproj
new file mode 100644
index 0000000..8e93b4c
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/Scribble.vcproj
@@ -0,0 +1,754 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/Scribble/Scribble.vcw b/external/win32cpp/WCE samples/Scribble/Scribble.vcw
new file mode 100644
index 0000000..9d11fe0
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/Scribble.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Scribble"=".\Scribble.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/Scribble/main.cpp b/external/win32cpp/WCE samples/Scribble/main.cpp
new file mode 100644
index 0000000..454a12f
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/main.cpp
@@ -0,0 +1,29 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "wincore.h"
+#include "resource.h"
+#include "FrameApp.h"
+
+
+int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
+{
+ TCHAR szBuf[100];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, 100);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ //Start the framework
+ CWceFrameApp MyApp;
+
+ //Process the window messages
+ return MyApp.Run();
+}
+
diff --git a/external/win32cpp/WCE samples/Scribble/newres.h b/external/win32cpp/WCE samples/Scribble/newres.h
new file mode 100644
index 0000000..e88ad5d
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/newres.h
@@ -0,0 +1,41 @@
+#ifndef __NEWRES_H__
+#define __NEWRES_H__
+
+#if !defined(UNDER_CE)
+#define UNDER_CE _WIN32_WCE
+#endif
+
+#if defined(_WIN32_WCE)
+ #if !defined(WCEOLE_ENABLE_DIALOGEX)
+ #define DIALOGEX DIALOG DISCARDABLE
+ #endif
+ #include
+ #define SHMENUBAR RCDATA
+ #if defined(WIN32_PLATFORM_PSPC) && (_WIN32_WCE >= 300)
+ #include
+ #define AFXCE_IDR_SCRATCH_SHMENU 28700
+ #else
+ #define I_IMAGENONE (-2)
+ #define NOMENU 0xFFFF
+ #define IDS_SHNEW 1
+
+ #define IDM_SHAREDNEW 10
+ #define IDM_SHAREDNEWDEFAULT 11
+ #endif // _WIN32_WCE_PSPC
+ #define AFXCE_IDD_SAVEMODIFIEDDLG 28701
+#endif // _WIN32_WCE
+
+#ifdef RC_INVOKED
+#ifndef _INC_WINDOWS
+#define _INC_WINDOWS
+ #include "winuser.h" // extract from windows header
+// #include "winver.h"
+#endif
+#endif
+
+#ifdef IDC_STATIC
+#undef IDC_STATIC
+#endif
+#define IDC_STATIC (-1)
+
+#endif //__NEWRES_H__
diff --git a/external/win32cpp/WCE samples/Scribble/res/Default.ico b/external/win32cpp/WCE samples/Scribble/res/Default.ico
new file mode 100644
index 0000000..83b3014
Binary files /dev/null and b/external/win32cpp/WCE samples/Scribble/res/Default.ico differ
diff --git a/external/win32cpp/WCE samples/Scribble/res/toolbar.bmp b/external/win32cpp/WCE samples/Scribble/res/toolbar.bmp
new file mode 100644
index 0000000..f82c0bd
Binary files /dev/null and b/external/win32cpp/WCE samples/Scribble/res/toolbar.bmp differ
diff --git a/external/win32cpp/WCE samples/Scribble/resource.h b/external/win32cpp/WCE samples/Scribble/resource.h
new file mode 100644
index 0000000..1870c16
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/resource.h
@@ -0,0 +1,34 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+// Used by DEFAULT.RC
+//
+
+#include "default_resource.h"
+
+// String resource IDs
+#define IDS_HELLO 100
+
+// Button resource IDs
+#define IDM_BLUE 110
+#define IDM_RED 111
+#define IDM_GREEN 112
+#define IDM_BLACK 113
+
+// Menu resource IDs
+#define IDM_MAIN_COMMAND1 120
+#define IDM_MAIN_COMMAND2 121
+#define IDM_MAIN_COMMAND3 122
+#define IDM_NEW 120 // Same as IDM_COMMAND1
+#define IDM_HELP 150
+#define IDM_HELP_ABOUT 151
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 201
+#endif
+#endif
diff --git a/external/win32cpp/WCE samples/Scribble/resource.rc b/external/win32cpp/WCE samples/Scribble/resource.rc
new file mode 100644
index 0000000..10cb1f7
--- /dev/null
+++ b/external/win32cpp/WCE samples/Scribble/resource.rc
@@ -0,0 +1,94 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+#include "newres.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON DISCARDABLE "res\\Default.ICO"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Data
+//
+
+IDW_MAIN SHMENUBAR MOVEABLE PURE
+BEGIN
+ IDW_MAIN, 2,
+ I_IMAGENONE, IDM_MAIN_COMMAND1, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE,
+ IDM_NEW, 0, NOMENU,
+ I_IMAGENONE, IDM_MAIN_COMMAND2, TBSTATE_ENABLED,
+ TBSTYLE_DROPDOWN | TBSTYLE_AUTOSIZE, IDM_HELP, 0, 1,
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menubar
+//
+
+IDW_MAIN MENU DISCARDABLE
+BEGIN
+ MENUITEM "New", IDM_NEW
+ POPUP "Help"
+ BEGIN
+ MENUITEM "About", IDM_HELP_ABOUT
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDW_ABOUT DIALOG DISCARDABLE 0, 0, 140, 57
+STYLE WS_POPUP | WS_CAPTION
+EXSTYLE 0x80000000L
+CAPTION "About Default"
+BEGIN
+ ICON IDW_MAIN,IDC_STATIC,11,17,20,20
+ LTEXT "Scribble Application",IDC_STATIC,40,10,70,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 2007",IDC_STATIC,40,25,70,8
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDW_MAIN ACCELERATORS DISCARDABLE
+BEGIN
+ "A", IDM_HELP_ABOUT, VIRTKEY, CONTROL, NOINVERT
+ "Q", IDW_QUIT, VIRTKEY, CONTROL, NOINVERT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDW_MAIN BITMAP DISCARDABLE "res\\toolbar.bmp"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "WinCE Scribble App"
+ IDM_NEW "New"
+ IDM_HELP "Help"
+END
+
diff --git a/external/win32cpp/WCE samples/Simple/Simple.sln b/external/win32cpp/WCE samples/Simple/Simple.sln
new file mode 100644
index 0000000..02b540d
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/Simple.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Simple", "Simple.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/Simple/Simple.vcp b/external/win32cpp/WCE samples/Simple/Simple.vcp
new file mode 100644
index 0000000..2718b35
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/Simple.vcp
@@ -0,0 +1,180 @@
+# Microsoft eMbedded Visual Tools Project File - Name="Simple" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=Simple - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Simple.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Simple.vcn" CFG="Simple - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Simple - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "Simple - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Simple - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "Simple - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "_DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /FR /YX /Gs8192 /GF /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ENDIF
+
+# Begin Target
+
+# Name "Simple - Win32 (WCE emulator) Release"
+# Name "Simple - Win32 (WCE emulator) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\main.cpp
+DEP_CPP_MAIN_=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\SimpleApp.h"\
+ ".\view.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\SimpleApp.cpp
+DEP_CPP_SIMPL=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\SimpleApp.h"\
+ ".\view.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_SIMPL=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\View.cpp
+DEP_CPP_VIEW_=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\view.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_VIEW_=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\SimpleApp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\view.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce400\STANDARDSDK\Include\Emulator\ceconfig.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\Default_Resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEstddef.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/Simple/Simple.vcproj b/external/win32cpp/WCE samples/Simple/Simple.vcproj
new file mode 100644
index 0000000..494e116
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/Simple.vcproj
@@ -0,0 +1,789 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/Simple/Simple.vcw b/external/win32cpp/WCE samples/Simple/Simple.vcw
new file mode 100644
index 0000000..283ea31
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/Simple.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Simple"=".\Simple.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/Simple/SimpleApp.cpp b/external/win32cpp/WCE samples/Simple/SimpleApp.cpp
new file mode 100644
index 0000000..49a37b3
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/SimpleApp.cpp
@@ -0,0 +1,13 @@
+#include "SimpleApp.h"
+
+CSimpleApp::CSimpleApp()
+{
+}
+
+BOOL CSimpleApp::InitInstance()
+{
+ //Create the Window
+ m_View.Create();
+
+ return TRUE;
+}
\ No newline at end of file
diff --git a/external/win32cpp/WCE samples/Simple/SimpleApp.h b/external/win32cpp/WCE samples/Simple/SimpleApp.h
new file mode 100644
index 0000000..8bac861
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/SimpleApp.h
@@ -0,0 +1,25 @@
+#ifndef SIMPLEAPP_H
+#define SIMPLEAPP_H
+
+#include "wincore.h"
+#include "view.h"
+
+
+class CSimpleApp : public CWinApp
+{
+public:
+ CSimpleApp();
+ virtual ~CSimpleApp() {}
+ virtual BOOL InitInstance();
+ CView& GetView() { return m_View; }
+
+private:
+ CView m_View;
+};
+
+
+// returns a reference to the CSimpleApp object
+inline CSimpleApp& GetSimpleApp() { return *((CSimpleApp*)GetApp()); }
+
+
+#endif //SIMPLEAPP_H
diff --git a/external/win32cpp/WCE samples/Simple/View.cpp b/external/win32cpp/WCE samples/Simple/View.cpp
new file mode 100644
index 0000000..6b012e9
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/View.cpp
@@ -0,0 +1,38 @@
+#include "view.h"
+#include "resource.h"
+
+
+void CView::OnDraw(CDC* pDC)
+{
+ // Define a rectangle to contain some text
+ CRect rc = GetClientRect();
+ rc.bottom = rc.bottom/2;
+
+ // Draw some text in our rectangle
+ LPCTSTR szString = TEXT("Use Debug mode. Click here");
+ pDC->DrawText(szString, lstrlen(szString), rc, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
+}
+
+
+LRESULT CView::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ // Terminate the application.
+ ::PostQuitMessage(0);
+ return 0;
+ case WM_LBUTTONDOWN:
+ // NOTE: You must be in debug mode to see the trace output
+ TRACE(TEXT("Left mouse button down message\n"));
+ break;
+ case WM_LBUTTONUP:
+ // NOTE: You must be in debug mode to see the trace output
+ TRACE(TEXT("Left mouse button up message\n"));
+ break;
+ }
+
+ // Pass unhandled messages on for default processing
+ return WndProcDefault(uMsg, wParam, lParam);
+}
+
diff --git a/external/win32cpp/WCE samples/Simple/main.cpp b/external/win32cpp/WCE samples/Simple/main.cpp
new file mode 100644
index 0000000..238cf6e
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/main.cpp
@@ -0,0 +1,27 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "SimpleApp.h"
+#include "resource.h"
+
+
+INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
+{
+ TCHAR szBuf[MAX_STRING_SIZE];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, MAX_STRING_SIZE -1);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ //Start the framework
+ CSimpleApp MyApp;
+
+ //Process the window messages
+ return MyApp.Run();
+}
diff --git a/external/win32cpp/WCE samples/Simple/resource.h b/external/win32cpp/WCE samples/Simple/resource.h
new file mode 100644
index 0000000..78d7832
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/resource.h
@@ -0,0 +1,21 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+//
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+// String resource ID
+#define IDS_HELLO 100
+
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 201
+#endif
+#endif
diff --git a/external/win32cpp/WCE samples/Simple/resource.rc b/external/win32cpp/WCE samples/Simple/resource.rc
new file mode 100644
index 0000000..3cf5bf0
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/resource.rc
@@ -0,0 +1,26 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "Simple Window"
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDW_MAIN ACCELERATORS DISCARDABLE
+BEGIN
+ "Q", IDW_QUIT, VIRTKEY, CONTROL, NOINVERT
+END
+
diff --git a/external/win32cpp/WCE samples/Simple/view.h b/external/win32cpp/WCE samples/Simple/view.h
new file mode 100644
index 0000000..684fb97
--- /dev/null
+++ b/external/win32cpp/WCE samples/Simple/view.h
@@ -0,0 +1,16 @@
+#ifndef VIEW_H
+#define VIEW_H
+
+#include "wincore.h"
+
+
+class CView : public CWnd
+{
+public:
+ CView() {}
+ virtual ~CView() {}
+ virtual void OnDraw(CDC* pDC);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+};
+
+#endif //VIEW_H
diff --git a/external/win32cpp/WCE samples/Subclass/Button.cpp b/external/win32cpp/WCE samples/Subclass/Button.cpp
new file mode 100644
index 0000000..c52d4e9
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Button.cpp
@@ -0,0 +1,50 @@
+/////////////////////////////
+// Button.cpp
+
+
+#include "Button.h"
+
+
+CButton::~CButton()
+{
+}
+
+void CButton::PreCreate(CREATESTRUCT &cs)
+{
+ cs.lpszClass = TEXT("BUTTON");
+ cs.style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
+ cs.x = 10;
+ cs.y = 10;
+ cs.cx = 100;
+ cs.cy = 100;
+ cs.lpszName = TEXT("OK");
+}
+
+LRESULT CButton::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_MOUSEMOVE:
+ TRACE(TEXT("WndProc - WM_MOUSEMOVE Message\n"));
+ break;
+ case WM_SETCURSOR:
+ TRACE(TEXT("WndProc - WM_SETCURSOR Message\n"));
+ break;
+ case WM_LBUTTONDOWN:
+ TRACE(TEXT("WndProc - WM_LBUTTONDOWN Message\n"));
+ break;
+ case WM_LBUTTONUP:
+ TRACE(TEXT("WndProc - WM_LBUTTONUP Message\n"));
+ break;
+ case WM_PAINT:
+ TRACE(TEXT("WndProc - WM_PAINT Message\n"));
+ break;
+
+ default:
+ TRACE(TEXT("WndProc - Unspecified Message\n"));
+ break;
+ }
+
+ // Pass unhandled messages on for default processing
+ return CWnd::WndProc(uMsg, wParam, lParam);
+}
diff --git a/external/win32cpp/WCE samples/Subclass/Button.h b/external/win32cpp/WCE samples/Subclass/Button.h
new file mode 100644
index 0000000..b89c913
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Button.h
@@ -0,0 +1,27 @@
+/////////////////////////////
+// Button.h
+
+
+#ifndef BUTTON_H
+#define BUTTON_H
+
+#include "wincore.h"
+
+
+class CButton : public CWnd
+{
+public:
+ CButton() {}
+ virtual ~CButton();
+ virtual void PreCreate(CREATESTRUCT &cs);
+
+protected:
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+};
+
+
+
+#endif //BUTTON_H
+
+
diff --git a/external/win32cpp/WCE samples/Subclass/MainWin.cpp b/external/win32cpp/WCE samples/Subclass/MainWin.cpp
new file mode 100644
index 0000000..032ed7d
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/MainWin.cpp
@@ -0,0 +1,29 @@
+//////////////////////////////
+// MainWin.Cpp
+
+#include "MainWin.h"
+
+
+CMainWin::CMainWin()
+{
+ ::InitCommonControls();
+}
+
+void CMainWin::OnCreate()
+{
+ m_Button.Create(this);
+}
+
+LRESULT CMainWin::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ // Terminate the application.
+ ::PostQuitMessage(0);
+ return 0L;
+ }
+
+ // Pass unhandled messages on for default processing
+ return WndProcDefault(uMsg, wParam, lParam);
+}
diff --git a/external/win32cpp/WCE samples/Subclass/MainWin.h b/external/win32cpp/WCE samples/Subclass/MainWin.h
new file mode 100644
index 0000000..f99a0dd
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/MainWin.h
@@ -0,0 +1,29 @@
+///////////////////////////////
+// MainWin.h
+
+
+#ifndef MAINWIN_H
+#define MAINWIN_H
+
+
+#include "Button.h"
+
+
+class CMainWin : public CWnd
+{
+public:
+ CMainWin();
+ ~CMainWin() {}
+
+protected:
+ LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void OnCreate();
+
+private:
+ CButton m_Button;
+};
+
+
+
+#endif //MAINWIN_H
+
diff --git a/external/win32cpp/WCE samples/Subclass/Subclass.sln b/external/win32cpp/WCE samples/Subclass/Subclass.sln
new file mode 100644
index 0000000..cc83ca8
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Subclass.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Subclass", "Subclass.vcproj", "{8559448A-4279-495E-B22B-CC35E87247E7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
+ Debug|Smartphone 2003 (ARMV4) = Debug|Smartphone 2003 (ARMV4)
+ Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
+ Release|Smartphone 2003 (ARMV4) = Release|Smartphone 2003 (ARMV4)
+ Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I) = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I) = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).ActiveCfg = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Build.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Smartphone 2003 (ARMV4).Deploy.0 = Debug|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Debug|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).ActiveCfg = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Build.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Smartphone 2003 (ARMV4).Deploy.0 = Release|Smartphone 2003 (ARMV4)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Pocket PC SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).ActiveCfg = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Build.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ {8559448A-4279-495E-B22B-CC35E87247E7}.Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I).Deploy.0 = Release|Windows Mobile 5.0 Smartphone SDK (ARMV4I)
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/external/win32cpp/WCE samples/Subclass/Subclass.vcp b/external/win32cpp/WCE samples/Subclass/Subclass.vcp
new file mode 100644
index 0000000..6281043
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Subclass.vcp
@@ -0,0 +1,208 @@
+# Microsoft eMbedded Visual Tools Project File - Name="Subclass" - Package Owner=<4>
+# Microsoft eMbedded Visual Tools Generated Build File, Format Version 6.02
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (WCE emulator) Application" 0xa601
+
+CFG=Subclass - Win32 (WCE emulator) Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "Subclass.vcn".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "Subclass.vcn" CFG="Subclass - Win32 (WCE emulator) Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Subclass - Win32 (WCE emulator) Release" (based on "Win32 (WCE emulator) Application")
+!MESSAGE "Subclass - Win32 (WCE emulator) Debug" (based on "Win32 (WCE emulator) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+# PROP ATL_Project 2
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "Subclass - Win32 (WCE emulator) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "emulatorRel"
+# PROP BASE Intermediate_Dir "emulatorRel"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "emulatorRel"
+# PROP Intermediate_Dir "emulatorRel"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "NDEBUG" /d "$(CePlatform)" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD CPP /nologo /W3 /GX /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "_i386_" /D UNDER_CE=$(CEVersion) /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /D "NDEBUG" /YX /Gs8192 /GF /O2 /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ELSEIF "$(CFG)" == "Subclass - Win32 (WCE emulator) Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "emulatorDbg"
+# PROP BASE Intermediate_Dir "emulatorDbg"
+# PROP BASE CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP BASE Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "emulatorDbg"
+# PROP Intermediate_Dir "emulatorDbg"
+# PROP CPU_ID "{32E52003-403E-442D-BE48-DE10F8C6131D}"
+# PROP Platform_ID "{8A9A2F80-6887-11D3-842E-005004848CBA}"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD RSC /l 0x409 /d "$(CePlatform)" /d UNDER_CE=$(CEVersion) /d _WIN32_WCE=$(CEVersion) /d "UNICODE" /d "_UNICODE" /d "DEBUG" /d "_X86_" /d "x86" /d "_i386_" /r
+# ADD BASE CPP /nologo /W3 /Zi /Od /D "DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /YX /Gs8192 /GF /c
+# ADD CPP /nologo /W3 /GX /Zi /Od /D "_DEBUG" /D "_i386_" /D UNDER_CE=$(CEVersion) /D _WIN32_WCE=$(CEVersion) /D "$(CePlatform)" /D "i_386_" /D "UNICODE" /D "_UNICODE" /D "_X86_" /D "x86" /FR /YX /Gs8192 /GF /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+# ADD LINK32 commctrl.lib coredll.lib $(CEx86Corelibc) /nologo /base:"0x00010000" /stack:0x10000,0x1000 /entry:"WinMainCRTStartup" /debug /nodefaultlib:"OLDNAMES.lib" /nodefaultlib:$(CENoDefaultLib) /subsystem:$(CESubsystem) /MACHINE:IX86
+
+!ENDIF
+
+# Begin Target
+
+# Name "Subclass - Win32 (WCE emulator) Release"
+# Name "Subclass - Win32 (WCE emulator) Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\Button.cpp
+DEP_CPP_BUTTO=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_BUTTO=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.cpp
+DEP_CPP_MAIN_=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\MainWin.h"\
+ ".\SubclassApp.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_MAIN_=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainWin.cpp
+DEP_CPP_MAINW=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\MainWin.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_MAINW=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\Resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\SubclassApp.cpp
+DEP_CPP_SUBCL=\
+ "..\..\include\WCEstddef.h"\
+ "..\..\include\WinCore.h"\
+ ".\Button.h"\
+ ".\MainWin.h"\
+ ".\SubclassApp.h"\
+ {$(INCLUDE)}"ceconfig.h"\
+
+NODEP_CPP_SUBCL=\
+ "..\..\include\DeviceResolutionAware.h"\
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\Button.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\MainWin.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SubclassApp.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Win32++"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE="..\..\..\..\..\..\..\..\Program Files\Windows CE Tools\wce400\STANDARDSDK\Include\Emulator\ceconfig.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\Default_Resource.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WCEstddef.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\..\include\WinCore.h"
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/external/win32cpp/WCE samples/Subclass/Subclass.vcproj b/external/win32cpp/WCE samples/Subclass/Subclass.vcproj
new file mode 100644
index 0000000..93a4886
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Subclass.vcproj
@@ -0,0 +1,751 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/external/win32cpp/WCE samples/Subclass/Subclass.vcw b/external/win32cpp/WCE samples/Subclass/Subclass.vcw
new file mode 100644
index 0000000..64562ef
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/Subclass.vcw
@@ -0,0 +1,29 @@
+Microsoft eMbedded Visual Tools Workspace File, Format Version 4.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Subclass"=".\Subclass.vcp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/external/win32cpp/WCE samples/Subclass/SubclassApp.cpp b/external/win32cpp/WCE samples/Subclass/SubclassApp.cpp
new file mode 100644
index 0000000..2241b09
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/SubclassApp.cpp
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////
+//SubclassApp.cpp - Definitions for the CSubclassApp class
+
+
+#include "SubclassApp.h"
+
+
+CSubclassApp::CSubclassApp()
+{
+}
+
+BOOL CSubclassApp::InitInstance()
+{
+ TRACE(TEXT("Move the mouse over the button to see messages"));
+
+ //Create the Outer Window
+ m_Win.Create();
+
+ return TRUE;
+}
+
+CSubclassApp::~CSubclassApp()
+{
+}
diff --git a/external/win32cpp/WCE samples/Subclass/SubclassApp.h b/external/win32cpp/WCE samples/Subclass/SubclassApp.h
new file mode 100644
index 0000000..cf35684
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/SubclassApp.h
@@ -0,0 +1,29 @@
+//////////////////////////////////////////////////
+// SubclassApp.h
+// Declaration of the CSubApp class
+
+#ifndef SUBCLASSAPP_H
+#define SUBCLASSAPP_H
+
+#include "MainWin.h"
+
+
+class CSubclassApp : public CWinApp
+{
+public:
+ CSubclassApp();
+ virtual ~CSubclassApp();
+ virtual BOOL InitInstance();
+ CMainWin& GetWin() { return m_Win; }
+
+private:
+ CMainWin m_Win;
+};
+
+
+// returns a reference to the CSubclassApp object
+inline CSubclassApp& GetSubApp() { return *((CSubclassApp*)GetApp()); }
+
+
+#endif // define SUBCLASSAPP_H
+
diff --git a/external/win32cpp/WCE samples/Subclass/main.cpp b/external/win32cpp/WCE samples/Subclass/main.cpp
new file mode 100644
index 0000000..8647f04
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/main.cpp
@@ -0,0 +1,28 @@
+///////////////////////////////////////
+// main.cpp
+
+#include "SubclassApp.h"
+#include "resource.h"
+
+INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPTSTR, int)
+{
+ TCHAR szBuf[MAX_STRING_SIZE];
+ ::LoadString(hInstance, IDW_MAIN, szBuf, MAX_STRING_SIZE -1);
+ HWND hWnd = FindWindow(szBuf, NULL);
+
+ // If application is already running, restore it and quit
+ if (hWnd)
+ {
+ SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));
+ TRACE(_T("Application Already running"));
+ return -1;
+ }
+
+ // Start Win32++
+ CSubclassApp theApp;
+
+ // Process the window messages
+ return theApp.Run();
+}
+
+
diff --git a/external/win32cpp/WCE samples/Subclass/resource.h b/external/win32cpp/WCE samples/Subclass/resource.h
new file mode 100644
index 0000000..5d13ec3
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/resource.h
@@ -0,0 +1,38 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft eMbedded Visual C++ generated include file.
+//
+
+// include the Resource IDs defined by Win32++
+#include "default_resource.h"
+
+// String resource ID
+#define IDS_HELLO 100
+
+// Button resource IDs
+#define IDM_BOLD 110
+#define IDM_ITALIC 111
+#define IDM_UNDERLINE 112
+
+// Menu resource IDs
+#define IDM_MAIN_COMMAND1 120
+#define IDM_MAIN_COMMAND2 121
+#define IDM_MAIN_COMMAND3 122
+#define IDM_NEW 130
+#define IDM_EDIT 140
+#define IDM_EDIT_CUT 141
+#define IDM_EDIT_COPY 142
+#define IDM_EDIT_PASTE 143
+#define IDM_EDIT_CLEAR 144
+#define IDM_TOOLS 150
+#define IDM_HELP_ABOUT 151
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 201
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1001
+#define _APS_NEXT_SYMED_VALUE 201
+#endif
+#endif
diff --git a/external/win32cpp/WCE samples/Subclass/resource.rc b/external/win32cpp/WCE samples/Subclass/resource.rc
new file mode 100644
index 0000000..29b9586
--- /dev/null
+++ b/external/win32cpp/WCE samples/Subclass/resource.rc
@@ -0,0 +1,18 @@
+//Microsoft eMbedded Visual C++ generated resource script.
+//
+
+#include "resource.h"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDW_MAIN "WinCE subclass example"
+END
+
+
+
diff --git a/external/win32cpp/help/Readme.TXT b/external/win32cpp/help/Readme.TXT
new file mode 100644
index 0000000..156ddd3
--- /dev/null
+++ b/external/win32cpp/help/Readme.TXT
@@ -0,0 +1,20 @@
+Some .CHM files may not render properly on Windows XP, Windows Vista and Windows 7.
+
+When attempting to open a Compiled HTML Help (.CHM) file, the file may open but display one of the following messages instead of the expected content:
+
+ * Navigation to the webpage was canceled.
+ * Action canceled.
+
+To resolve this issue, carry out the following steps:
+
+ 1. Right-click the .CHM file and choose Properties
+ 2. On the General tab, click the button labeled "Unblock"
+ 3. Click OK
+
+For further information in this issue, refer to the following Microsoft articles.
+
+For Windows XP
+http://support.microsoft.com/kb/902225
+
+For Windows Vista and Windows 7
+http://support.microsoft.com/kb/2021383
\ No newline at end of file
diff --git a/external/win32cpp/help/Win32++.chm b/external/win32cpp/help/Win32++.chm
new file mode 100644
index 0000000..e38654a
Binary files /dev/null and b/external/win32cpp/help/Win32++.chm differ
diff --git a/external/win32cpp/help/Win32++.chw b/external/win32cpp/help/Win32++.chw
new file mode 100644
index 0000000..67ece11
Binary files /dev/null and b/external/win32cpp/help/Win32++.chw differ
diff --git a/external/win32cpp/include/changes.txt b/external/win32cpp/include/changes.txt
new file mode 100644
index 0000000..e46fae3
--- /dev/null
+++ b/external/win32cpp/include/changes.txt
@@ -0,0 +1,1423 @@
+Version 7.2
+===========
+
+New Features and Enhancements
+-----------------------------
+* Added CString class
+ The CString class is intended to provide much of the same functionality
+ as the CString class provided with MFC/ATL.
+* Added CMenu
+ The CMenu class is intended to provide much of the same functionality
+ as the CMenu class provided with MFC. The library now standardises on
+ using pointers to CMenu, instead of HMENU.
+* Added CFile
+ This class provides a convenient wrapper for functions dealing with files.
+* Added Idle processing.
+ The Idle processing is used by the Win32++ library for some internal
+ processing. It is also available for use by users, and is used in much the
+ same way as OnIdle processing in MFC.
+* Enhanced the CDC class, and added CWindowDC, CClientDC, CMemDC, CPaintDC
+ and CMetaFileDC. The creation of the various different types of CDCs has
+ been simplified, and the CDC functions now use CDC pointers instead of
+ HDCs. These changes improve the compatibility between Win32++ and MFC.
+* Enhanced the various GDI object classes, namely CBitmap, CBrush, CFont,
+ CPalette, CPen and CRgn, and added CGDIObject. The library now standardises
+ on using pointers to theses classes instead of raw GDI handles (like HPEN).
+ These changes improve the compatibility between Win32++ and MFC.
+
+Changes in detail
+-----------------
+- Added CustomControl sample
+- Added CMenu
+- Added CString
+- Added CFile
+- Added CClientDC
+- Added CMemDC
+- Added CPaintDC
+- Added CWindowDC
+- Added CMetaFileDC
+- Added BSTR2A
+- Added BSTR2T
+- Added BSTR2W
+- Added FromHandle. Several global functions. They return pointers for:
+ - CBitmap
+ - CBrush
+ - CFont
+ - CPalette
+ - CPen
+ - CDC
+ - CMenu
+ - CWnd
+- Added CDC::Destroy
+- Added CDC::GetDCBrushColor
+- Added CDC::SetDCBrushColor
+- Added CDC::SelectObject (several versions)
+- Added CDC::SelectPalete
+- Added CDC::SelectClipRgn
+- Added CDC::SelectStockObject
+- Added CDocker::GetActiveDocker
+- Added CDocker::SetCaptionColors
+- Added CTab::SetTabIcon
+- Added CWinApp::GetAccelerators
+- Added CWinApp::OnIdle
+- Added CWinApp::PreTranslateMessage
+- Added CWinException::GetError
+- Added CWnd::ChildWindowFromPoint
+- Added CWnd::WindowFromPoint
+- Modified LoadString now returns CString
+- Modified CBrush::CreatePatternBrush now accepts a CBitmap pointer
+- Modified CDC::BitBlt now accepts a CDC pointer
+- Modified CDC::CreateCompatibleDC now accepts a CDC pointer and attaches the DC
+- Modified CDC::CreateDC now attaches the DC
+- Modified CDC::CreateIC now attaches the DC
+- Modified CDC::CreateCompatibleBitmap now accepts a CDC pointer
+- Modified CDC::CreateDIBitmap now accepts a CDC pointer
+- Modified CDC::CreateDIBSection now accepts a CDC pointer
+- Modified CDC::StretchBlt now accepts a CDC pointer
+- Modified CDocker::IsChildOfDocker now accepts a CWnd pointer instead of HWND
+- Modified CDocker::IsRelated now accepts a CWnd pointer instead of HWND
+- Modified CWnd::CreateEx now accepts a CMenu pointer
+- Modified CWnd::GetAncestor now accepts a gaFlags parameter
+- Modified CWnd::GetFont now returns a CFont pointer
+- Modified CWnd::GetMenu now accepts a CMenu pointer
+- Modified CWnd::GetNextDlgGroupItem now accepts a CWnd pointer
+- Modified CWnd::GetNextDlgTabItem now accepts a CWnd pointer
+- Modified CWnd::GetSystemMenu now accepts a CMenu pointer
+- Modified CWnd::GetUpdateRgn now accepts a CRgn pointer
+- Modified CWnd::GetWindowDC now returns a CDC pointer
+- Modified CWnd::HiliteMenuItem now accepts a CMenu pointer
+- Modified CWnd::InvalidateRgn now accepts a CRgn pointer
+- Modified CWnd::OnEraseBkgnd now accepts a CDC pointer
+- Modified CWnd::RedrawWindow now accepts a CRgn pointer
+- Modified CWnd::ReleaseDC now accepts a CDC pointer
+- Modified CWnd::ScrollWindowEx now accepts a CRgn pointer
+- Modified CWnd::SetFont now accepts a CFont pointer
+- Modified CWnd::SetMenu now accepts a CMenu pointer
+- Modified CWnd::SetWindowRgn now accepts a CRgn pointer
+- Modified CResizer::AddChild now accepts a CWnd pointer
+- Removed CLoadString
+- Removed CDC::AttachBitmap
+- Removed CDC::AttachBrush
+- Removed CDC::AttachFont
+- Removed CDC::AttachPalette
+- Removed CDC::AttachPen
+- Removed CDC::DetachBitmap
+- Removed CDC::DetachBrush
+- Removed CDC::DetachFont
+- Removed CDC::DetachPalette
+- Removed CDC::DetachPen
+- Removed CTab::SetTabImage
+- Removed GetWindowType for all CWnd classes
+- Renamed CDocker::GetDockTopLevel to CDocker::GetTopmostDocker
+- Renamed CWnd::OnPaint to CWnd::OnDraw
+
+- Extended the help documentation to describe the new features.
+- Added an index to the help documentation.
+
+
+Incompatibilities with previous versions
+----------------------------------------
+* The Win32++ now uses Run Time Type Information (RTTI). Older Microsoft
+ compilers (Visual Studio 2003 and earlier) may need to enable the option to
+ support RTTI.
+* LoadString now returns a CString.
+* CWnd::OnEraseBkgnd has changed. This function now uses a CDC pointer instead
+ of a CDC reference. This change will need to be made for any function that
+ overrides OnEraseBkgnd in order for it to get called.
+* CWnd::OnPaint has been removed and replaced with OnPaint. Code that previously
+ overrode OnPaint will now need to override OnPaint instead. OnPaint uses a
+ CDC pointer, not a CDC reference.
+* Changes made to the CDC class (and the addition of CClientDC, CWindowDC, CMemDC,
+ etc.) are rather likely to affect existing code.
+ - CDC functions now use a CDC pointer argument instead of a HDC.
+ - CWnd functions like GetDC return a pointer to a CDC instead of a HDC.
+ - use CClientDC for client window DCs instead of CDC MyDC = GetDC().
+ - use CWindowDC for window DCs instead of CDC MyDC = GetWindowDC().
+ - use CMemDC for memory DCs instead of CDC MyDC = CreateCompatibleDC(dc).
+ - use CDC::FromHandle to conveniently convert a HDC provided to us by say
+ CustomDraw to a CDC pointer.
+
+ Coding example:
+ CClientDC dcClient(this); // Create a client window DC for this CWnd
+ CMemDC dcMem(&dcClient); // Create a Memory DC from the Client DC.
+ CMemDC.CreatePen(PS_SOLID, 1, RGB(255,0,0);
+ CMemDC.MoveTo(0, 0);
+ CMemDC.LineTo(50, 50);
+ dcClient.BitBlt(0, 0, cx, cy, &CMemDC, 0, 0);
+
+Version 7.1.3
+=============
+This version has some additional bug fixes:
+* Fixed a thread safety issue in CWinApp::SetTLSIndex introduced in version 7.1.2.
+* Added CWinApp::PreTranslateMessage to simplify overloading CWinApp::MessageLoop.
+* The Explorer sample now ends without throwing an exeption on Win2000.
+* CResizer now preserves the tab order in a dialog.
+
+Version 7.1.2
+=============
+This version has some additional bug fixes:
+* CDC Attach and CDC(HDC hDC) now succeed when the HDC is already attached to another CDC.
+* Fixed a resource leak in CTab::Paint which affected CTab, CTabbedMDI and CDockContainer
+* Tabs without owner draw now display their icons.
+* A CDC can now be reused after its HDC has been detached.
+* CBrush::CBrush(COLORREF crColor) now works as expected.
+* CResize now supports controls that issue WM_HSCROLL and WM_VSCROLL messages.
+
+Version 7.1.1
+=============
+Version 7.1.1 has some minor bug fixes for 7.1, namely:
+* Corrected an incorrect dock size when docking a docker.
+* Corrected a drawing error in the tutorials and scribble sample which occurred when
+ dragging the mouse over the view window with the left button down.
+* Added a missing typedef for BSTR2T.
+
+Version 7.1
+===========
+New Features and Enhancements
+-----------------------------
+* Added support for Task Dialogs
+* Added the following set of GDI classes: CBitmap, CBrush, CFont, CPalette,
+ CPen and CRgn. These work in cooperation with the existing CDC class.
+* Added a set of new Text conversion functions based on classes.
+ The complete set of functions are:
+ A2BSTR ANSI to BSTR
+ A2OLE ANSI to OLE
+ A2T ANSI to TCHAR
+ A2W ANSI to WCHAR
+ OLE2A OLE to ANSI
+ OLE2T OLE to TCHAR
+ OLE2W OLE to WCHAR
+ T2A TCHAR to ANSI
+ T2BSTR TCHAR to BSTR
+ T2OLE TCHAR to OLE
+ T2W TCHAR to Wide
+ W2A WCHAR to ANSI
+ W2BSTR WCHAR to BSTR
+ W2OLE WCHAR to OLE
+ W2T WCHAR to TCHAR
+ Refer to the help documentation for instructions on using these functions.
+* Added CLoadString (and LoadString) to return a string resource.
+* OnEraseBkgnd is now called automatically when a CWnd's background needs
+ erasing. Return TRUE to prevent default erasure.
+* Scribble Tutorial now demonstrates the use of command line arguments
+* Enhanced CResizer.
+ - The anchor points are now fixed instead of proportional
+ - Scrollbars are now added when required.
+ - Added the DialogResizing sample to demonstrate CResizer's new features.
+* Create now use a CWnd pointer instead of a HWND when specifying the
+ parent window.
+* Dialogs and Property Sheets now use a CWnd pointer instead of a HWND
+ when specifying the parent window.
+* CTab has been enhanced. The TCS_FIXEDWIDTH and TCS_OWNERDRAWFIXED styles
+ are now optional.
+* Extended the CSize, CPoint and CRect classes
+* Extended CMDIFrame and CMDIChild. CMDIChild::SetHandles is now used to set
+ the MDI child's menu and accelerator table.
+* A docker can now be resized while docked using CDocker::SetDockSize.
+* Extended the "Using Win32++ section of the Win32++ help documentation.
+
+Changes in detail
+-----------------
+- Added CBitmap
+- Added CBrush
+- Added CFont
+- Added CPalette
+- Added CPen
+- Added CRgn
+- Added CTaskDialog
+- Added CLoadString
+- Added LoadString (uses CLoadString, replaces CWnd::LoadString)
+- Added tStringStream typedef (a TCHAR stringstream)
+- Added A2BSTR
+- Added A2OLE
+- Added A2T
+- Added A2W
+- Added OLE2A
+- Added OLE2T
+- Added OLE2W
+- Added T2A
+- Added T2BSTR
+- Added T2OLE
+- Added T2W
+- Added W2A
+- Added W2BSTR
+- Added W2OLE
+- Added W2T
+- Added CDC::AttachPalette
+- Added CDC::CreatePalette
+- Added CDC::CreateHalftonePalette
+- Added CDC::DetachPalette
+- Added CDC::GetBitmap
+- Added CDC::GetBitmapInfo
+- Added CDC::GetBrusg
+- Added CDC::GetBrushInfo
+- Added CDC::GetFont
+- Added CDC::GetFontInfo
+- Added CDC::GetPen
+- Added CDC::GetPenInfo
+- Added CDC::ExtSelectClipRgn
+- Added CDC::ExcludeClipRect
+- Added CDC::GetClipBox
+- Added CDC::GetClipRgn
+- Added CDC::GetRgn
+- Added CDC::IntersectClipRect
+- Added CDC::OffsetClipRgn
+- Added CDC::PtVisible
+- Added CDC::RectVisible
+- Added CDC::SelectClipRgn
+- Added CDialog::AttachItem
+- Added CDockContainer::SetActiveContainer
+- Added CDocker::Close
+- Added CDocker::SetCaptionHeight
+- Added CFrame::GetFrameAccel
+- Added CFrame::ShowMenu
+- Added CMDIChild::GetMDIFrame
+- Added CMDIChild::SetHandles
+- Added CMDIFrame::GetMDIClient
+- Added CMDIFrame::MDICascade
+- Added CMDIFrame::MDIIconArrange
+- Added CMDIFrame::MDIMaximize
+- Added CMDIFrame::MDINext
+- Added CMDIFrame::MDIPrev
+- Added CMDIFrame::MDIRestore
+- Added CMDIFrame::MDITile
+- Added CResizer::GetMaxRect
+- Added CResizer::GetMinRect
+- Added CResizer::HandleMessage
+- Added CTab::GetListMenu
+- Added CTab::SetFixedWidth
+- Added CTab::SetOwnerDraw
+- Added CTabbedMDI::GetListMenu
+- Added CWinApp::SetAccelerators
+- Added CWnd::BeginPaint
+- Added CWnd::ClientToScreen
+- Added CWnd::CheckRadioButton
+- Added CWnd::DlgDirList
+- Added CWnd::DlgDirListComboBox
+- Added CWnd::DlgDirSelectEx
+- Added CWnd::DlgDirSelectComboBoxEx
+- Added CWnd::DrawAnimatedRects
+- Added CWnd::DrawCaption
+- Added CWnd::EndPaint
+- Added CWnd::GetDesktopWindow
+- Added CWnd::GetNextDlgGroupItem
+- Added CWnd::GetNextDlgTabItem
+- Added CWnd::GetSystemMenu
+- Added CWnd::GetUpdateRect
+- Added CWnd::GetUpdateRgn
+- Added CWnd::HiliteMenuItem
+- Added CWnd::IsDialogMessage
+- Added CWnd::IsDlgButtonChecked
+- Added CWnd::MapWindowPoints
+- Added CWnd::OnEraseBkgnd
+- Added CWnd::Print
+- Added CWnd::ScreenToClient
+- Added CWnd::SendNotifyMessage
+- Modified CDialog now takes a CWnd pointer instead of HWND
+- Modified CResizer::AddChild now takes a CWnd reference
+- Modified CWnd::Create now takes a CWnd pointer instead of HWND
+- Modified CWnd::CreateEx now takes a CWnd pointer instead of HWND
+- Moved CWnd::LoadBitmap to LoadBitmap
+- Removed CDC::AttachClipRgn
+- Removed CDC::DetachClipRgn
+- Removed CMDIChild::SetChildMenu
+- Renamed CDocker::GetDockWidth to CDocker::GetDockSize
+- Renamed CDocker::SetDockWidth to CDocker::SetDockSize
+- Renamed CDC::AttachClipRegion to CDC::AttachClipRgn
+- Renamed CDC::DetachClipRegion to CDC::DetachClipRgn
+- Replaced CharToWide with A2W
+- Replaced CharToTChar with A2T
+- Replaced TCharToChar with T2A
+- Replaced TCharToWide with T2W
+- Replaced WideToChar with W2A
+- Replaced WideToTChar with W2T
+- Replaced CWnd::LoadString with CLoadString (and ::LoadString)
+- Added several functions to CPoint
+- Added several functions to CSize
+- Added many functions to CRect
+
+The problem with the previous the text functions
+------------------------------------------------
+While the previous text conversion functions generally worked well, there were
+ambiguities about usage, and corner cases where they produced undesirable
+results. For example:
+// Problem 1
+// This worked well
+ ExampleFunction(CharToTChar(pAnsi1));
+
+// But this failed to produce expected results
+ ExampleFunction(CharToTChar(pAnsi1), CharToTChar(pAnsi2));
+
+Problem 2
+// This worked as expected
+ LPCTSTR pStr = CharToTChar(pAnsi1);
+
+// But this fails to work as expected
+ LPCTSTR pStr1 = CharToTChar(pAnsi1);
+ LPCTSTR pStr2 = CharToTChar(pAnsi2);
+
+The new text conversion functions (classes) resolve problem 1 and render all of
+problem 2's usage invalid (making usage less ambiguous).
+
+Refer to the "Text Conversions" topic in the "Using Win32++" section of the
+help documentation that ships with Win32++ for information on how to use the
+new functions.
+
+Incompatibilities with previous versions
+----------------------------------------
+* The old text conversion functions have been replaced with a set of new functions
+ which look and behave more like the functions used in MFC, ATL and WTL.
+* Windows, dialogs and property sheets now use a CWnd pointer instead of a HWND
+ to specify the parent window.
+* CTab defaults to not using the CS_FIXEDWIDTH and TCS_OWNERDRAWFIXED styles.
+ The SetFixedWidth and SetOwnerDraw functions can be used to change these
+ styles.
+* Users of Borland's C++ compiler version 5.5 will need to install the
+ compiler's service pack 2 for stringsteam support.
+* MDI Children use SetHandles instead of SetChildMenu to set the menu. SetHandles
+ also sets the MDI child's accelerator table (if any).
+* LoadString now returns a tString instead of a LPCTSTR.
+
+Version 7.0.2
+=============
+* Fix for a memory leak in CDC
+* Fix for accelerators in WinCE
+* Fix for menu check marks when themes are disabled
+* Fix for OnMessageReflect in dialogs
+
+Version 7.0.1
+=============
+* Supports the latest version of MinGW compiler
+* DialogProc now returns INT_PTR instead of BOOL
+* Fixed several x64 warnings
+* Fixed DragAcceptFiles error when WIN32_LEAN_AND_MEAN is defined
+* Added OnPaint to CDialog and CPropertyPage
+* Minor update to the documentation
+* Added targetver.h to samples
+* Supports VS2010's resource editor
+
+Incompatibilities with previous versions
+----------------------------------------
+DialogProc now returns INT_PTR instead of BOOL. This change will be required
+in user code as well.
+
+
+Version 7.0
+===========
+
+New Features and Enhancements
+-----------------------------
+* The following function now return CWnd* instead of HWND:
+ GetActiveWindow, GetAncestor, GetCapture, GetFocus, GetDlgItem, GetWindow,
+ GetLastAtivePopup, GetParent, GetTopWindow, SetActiveWindow, SetCapture,
+ SetFocus, and SetParent. This helps the framework to be more object
+ orientated, by allowing the programmer to work more directly with CWnds.
+ It also reduces the need to convert between CWnds and HWNDs in user code.
+ If a CWnd object for the HWND doesn't already exist, Win32++ creates a
+ temporary CWnd. The pointers returned by these functions should not be
+ stored and used later, as they might not be valid then.
+* Added CThread class to simplify the task of using threads and creating
+ windows in different threads. CThread can be used for both worker threads
+ and GUI threads. Refer to the Thread and DirectX samples for examples of
+ how to use CThread to create windows in a different thread. The DirectX
+ sample also uses a customized message loop for the thread.
+* Added the following control wrappers: CAnimation, CComboBox, CComboBoxEx,
+ CProgressBar, CScrollBar, CSlider, and CSpinButton.
+* Renamed CToolbar to CToolBar, CStatusbar to CStatusBar, CRebar to CReBar
+ and CMenubar to CMenuBar. This matches the MFC names, and is also more
+ consistent with Win32++'s naming conventions.
+* Added support for re-sizable dialogs. The CResizer class has been added
+ to dialog.h to facilitate dialog resizing. Refer to the forms sample for
+ an example of how to put CResizer to use.
+* Added IPv6 support to CSocket. The network samples have been updated to
+ take advantage of IPv6 support. IP version 6 is supported on Vista
+ operating systems and newer.
+* Added Shared_Ptr class. Note that a "shared_ptr" will be available for the
+ updated C++ standard. It is already available with some modern compilers,
+ and also for users of the Boost library. The "Shared_Ptr" class is intended
+ as an alternative for those users who would like to use a "shared_ptr", but
+ don't have access to one yet. Unlike auto-ptr's, shared_ptr's can be used
+ to safely store pointers in vectors and other STL containers.
+* Extended the CToolbar class.
+* Added the GDIPlus sample to demonstrate how to use the GDIPlus library
+ provided with modern Windows operating systems (XP and above).
+* Win32++ can now be run from inside a DLL. The "DLL" sample demonstrates how to
+ put a Win32++ dialog in a dll, and run it from a test program.
+* Dialogs and Property Sheets now use DWLP_MSGRESULT to automatically handle the
+ value returned by notifications in their message handling. This allows a
+ dialog's controls to use custom draw.
+* Improved the appearance of frames without themes. The frame sample demonstrates
+ how override CMainFrame::OnCreate to customize the frame's appearance.
+* Asserts are used more liberally to test for programming errors. Any message
+ sent to a non-existent window, for example, will now assert. More asserts
+ are intended to help users write code that is more robust. Note that asserts
+ are only evaluated in Debug mode, and have no effect in Release mode.
+* Exceptions are thrown less often. They are now thrown to indicate a critical
+ problem, outside the programmer's control. Throwing fewer exceptions results
+ in slightly smaller executables, and gives users more flexibility and
+ control over their own exception methodology. They are thrown when:
+ - a window creation fails.
+ - a critical dll cannot be loaded.
+ - a window message cannot be routed to a CWnd object.
+ - an attempt to read from or write to the registry fails unexpectedly.
+* Vectors are now used as a replacement for all dynamically allocated arrays,
+ ensuring the arrays are automatically deleted when they go out of scope.
+ Creating an array with "new" runs the risk of causing a memory leak,
+ particularly when an exception is thrown. Using a vector to create the
+ array guarantees that it will be deleted properly under all circumstances.
+* The OnPaint function now uses a CDC reference as its argument instead of a
+ HDC. This simplifies the task of using a CDC when overriding OnPaint.
+* Extended the help documentation.
+
+Changes in detail
+-----------------
+Added CAnimation
+Added CComboBox
+Added CComboBoxEx
+Added CProgressBar
+Added CResizer
+Added CScrollBar
+Added CSlider
+Added CSpinButton
+Added Shared_Ptr
+Added CThread
+Updated CSocket to support IPv6
+Added CMDIChild::MDIActivate
+Added CMDIChild::MDIDestroy
+Added CMDIChild::MDIMaximize
+Added CMDIChild::Restore
+Added CPropertySheet::SetIcon
+Added CPropertyPage::SetWizardButtons
+Added CPropertyPage::QuerySiblings
+Added CRebar::SizeToRect
+Added CSocket::IsIPV6Supported
+Added CSocket::FreeAddrInfo
+Added CSocket::GetAddrInfo
+Added CSocket::GetLastError
+Added CTabbedMDI::SetActiveMDITab
+Added CToolBar::AddButtons
+Added CToolBar::AddString
+Added CToolBar::AutoSize
+Added CToolBar::CheckButton
+Added CToolBar::DeleteButton
+Added CToolBar::GetButton
+Added CToolBar::GetButtonSize
+Added CToolBar::GetButtonText
+Added CToolBar::GetDisabledImageList
+Added CToolBar::GetHotItem
+Added CToolBar::GetImageList
+Added CToolBar::GetPadding
+Added CToolBar::GetRect
+Added CToolBar::GetRows
+Added CToolBar::GetTextRows
+Added CToolBar::GetToolTips
+Added CToolBar::HideButton
+Added CToolBar::Indeterminate
+Added CToolBar::InsertButton
+Added CToolBar::IsButtonHidden
+Added CToolBar::IsButtonHighlighted
+Added CToolBar::IsButtonIndeterminate
+Added CToolBar::IsButtonPressed
+Added CToolBar::MapAccelerator
+Added CToolBar::MarkButton
+Added CToolBar::MoveButton
+Added CToolBar::PressButton
+Added CToolBar::SaveRestore
+Added CToolBar::SetDisabledImageList
+Added CToolBar::SetDrawTextFlags
+Added CToolBar::SetExtendedStyle
+Added CToolBar::SetHotImageList
+Added CToolBar::SetHotItem
+Added CToolBar::SetImageList
+Added CToolBar::SetIndent
+Added CToolBar::SetMaxTextRows
+Added CToolBar::SetPadding
+Added CToolBar::SetToolTips
+Added CWinException::what
+Added CWnd::DragAcceptFiles
+Added CWnd::GetActiveWindow
+Added CWnd::GetCapture
+Added CWnd::GetFocus
+Added CWnd::GetFont
+Added CWnd::GetIcon
+Added CWnd::GetLastActivePopup
+Added CWnd::GetTopWindow
+Added CWnd::GetWindowTextLength
+Added CWnd::OpenIcon
+Added CWnd::SetFont
+Added CWnd::SetIcon
+Added CWnd::SetWindowTheme
+Added CWnd::ShowOwnedPopups
+Added CWnd::ShowWindowAsync
+Added CWnd::WindowFromDC
+Added ::IsAeroThemed
+Modified CPropertyPage::Apply now returns int
+Modified CPropertyPage::OnKillActive now returns BOOL
+Modified CPropertyPage::OnOK now returns int
+Modified CPropertyPage::OnSetActive now returns int
+Modified CPropertyPage::OnWizardBack now returns int
+Modified CPropertyPage::OnFinish now returns BOOL
+Modified CPropertyPage::OnWizardBack now returns int
+Modified CPropertyPage::OnWizardFinish now returns BOOL
+Modified CPropertyPage::OnWizardNext now returns int
+Modified CSocket::Bind now uses TCHAR instead of char
+Modified CSocket::Connect now uses TCHAR instead of char
+Modified CSocket::Receive now uses TCHAR instead of char
+Modified CSocket::ReceiveFrom now uses TCHAR instead of char
+Modified CSocket::Send now uses TCHAR instead of char
+Modified CSocket::SentTo now uses TCHAR instead of char
+Modified CWinException::what now outputs text to debugger
+Modified CWnd::OnPaint now takes a CDC& argument instead of HDC
+Renamed CMenubar to CMenuBar
+Renamed CRebar to CReBar
+Renamed CStatusbar to CStatusBar
+Renamed CToolbar to CToolBar
+Renamed RebarTheme to ReBarTheme
+Renamed ToolbarTheme to ToolBarTheme
+Renamed CToolBar::AddToolbarButton to CToolBar::AddButton
+Moved CWnd::CharToTChar to ::CharToTChar
+Moved CWnd::CharToWide to ::CharToWide
+Moved CWnd::TCharToChar to ::TCharToChar
+Moved CWnd::TCharToWide to ::TCharToWide
+Moved CWnd::WideToChar to ::WideToChar
+Moved CWnd::WideToTChar to ::WideToTChar
+Removed CWinException::MessageBox
+Removed CPropertySheet::QuerySiblings
+
+Added DS_NO_CLOSE style to suppress the closing of docked dockers
+Added DS_FIXED_RESIZE style to perform a fixed (not proportional) resize
+ on dock children
+Added WM_PAINT handler to CDialog::DialogProcDefault
+Added WM_PAINT handler to CPropertyPage::DialogProcDefault
+
+Added GDIPlus sample
+Updated Network samples
+Updated FormDemo sample
+
+Incompatibilities with previous versions
+----------------------------------------
+* The OnPaint function definition has changed to:
+ virtual void OnPaint(CDC& dc);
+ The older OnPaint function will be ignored.
+* The stricter testing with asserts might reveal previously hidden errors in
+ user's code.
+* Some CSocket functions take TCHAR as an argument instead of char.
+* CFrame::LoadRegistrySettings, CFrame::LoadRegistryMRUSettings and
+ CFrame::SaveRegistrySettings return BOOL.
+* CPropertySheet.m_PSH is now private. Use SetIcon to set the icon.
+* CPropertyPage change the return types of several functions.
+* Replace all instances of "Menubar" with "MenuBar"
+* Replace all instances of "Rebar" with "ReBar"
+* Replace all instances of "Statusbar" with "StatusBar"
+* Replace all instances of "Toolbar" with "ToolBar"
+* The following functions now return a CWnd pointer instead of a HWND:
+ GetActiveWindow, GetAncestor, GetCapture, GetFocus, GetDlgItem, GetWindow,
+ GetLastAtivePopup, GetParent, GetTopWindow, SetActiveWindow, SetCapture,
+ SetFocus, and SetParent.
+
+
+Version 6.9
+===========
+
+New Features and Enhancements
+-----------------------------
+* Added a WebBrowser class called CWebBrowser. This class provides a web
+ browser in a window. This class can be used as a view window anywhere
+ view windows are used, such as in frames, dockers, MDI Children,
+ Tabbed MDIs etc. It has no dependence on ATL, greatly simplifying the
+ approach to adding a browser window to any application. It can be compiled
+ by any of the supported compilers including Dev-C++, MinGW and the Borland
+ compilers as well as the compilers from Microsoft.
+* Added an ActiveX host class called CAXWindow.
+* The CTab, CMDITab, CDocker and CDockContainer classes are now flicker free,
+ providing a more professional look during resizing and docker moving.
+* Improved the dock targeting and dock hinting.
+* Introduced a new set of text conversion functions to convert between Ansi,
+ Unicode and Wide characters.
+* CWnd objects can now report their type with GetWindowType.
+* Modified the Browser sample to use the new CWebBrowser class. It also
+ demonstrates how to use an event sink to get notification of browser events.
+* Added a Tray sample which demonstrates how to create an application
+ which can be minimised to the system tray, and restored.
+* The visual editor that ships with VS2008 and VS2010 can now be used to
+ modify the resource files (Resource.rc and resource.h) without mangling them.
+
+Changes in detail
+-----------------
+Added CAXWindow
+Added CWebBrowser
+Added CWnd::CharToWide
+Added CWnd::WideToChar
+Added CWnd::TCharToWide
+Added CWnd::WideToTChar
+Added CWnd::CharToTChar
+Added CWnd::TCharToChar
+Added CWnd::GetClassName
+Added CWnd::GetDlgItemText
+Added CWnd::GetWindowText
+Added CWnd::GetWindowType
+Added CWnd::KillTimer
+Added CWnd::SetTimer
+Added GetSizeofMenuItemInfo
+Removed CharToTString
+Removed TCharToString
+Removed TCharToWide
+Removed CWnd::GetWindowString
+Removed CWnd::GetClassString
+Removed CWnd::GetDlgItemString
+Removed CWnd::IsContainer
+Removed CWnd::IsDocker
+Removed CWnd::IsFrame
+Removed CWnd::IsMenubar
+Removed CWnd::IsMDIChild
+Removed CWnd::IsMDIFrame
+Removed CWnd::IsRebar
+Removed CWnd::IsStatusbar
+Removed CWnd::IsTab
+Removed CWnd::IsTabbedMDI
+Removed CWnd::IsToolbar
+Renamed CContainer to CDockContainer
+
+Modified Browser Sample
+Added MDIFrameSplitter demo
+Added Tray demo
+
+
+Incompatibilities with previous versions
+----------------------------------------
+* CContainer has been renamed to CDockContainer
+* The global string functions CharToTString, TCharToString and TCharToWide have
+ been replaced with CWnd::CharToWide, CWnd::WideToChar, CWnd::TCharToWide,
+ CWnd::WideToTChar, CWnd::CharToTChar and CWnd::TCharToChar.
+
+
+Version 6.8
+===========
+
+New Features
+------------
+* Support has been added for the Windows Ribbon Framework available on
+ Windows 7 operating systems. The RibbonFrame and RibbonSimple samples
+ demonstrates how to implement the ribbon. RibbonFrame reverts back to
+ using the traditional Toolbar and Menubar if the operating system doesn't
+ support the ribbon framework.
+
+* Helper classes have been added for the standard controls, namely the Button,
+ Edit, Listbox, and Static controls.
+
+* Dockers can now be hidden and unhidden. Refer to the Splitter sample for a
+ demonstration of this feature.
+
+* Modal dialogs now support pretranslated messages.
+
+
+Changes
+-------
+Added CButton class
+Added CEdit class
+Added CListBox class
+Added CRibbon class
+Added CRibbonFrame class
+Added CStatic class
+Removed CSplitter class
+
+Added CDocker::Dock
+Added CDocker::DockInContainer
+Added CDocker::Hide
+Added CDocker::Undock
+Added CDocker::UndockContainer
+Added CFrame::GetRebarTheme
+Added CFrame::GetToolbarTheme
+Added CFrame::GetMRUEntries
+Renamed ThemeMenu to MenuTheme
+Renamed ThemeRebar to RebarTheme
+Renamed ThemeToolbar to ToolbarTheme
+Renamed CFrame::GetThemeMenu to CFrame::GetMenuTheme
+
+Added UWM_GETMENUTHEME message
+Added UWM_GETREBARTHEME message
+Added UWM_GETTOOLBARTHEME message
+
+Added RibbonFrame sample
+Added RibbonSimple sample
+
+Added 'Compile VS2005 Express' tool
+Added 'Compile VS2008 Express' tool
+Added 'Compile VS2010 Express' tool
+
+Added PreTranslate Message support for modal dialogs
+
+Bug Fixes
+---------
+- Fixed TCharToString
+- Dockers can now be used as the view for CMDIChild
+
+Version 6.7
+===========
+Bug fixes:
+- Fixed dialog destruction
+- Fixed thread safety when creating multi-threaded windows simultaneously
+- Fixed TintBitmap for 16 bit colours
+- The close button on docked dockers now works.
+- Fixed PreTranslateMessage
+
+Changes
+-------
+* The directory layout of Win32++ has changed. It now contains the following
+ folders:
+ help The help for Win32++
+ include The Win32++ library for typical use
+ lib The static library files when they are build
+ Library Projects The project files used to build the static library
+ new projects A set of projects to be used in your new projects
+ src The Win32++ library for building the static library
+ tests A directory which contains the output of some tools
+ tools A set of useful batch files for Win32++
+
+* The Win32++ include directory is specified within the project rather than
+ hard coded into the source files. To specify a different location for the
+ Win32++ files in a project, specify the "Additional Include Directories" for
+ both "C/C++" and "Resources".
+
+* The projects now provide the option of compiling with a static library or
+ directly from the file in Win32++\include. To build the static libraries,
+ see below.
+
+* A set of projects have been supplied to build the Win32++ into a static
+ library. These projects are contained within the Win32++\Library Projects
+ folder. The lib file created is placed within the lib directory.
+
+* The projects are now configured to take advantage of precompiled headers.
+
+* A set of tools is now provided in the tools folder. They include a set of
+ batch files for compiling the examples and batch files to "clean" them.
+
+* The CDC class has been extended. Several functions have been added, and
+ CDC::GetDC has been renamed to CDC::GetHDC.
+
+* Support has been added for Right to Left languages which include Hebrew and
+ Arabic. The CFrame and CDocker classes now honour the WS_EX_LAYOUTRTL
+ extended style used by these languages. To take advantage of this feature,
+ use PreCreate to set this extended when using CFrame, CMDIFrame, CTab,
+ CTabbedMDI, and CDocker.
+
+* OnInitialUpdate is now called after Attach or AttachDlgItem.
+
+* IsChild now takes a HWND argument.
+
+* Win32++ is now available as a single download, rather than a collection of
+ files.
+
+* Each program example now has a Readme.txt file which describes what it does,
+ and the features it demonstrates.
+
+
+Version 6.6
+===========
+Changes
+-------
+* The number of arguments have changed for WndProc and WndProcDefault.
+ - The HWND parameter has been dropped in both of these functions. It's
+ presence was redundant and possibly confusing. Users will need to modify
+ their WndProc and WndProc functions accordingly. If needed, the m_hWnd
+ member variable can be used in place of hwnd within the WndProc function.
+* The number of arguments have changed for DialogProc and DialogProcDefault.
+ - The HWND parameter has been dropped in both of these functions. It's
+ presence was redundant and possibly confusing. Users will need to modify
+ their WndProc and WndProc functions accordingly. If needed, the m_hWnd
+ member variable can be used in place of hwnd in the WndProc function.
+* Enhancements to docking, containers and tabs.
+ - By default the dockers are immediately resized while the splitter bar is
+ being dragged. To defer resizing until the splitter bar is released, use
+ SetDragAutoResize(FALSE).
+ - The close and list buttons now indicate when they are hot and pressed.
+ - Added SetTabText, SetTabImage and SwapTabs to the CTab class.
+ - Minor improvements to the painting of tabs, containers and dockers.
+* Enhancements to GDI graphics support.
+ - The CDC class has been extended. It now includes wrapper functions for
+ the Device Context related functions.
+ - Added the CBitmapInfoPtr class. This simplifies the use of the BITMAPINFO
+ structure in functions like GetDIBits and SetDIBits.
+ - Added GrayScaleBitmap function to gdi.h. It converts a colored bitmap to
+ to gray-scale.
+* Automated menu updating.
+ - When a menu is about to be displayed, OnUpdateMenu is called to provide
+ an opportunity to modify the check state of the menu items.
+* Enhancements to frames
+ - The style of the rebarband is now specified in AddToolbarBand. This
+ facilities saving and restoring toolbar settings from the registry (as
+ demonstrated in the Themes example.)
+ - The Frame's ShowToolbar and ShowStatusbar states are now saved in the
+ registry.
+* Modification to CRect class
+ - The various function now use references instead of naked pointers.
+* Updated the Themes example.
+ - Added check boxes for the various rebar theme option
+ - Added Hide/Show option for the additional toolbars
+ - Save/Load the theme options in the registry
+ - Save/Load the rebar band positions and styles in the registry
+* Replaced the Form example with the DocViewForm example.
+ - This example now demonstrates a form using a Doc/View architecture, much
+ like the traditional Doc/View of MFC.
+ - Added OnUpdateMenu handling.
+* Updated the FastGDI example.
+ - Added gray-scale transformation
+ - Added file save.
+ - Added Scroll bars.
+* Updated the picture example.
+ - Added Scroll bars.
+* Updated the DockContainer and DockTabbedMDI examples
+ - These examples now demonstrate how to theme a container's toolbar.
+
+
+Incompatibilities with previous versions
+----------------------------------------
+- WndProc now takes 3 arguments, not 4:
+ WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+- WndProcDefault now takes 3 arguments, not 4:
+ WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+- DialogProc now takes 3 arguements, not 4:
+ DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+- DialogProcDefault now takes 3 arguements, not 4:
+ DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+- CFrame::AddToolbarBand now requires three arguements
+- The various CRect functions use references to RECT rather than pointers
+- CWnd::IsVisable has been renamed to CWnd::IsWindowVisible
+- CWnd::IsEnabled has been renamed to CWnd::IsWindowEnabled
+
+Version 6.5
+===========
+Major Changes
+-------------
+* Added StaticLibrary example
+ This example has the code to build Win32++ into a a static library, and also
+ demonstrates the use of Precompiled Headers. More experienced users might
+ prefer this approach as it provides for much faster compile times.
+* Added CTab class.
+ This class is used by CContainer and CTabbedMDI, and can also be used as a
+ view window.
+* Added TabDemo example.
+ Refer to the TabDemo example for a demonstration of how CTab class is
+ used as a view window in a frame. TabDialogDemo also uses CTab.
+* Added CTabbedMDI class.
+ A TabbedMDI can be used as a view window for a Frame or a Dockable. As the
+ name suggests, it provides tabs for a MDI window.
+* Added TabbedMDI example within docking.
+ Refer to the docking TabbedMDI example for a demonstration of how CTabbedMDI
+ class is used.
+* Enhancements to docking.
+ - Dockers can now be docked into, and undocked from all other dockers,
+ including those that are undocked.
+ - Containers can also be docked into and undocked all from containers,
+ including those that are undocked.
+ - Containers can display their tabs at the top or bottom of the window.
+ - Containers can also display a tab list button.
+ - Docker and container objects are destroyed when their window is closed.
+ - CContainer::SetupToolbar can be used to specify the toolbar's resource IDs.
+ - Dockers and containers can save their layout in and load their layout from
+ the registry.
+* Improvements to toolbars
+ - Resource IDs should be specified in SetupToolbar, rather than CMainFrame's
+ constructor.
+ - Other configurations for the toolbar such as disabled buttons and alternate
+ bitmaps should be specified in SetupToolbar, rather than in OnCreate.
+ - Configuration of additional toolbars if any should also be done in
+ SetupToolbar. Refer to the Themes example for a demonstration of this.
+ - CToolbar now holds the vector of Resource IDs, which can be retrieved
+ with the GetToolbarData function. There is no need to specify a vector
+ when adding additional toolbars.
+ - There is now no need to specify the number of toolbar buttons in the
+ AddBitmap, ReplaceBitmap, SetBitmap and SetImages functions.
+ - The AddToolbarButton can now add a toolbar button which is initially
+ disabled.
+ - There is no need to call SetButtons when adding additional toolbars.
+ - Tooltips for all toolbars in the rebar are now displayed.
+* MIN and MAX macros have been defined and can be used in place of min and max.
+ This avoids incompatibilities between the way different compliers support
+ these macros. It also avoids clashes between the macro definitions of
+ min and max, and the STL definitions of min and max.
+
+All Changes
+-----------
+Added CTab class
+Added CTabbedMDI class
+Added TabDemo example
+Added Docking TabbedMDI example
+Added CFrame::SetupToolbar
+Added CFrame::m_bUseToolbar
+Added CContainer::SetupToolbar
+Added CDocker::GetDockTopLevel
+Added CDocker::GetContainer
+Added CDocker::GetTabbedMDI
+Added CDocker::IsRelated
+Added CDocker::LoadRegistrySettings
+Added CDocker::NewDockerFromID
+Added CDocker::SaveRegistrySettings
+Added CToolbar::GetToolbarData
+Added CWnd::GetClassString
+Added CWnd::IsFrame
+Added CWnd::IsMenubar
+Added CWnd::IsRebar
+Added CWnd::IsTabbedMDI
+Added CWnd::IsToolbar
+Changed CFrame::SetToolbarImages
+Changed CToolbar::SetImages
+Changed CToolbar::SetBitmap
+Changed CToolbar::AddBitmap
+Changed CToolbar::ReplaceBitmap
+Renamed CDockable to CDocker
+Renamed CDocker::CheckDockables to CDocker::VerifyDockers
+Renamed CFrame::OnFrameDrawItem to CFrame::OnDrawItem
+Renamed CFrame::OnFrameExitMenuLoop to CFrame::OnExitMenuLoop
+Renamed CFrame::OnFrameInitMenuPopup to CFrame::OnInitMenuPopup
+Renamed CFrame::OnFrameMeasureItem to CFrame::OnMeasureItem
+Renamed CFrame::OnFrameClose to CFrame::OnClose
+Renamed CFrame::OnFrameNotify to CFrame::OnNotify
+Renamed CFrame::OnFrameSetFocus to CFrame::OnSetFocus
+Renamed CFrame::OnFrameSysColorChange to CFrame::OnSysColorChange
+Renamed CFrame::OnFrameTimer to CFrame::OnTimer
+Removed OnFrameCommand
+
+Incompatiblities with previous versions
+---------------------------------------
+- Many of the functions associated with adding toolbars to frames have changed.
+ CFrame::SetupToolbar should be overridden to perform toolbar configuration.
+ Refer to the Themes example for a demonstration of how to add multiple toolbars
+ to a frame.
+- The renaming of the CFrame::OnXXXX may affect overloading. Calling the base
+ function may now be required particularly for CFrame::OnNotify.
+- The OnCommand handlers for OnViewStatusbar and OnViewToolbar have been removed
+ from CFrame, and should be added to CMainFrame::OnCommand if required.
+- CDocker has been renamed to CDocker
+- dockable.h has been renamed to docking.h
+
+Version 6.4.1
+=============
+This release has the following bug fixes:
+- Assertions in CContainer reported by VS2005(express) and VS2008(express)
+- Definition of OPENFILENAME_SIZE_VERSION_400 added for VS6
+
+Version 6.4
+===========
+
+Major Changes
+------------
+* Docking:
+ - Added tabbed docking container with optional toolbar
+ - Added close button to the caption of docked windows
+ - Added 'outer' docking ie. docking at the side of the frame rather
+ than inside another Docker.
+ - Added a second docking example demonstrating containers
+ - Added save/restore dock layout to docking examples
+ - Added Close All Dockables and Default Dock Layout to docking examples
+ - Added Win98 and WinME support for docking.
+* Added Region support to CDC class.
+* Notepad example enhancements:
+ - Now capable of handling Unicode text
+* Themes example now demonstrates a ComboBoxEx control in its toolbar
+
+
+Fixes
+-----
+Various fixes to docking, including:
+ - Fixed Z order of undocked windows
+ - Fixed focus for child windows
+ - Improved undocking
+ - Reduced flicker
+ - Better sizing of docked windows
+
+Incompatibilities with previous versions
+----------------------------------------
+* CWnd::m_hWndParent has been removed. Use GetParent() in its place.
+* Some functions have been added to CWnd which have the same name as their
+ Win32 counterparts. Prefix functions with the global scope specifier '::'
+ to use the original Win32 API function instead of the Win32++ version.
+* CSplitter has been superseded by CDocker. Use a CDocker with the
+ DS_NO_UNDOCK and DS_NO_CAPTION styles to duplicate the behaviour of
+ CSplitter. CSplitter will be retained for backwards compatibility, as
+ well as for those who require its 'immediate' mode.
+
+More About Docking Containers
+-----------------------------
+A container can be used is a view window for a frame, MDI child, dockable etc.
+It has a tab control, and is capable of containing and displaying other
+containers. Each container will in turn have a view window of its own. The view
+for each container as well as it's toolbar (if any) is displayed in the tab's
+page. When used as the view window of a dockable, the container also permits
+ docking and undocking of it's containers.
+
+In Summary:
+* Any CWnd object inherited from CContainer is capable of containing other CWnd
+ objects inherrited from CContainer. There is no theoretical limit as to the
+ number of containers that can be contained.
+* A child container (a container contained within another) can not in turn
+ contain other containers.
+* Containers have a View window, just like Frames, MDI children and dockables.
+* Containers can set an icon and text for the tab, as well as text for the
+ docking caption.
+* Containers can optionally include a toolbar.
+* When a container contains other containers, each container's view is displayed
+ in a separate tab.
+* When a container is the view window for a dockable, any container children
+ can be individually undocked from their parent container.
+* When used a the view for a docker, a container with child containers can be
+ undocked as a group.
+* An undocked container group (container with children) can be docked as a
+ group inside another docked container.
+
+
+Version 6.3
+===========
+
+Major Changes
+-------------
+* Added support for docking. See below for more information on Docking
+ - Note: CDocker is now recommended over CSplitter for splitter apps.
+* Added the Fast GDI demo. This demonstrates the use of the TintBitmap function.
+* MDI child windows now require a view window. The use of a view window is
+ now the same for Frames, MDI children, and dockables. The MDI demo example
+ has been extended to include ListView and TreeView views.
+* Added message translation. This allows modeless dialogs and propertysheets
+ to process the tab (and other) keys.
+* Added a CWnd::Destroy function. This returns a CWnd back to its default
+ state ready to be reused.
+* SetView can now be used to change the frame's view from one CWnd to
+ another.
+* The Frame now stores which child window had focus before it is de-activated,
+ and returns focus to this child when the frame application is reactivated.
+
+
+Fixes
+-----
+* CFrame now supports Extra Large fonts in the menu and status bar. Also, font
+ size can be changed while the application is running.
+* 16Bit colours (and grey-scale) are now rendered properly
+* Tabbing now works for modeless dialogs and property sheets
+ (uses PreTranslateMessage).
+
+
+Incompatibilities with previous versions
+----------------------------------------
+* MDI Child windows now require a view. Refer to the MDI Demo example for an
+ example of how to add views to a MDI child.
+* Some functions have been added to CWnd which have the same name as their
+ Win32 counterparts. Prefix functions with the global scope specifier '::'
+ to use the original Win32 API function instead of the Win32++ version.
+
+
+More About Docking
+------------------
+* Any CWnd object inherited from CDocker is capable of docking other CWnd
+ objects inherrited from CDocker.
+* Dockables can be docked in any of the 4 sides. Any number of windows can be
+ docked on a side.
+* A dockable could be docked inside another dockable which in turn is docked
+ inside another. There is no theoretical limit as to depth of dockables
+ within dockables.
+* Dockables have a View window, just like the Frame, and MDI children.
+* Dockables are separated by a movable splitter bar.
+* Dockables use a modern style of dock targeting and dock hinting (the same
+ as Visual Studio 2005 and 2008).
+* Dockables can have styles including:
+ - DS_NOTDOCKED
+ - DS_DOCKED_LEFT
+ - DS_DOCKED_RIGHT
+ - DS_DOCKED_TOP
+ - DS_DOCKED_BOTTOM
+ - DS_NODOCKCHILD_LEFT
+ - DS_NODOCKCHILD_RIGHT
+ - DS_NODOCKCHILD_TOP
+ - DS_NODOCKCHILD_BOTTOM
+ - DS_NO_RESIZE
+ - DS_NO_CAPTION
+ - DS_NO_UNDOCK
+* CDocker is now the recommended alternative to CSplitter (being much simpler
+ to implement - see the example below). The DS_NO_CAPTION and DS_NO_UNDOCK
+ styles should be specified if docking and undocking are not required.
+
+Example of how to dock 8 dockables inside a dockable view:
+----------------------------------------------------------
+void CMainFrame::OnInitialUpdate()
+{
+ // CTextDockable in inherited from CDocker
+ CDocker* pDockLeft = m_DockView.AddDockedChild(new CTextDockable, DS_DOCKED_LEFT, 100);
+ CDocker* pDockRight = m_DockView.AddDockedChild(new CTextDockable, DS_DOCKED_RIGHT, 100);
+ CDocker* pDockTop = m_DockView.AddDockedChild(new CTextDockable, DS_DOCKED_TOP, 100);
+ CDocker* pDockBottom = m_DockView.AddDockedChild(new CTextDockable, DS_DOCKED_BOTTOM, 100);
+
+ // Dock 4 dockables inside other dockables
+ pDockLeft->AddDockedChild(new CTextDockable, DS_DOCKED_BOTTOM, 100);
+ pDockRight->AddDockedChild(new CTextDockable, DS_DOCKED_BOTTOM, 100);
+ pDockTop->AddDockedChild(new CTextDockable, DS_DOCKED_RIGHT, 100);
+ pDockBottom->AddDockedChild(new CTextDockable, DS_DOCKED_RIGHT, 100);
+}
+
+(Refer to the Docking example for an example of to use CDocker.)
+
+
+Version 6.2
+===========
+
+Changes
+-------
+* The default colour scheme has been changed from blue to grey.
+ The blue, olive and silver colour schemes continue to be used on Windows XP
+ with themes enabled.
+
+New Features
+------------
+* Frame applications now store the window size and position in the registry.
+To enable this, set the m_KeyName member variable in CMainFrame's constructor.
+This member variable can be used to reflect the company name and application
+name, for example:
+ m_KeyName = _T("SomeCompany\\SomeApp");
+
+* Frame applications now provide a Most Recently Used (MRU) list. This list is
+stored in the registry.
+
+* Extended CWnd
+CWnd now includes functions which wrap many of the Windows API functions that
+affect to windows.
+
+
+Version 6.1
+===========
+
+New Features
+------------
+* All Win32++ code has been moved to header files.
+This simplifies the use of Win32++. To add Win32++ to a project, simply
+include the appropriate Win32++ header files in your code. There is no longer
+any need to add the Win32++ files to the project, although doing so may
+still prove useful under some circumstances. Depending on the compiler/IDE
+used, adding the Win32++ header files to the project may add the various
+Win32++ classes to the class view.
+
+* Added CListView class.
+This class encapsulates the various messages and macros used by the Win32/64
+API to manage the List-View common control. You can inherit from this class
+when creating your own List-View control in a window, or attaching a
+List-View control from a dialog.
+
+* Added CTreeView class.
+This class encapsulates the various messages and macros used by the Win32/64
+API to manage the Tree-View common control. You can inherit from this class
+when creating your own Tree-View control in a window, or attaching a
+Tree-View control from a dialog.
+
+* Added CPoint CRect and CSize classes
+The CPoint, CRect and CSize classes can be used anywhere a POINT, RECT
+or CSize struct can be used respectively. In addition:
+- The constructors ensure that members are set to reasonable values.
+ They also allow a default value to be set when the class is used as a
+ function argument.
+- The classes have additional member functions, including operator==
+ and operator!= .
+- These classes makes porting code from MFC or WTL a little easier.
+
+* Extended the CRebar, CToolbar and CStatusbar classes.
+
+
+Version 6.0.2
+=============
+
+New Features
+------------
+* Added support for x64 applications.
+
+Win32++ can now be used to build 64 bit applications. The manifest file has
+been modified to support both 32bit and 64bit applications. The new manifest
+should be used for any 64 bit applications that use common controls.
+
+Users are encouraged to use the modern Win64 API functions like:
+GetWindowLongPtr, SetWindowLongPtr, GetClassLongPtr and SetClassLongPtr.
+Win32++ will convert these back to their Win32 API counterparts if required.
+
+
+Version 6.0.1
+=============
+Added CFrame::SetMenuIcons
+Added CFrame::SetToolbarImages
+Removed CToolbar::SetToolbarImageList
+Added CToolbar::SetBitmap
+Moved CreateDisabledImageList to CFrame::CreateDisabledImageList
+Modified CFrame::AddMenuIcons
+
+New Features:
+------------
+* 32 bit bitmaps are now supported for toolbars (requires XP or Vista)
+* SetMenuIcons and AddMenuIcons now also accept a bitmap for disabled icons
+ in addition to the bitmap for normal icons.
+
+
+Version 6.0
+===========
+
+New Features
+------------
+* Win32++ now also directly supports the Windows CE operating systems.
+ Windows CE is the operating system used on such things as Pocket PCs,
+ embedded systems and SmartPhones. The Win32++ examples for Windows CE
+ include the project files for eMbedded Visual C++ 4.0, and Visual
+ Studio 2005.
+
+* Added Networking support. Win32++ now includes a CSocket class which
+ encapsulates much of the Winsock API. This class is capable of monitoring
+ network events, such as connection requests from clients, and notification
+ that the socket has data ready to be received. Command line and dialog
+ examples are provide to demonstrate how the class can be used to create
+ TCP/IP (and UDP/IP) servers and clients.
+
+* Added a CDC class. This class simplifies the drawing to device contexts.
+ This class can be used anywhere we would normally use a handle to a
+ device context (HDC). Its features include:
+ - Automates the selection of GDI objects into the device context.
+ - Automates the destruction of GDI objects.
+ - Automates the deletion or release of the device contexts.
+
+* PreRegisterClass can now be used to set the WNDCLASS parameters before the
+ window class is registered. This provides a convenient way to set a window's
+ background brush or cursor.
+
+* Improvements to tracing. It now uses OutputDebugString to send the trace
+ output the debug/output pane of the various IDE's. This is now also
+ compatible with debuggers, should you choose to use them. Previously the
+ tracing created a separate window to display text.
+
+* Added an immediate mode to CSplitter. There is now the choice of resizing
+ the panes while the splitter bar is being dragged, or defer the resizing
+ until the splitter bar drag is complete (as before). CSplitter's
+ constructor now requires no arguments, making the class simpler to use.
+
+* Automatically detects the XP theme used (Default, Silver or Olive), and
+ adjusts the theme colors accordingly.
+
+* Added project files for Borland's Turbo C++ 2006. This is a free compiler
+ available from Borland. It can be downloaded here:
+ http://www.codegear.com/downloads/free/turbo
+
+* Enhanced the tutorial. It now also demonstrates file operations and printing.
+
+
+Version 5.6
+===========
+* Property Sheets are now supported. The files PropertySheet.cpp and
+ PropertySheet.h have been added to Win32++. These files define
+ the CPropertySheet and CPropertyPage classes. The Property sheet generic
+ demonstrates the following:
+ - Modal property sheets.
+ - Modeless property sheets.
+ - Wizards.
+
+
+Version 5.5
+===========
+* Added Menubar theme support
+ - Gradient background for hot buttons (any two colors)
+ - Gradient background for pressed buttons (any two colors)
+ - Gradient Sidebar for menu items based on pressed button colors.
+ - A border color for Menubar buttons and selected menu items
+
+
+Version 5.4
+===========
+* Added Rebar themes, including:
+ - Gradient background for the rebar control (any two colors)
+ - Gradient background for the rebar bands (any two colors)
+ - The Menubar can be locked in place.
+ - The bands can be kept left.
+ - Short bands
+ - Bands can have rounded borders
+ - Bands with rounded borders can have a flat style
+* Added Toolbar themes, including:
+ - Gradient background for hot buttons (any two colors)
+ - Gradient background for pressed buttons (any two colors)
+ - Colored outline for hot and pressed buttons (any color)
+* Built in support for multiple toolbars (in rebars) with AddToolbarBand
+* Added Forms example
+* Added Themes example
+
+
+Version 5.3
+===========
+* Owner drawn drop down menu items with icons. CMenubar::SetIcons is
+ used to determine which menu items display an icon. By default, the
+ framework uses the toolbar's bitmap and resource IDs for displaying
+ icons. Override CFrame::SetButtons to change this behavior.
+* Automatic subclassing for windows using Windows API defined window classes.
+ Now when a window is based on predefined window classes, like the
+ common controls (e.g. list-view, tree-view, richedit), the window is
+ automatically subclassed. There is now no need to call the subclass
+ function in user code.
+
+
+Version 5.2
+===========
+* Added a separate HINSTANCE for resources. This provides for multilingual
+ support, when resources are loaded via a DLL.
+* Added the Internet Browser example. It demonstrates how to host an ActiveX
+ control in a Win32++ window. It requires ATL.
+* Added the Performance example. This program now also conducts a simple
+ performance test to measure the efficiency of the message handling.
+
+
+Version 5.1
+===========
+* Existing windows can be subclassed and converted to CWnd objects using Attach
+* Dialog items can be sublcassed and converted to CWnd objects, using
+ AttachDlgItem.
+* Improvements to CToolbar. The toolbar uses image lists which support using
+ separate bitmaps for normal, hot and disabled buttons. Text can be added
+ to toolbar buttons, and the style can be set.
+* Improvements to CStatusbar.
+* Notifications from common controls are reflected back to the CWnd object that
+ generated them.
+* Messages from old style common controls are reflected back to the CWnd object
+ that generated them.
+
+
+Version 5.0
+===========
+* Added rebars to the frame window
+* Added a menubar to the frame window
+* Added MDI frame support
+* Added splitter window support
+
+
+Version 4
+=========
+* Changed the method of associating the Window's handle (HWND) and
+ the CWnd pointer. Previously SetWindowLong was used to store the
+ CWin pointer in the windows data area. Now std::map is used to
+ associate a CWnd pointer with the HWND (i.e. the window's handle).
+* Added the lpParam parameter to both versions of the CWnd::CreateEx
+ function. Users are now free to use lpParam for their own
+ purposes. This parameter defaults to NULL for backwards
+ compatibility.
+
+
+Version 3
+=========
+* Added Tracing. To use tracing, ensure that you are in Debug mode,
+ i.e. the variable _DEBUG is defined, and use the TRACE("xxxxx")
+ function to send trace messages. The first TRACE(...) creates
+ the Trace output window.
+* Enhanced the error reporting in the event of an exception. The
+ GetLastError information is now decoded and displayed if it
+ provides any additional information.
+* Added support for multi-threaded applications.
+
+
+Version 2
+=========
+* The code is now Unicode compliant.
+* Added CWinApp class to start Win32++.
+* Added CDialog class to support modal and modeless dialogs as well
+ as indirect dialogs (dialogs created from a dialog template in
+ memory).
+* Added the Create function to simplify window creation.
+
+
+Version 1.0
+===========
+Initial Release
\ No newline at end of file
diff --git a/external/win32cpp/include/controls.h b/external/win32cpp/include/controls.h
new file mode 100644
index 0000000..a15c8b5
--- /dev/null
+++ b/external/win32cpp/include/controls.h
@@ -0,0 +1,1074 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// controls.h
+// Declaration of the following classes:
+// CAnimation, CComboBox, CComboBoxEx, CProgressBar,
+// CScrollBar, CSlider, CSpinButton
+
+
+#ifndef _WIN32XX_CONTROLS_H_
+#define _WIN32XX_CONTROLS_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+ class CAnimation : public CWnd
+ {
+ public:
+ CAnimation() {}
+ virtual ~CAnimation() {}
+
+ BOOL Close() const;
+ BOOL Open(LPTSTR lpszName) const;
+ BOOL Play(UINT wFrom, UINT wTo, UINT cRepeat) const;
+ BOOL Seek(UINT wFrame) const;
+ BOOL Stop() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = ANIMATE_CLASS; }
+ };
+
+
+ class CComboBox : public CWnd
+ {
+ public:
+ CComboBox() {}
+ virtual ~CComboBox() {}
+
+ int AddString(LPCTSTR lpszString) const;
+ void Clear() const;
+ void Copy() const;
+ void Cut() const;
+ int DeleteString(int nIndex) const;
+ int Dir(UINT attr, LPCTSTR lpszWildCard ) const;
+ int FindString(int nIndexStart, LPCTSTR lpszString) const;
+ int FindStringExact(int nIndexStart, LPCTSTR lpszString) const;
+ int GetCount() const;
+ int GetCurSel() const;
+ CRect GetDroppedControlRect() const;
+ BOOL GetDroppedState() const;
+ int GetDroppedWidth() const;
+ DWORD GetEditSel() const;
+ BOOL GetExtendedUI() const;
+ int GetHorizontalExtent() const;
+ DWORD GetItemData(int nIndex) const;
+ int GetItemHeight(int nIndex) const;
+ int GetLBText(int nIndex, LPTSTR lpszText) const;
+ int GetLBTextLen(int nIndex) const;
+ LCID GetLocale() const;
+ int GetTopIndex() const;
+ int InitStorage(int nItems, int nBytes) const;
+ int InsertString(int nIndex, LPCTSTR lpszString) const;
+ void LimitText(int nMaxChars) const;
+ void Paste() const;
+ void ResetContent() const;
+ int SelectString(int nStartAfter, LPCTSTR lpszString) const;
+ int SetCurSel(int nIndex) const;
+ int SetDroppedWidth(int nWidth) const;
+ BOOL SetEditSel(int nStartChar, int nEndChar) const;
+ int SetExtendedUI(BOOL bExtended = TRUE) const;
+ void SetHorizontalExtent(UINT nExtent ) const;
+ int SetItemData(int nIndex, DWORD dwItemData) const;
+ int SetItemHeight(int nIndex, UINT cyItemHeight) const;
+ LCID SetLocale( LCID NewLocale ) const;
+ int SetTopIndex(int nIndex) const;
+ void ShowDropDown(BOOL bShow = TRUE) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = _T("ComboBox"); }
+ };
+
+
+ class CComboBoxEx : public CWnd
+ {
+ public:
+ CComboBoxEx() {}
+ virtual ~CComboBoxEx() {}
+
+ int DeleteItem(int nIndex ) const;
+ CWnd* GetComboBoxCtrl() const;
+ CWnd* GetEditCtrl() const;
+ DWORD GetExtendedStyle() const;
+ HIMAGELIST GetImageList() const;
+ BOOL GetItem(COMBOBOXEXITEM* pCBItem) const;
+ BOOL HasEditChanged () const;
+ int InsertItem(COMBOBOXEXITEM* lpcCBItem) const;
+ DWORD SetExtendedStyle(DWORD dwExMask, DWORD dwExStyles ) const;
+ HIMAGELIST SetImageList(HIMAGELIST himl) const;
+ BOOL SetItem(PCOMBOBOXEXITEM lpcCBItem) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_COMBOBOXEX; }
+ };
+
+
+ class CProgressBar : public CWnd
+ {
+ public:
+ CProgressBar() {}
+ virtual ~CProgressBar() {}
+
+ int GetPos() const;
+ int GetRange(BOOL fWhichLimit, PPBRANGE ppBRange) const;
+ int OffsetPos(int nIncrement) const;
+ int SetPos(int nNewPos) const;
+ int SetRange(short nMinRange, short nMaxRange) const;
+ int SetStep(int nStepInc) const;
+ int StepIt() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = PROGRESS_CLASS; }
+ };
+
+
+ class CScrollBar : public CWnd
+ {
+ public:
+ CScrollBar() {}
+ virtual ~CScrollBar() {}
+
+ BOOL EnableScrollBar( UINT nArrowFlags = ESB_ENABLE_BOTH ) const;
+ BOOL GetScrollInfo(LPSCROLLINFO lpsi) const;
+ int GetScrollPos() const;
+ BOOL GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos ) const;
+ BOOL SetScrollInfo(LPSCROLLINFO lpsi, BOOL bRedraw = TRUE ) const;
+ int SetScrollPos(int nPos, BOOL bRedraw) const;
+ BOOL SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw = TRUE ) const;
+ BOOL ShowScrollBar(BOOL bShow) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = _T("SCROLLBAR"); ; }
+ };
+
+
+ class CSlider : public CWnd
+ {
+ public:
+ CSlider() {}
+ virtual ~CSlider() {}
+
+ void ClearSel() const;
+ void ClearTics(BOOL bRedraw = FALSE ) const;
+ CWnd* GetBuddy(BOOL fLocation = TRUE ) const;
+ CRect GetChannelRect() const;
+ int GetLineSize() const;
+ int GetNumTics() const;
+ int GetPageSize() const;
+ int GetPos() const;
+ int GetRangeMax() const;
+ int GetRangeMin() const;
+ int GetSelEnd() const;
+ int GetSelStart() const;
+ int GetThumbLength() const;
+ CRect GetThumbRect() const;
+ int GetTic(int nTic ) const;
+ int GetTicPos(int nTic) const;
+ CWnd* GetToolTips() const;
+ CWnd* SetBuddy(CWnd* pBuddy, BOOL fLocation = TRUE ) const;
+ int SetLineSize(int nSize) const;
+ int SetPageSize(int nSize) const;
+ void SetPos(int nPos, BOOL bRedraw = FALSE) const;
+ void SetRangeMax(int nMax, BOOL bRedraw = FALSE) const;
+ void SetRangeMin(int nMax, BOOL bRedraw = FALSE) const;
+ void SetSelection(int nMin, int nMax, BOOL bRedraw = FALSE) const;
+ BOOL SetTic(int nTic) const;
+ void SetTicFreq(int nFreq) const;
+ int SetTipSide(int nLocation) const;
+ void SetToolTips(CWnd* pToolTip) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = TRACKBAR_CLASS; }
+ };
+
+
+ // Also known as an Up/Down control
+ class CSpinButton : public CWnd
+ {
+ public:
+ CSpinButton() {}
+ virtual ~CSpinButton() {}
+
+ int GetAccel(int cAccels, LPUDACCEL paAccels) const;
+ int GetBase() const;
+ CWnd* GetBuddy() const;
+ int GetPos() const;
+ DWORD GetRange() const;
+ BOOL SetAccel(int cAccels, LPUDACCEL paAccels) const;
+ int SetBase(int nBase) const;
+ CWnd* SetBuddy(CWnd* hwndBuddy) const;
+ int SetPos(int nPos) const;
+ void SetRange(int nLower, int nUpper) const;
+
+ protected:
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+} // namespace Win32xx
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////
+ // Definitions for the CAnimation class
+ //
+ inline BOOL CAnimation::Close() const
+ // Closes an AVI clip.
+ {
+ assert(IsWindow());
+ return Animate_Close(m_hWnd);
+ }
+
+ inline BOOL CAnimation::Open(LPTSTR lpszName) const
+ // Opens an AVI clip and displays its first frame in an animation control.
+ {
+ assert(IsWindow());
+ return Animate_Open(m_hWnd, lpszName);
+ }
+
+ inline BOOL CAnimation::Play(UINT wFrom, UINT wTo, UINT cRepeat) const
+ // Plays an AVI clip in an animation control. The control plays the clip
+ // in the background while the thread continues executing.
+ {
+ assert(IsWindow());
+ return Animate_Play(m_hWnd, wFrom, wTo, cRepeat);
+ }
+
+ inline BOOL CAnimation::Seek(UINT wFrame) const
+ // Directs an animation control to display a particular frame of an AVI clip.
+ // The control displays the clip in the background while the thread continues executing.
+ {
+ assert(IsWindow());
+ return Animate_Seek(m_hWnd, wFrame);
+ }
+
+ inline BOOL CAnimation::Stop() const
+ // Stops playing an AVI clip in an animation control.
+ {
+ assert(IsWindow());
+ return Animate_Stop(m_hWnd);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CComboBox class
+ //
+ inline int CComboBox::AddString(LPCTSTR lpszString) const
+ // Adds a string to the list box of a combo box. If the combo box does not
+ // have the CBS_SORT style, the string is added to the end of the list.
+ // Otherwise, the string is inserted into the list, and the list is sorted.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_ADDSTRING, 0, (LPARAM)lpszString);
+ }
+
+ inline void CComboBox::Clear() const
+ // Deletes the current selection, if any, from the combo box's edit control.
+ {
+ assert(IsWindow());
+ SendMessage(WM_CLEAR, 0, 0);
+ }
+
+ inline void CComboBox::Copy() const
+ // Copies the current selection to the clipboard in CF_TEXT format.
+ {
+ assert(IsWindow());
+ SendMessage(WM_COPY, 0, 0);
+ }
+
+ inline void CComboBox::Cut() const
+ // Deletes the current selection, if any, in the edit control and copies
+ // the deleted text to the clipboard in CF_TEXT format.
+ {
+ assert(IsWindow());
+ SendMessage(WM_CUT, 0, 0);
+ }
+
+ inline int CComboBox::DeleteString(int nIndex) const
+ // Deletes a string in the list box of a combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_DELETESTRING, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::Dir(UINT attr, LPCTSTR lpszWildCard ) const
+ // Adds the names of directories and files that match a specified string
+ // and set of file attributes.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_DIR, (WPARAM)attr, (LPARAM)lpszWildCard);
+ }
+
+ inline int CComboBox::FindString(int nIndexStart, LPCTSTR lpszString) const
+ // Search the list box of a combo box for an item beginning with the
+ // characters in a specified string.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_FINDSTRING, (WPARAM)nIndexStart, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::FindStringExact(int nIndexStart, LPCTSTR lpszString) const
+ // Find the first list box string in a combo box that matches the string specified in lpszString.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_FINDSTRINGEXACT, (WPARAM)nIndexStart, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::GetCount() const
+ // Retrieves the number of items in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETCOUNT, 0,0);
+ }
+
+ inline int CComboBox::GetCurSel() const
+ // Retrieves the index of the currently selected item, if any, in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETCURSEL, 0,0);
+ }
+
+ inline CRect CComboBox::GetDroppedControlRect() const
+ // Retrieves the screen coordinates of the combo box in its dropped-down state.
+ {
+ assert(IsWindow());
+ CRect rc;
+ SendMessage(CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline BOOL CComboBox::GetDroppedState() const
+ // Determines whether the list box of the combo box is dropped down.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_GETDROPPEDSTATE, 0, 0);
+ }
+
+ inline int CComboBox::GetDroppedWidth() const
+ // Retrieves the minimum allowable width, in pixels, of the list box of the combo box
+ // with the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETDROPPEDWIDTH, 0, 0);
+ }
+
+ inline DWORD CComboBox::GetEditSel() const
+ // Gets the starting and ending character positions of the current selection
+ // in the edit control of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETEDITSEL, 0, 0);
+ }
+
+ inline BOOL CComboBox::GetExtendedUI() const
+ // Determines whether the combo box has the default user interface or the extended user interface.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_GETEXTENDEDUI, 0, 0);
+ }
+
+ inline int CComboBox::GetHorizontalExtent() const
+ // Retrieve from the combo box the width, in pixels, by which the list box can
+ // be scrolled horizontally (the scrollable width).
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETHORIZONTALEXTENT, 0, 0);
+ }
+
+ inline DWORD CComboBox::GetItemData(int nIndex) const
+ // Retrieves the application-supplied value associated with the specified item in the combo box.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CB_GETITEMDATA, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::GetItemHeight(int nIndex) const
+ // Determines the height of list items or the selection field in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETITEMHEIGHT, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::GetLBText(int nIndex, LPTSTR lpszText) const
+ // Retrieves a string from the list of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETLBTEXT, (WPARAM)nIndex, (LPARAM)lpszText);
+ }
+
+ inline int CComboBox::GetLBTextLen(int nIndex) const
+ // Retrieves the length, in characters, of a string in the list of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETLBTEXTLEN, (WPARAM)nIndex, 0);
+ }
+
+ inline LCID CComboBox::GetLocale() const
+ // Retrieves the current locale of the combo box.
+ {
+ assert(IsWindow());
+ return (LCID)SendMessage(CB_GETLOCALE, 0, 0);
+ }
+
+ inline int CComboBox::GetTopIndex() const
+ // Retrieves the zero-based index of the first visible item in the list box portion of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_GETTOPINDEX, 0, 0);
+ }
+
+ inline int CComboBox::InitStorage(int nItems, int nBytes) const
+ // Allocates memory for storing list box items. Use this before adding a
+ // large number of items to the list box portion of a combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_INITSTORAGE, (WPARAM)nItems, (LPARAM)nBytes);
+ }
+
+ inline int CComboBox::InsertString(int nIndex, LPCTSTR lpszString) const
+ // Inserts a string into the list box of the combo box. Unlike the AddString,
+ // a list with the CBS_SORT style is not sorted.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_INSERTSTRING, (WPARAM)nIndex, (LPARAM)lpszString);
+ }
+
+ inline void CComboBox::Paste() const
+ // Copies the current content of the clipboard to the combo box's edit control at the current caret position.
+ {
+ assert(IsWindow());
+ SendMessage(WM_PASTE, 0, 0);
+ }
+
+ inline void CComboBox::LimitText(int nMaxChars) const
+ // Limits the length of the text the user may type into the edit control of the combo box.
+ {
+ assert(IsWindow());
+ SendMessage(CB_LIMITTEXT, (WPARAM)nMaxChars, 0);
+ }
+
+ inline void CComboBox::ResetContent() const
+ // Removes all items from the list box and edit control of the combo box.
+ {
+ assert(IsWindow());
+ SendMessage(CB_RESETCONTENT, 0, 0);
+ }
+
+ inline int CComboBox::SelectString(int nStartAfter, LPCTSTR lpszString) const
+ // Searches the list of a combo box for an item that begins with the characters in a
+ // specified string. If a matching item is found, it is selected and copied to the edit control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SELECTSTRING, (WPARAM)nStartAfter, (LPARAM)lpszString);
+ }
+
+ inline int CComboBox::SetCurSel(int nIndex) const
+ // Selects a string in the list of the combo box. If necessary, the list scrolls the string into view.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETCURSEL, (WPARAM)nIndex, 0);
+ }
+
+ inline int CComboBox::SetDroppedWidth(int nWidth) const
+ // Sets the maximum allowable width, in pixels, of the list box of the combo box with
+ // the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETDROPPEDWIDTH, (WPARAM)nWidth, 0);
+ }
+
+ inline BOOL CComboBox::SetEditSel(int nStartChar, int nEndChar) const
+ // Selects characters in the edit control of the combo box.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CB_SETEDITSEL, 0, (LPARAM)MAKELONG(nStartChar,nEndChar));
+ }
+
+ inline int CComboBox::SetExtendedUI(BOOL bExtended) const
+ // Selects either the default user interface or the extended user interface for the combo box that
+ // has the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETEXTENDEDUI, (WPARAM)bExtended, 0);
+ }
+
+ inline void CComboBox::SetHorizontalExtent(UINT nExtent ) const
+ // Sets the width, in pixels, by which the list box can be scrolled horizontally (the scrollable width).
+ {
+ assert(IsWindow());
+ SendMessage(CB_SETHORIZONTALEXTENT, (WPARAM)nExtent, 0);
+ }
+
+ inline int CComboBox::SetItemData(int nIndex, DWORD dwItemData) const
+ // Sets the value associated with the specified item in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETITEMDATA, (WPARAM)nIndex, (LPARAM)dwItemData);
+ }
+
+ inline int CComboBox::SetItemHeight(int nIndex, UINT cyItemHeight) const
+ // Sets the height of list items or the selection field in the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETITEMHEIGHT, (WPARAM)nIndex, (LPARAM)cyItemHeight);
+ }
+
+ inline LCID CComboBox::SetLocale( LCID NewLocale ) const
+ // Sets the current locale of the combo box.
+ {
+ assert(IsWindow());
+ return (LCID)SendMessage(CB_SETLOCALE, (WPARAM)NewLocale, 0);
+ }
+
+ inline int CComboBox::SetTopIndex(int nIndex) const
+ // Ensure that a particular item is visible in the list box of the combo box.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CB_SETTOPINDEX, (WPARAM)nIndex, 0);
+ }
+
+ inline void CComboBox::ShowDropDown(BOOL bShow) const
+ // Shows or hides the list box of the combo box that has the CBS_DROPDOWN or CBS_DROPDOWNLIST style.
+ {
+ assert(IsWindow());
+ SendMessage(CB_SHOWDROPDOWN, (WPARAM)bShow, 0);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CComboBoxEx class
+ //
+ inline int CComboBoxEx::DeleteItem(int nIndex ) const
+ // Removes an item from the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CBEM_DELETEITEM, (WPARAM)nIndex, 0);
+ }
+
+ inline CWnd* CComboBoxEx::GetComboBoxCtrl() const
+ // Retrieves the handle to the child combo box control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
+ }
+
+ inline CWnd* CComboBoxEx::GetEditCtrl() const
+ // Retrieves the handle to the edit control portion of the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(CBEM_GETEDITCONTROL, 0, 0));
+ }
+
+ inline DWORD CComboBoxEx::GetExtendedStyle() const
+ // Retrieves the extended styles that are in use for the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CBEM_GETEXTENDEDSTYLE, 0, 0);
+ }
+
+ inline HIMAGELIST CComboBoxEx::GetImageList() const
+ // Retrieves the handle to an image list assigned to the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (HIMAGELIST)SendMessage(CBEM_GETIMAGELIST, 0, 0);
+ }
+
+ inline BOOL CComboBoxEx::GetItem(COMBOBOXEXITEM* pCBItem) const
+ // Retrieves item information for the given ComboBoxEx item.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_GETITEM, 0, (LPARAM)pCBItem);
+ }
+
+ inline BOOL CComboBoxEx::HasEditChanged () const
+ // Determines whether or not the user has changed the text of the ComboBoxEx edit control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_HASEDITCHANGED, 0, 0);
+ }
+
+ inline int CComboBoxEx::InsertItem(COMBOBOXEXITEM* lpcCBItem) const
+ // Inserts a new item in the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(CBEM_INSERTITEM, 0, (LPARAM)lpcCBItem);
+ }
+
+ inline DWORD CComboBoxEx::SetExtendedStyle(DWORD dwExMask, DWORD dwExStyles ) const
+ // Sets extended styles within the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(CBEM_SETEXTENDEDSTYLE, (WPARAM)dwExMask, (LPARAM)dwExStyles);
+ }
+
+ inline HIMAGELIST CComboBoxEx::SetImageList(HIMAGELIST himl) const
+ // Sets an image list for the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (HIMAGELIST)SendMessage(CBEM_SETIMAGELIST, 0, (LPARAM)himl);
+ }
+
+ inline BOOL CComboBoxEx::SetItem(PCOMBOBOXEXITEM lpcCBItem) const
+ // Sets the attributes for an item in the ComboBoxEx control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(CBEM_SETITEM, 0, (LPARAM)lpcCBItem);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CProgressBar class
+ //
+ inline int CProgressBar::GetPos() const
+ // Retrieves the current position of the progress bar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_GETPOS, 0, 0);
+ }
+
+ inline int CProgressBar::GetRange(BOOL fWhichLimit, PPBRANGE ppBRange) const
+ // Retrieves information about the current high and low limits of the progress bar control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_GETRANGE, (WPARAM)fWhichLimit, (LPARAM) (PPBRANGE) ppBRange);
+ }
+
+ inline int CProgressBar::OffsetPos(int nIncrement) const
+ // Advances the current position of the progress bar by a specified increment and redraws
+ // the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_DELTAPOS, (WPARAM)nIncrement, 0);
+ }
+
+ inline int CProgressBar::SetPos(int nNewPos) const
+ // Sets the current position for the progress bar and redraws the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETPOS, (WPARAM)nNewPos, 0);
+ }
+
+ inline int CProgressBar::SetRange(short nMinRange, short nMaxRange) const
+ // Sets the minimum and maximum values for the progress bar and redraws the bar to reflect the new range.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETRANGE, 0, (LPARAM) MAKELPARAM (nMinRange, nMaxRange));
+ }
+
+ inline int CProgressBar::SetStep(int nStepInc) const
+ // Specifies the step increment for the progress bar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_SETSTEP, (WPARAM)nStepInc, 0);
+ }
+
+ inline int CProgressBar::StepIt() const
+ // Advances the current position for a progress bar by the step increment and
+ // redraws the bar to reflect the new position.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(PBM_STEPIT, 0, 0);
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CScrollBar class
+ //
+ inline BOOL CScrollBar::EnableScrollBar( UINT nArrowFlags ) const
+ // Enables or disables the scroll bar arrows.
+ {
+ assert(IsWindow());
+ return ::EnableScrollBar(m_hWnd, SB_CTL, nArrowFlags);
+ }
+
+ inline BOOL CScrollBar::GetScrollInfo(LPSCROLLINFO lpsi) const
+ // Retrieves the parameters of a scroll bar, including the minimum and maximum
+ // scrolling positions, the page size, and the position of the scroll box (thumb).
+ {
+ assert(IsWindow());
+ return ::GetScrollInfo(m_hWnd, SB_CTL, lpsi);
+ }
+
+ inline int CScrollBar::GetScrollPos() const
+ // Retrieves the current position of the scroll box (thumb) in the scroll bar.
+ {
+ assert(IsWindow());
+ return ::GetScrollPos(m_hWnd, SB_CTL);
+ }
+
+ inline BOOL CScrollBar::GetScrollRange(LPINT lpMinPos, LPINT lpMaxPos ) const
+ // Retrieves the current minimum and maximum scroll box (thumb) positions for the scroll bar.
+ {
+ assert(IsWindow());
+ return ::GetScrollRange(m_hWnd, SB_CTL, lpMinPos, lpMaxPos);
+ }
+
+ inline BOOL CScrollBar::SetScrollInfo(LPSCROLLINFO lpsi, BOOL bRedraw ) const
+ // Sets the parameters of the scroll bar, including the minimum and maximum scrolling positions,
+ // the page size, and the position of the scroll box (thumb).
+ {
+ assert(IsWindow());
+ return ::SetScrollInfo(m_hWnd, SB_CTL, lpsi, bRedraw);
+ }
+
+ inline int CScrollBar::SetScrollPos(int nPos, BOOL bRedraw) const
+ // Sets the position of the scroll box (thumb) in the scroll bar and, if requested,
+ // redraws the scroll bar to reflect the new position of the scroll box.
+ {
+ assert(IsWindow());
+ return ::SetScrollPos(m_hWnd, SB_CTL, nPos, bRedraw);
+ }
+
+ inline BOOL CScrollBar::SetScrollRange( int nMinPos, int nMaxPos, BOOL bRedraw ) const
+ // Sets the minimum and maximum scroll box positions for the scroll bar.
+ {
+ assert(IsWindow());
+ return ::SetScrollRange(m_hWnd, SB_CTL, nMinPos, nMaxPos, bRedraw);
+ }
+
+ inline BOOL CScrollBar::ShowScrollBar(BOOL bShow) const
+ // Shows or hides the scroll bar.
+ {
+ assert(IsWindow());
+ return ::ShowScrollBar(m_hWnd, SB_CTL, bShow);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CSlider class
+ //
+ inline void CSlider::ClearSel() const
+ // Clears the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_CLEARSEL, 0, 0);
+ }
+
+ inline void CSlider::ClearTics(BOOL bRedraw) const
+ // Removes the current tick marks from the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_CLEARTICS, (WPARAM)bRedraw, 0);
+ }
+
+ inline CWnd* CSlider::GetBuddy(BOOL fLocation) const
+ // Retrieves the handle to the trackbar control buddy window at a given location.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_GETBUDDY, (WPARAM)fLocation, 0));
+ }
+
+ inline CRect CSlider::GetChannelRect() const
+ // Retrieves the size and position of the bounding rectangle for the trackbar's channel.
+ {
+ assert(IsWindow());
+ CRect rc;
+ SendMessage(TBM_GETCHANNELRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CSlider::GetLineSize() const
+ // Retrieves the number of logical positions the trackbar's slider moves in response
+ // to keyboard input from the arrow keys.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETLINESIZE, 0, 0);
+ }
+
+ inline int CSlider::GetNumTics() const
+ // Retrieves the number of tick marks in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETNUMTICS, 0, 0);
+ }
+
+ inline int CSlider::GetPageSize() const
+ // Retrieves the number of logical positions the trackbar's slider moves in response to
+ // keyboard input, or mouse input, such as clicks in the trackbar's channel.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETPAGESIZE, 0, 0);
+ }
+
+ inline int CSlider::GetPos() const
+ // Retrieves the current logical position of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETPOS, 0, 0);
+ }
+
+ inline int CSlider::GetRangeMax() const
+ // Retrieves the maximum position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETRANGEMAX, 0, 0);
+ }
+
+ inline int CSlider::GetRangeMin() const
+ // Retrieves the minimum position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETRANGEMIN, 0, 0);
+ }
+
+ inline int CSlider::GetSelEnd() const
+ // Retrieves the ending position of the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETSELEND, 0, 0);
+ }
+
+ inline int CSlider::GetSelStart() const
+ // Retrieves the starting position of the current selection range in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETSELSTART, 0, 0);
+ }
+
+ inline int CSlider::GetThumbLength() const
+ // Retrieves the length of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTHUMBLENGTH, 0, 0);
+ }
+
+ inline CRect CSlider::GetThumbRect() const
+ // Retrieves the size and position of the bounding rectangle for the slider in the trackbar.
+ {
+ CRect rc;
+ SendMessage(TBM_GETTHUMBRECT, 0, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CSlider::GetTic(int nTic ) const
+ // Retrieves the logical position of a tick mark in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTIC, (WPARAM)nTic, 0);
+ }
+
+ inline int CSlider::GetTicPos(int nTic) const
+ // Retrieves the current physical position of a tick mark in the trackbar.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_GETTICPOS, (WPARAM)nTic, 0);
+ }
+
+ inline CWnd* CSlider::GetToolTips() const
+ // Retrieves the handle to the ToolTip control assigned to the trackbar, if any.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_GETTOOLTIPS, 0, 0));
+ }
+
+ inline CWnd* CSlider::SetBuddy(CWnd* pBuddy, BOOL fLocation /*= TRUE*/ ) const
+ // Assigns a window as the buddy window for the trackbar control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(TBM_SETBUDDY, (WPARAM)fLocation, (LPARAM)pBuddy->GetHwnd()));
+ }
+
+ inline int CSlider::SetLineSize(int nSize) const
+ // Sets the number of logical positions the trackbar's slider moves in response to
+ // keyboard input from the arrow keys.
+ {
+ assert(IsWindow());
+ return(int)SendMessage(TBM_SETLINESIZE, 0, (LPARAM)nSize);
+ }
+
+ inline int CSlider::SetPageSize(int nSize) const
+ // Sets the number of logical positions the trackbar's slider moves in response to
+ // keyboard input, or mouse input such as clicks in the trackbar's channel.
+ {
+ assert(IsWindow());
+ return(int)SendMessage(TBM_SETPAGESIZE, 0, (LPARAM)nSize);
+ }
+
+ inline void CSlider::SetPos(int nPos, BOOL bRedraw) const
+ // Sets the current logical position of the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETPOS, (WPARAM)bRedraw, (LPARAM)nPos);
+ }
+
+ inline void CSlider::SetRangeMax(int nMax, BOOL bRedraw) const
+ // Sets the maximum logical position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETRANGEMAX, (WPARAM)bRedraw, (LPARAM)nMax);
+ }
+
+ inline void CSlider::SetRangeMin(int nMax, BOOL bRedraw) const
+ // Sets the minimum logical position for the slider in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETRANGEMIN, (WPARAM)bRedraw, (LPARAM)nMax);
+ }
+
+ inline void CSlider::SetSelection(int nMin, int nMax, BOOL bRedraw) const
+ // Sets the starting and ending positions for the available selection range in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETSEL, (WPARAM)bRedraw, (LPARAM)MAKELONG(nMax, nMin));
+ }
+
+ inline BOOL CSlider::SetTic(int nTic) const
+ // Sets a tick mark in the trackbar at the specified logical position.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(TBM_SETTIC, 0, nTic);
+ }
+
+ inline void CSlider::SetTicFreq(int nFreq) const
+ // Sets the interval frequency for tick marks in the trackbar.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETTICFREQ, (WPARAM)nFreq, 0);
+ }
+
+ inline int CSlider::SetTipSide(int nLocation) const
+ // Positions a ToolTip control used by the trackbar control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(TBM_SETTIPSIDE, (WPARAM)nLocation, 0);
+ }
+
+ inline void CSlider::SetToolTips(CWnd* pToolTip) const
+ // Assigns a ToolTip control to the trackbar control.
+ {
+ assert(IsWindow());
+ SendMessage(TBM_SETTOOLTIPS, (WPARAM)pToolTip->GetHwnd(), 0);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CSpinButton class
+ //
+ inline int CSpinButton::GetAccel(int cAccels, LPUDACCEL paAccels) const
+ // Retrieves acceleration information for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETACCEL, (WPARAM)cAccels, (LPARAM)paAccels);
+ }
+
+ inline int CSpinButton::GetBase() const
+ // Retrieves the current radix base (that is, either base 10 or 16) for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETBASE, 0, 0);
+ }
+
+ inline CWnd* CSpinButton::GetBuddy() const
+ // Retrieves the handle to the current buddy window.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(UDM_GETBUDDY, 0, 0));
+ }
+
+ inline int CSpinButton::GetPos() const
+ // Retrieves the current position of the up-down control with 16-bit precision.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_GETPOS, 0, 0);
+ }
+
+ inline DWORD CSpinButton::GetRange() const
+ // Retrieves the minimum and maximum positions (range) for the up-down control.
+ {
+ assert(IsWindow());
+ return (DWORD)SendMessage(UDM_GETRANGE, 0, 0);
+ }
+
+ inline void CSpinButton::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VISIBLE |UDS_SETBUDDYINT;
+ }
+
+ inline void CSpinButton::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = UPDOWN_CLASS;
+ }
+
+ inline BOOL CSpinButton::SetAccel(int cAccels, LPUDACCEL paAccels) const
+ // Sets the acceleration for the up-down control.
+ {
+ assert(IsWindow());
+ return (BOOL)SendMessage(UDM_SETACCEL, (WPARAM)cAccels, (LPARAM)paAccels);
+ }
+
+ inline int CSpinButton::SetBase(int nBase) const
+ // Sets the radix base for the up-down control.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_SETBASE, (WPARAM)nBase, 0);
+ }
+
+ inline CWnd* CSpinButton::SetBuddy(CWnd* pBuddy) const
+ // Sets the buddy window for the up-down control.
+ {
+ assert(IsWindow());
+ return FromHandle((HWND)SendMessage(UDM_SETBUDDY, (WPARAM)pBuddy->GetHwnd(), 0));
+ }
+
+ inline int CSpinButton::SetPos(int nPos) const
+ // Sets the current position for the up-down control with 16-bit precision.
+ {
+ assert(IsWindow());
+ return (int)SendMessage(UDM_SETPOS, 0, (LPARAM)MAKELONG ((short) nPos, 0));
+ }
+
+ inline void CSpinButton::SetRange(int nLower, int nUpper) const
+ // Sets the minimum and maximum positions (range) for the up-down control.
+ {
+ assert(IsWindow());
+ SendMessage(UDM_SETRANGE, 0, (LPARAM)MAKELONG(nUpper, nLower));
+ }
+
+} // namespace Win32xx
+
+#endif // define _WIN32XX_CONTROLS_H_
+
diff --git a/external/win32cpp/include/copyright.txt b/external/win32cpp/include/copyright.txt
new file mode 100644
index 0000000..d2222fa
--- /dev/null
+++ b/external/win32cpp/include/copyright.txt
@@ -0,0 +1,33 @@
+Win32++ Version 7.2
+Released: 5th AUgust 2011
+
+ David Nash
+ email: dnash@bigpond.net.au
+ url: https://sourceforge.net/projects/win32-framework
+
+
+Copyright (c) 2005-2011 David Nash
+
+Permission is hereby granted, free of charge, to
+any person obtaining a copy of this software and
+associated documentation files (the "Software"),
+to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/external/win32cpp/include/cstring.h b/external/win32cpp/include/cstring.h
new file mode 100644
index 0000000..faf574d
--- /dev/null
+++ b/external/win32cpp/include/cstring.h
@@ -0,0 +1,905 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+// Acknowledgements:
+// Thanks to Adam Szulc for his initial CString code.
+
+////////////////////////////////////////////////////////
+// cstring.h
+// Declaration of the cstring.h
+
+// This class is intended to provide a simple alternative to the MFC/ATL
+// CString class that ships with Microsoft compilers. The CString class
+// specified here is compatible with other compilers such as Borland 5.5
+// and MinGW.
+
+// Differences between this class and the MFC/ATL CString class
+// ------------------------------------------------------------
+// 1) The constructors for this class accepts only TCHARs. The various text conversion
+// functions can be used to convert from other character types to TCHARs.
+//
+// 2) This class is not reference counted, so these CStrings should be passed as
+// references or const references when used as function arguments. As a result there
+// is no need for functions like LockBuffer and UnLockBuffer.
+//
+// 3) The Format functions only accepts POD (Plain Old Data) arguments. It does not
+// accept arguments which are class or struct objects. In particular it does not
+// accept CString objects, unless these are cast to LPCTSTR.
+// This is demonstrates valid and invalid usage:
+// CString string1(_T("Hello World"));
+// CString string2;
+//
+// // This is invalid, and produces undefined behaviour.
+// string2.Format(_T("String1 is: %s"), string1); // No! you can't do this
+//
+// // This is ok
+// string2.Format(_T("String1 is: %s"), (LPCTSTR)string1); // Yes, this is correct
+//
+// Note: The MFC/ATL CString class uses a non portable hack to make its CString class
+// behave like a POD. Other compilers (such as the MinGW compiler) specifically
+// prohibit the use of non POD types for functions with variable argument lists.
+//
+// 4) This class provides a few additional functions:
+// b_str Returns a BSTR string. This an an alternative for casting to BSTR.
+// c_str Returns a const TCHAR string. This is an alternative for casting to LPCTSTR.
+// GetErrorString Assigns CString to the error string for the specified System Error Code
+// (from ::GetLastErrror() for example).
+// GetString Returns a reference to the underlying std::basic_string. This
+// reference can be used to modify the string directly.
+
+
+
+#ifndef _WIN32XX_CSTRING_H_
+#define _WIN32XX_CSTRING_H_
+
+
+#include "wincore.h"
+
+
+namespace Win32xx
+{
+
+ class CString
+ {
+ // friend functions allow the left hand side to be something other than CString
+ friend CString operator + (const CString& string1, const CString& string2);
+ friend CString operator + (const CString& string, LPCTSTR pszText);
+ friend CString operator + (const CString& string, TCHAR ch);
+ friend CString operator + (LPCTSTR pszText, const CString& string);
+ friend CString operator + (TCHAR ch, const CString& string);
+
+ public:
+ CString();
+ ~CString();
+ CString(const CString& str);
+ CString(LPCTSTR pszText);
+ CString(TCHAR ch, int nLength = 1);
+ CString(LPCTSTR pszText, int nLength);
+
+ CString& operator = (const CString& str);
+ CString& operator = (const TCHAR ch);
+ CString& operator = (LPCTSTR pszText);
+ BOOL operator == (LPCTSTR pszText);
+ BOOL operator != (LPCTSTR pszText);
+ BOOL operator < (LPCTSTR pszText);
+ BOOL operator > (LPCTSTR pszText);
+ BOOL operator <= (LPCTSTR pszText);
+ BOOL operator >= (LPCTSTR pszText);
+ operator LPCTSTR() const;
+ operator BSTR() const;
+ TCHAR& operator [] (int nIndex);
+ CString& operator += (const CString& str);
+
+ // Attributes
+ BSTR b_str() const { return T2W(m_str.c_str()); } // alternative for casting to BSTR
+ LPCTSTR c_str() const { return m_str.c_str(); } // alternative for casting to LPCTSTR
+ tString& GetString() { return m_str; } // returns a reference to the underlying std::basic_string
+ int GetLength() const { return (int)m_str.length(); } // returns the length in characters
+
+ // Operations
+ BSTR AllocSysString() const;
+ void AppendFormat(LPCTSTR pszFormat,...);
+ void AppendFormat(UINT nFormatID, ...);
+ int Compare(LPCTSTR pszText) const;
+ int CompareNoCase(LPCTSTR pszText) const;
+ int Delete(int nIndex, int nCount = 1);
+ int Find(TCHAR ch, int nIndex = 0 ) const;
+ int Find(LPCTSTR pszText, int nStart = 0) const;
+ int FindOneOf(LPCTSTR pszText) const;
+ void Format(UINT nID, ...);
+ void Format(LPCTSTR pszFormat,...);
+ void FormatV(LPCTSTR pszFormat, va_list args);
+ void FormatMessage(LPCTSTR pszFormat,...);
+ void FormatMessageV(LPCTSTR pszFormat, va_list args);
+ TCHAR GetAt(int nIndex) const;
+ LPTSTR GetBuffer(int nMinBufLength);
+ void GetErrorString(DWORD dwError);
+ void Empty();
+ int Insert(int nIndex, TCHAR ch);
+ int Insert(int nIndex, const CString& str);
+ BOOL IsEmpty() const;
+ CString Left(int nCount) const;
+ BOOL LoadString(UINT nID);
+ void MakeLower();
+ void MakeReverse();
+ void MakeUpper();
+ CString Mid(int nFirst) const;
+ CString Mid(int nFirst, int nCount) const;
+ void ReleaseBuffer( int nNewLength = -1 );
+ int Remove(LPCTSTR pszText);
+ int Replace(TCHAR chOld, TCHAR chNew);
+ int Replace(const LPCTSTR pszOld, LPCTSTR pszNew);
+ int ReverseFind(LPCTSTR pszText, int nStart = -1) const;
+ CString Right(int nCount) const;
+ void SetAt(int nIndex, TCHAR ch);
+ BSTR SetSysString(BSTR* pBstr) const;
+ CString SpanExcluding(LPCTSTR pszText) const;
+ CString SpanIncluding(LPCTSTR pszText) const;
+ CString Tokenize(LPCTSTR pszTokens, int& iStart) const;
+ void Trim();
+ void TrimLeft();
+ void TrimLeft(TCHAR chTarget);
+ void TrimLeft(LPCTSTR pszTargets);
+ void TrimRight();
+ void TrimRight(TCHAR chTarget);
+ void TrimRight(LPCTSTR pszTargets);
+ void Truncate(int nNewLength);
+
+#ifndef _WIN32_WCE
+ int Collate(LPCTSTR pszText) const;
+ int CollateNoCase(LPCTSTR pszText) const;
+ BOOL GetEnvironmentVariable(LPCTSTR pszVar);
+#endif
+
+ private:
+ tString m_str;
+ std::vector m_buf;
+ };
+
+ inline CString::CString()
+ {
+ }
+
+ inline CString::~CString()
+ {
+ }
+
+ inline CString::CString(const CString& str)
+ {
+ m_str.assign(str);
+ }
+
+ inline CString::CString(LPCTSTR pszText)
+ {
+ m_str.assign(pszText);
+ }
+
+ inline CString::CString(TCHAR ch, int nLength)
+ {
+ m_str.assign(nLength, ch);
+ }
+
+ inline CString::CString(LPCTSTR pszText, int nLength)
+ {
+ m_str.assign(pszText, nLength);
+ }
+
+ inline CString& CString::operator = (const CString& str)
+ {
+ m_str.assign(str);
+ return *this;
+ }
+
+ inline CString& CString::operator = (const TCHAR ch)
+ {
+ m_str.assign(1, ch);
+ return *this;
+ }
+
+ inline CString& CString::operator = (LPCTSTR pszText)
+ {
+ m_str.assign(pszText);
+ return *this;
+ }
+
+ inline BOOL CString::operator == (LPCTSTR pszText)
+ // Returns TRUE if the strings have the same content
+ {
+ assert(pszText);
+ return (0 == Compare(pszText));
+ }
+
+ inline BOOL CString::operator != (LPCTSTR pszText)
+ // Returns TRUE if the strings have a different content
+ {
+ assert(pszText);
+ return Compare(pszText) != 0;
+ }
+
+ inline BOOL CString::operator < (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) < 0;
+ }
+
+ inline BOOL CString::operator > (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) > 0;
+ }
+
+ inline BOOL CString::operator <= (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) <= 0;
+ }
+
+ inline BOOL CString::operator >= (LPCTSTR pszText)
+ {
+ assert(pszText);
+ return Compare(pszText) >= 0;
+ }
+
+ inline CString::operator LPCTSTR() const
+ {
+ return m_str.c_str();
+ }
+
+ inline TCHAR& CString::operator [] (int nIndex)
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ return m_str[nIndex];
+ }
+
+ inline CString& CString::operator += (const CString& str)
+ {
+ m_str.append(str);
+ return *this;
+ }
+
+ inline BSTR CString::AllocSysString() const
+ // Allocates a BSTR from the CString content.
+ {
+ return ::SysAllocStringLen(T2W(m_str.c_str()), (UINT)m_str.size());
+ }
+
+ inline void CString::AppendFormat(LPCTSTR pszFormat,...)
+ // Appends formatted data to an the CString content.
+ {
+ CString str;
+ str.Format(pszFormat);
+ m_str.append(str);
+ }
+
+ inline void CString::AppendFormat(UINT nFormatID, ...)
+ // Appends formatted data to an the CString content.
+ {
+ CString str1;
+ CString str2;
+ if (str1.LoadString(nFormatID))
+ {
+ str2.Format(str1);
+ m_str.append(str2);
+ }
+ }
+
+#ifndef _WIN32_WCE
+ inline int CString::Collate(LPCTSTR pszText) const
+ // Performs a case sensitive comparison of the two strings using locale-specific information.
+ {
+ assert(pszText);
+ return _tcscoll(m_str.c_str(), pszText);
+ }
+
+ inline int CString::CollateNoCase(LPCTSTR pszText) const
+ // Performs a case insensitive comparison of the two strings using locale-specific information.
+ {
+ assert(pszText);
+ return _tcsicoll(m_str.c_str(), pszText);
+ }
+#endif // _WIN32_WCE
+
+ inline int CString::Compare(LPCTSTR pszText) const
+ // Performs a case sensitive comparison of the two strings.
+ {
+ assert(pszText);
+ return m_str.compare(pszText);
+ }
+
+ inline int CString::CompareNoCase(LPCTSTR pszText) const
+ // Performs a case insensitive comparison of the two strings.
+ {
+ assert(pszText);
+ return _tcsicmp(m_str.data(), pszText);
+ }
+
+ inline int CString::Delete(int nIndex, int nCount /* = 1 */)
+ // Deletes a character or characters from the string.
+ {
+ assert(nIndex >= 0);
+ assert(nCount >= 0);
+
+ m_str.erase(nIndex, nCount);
+ return (int)m_str.size();
+ }
+
+ inline void CString::Empty()
+ // Erases the contents of the string.
+ {
+ m_str.erase();
+ }
+
+ inline int CString::Find(TCHAR ch, int nIndex /* = 0 */) const
+ // Finds a character in the string.
+ {
+ assert(nIndex >= 0);
+ return (int)m_str.find(ch, nIndex);
+ }
+
+ inline int CString::Find(LPCTSTR pszText, int nIndex /* = 0 */) const
+ // Finds a substring within the string.
+ {
+ assert(pszText);
+ assert(nIndex >= 0);
+ return (int)m_str.find(pszText, nIndex);
+ }
+
+ inline int CString::FindOneOf(LPCTSTR pszText) const
+ // Finds the first matching character from a set.
+ {
+ assert(pszText);
+ return (int)m_str.find_first_of(pszText);
+ }
+
+ inline void CString::Format(LPCTSTR pszFormat,...)
+ // Formats the string as sprintf does.
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ FormatV(pszFormat, args);
+ va_end(args);
+ }
+
+ inline void CString::Format(UINT nID, ...)
+ // Formats the string as sprintf does.
+ {
+ Empty();
+ CString str;
+ if (str.LoadString(nID))
+ Format(str);
+ }
+
+ inline void CString::FormatV(LPCTSTR pszFormat, va_list args)
+ // Formats the string using a variable list of arguments.
+ {
+ if (pszFormat)
+ {
+ int nResult = -1, nLength = 256;
+
+ // A vector is used to store the TCHAR array
+ std::vector vBuffer;( nLength+1, _T('\0') );
+
+ while (-1 == nResult)
+ {
+ vBuffer.assign( nLength+1, _T('\0') );
+ nResult = _vsntprintf(&vBuffer[0], nLength, pszFormat, args);
+ nLength *= 2;
+ }
+ m_str.assign(&vBuffer[0]);
+ }
+ }
+
+ inline void CString::FormatMessage(LPCTSTR pszFormat,...)
+ // Formats a message string.
+ {
+ va_list args;
+ va_start(args, pszFormat);
+ FormatMessageV(pszFormat, args);
+ va_end(args);
+ }
+
+ inline void CString::FormatMessageV(LPCTSTR pszFormat, va_list args)
+ // Formats a message string using a variable argument list.
+ {
+ LPTSTR pszTemp = 0;
+ if (pszFormat)
+ {
+ DWORD dwResult = ::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, pszFormat, 0, 0, pszTemp, 0, &args);
+
+ if (0 == dwResult || 0 == pszTemp )
+ throw std::bad_alloc();
+
+ m_str = pszTemp;
+ LocalFree(pszTemp);
+ }
+ }
+
+ inline TCHAR CString::GetAt(int nIndex) const
+ // Returns the character at the specified location within the string.
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ return m_str[nIndex];
+ }
+
+ inline LPTSTR CString::GetBuffer(int nMinBufLength)
+ // Creates a buffer of nMinBufLength charaters (+1 extra for NULL termination) and returns
+ // a pointer to this buffer. This buffer can be used by any function which accepts a LPTSTR.
+ // Care must be taken not to exceed the length of the buffer. Use ReleaseBuffer to safely
+ // copy this buffer back to the CString object.
+ //
+ // Note: The buffer uses a vector. Vectors are required to be contiguous in memory under
+ // the current standard, whereas std::strings do not have this requirement.
+ {
+ assert (nMinBufLength >= 0);
+
+ m_buf.assign(nMinBufLength + 1, _T('\0'));
+ tString::iterator it_end;
+
+ if (m_str.length() >= (size_t)nMinBufLength)
+ {
+ it_end = m_str.begin();
+ std::advance(it_end, nMinBufLength);
+ }
+ else
+ it_end = m_str.end();
+
+ std::copy(m_str.begin(), it_end, m_buf.begin());
+
+ return &m_buf[0];
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CString::GetEnvironmentVariable(LPCTSTR pszVar)
+ // Sets the string to the value of the specified environment variable.
+ {
+ assert(pszVar);
+ Empty();
+
+ int nLength = ::GetEnvironmentVariable(pszVar, NULL, 0);
+ if (nLength > 0)
+ {
+ std::vector vBuffer( nLength+1, _T('\0') );
+ ::GetEnvironmentVariable(pszVar, &vBuffer[0], nLength);
+ m_str = &vBuffer[0];
+ }
+
+ return (BOOL)nLength;
+ }
+#endif // _WIN32_WCE
+
+ inline void CString::GetErrorString(DWORD dwError)
+ // Returns the error string for the specified System Error Code (e.g from GetLastErrror).
+ {
+ m_str.erase();
+
+ if (dwError != 0)
+ {
+ TCHAR* pTemp = 0;
+ DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+ ::FormatMessage(dwFlags, NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pTemp, 1, NULL);
+ m_str.assign(pTemp);
+ ::LocalFree(pTemp);
+ }
+ }
+
+ inline int CString::Insert(int nIndex, TCHAR ch)
+ // Inserts a single character or a substring at the given index within the string.
+ {
+ assert(nIndex >= 0);
+ assert(ch);
+
+ m_str.insert(nIndex, &ch, 1);
+ return (int)m_str.size();
+ }
+
+ inline int CString::Insert(int nIndex, const CString& str)
+ // Inserts a single character or a substring at the given index within the string.
+ {
+ assert(nIndex >= 0);
+
+ m_str.insert(nIndex, str);
+ return (int)m_str.size();
+ }
+
+ inline BOOL CString::IsEmpty() const
+ // Returns TRUE if the string is empty
+ {
+ return m_str.empty();
+ }
+
+ inline CString CString::Left(int nCount) const
+ // Extracts the left part of a string.
+ {
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), 0, nCount);
+ return str;
+ }
+
+ inline BOOL CString::LoadString(UINT nID)
+ // Loads the string from a Windows resource.
+ {
+ assert (GetApp());
+
+ int nSize = 64;
+ TCHAR* pTCharArray = 0;
+ std::vector vString;
+ int nTChars = nSize;
+
+ Empty();
+
+ // Increase the size of our array in a loop until we load the entire string
+ // The ANSI and _UNICODE versions of LoadString behave differently. This technique works for both.
+ while ( nSize-1 <= nTChars )
+ {
+ nSize = nSize * 4;
+ vString.assign(nSize+1, _T('\0'));
+ pTCharArray = &vString[0];
+ nTChars = ::LoadString (GetApp()->GetResourceHandle(), nID, pTCharArray, nSize);
+ }
+
+ if (nTChars > 0)
+ m_str.assign(pTCharArray);
+
+ return (nTChars != 0);
+ }
+
+ inline void CString::MakeLower()
+ // Converts all the characters in this string to lowercase characters.
+ {
+ std::transform(m_str.begin(), m_str.end(), m_str.begin(), &::tolower);
+ }
+
+ inline void CString::MakeReverse()
+ // Reverses the string.
+ {
+ std::reverse(m_str.begin(), m_str.end());
+ }
+
+ inline void CString::MakeUpper()
+ // Converts all the characters in this string to uppercase characters.
+ {
+ std::transform(m_str.begin(), m_str.end(), m_str.begin(), &::toupper);
+ }
+
+ inline CString CString::Mid(int nFirst) const
+ // Extracts the middle part of a string.
+ {
+ return Mid(nFirst, GetLength());
+ }
+
+ inline CString CString::Mid(int nFirst, int nCount) const
+ // Extracts the middle part of a string.
+ {
+ assert(nFirst >= 0);
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), nFirst, nFirst + nCount);
+ return str;
+ }
+
+ inline int CString::ReverseFind(LPCTSTR pszText, int nIndex /* = -1 */) const
+ // Search for a substring within the string, starting from the end.
+ {
+ assert(pszText);
+ return (int)m_str.rfind(pszText, nIndex);
+ }
+
+ inline void CString::SetAt(int nIndex, TCHAR ch)
+ // Sets the character at the specificed position to the specified value.
+ {
+ assert(nIndex >= 0);
+ assert(nIndex < GetLength());
+ m_str[nIndex] = ch;
+ }
+
+ inline void CString::ReleaseBuffer( int nNewLength /*= -1*/ )
+ // This copies the contents of the buffer (acquired by GetBuffer) to this CString,
+ // and releases the contents of the buffer. The default length of -1 copies from the
+ // buffer until a null terminator is reached. If the buffer doesn't contain a null
+ // terminator, you must specify the buffer's length.
+ {
+ assert (nNewLength > 0 || -1 == nNewLength);
+ assert (nNewLength < (int)m_buf.size());
+
+ if (-1 == nNewLength)
+ nNewLength = lstrlen(&m_buf[0]);
+ m_str.assign(nNewLength+1, _T('\0'));
+
+ std::vector::iterator it_end = m_buf.begin();
+ std::advance(it_end, nNewLength);
+
+ std::copy(m_buf.begin(), it_end, m_str.begin());
+ m_buf.clear();
+ }
+
+ inline int CString::Remove(LPCTSTR pszText)
+ // Removes each occurrence of the specified substring from the string.
+ {
+ assert(pszText);
+
+ int nCount = 0;
+ size_t pos = 0;
+ while ((pos = m_str.find(pszText, pos)) != std::string::npos)
+ {
+ m_str.erase(pos, lstrlen(pszText));
+ ++nCount;
+ }
+ return nCount;
+ }
+
+ inline int CString::Replace(TCHAR chOld, TCHAR chNew)
+ // Replaces each occurance of the old character with the new character.
+ {
+ int nCount = 0;
+ tString::iterator it = m_str.begin();
+ while (it != m_str.end())
+ {
+ if (*it == chOld)
+ {
+ *it = chNew;
+ ++nCount;
+ }
+ ++it;
+ }
+ return nCount;
+ }
+
+ inline int CString::Replace(LPCTSTR pszOld, LPCTSTR pszNew)
+ // Replaces each occurance of the old substring with the new substring.
+ {
+ assert(pszOld);
+ assert(pszNew);
+
+ int nCount = 0;
+ size_t pos = 0;
+ while ((pos = m_str.find(pszOld, pos)) != std::string::npos)
+ {
+ m_str.replace(pos, lstrlen(pszOld), pszNew);
+ pos += lstrlen(pszNew);
+ ++nCount;
+ }
+ return nCount;
+ }
+
+ inline CString CString::Right(int nCount) const
+ // Extracts the right part of a string.
+ {
+ assert(nCount >= 0);
+
+ CString str;
+ str.m_str.assign(c_str(), m_str.size() - nCount, nCount);
+ return str;
+ }
+
+ inline BSTR CString::SetSysString(BSTR* pBstr) const
+ // Sets an existing BSTR object to the string.
+ {
+ assert(pBstr);
+
+ if ( !::SysReAllocStringLen(pBstr, T2W(m_str.c_str()), (UINT)m_str.length()) )
+ throw std::bad_alloc();
+
+ return *pBstr;
+ }
+
+ inline CString CString::SpanExcluding(LPCTSTR pszText) const
+ // Extracts characters from the string, starting with the first character,
+ // that are not in the set of characters identified by pszCharSet.
+ {
+ assert (pszText);
+
+ CString str;
+ size_t pos = 0;
+
+ while ((pos = m_str.find_first_not_of(pszText, pos)) != std::string::npos)
+ {
+ str.m_str.append(1, m_str[pos++]);
+ }
+
+ return str;
+ }
+
+ inline CString CString::SpanIncluding(LPCTSTR pszText) const
+ // Extracts a substring that contains only the characters in a set.
+ {
+ assert (pszText);
+
+ CString str;
+ size_t pos = 0;
+
+ while ((pos = m_str.find_first_of(pszText, pos)) != std::string::npos)
+ {
+ str.m_str.append(1, m_str[pos++]);
+ }
+
+ return str;
+ }
+
+ inline CString CString::Tokenize(LPCTSTR pszTokens, int& iStart) const
+ // Extracts specified tokens in a target string.
+ {
+ assert(pszTokens);
+ assert(iStart >= 0);
+
+ CString str;
+ size_t pos1 = m_str.find_first_not_of(pszTokens, iStart);
+ size_t pos2 = m_str.find_first_of(pszTokens, pos1);
+
+ iStart = (int)pos2 + 1;
+ if (pos2 == m_str.npos)
+ iStart = -1;
+
+ if (pos1 != m_str.npos)
+ str.m_str = m_str.substr(pos1, pos2-pos1);
+
+ return str;
+ }
+
+ inline void CString::Trim()
+ // Trims all leading and trailing whitespace characters from the string.
+ {
+ TrimLeft();
+ TrimRight();
+ }
+
+ inline void CString::TrimLeft()
+ // Trims leading whitespace characters from the string.
+ {
+ // This method is supported by the Borland 5.5 compiler
+ tString::iterator iter;
+ for (iter = m_str.begin(); iter < m_str.end(); ++iter)
+ {
+ if (!isspace(*iter))
+ break;
+ }
+
+ m_str.erase(m_str.begin(), iter);
+ }
+
+ inline void CString::TrimLeft(TCHAR chTarget)
+ // Trims the specified character from the beginning of the string.
+ {
+ m_str.erase(0, m_str.find_first_not_of(chTarget));
+ }
+
+ inline void CString::TrimLeft(LPCTSTR pszTargets)
+ // Trims the specified set of characters from the beginning of the string.
+ {
+ assert(pszTargets);
+ m_str.erase(0, m_str.find_first_not_of(pszTargets));
+ }
+
+ inline void CString::TrimRight()
+ // Trims trailing whitespace characters from the string.
+ {
+ // This method is supported by the Borland 5.5 compiler
+ tString::reverse_iterator riter;
+ for (riter = m_str.rbegin(); riter < m_str.rend(); ++riter)
+ {
+ if (!isspace(*riter))
+ break;
+ }
+
+ m_str.erase(riter.base(), m_str.end());
+ }
+
+ inline void CString::TrimRight(TCHAR chTarget)
+ // Trims the specified character from the end of the string.
+ {
+ size_t pos = m_str.find_last_not_of(chTarget);
+ if (pos != std::string::npos)
+ m_str.erase(++pos);
+ }
+
+ inline void CString::TrimRight(LPCTSTR pszTargets)
+ // Trims the specified set of characters from the end of the string.
+ {
+ assert(pszTargets);
+
+ size_t pos = m_str.find_last_not_of(pszTargets);
+ if (pos != std::string::npos)
+ m_str.erase(++pos);
+ }
+
+ inline void CString::Truncate(int nNewLength)
+ // Reduces the length of the string to the specified amount.
+ {
+ if (nNewLength < GetLength())
+ {
+ assert(nNewLength >= 0);
+ m_str.erase(nNewLength);
+ }
+ }
+
+
+ ///////////////////////////////////
+ // Global Functions
+ //
+
+ // friend functions of CString
+ inline CString operator + (const CString& string1, const CString& string2)
+ {
+ CString str(string1);
+ str.m_str.append(string2.m_str);
+ return str;
+ }
+
+ inline CString operator + (const CString& string, LPCTSTR pszText)
+ {
+ CString str(string);
+ str.m_str.append(pszText);
+ return str;
+ }
+
+ inline CString operator + (const CString& string, TCHAR ch)
+ {
+ CString str(string);
+ str.m_str.append(1, ch);
+ return str;
+ }
+
+ inline CString operator + (LPCTSTR pszText, const CString& string)
+ {
+ CString str(pszText);
+ str.m_str.append(string);
+ return str;
+ }
+
+ inline CString operator + (TCHAR ch, const CString& string)
+ {
+ CString str(ch);
+ str.m_str.append(string);
+ return str;
+ }
+
+ // Global LoadString
+ inline CString LoadString(UINT nID)
+ {
+ CString str;
+ str.LoadString(nID);
+ return str;
+ }
+
+
+} // namespace Win32xx
+
+#endif//_WIN32XX_CSTRING_H_
diff --git a/external/win32cpp/include/default_resource.h b/external/win32cpp/include/default_resource.h
new file mode 100644
index 0000000..b616a18
--- /dev/null
+++ b/external/win32cpp/include/default_resource.h
@@ -0,0 +1,94 @@
+// This file contains the resource ID definitions for Win32++.
+
+
+// The resource ID for MENU, ICON, ToolBar Bitmap, Accelerator,
+// and Window Caption
+#define IDW_MAIN 51
+
+// Resource ID for the About dialog
+#define IDW_ABOUT 52
+
+// Resource IDs for menu items
+#define IDW_VIEW_TOOLBAR 53
+#define IDW_VIEW_STATUSBAR 54
+
+// Resource IDs for the Command Bands
+#define IDW_CMD_BANDS 55
+#define IDW_MENUBAR 56
+#define IDW_TOOLBAR 57
+
+// Resource ID for the Accelerator key
+#define IDW_QUIT 58
+
+// Resource IDs for MDI menu items
+#define IDW_MDI_CASCADE 60
+#define IDW_MDI_TILE 61
+#define IDW_MDI_ARRANGE 62
+#define IDW_MDI_CLOSEALL 63
+#define IDW_FIRSTCHILD 64
+#define IDW_CHILD2 65
+#define IDW_CHILD3 66
+#define IDW_CHILD4 67
+#define IDW_CHILD5 68
+#define IDW_CHILD6 69
+#define IDW_CHILD7 70
+#define IDW_CHILD8 71
+#define IDW_CHILD9 72
+#define IDW_CHILD10 73
+
+#define IDW_FILE_MRU_FILE1 75
+#define IDW_FILE_MRU_FILE2 76
+#define IDW_FILE_MRU_FILE3 77
+#define IDW_FILE_MRU_FILE4 78
+#define IDW_FILE_MRU_FILE5 79
+#define IDW_FILE_MRU_FILE6 80
+#define IDW_FILE_MRU_FILE7 81
+#define IDW_FILE_MRU_FILE8 82
+#define IDW_FILE_MRU_FILE9 83
+#define IDW_FILE_MRU_FILE10 84
+#define IDW_FILE_MRU_FILE11 85
+#define IDW_FILE_MRU_FILE12 86
+#define IDW_FILE_MRU_FILE13 87
+#define IDW_FILE_MRU_FILE14 88
+#define IDW_FILE_MRU_FILE15 89
+#define IDW_FILE_MRU_FILE16 90
+
+// Cursor Resources
+#define IDW_SPLITH 91
+#define IDW_SPLITV 92
+#define IDW_TRACK4WAY 93
+
+// Docking Bitmap Resources
+#define IDW_SDBOTTOM 94
+#define IDW_SDCENTER 95
+#define IDW_SDLEFT 96
+#define IDW_SDMIDDLE 97
+#define IDW_SDRIGHT 98
+#define IDW_SDTOP 99
+
+
+// A generic ID for any static control
+#ifndef IDC_STATIC
+ #define IDC_STATIC -1
+#endif
+
+
+
+// Notes about Resource IDs
+// * In general, resource IDs can have values from 1 to 65535. Programs with
+// resource IDs higher than 65535 aren't supported on Windows 95
+//
+// * CMenuBar uses resource IDs beginning from 0 for the top level menu items.
+// Win32++ leaves resource IDs below 51 unallocated for top level menu items.
+//
+// * Windows uses the icon with the lowest resource ID as the application's
+// icon. The application's icon is IDW_MAIN, which is the first resource ID
+// defined by Win32++.
+//
+// * When more than one static control is used in a dialog, the controls should
+// have a unique ID, unless a resource ID of -1 is used.
+//
+// * Users of Win32++ are advised to begin their resource IDs from 120 to
+// allow for possible expansion of Win32++.
+
+
diff --git a/external/win32cpp/include/default_resource.rc b/external/win32cpp/include/default_resource.rc
new file mode 100644
index 0000000..d53479f
--- /dev/null
+++ b/external/win32cpp/include/default_resource.rc
@@ -0,0 +1,250 @@
+// An example of a resource file
+//
+
+#include "resource.h"
+#include "windows.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// RT_MANIFEST
+//
+
+1 24 DISCARDABLE "res/Win32++.manifest"
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+
+IDW_MAIN MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "New &View", IDM_FILE_NEWVIEW
+ MENUITEM SEPARATOR
+ MENUITEM "Recent Files", IDW_FILE_MRU_FILE1, GRAYED
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Undo\tCtrl+Z", IDM_EDIT_UNDO
+ MENUITEM "Redo\tShift+Ctrl+Z", IDM_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cut\tCtrl+X", IDM_EDIT_CUT
+ MENUITEM "Copy\tCtrl+C", IDM_EDIT_COPY
+ MENUITEM "Paste\tCtrl+V", IDM_EDIT_PASTE
+ MENUITEM "Delete\tDel", IDM_EDIT_DELETE
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "&Tool Bar", IDW_VIEW_TOOLBAR, CHECKED
+ MENUITEM "&Status Bar", IDW_VIEW_STATUSBAR, CHECKED
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About", IDM_HELP_ABOUT
+ END
+END
+
+MDIMENUVIEW MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "New &View", IDM_FILE_NEWVIEW
+ MENUITEM "&Close", IDM_FILE_CLOSE
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_FILE_EXIT
+ END
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Undo", IDM_EDIT_UNDO
+ MENUITEM "Redo", IDM_EDIT_REDO
+ MENUITEM SEPARATOR
+ MENUITEM "Cu&t", IDM_EDIT_CUT
+ MENUITEM "&Copy", IDM_EDIT_COPY
+ MENUITEM "&Paste", IDM_EDIT_PASTE
+ MENUITEM "De&lete", IDM_EDIT_DELETE
+ END
+ POPUP "&View"
+ BEGIN
+ MENUITEM "Tool Bar", IDW_VIEW_TOOLBAR, CHECKED
+ MENUITEM "Status Bar", IDW_VIEW_STATUSBAR, CHECKED
+ END
+ POPUP "&Color"
+ BEGIN
+ MENUITEM "&Black", IDM_COLOR_BLACK
+ MENUITEM "&Red", IDM_COLOR_RED
+ MENUITEM "&Green", IDM_COLOR_GREEN
+ MENUITEM "B&lue", IDM_COLOR_BLUE
+ MENUITEM "&White", IDM_COLOR_WHITE
+ END
+ POPUP "&Window"
+ BEGIN
+ MENUITEM "&Cascade\tShift+F5", IDW_WINDOW_CASCADE
+ MENUITEM "&Tile\tShift+F4", IDW_WINDOW_TILE
+ MENUITEM "Arrange &Icons", IDW_WINDOW_ARRANGE
+ MENUITEM "Close &All", IDW_WINDOW_CLOSEALL
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "About", IDM_HELP_ABOUT
+ END
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDW_MAIN ICON "res/mdi.ico"
+IDI_VIEW ICON "res/view.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDW_MAIN BITMAP "res/toolbar.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDW_ABOUT DIALOGEX 0, 0, 186, 90
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "About"
+FONT 8, "MS Shell Dlg", 400, 0
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,68,49,50,14
+ CTEXT "MDI Frame",IDC_STATIC,60,22,64,11
+ ICON IDW_MAIN,0,4,4,20,20
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDW_MAIN ACCELERATORS
+BEGIN
+ "N", IDM_FILE_NEW, VIRTKEY, CONTROL, NOINVERT
+ "O", IDM_FILE_OPEN, VIRTKEY, CONTROL, NOINVERT
+ "P", IDM_FILE_PRINT, VIRTKEY, CONTROL, NOINVERT
+ "S", IDM_FILE_SAVE, VIRTKEY, CONTROL, NOINVERT
+ "C", IDM_EDIT_COPY, VIRTKEY, CONTROL, NOINVERT
+ "X", IDM_EDIT_CUT, VIRTKEY, CONTROL, NOINVERT
+ "V", IDM_EDIT_PASTE, VIRTKEY, CONTROL, NOINVERT
+ "Z", IDM_EDIT_UNDO, VIRTKEY, CONTROL, NOINVERT
+ "Y", IDM_EDIT_REDO, VIRTKEY, SHIFT, CONTROL, NOINVERT
+ VK_DELETE, IDM_EDIT_DELETE, VIRTKEY, NOINVERT
+END
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDW_MAIN "MDI Frame"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_FILE_NEW "Create a New Document"
+ IDM_FILE_OPEN "Open Existing Document"
+ IDM_FILE_SAVE "Save the Document"
+ IDM_FILE_SAVEAS "Save the Document with a new name"
+ IDM_FILE_PRINT "Print the Document"
+ IDM_FILE_EXIT "End the Program"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_EDIT_UNDO "Undo the last action"
+ IDM_EDIT_REDO "Redo the previously undone action"
+ IDM_EDIT_CUT "Cut the Selected Contents to the Clipboard"
+ IDM_EDIT_COPY "Copy the Selected Contents to the Clipboard"
+ IDM_EDIT_PASTE "Paste the Clipboard Contents to the Document"
+ IDM_EDIT_DELETE "Erase the selected Contents"
+ IDW_VIEW_TOOLBAR "Show or hide the tool bar"
+ IDW_VIEW_STATUSBAR "Show or hide the status bar"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_HELP_ABOUT "Display Information about this program"
+END
+
+STRINGTABLE
+BEGIN
+ IDW_FIRSTCHILD "Activate this window"
+ IDW_CHILD2 "Activate this window"
+ IDW_CHILD3 "Activate this window"
+ IDW_CHILD4 "Activate this window"
+ IDW_CHILD5 "Activate this window"
+ IDW_CHILD6 "Activate this window"
+ IDW_CHILD7 "Activate this window"
+ IDW_CHILD8 "Activate this window"
+ IDW_CHILD9 "Activate this window"
+ IDW_CHILD10 "Select a window"
+END
+
+STRINGTABLE
+BEGIN
+ IDM_FILE_NEWVIEW "Create View MDI Child"
+ IDM_FILE_CLOSE "Close MDI Window"
+ IDM_COLOR_BLACK "Use Black Printing"
+ IDM_COLOR_RED "Use Red Printing"
+ IDM_COLOR_GREEN "Use Green Printing"
+ IDM_COLOR_BLUE "Use Blue Printing"
+ IDM_COLOR_WHITE "Use White Printing"
+ IDW_WINDOW_CASCADE "Cascade MDI Windows"
+ IDW_WINDOW_TILE "Tile MDI Windows"
+ IDW_WINDOW_ARRANGE "Arrange Icons"
+ IDW_WINDOW_CLOSEALL "Close All MDI Windows"
+END
+
+STRINGTABLE
+BEGIN
+ SC_CLOSE "Close the Window"
+ SC_MAXIMIZE "Maximize the Window"
+ SC_MINIMIZE "Minimize the WIndow"
+ SC_MOVE "Move the Window"
+ SC_NEXTWINDOW "Select Next Window"
+ SC_PREVWINDOW "Select Previous Window"
+ SC_RESTORE "Restore the Window"
+ SC_SIZE "Resize the Window"
+END
+
+STRINGTABLE
+BEGIN
+ IDW_FILE_MRU_FILE1 "Open this document"
+ IDW_FILE_MRU_FILE2 "Open this document"
+ IDW_FILE_MRU_FILE3 "Open this document"
+ IDW_FILE_MRU_FILE4 "Open this document"
+ IDW_FILE_MRU_FILE5 "Open this document"
+ IDW_FILE_MRU_FILE6 "Open this document"
+ IDW_FILE_MRU_FILE7 "Open this document"
+ IDW_FILE_MRU_FILE8 "Open this document"
+ IDW_FILE_MRU_FILE9 "Open this document"
+ IDW_FILE_MRU_FILE10 "Open this document"
+ IDW_FILE_MRU_FILE11 "Open this document"
+ IDW_FILE_MRU_FILE12 "Open this document"
+ IDW_FILE_MRU_FILE13 "Open this document"
+ IDW_FILE_MRU_FILE14 "Open this document"
+ IDW_FILE_MRU_FILE15 "Open this document"
+ IDW_FILE_MRU_FILE16 "Open this document"
+END
+
+
diff --git a/external/win32cpp/include/dialog.h b/external/win32cpp/include/dialog.h
new file mode 100644
index 0000000..e512330
--- /dev/null
+++ b/external/win32cpp/include/dialog.h
@@ -0,0 +1,876 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// dialog.h
+// Declaration of the CDialog class
+
+// CDialog adds support for dialogs to Win32++. Dialogs are specialised
+// windows which are a parent window for common controls. Common controls
+// are special window types such as buttons, edit controls, tree views,
+// list views, static text etc.
+
+// The layout of a dialog is typically defined in a resource script file
+// (often Resource.rc). While this script file can be constructed manually,
+// it is often created using a resource editor. If your compiler doesn't
+// include a resource editor, you might find ResEdit useful. It is a free
+// resource editor available for download at:
+// http://www.resedit.net/
+
+// CDialog supports modal and modeless dialogs. It also supports the creation
+// of dialogs defined in a resource script file, as well as those defined in
+// a dialog template.
+
+// Use the Dialog generic program as the starting point for your own dialog
+// applications.
+// The DlgSubclass sample demonstrates how to use subclassing to customise
+// the behaviour of common controls in a dialog.
+
+
+#ifndef _WIN32XX_DIALOG_H_
+#define _WIN32XX_DIALOG_H_
+
+#include "wincore.h"
+
+#ifndef SWP_NOCOPYBITS
+ #define SWP_NOCOPYBITS 0x0100
+#endif
+
+namespace Win32xx
+{
+
+ class CDialog : public CWnd
+ {
+ public:
+ CDialog(UINT nResID, CWnd* pParent = NULL);
+ CDialog(LPCTSTR lpszResName, CWnd* pParent = NULL);
+ CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);
+ virtual ~CDialog();
+
+ // You probably won't need to override these functions
+ virtual void AttachItem(int nID, CWnd& Wnd);
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual INT_PTR DoModal();
+ virtual HWND DoModeless();
+ virtual void SetDlgParent(CWnd* pParent);
+ BOOL IsModal() const { return m_IsModal; }
+ BOOL IsIndirect() const { return (NULL != m_lpTemplate); }
+
+ protected:
+ // These are the functions you might wish to override
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void EndDialog(INT_PTR nResult);
+ virtual void OnCancel();
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+ // Can't override these functions
+ static INT_PTR CALLBACK StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ #ifndef _WIN32_WCE
+ static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
+ #endif
+
+ private:
+ CDialog(const CDialog&); // Disable copy construction
+ CDialog& operator = (const CDialog&); // Disable assignment operator
+
+ BOOL m_IsModal; // a flag for modal dialogs
+ LPCTSTR m_lpszResName; // the resource name for the dialog
+ LPCDLGTEMPLATE m_lpTemplate; // the dialog template for indirect dialogs
+ HWND m_hParent; // handle to the dialogs's parent window
+ };
+
+
+#ifndef _WIN32_WCE
+
+ //////////////////////////////////////
+ // Declaration of the CResizer class
+ //
+ // The CResizer class can be used to rearrange a dialog's child
+ // windows when the dialog is resized.
+
+ // To use CResizer, follow the following steps:
+ // 1) Use Initialize to specify the dialog's CWnd, and min and max size.
+ // 3) Use AddChild for each child window
+ // 4) Call HandleMessage from within DialogProc.
+ //
+
+ // Resize Dialog Styles
+#define RD_STRETCH_WIDTH 0x0001 // The item has a variable width
+#define RD_STRETCH_HEIGHT 0x0002 // The item has a variable height
+
+ // Resize Dialog alignments
+ enum Alignment { topleft, topright, bottomleft, bottomright };
+
+ class CResizer
+ {
+ public:
+ CResizer() : m_pParent(0), m_xScrollPos(0), m_yScrollPos(0) {}
+ virtual ~CResizer() {}
+
+ virtual void AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle);
+ virtual void AddChild(HWND hWnd, Alignment corner, DWORD dwStyle);
+ virtual void HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void Initialize(CWnd* pParent, RECT rcMin, RECT rcMax = CRect(0,0,0,0));
+ virtual void OnHScroll(WPARAM wParam, LPARAM lParam);
+ virtual void OnVScroll(WPARAM wParam, LPARAM lParam);
+ virtual void RecalcLayout();
+ CRect GetMinRect() const { return m_rcMin; }
+ CRect GetMaxRect() const { return m_rcMax; }
+
+ struct ResizeData
+ {
+ CRect rcInit;
+ CRect rcOld;
+ Alignment corner;
+ BOOL bFixedWidth;
+ BOOL bFixedHeight;
+ HWND hWnd;
+ };
+
+ private:
+ CWnd* m_pParent;
+ std::vector m_vResizeData;
+
+ CRect m_rcInit;
+ CRect m_rcMin;
+ CRect m_rcMax;
+
+ int m_xScrollPos;
+ int m_yScrollPos;
+ };
+
+#endif
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+ ////////////////////////////////////
+ // Definitions for the CDialog class
+ //
+ inline CDialog::CDialog(LPCTSTR lpszResName, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(lpszResName), m_lpTemplate(NULL)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ inline CDialog::CDialog(UINT nResID, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(MAKEINTRESOURCE (nResID)), m_lpTemplate(NULL)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ //For indirect dialogs - created from a dialog box template in memory.
+ inline CDialog::CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent/* = NULL*/)
+ : m_IsModal(TRUE), m_lpszResName(NULL), m_lpTemplate(lpTemplate)
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ ::InitCommonControls();
+ }
+
+ inline CDialog::~CDialog()
+ {
+ if (m_hWnd != NULL)
+ {
+ if (IsModal())
+ ::EndDialog(m_hWnd, 0);
+ else
+ Destroy();
+ }
+ }
+
+ inline void CDialog::AttachItem(int nID, CWnd& Wnd)
+ // Attach a dialog item to a CWnd
+ {
+ Wnd.AttachDlgItem(nID, this);
+ }
+
+ inline HWND CDialog::Create(CWnd* pParent /* = NULL */)
+ {
+ // Allow a dialog to be used as a child window
+
+ assert(GetApp());
+ SetDlgParent(pParent);
+ return DoModeless();
+ }
+
+ inline INT_PTR CDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CDialog if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Windows API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Windows API documentation
+ // }
+
+ // Always pass unhandled messages on to DialogProcDefault
+ return DialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline INT_PTR CDialog::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All DialogProc functions should pass unhandled messages to this function
+ {
+ LRESULT lr = 0;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+ case WM_INITDIALOG:
+ {
+ // Center the dialog
+ CenterWindow();
+ }
+ return OnInitDialog();
+ case WM_COMMAND:
+ switch (LOWORD (wParam))
+ {
+ case IDOK:
+ OnOK();
+ return TRUE;
+ case IDCANCEL:
+ OnCancel();
+ return TRUE;
+ default:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break; // Some commands require default processing
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+
+ // Set the return code for notifications
+ if (IsWindow())
+ SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
+
+ return (BOOL)lr;
+ }
+
+ case WM_PAINT:
+ {
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ return MessageReflect(m_hWnd, uMsg, wParam, lParam);
+
+ } // switch(uMsg)
+ return FALSE;
+
+ } // INT_PTR CALLBACK CDialog::DialogProc(...)
+
+ inline INT_PTR CDialog::DoModal()
+ {
+ // Create a modal dialog
+ // A modal dialog box must be closed by the user before the application continues
+
+ assert( GetApp() ); // Test if Win32++ has been started
+ assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
+
+ INT_PTR nResult = 0;
+
+ try
+ {
+ m_IsModal=TRUE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ #ifndef _WIN32_WCE
+ BOOL IsHookedHere = FALSE;
+ if (NULL == pTLSData->hHook )
+ {
+ pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
+ IsHookedHere = TRUE;
+ }
+ #endif
+
+ HINSTANCE hInstance = GetApp()->GetInstanceHandle();
+ pTLSData->pCWnd = this;
+
+ // Create a modal dialog
+ if (IsIndirect())
+ nResult = ::DialogBoxIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ else
+ {
+ if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
+ hInstance = GetApp()->GetResourceHandle();
+ nResult = ::DialogBox(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ }
+
+ // Tidy up
+ m_hWnd = NULL;
+ pTLSData->pCWnd = NULL;
+ GetApp()->CleanupTemps();
+
+ #ifndef _WIN32_WCE
+ if (IsHookedHere)
+ {
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+ pTLSData->hHook = NULL;
+ }
+ #endif
+
+ if (nResult == -1)
+ throw CWinException(_T("Failed to create modal dialog box"));
+
+ }
+
+ catch (const CWinException &e)
+ {
+ TRACE(_T("\n*** Failed to create dialog ***\n"));
+ e.what(); // Display the last error message.
+
+ // eat the exception (don't rethrow)
+ }
+
+ return nResult;
+ }
+
+ inline HWND CDialog::DoModeless()
+ {
+ assert( GetApp() ); // Test if Win32++ has been started
+ assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
+
+ try
+ {
+ m_IsModal=FALSE;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the CWnd pointer in Thread Local Storage
+ pTLSData->pCWnd = this;
+
+ HINSTANCE hInstance = GetApp()->GetInstanceHandle();
+
+ // Create a modeless dialog
+ if (IsIndirect())
+ m_hWnd = ::CreateDialogIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ else
+ {
+ if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
+ hInstance = GetApp()->GetResourceHandle();
+
+ m_hWnd = ::CreateDialog(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
+ }
+
+ // Tidy up
+ pTLSData->pCWnd = NULL;
+
+ // Now handle dialog creation failure
+ if (!m_hWnd)
+ throw CWinException(_T("Failed to create dialog"));
+ }
+
+ catch (const CWinException &e)
+ {
+ TRACE(_T("\n*** Failed to create dialog ***\n"));
+ e.what(); // Display the last error message.
+
+ // eat the exception (don't rethrow)
+ }
+
+ return m_hWnd;
+ }
+
+ inline void CDialog::EndDialog(INT_PTR nResult)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ if (IsModal())
+ ::EndDialog(m_hWnd, nResult);
+ else
+ Destroy();
+
+ m_hWnd = NULL;
+ }
+
+ inline void CDialog::OnCancel()
+ {
+ // Override to customize OnCancel behaviour
+ EndDialog(IDCANCEL);
+ }
+
+ inline BOOL CDialog::OnInitDialog()
+ {
+ // Called when the dialog is initialized
+ // Override it in your derived class to automatically perform tasks
+ // The return value is used by WM_INITDIALOG
+
+ return TRUE;
+ }
+
+ inline void CDialog::OnOK()
+ {
+ // Override to customize OnOK behaviour
+ EndDialog(IDOK);
+ }
+
+ inline BOOL CDialog::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ // Process dialog keystrokes for modeless dialogs
+ if (!IsModal())
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ if (NULL == pTLSData->hHook)
+ {
+ if (IsDialogMessage(pMsg))
+ return TRUE;
+ }
+ else
+ {
+ // A modal message loop is running so we can't do IsDialogMessage.
+ // Avoid having modal dialogs create other windows, because those
+ // windows will then use the modal dialog's special message loop.
+ }
+ }
+ }
+
+ return FALSE;
+ }
+
+ inline void CDialog::SetDlgParent(CWnd* pParent)
+ // Allows the parent of the dialog to be set before the dialog is created
+ {
+ m_hParent = pParent? pParent->GetHwnd() : NULL;
+ }
+
+ inline INT_PTR CALLBACK CDialog::StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Find the CWnd pointer mapped to this HWND
+ CDialog* w = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (0 == w)
+ {
+ // The HWND wasn't in the map, so add it now
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Retrieve pointer to CWnd object from Thread Local Storage TLS
+ w = (CDialog*)pTLSData->pCWnd;
+ assert(w);
+ pTLSData->pCWnd = NULL;
+
+ // Store the Window pointer into the HWND map
+ w->m_hWnd = hWnd;
+ w->AddToMap();
+ }
+
+ return w->DialogProc(uMsg, wParam, lParam);
+
+ } // INT_PTR CALLBACK CDialog::StaticDialogProc(...)
+
+#ifndef _WIN32_WCE
+ inline LRESULT CALLBACK CDialog::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ // Used by Modal Dialogs to PreTranslate Messages
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+
+ if (nCode == MSGF_DIALOGBOX)
+ {
+ MSG* lpMsg = (MSG*) lParam;
+
+ // only pre-translate keyboard events
+ if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST))
+ {
+ for (HWND hWnd = lpMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
+ {
+ CDialog* pDialog = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (pDialog && (lstrcmp(pDialog->GetClassName(), _T("#32770")) == 0)) // only for dialogs
+ {
+ pDialog->PreTranslateMessage(lpMsg);
+ break;
+ }
+ }
+ }
+ }
+
+ return ::CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
+ }
+#endif
+
+
+
+#ifndef _WIN32_WCE
+
+ /////////////////////////////////////
+ // Definitions for the CResizer class
+ //
+
+ void inline CResizer::AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle)
+ // Adds a child window (usually a dialog control) to the set of windows managed by
+ // the Resizer.
+ //
+ // The alignment corner should be set to the closest corner of the dialog. Allowed
+ // values are topleft, topright, bottomleft, and bottomright.
+ // Set bFixedWidth to TRUE if the width should be fixed instead of variable.
+ // Set bFixedHeight to TRUE if the height should be fixed instead of variable.
+ {
+ ResizeData rd;
+ rd.corner = corner;
+ rd.bFixedWidth = !(dwStyle & RD_STRETCH_WIDTH);
+ rd.bFixedHeight = !(dwStyle & RD_STRETCH_HEIGHT);
+ CRect rcInit = pWnd->GetWindowRect();
+ m_pParent->ScreenToClient(rcInit);
+ rd.rcInit = rcInit;
+ rd.hWnd = pWnd->GetHwnd();
+
+ m_vResizeData.insert(m_vResizeData.begin(), rd);
+ }
+
+ void inline CResizer::AddChild(HWND hWnd, Alignment corner, DWORD dwStyle)
+ // Adds a child window (usually a dialog control) to the set of windows managed by
+ // the Resizer.
+ {
+ AddChild(FromHandle(hWnd), corner, dwStyle);
+ }
+
+ inline void CResizer::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ break;
+
+ case WM_HSCROLL:
+ if (0 == lParam)
+ OnHScroll(wParam, lParam);
+ break;
+
+ case WM_VSCROLL:
+ if (0 == lParam)
+ OnVScroll(wParam, lParam);
+ break;
+ }
+ }
+
+ void inline CResizer::Initialize(CWnd* pParent, RECT rcMin, RECT rcMax)
+ // Sets up the Resizer by specifying the parent window (usually a dialog),
+ // and the minimum and maximum allowed rectangle sizes.
+ {
+ assert (NULL != pParent);
+
+ m_pParent = pParent;
+ m_rcInit = pParent->GetClientRect();
+ m_rcMin = rcMin;
+ m_rcMax = rcMax;
+
+ // Add scroll bar support to the parent window
+ DWORD dwStyle = (DWORD)m_pParent->GetClassLongPtr(GCL_STYLE);
+ dwStyle |= WS_HSCROLL | WS_VSCROLL;
+ m_pParent->SetClassLongPtr(GCL_STYLE, dwStyle);
+ }
+
+ void inline CResizer::OnHScroll(WPARAM wParam, LPARAM /*lParam*/)
+ {
+ int xNewPos;
+
+ switch (LOWORD(wParam))
+ {
+ case SB_PAGEUP: // User clicked the scroll bar shaft left of the scroll box.
+ xNewPos = m_xScrollPos - 50;
+ break;
+
+ case SB_PAGEDOWN: // User clicked the scroll bar shaft right of the scroll box.
+ xNewPos = m_xScrollPos + 50;
+ break;
+
+ case SB_LINEUP: // User clicked the left arrow.
+ xNewPos = m_xScrollPos - 5;
+ break;
+
+ case SB_LINEDOWN: // User clicked the right arrow.
+ xNewPos = m_xScrollPos + 5;
+ break;
+
+ case SB_THUMBPOSITION: // User dragged the scroll box.
+ xNewPos = HIWORD(wParam);
+ break;
+
+ case SB_THUMBTRACK: // User dragging the scroll box.
+ xNewPos = HIWORD(wParam);
+ break;
+
+ default:
+ xNewPos = m_xScrollPos;
+ }
+
+ // Scroll the window.
+ xNewPos = MAX(0, xNewPos);
+ xNewPos = MIN( xNewPos, GetMinRect().Width() - m_pParent->GetClientRect().Width() );
+ int xDelta = xNewPos - m_xScrollPos;
+ m_xScrollPos = xNewPos;
+ m_pParent->ScrollWindow(-xDelta, 0, NULL, NULL);
+
+ // Reset the scroll bar.
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = m_xScrollPos;
+ m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
+ }
+
+ void inline CResizer::OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
+ {
+ int yNewPos;
+
+ switch (LOWORD(wParam))
+ {
+ case SB_PAGEUP: // User clicked the scroll bar shaft above the scroll box.
+ yNewPos = m_yScrollPos - 50;
+ break;
+
+ case SB_PAGEDOWN: // User clicked the scroll bar shaft below the scroll box.
+ yNewPos = m_yScrollPos + 50;
+ break;
+
+ case SB_LINEUP: // User clicked the top arrow.
+ yNewPos = m_yScrollPos - 5;
+ break;
+
+ case SB_LINEDOWN: // User clicked the bottom arrow.
+ yNewPos = m_yScrollPos + 5;
+ break;
+
+ case SB_THUMBPOSITION: // User dragged the scroll box.
+ yNewPos = HIWORD(wParam);
+ break;
+
+ case SB_THUMBTRACK: // User dragging the scroll box.
+ yNewPos = HIWORD(wParam);
+ break;
+
+ default:
+ yNewPos = m_yScrollPos;
+ }
+
+ // Scroll the window.
+ yNewPos = MAX(0, yNewPos);
+ yNewPos = MIN( yNewPos, GetMinRect().Height() - m_pParent->GetClientRect().Height() );
+ int yDelta = yNewPos - m_yScrollPos;
+ m_yScrollPos = yNewPos;
+ m_pParent->ScrollWindow(0, -yDelta, NULL, NULL);
+
+ // Reset the scroll bar.
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_POS;
+ si.nPos = m_yScrollPos;
+ m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
+ }
+
+ void inline CResizer::RecalcLayout()
+ // Repositions the child windows. Call this function when handling
+ // the WM_SIZE message in the parent window.
+ {
+ assert (m_rcInit.Width() > 0 && m_rcInit.Height() > 0);
+ assert (NULL != m_pParent);
+
+ CRect rcCurrent = m_pParent->GetClientRect();
+
+ // Adjust the scrolling if required
+ m_xScrollPos = MIN(m_xScrollPos, MAX(0, m_rcMin.Width() - rcCurrent.Width() ) );
+ m_yScrollPos = MIN(m_yScrollPos, MAX(0, m_rcMin.Height() - rcCurrent.Height()) );
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMax = m_rcMin.Width();
+ si.nPage = rcCurrent.Width();
+ si.nPos = m_xScrollPos;
+ m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
+ si.nMax = m_rcMin.Height();
+ si.nPage = rcCurrent.Height();
+ si.nPos = m_yScrollPos;
+ m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
+
+ rcCurrent.right = MAX( rcCurrent.Width(), m_rcMin.Width() );
+ rcCurrent.bottom = MAX( rcCurrent.Height(), m_rcMin.Height() );
+ if (!m_rcMax.IsRectEmpty())
+ {
+ rcCurrent.right = MIN( rcCurrent.Width(), m_rcMax.Width() );
+ rcCurrent.bottom = MIN( rcCurrent.Height(), m_rcMax.Height() );
+ }
+
+ // Declare an iterator to step through the vector
+ std::vector::iterator iter;
+
+ for (iter = m_vResizeData.begin(); iter < m_vResizeData.end(); ++iter)
+ {
+ int left = 0;
+ int top = 0;
+ int width = 0;
+ int height = 0;
+
+ // Calculate the new size and position of the child window
+ switch( (*iter).corner )
+ {
+ case topleft:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.left;
+ top = (*iter).rcInit.top;
+ break;
+ case topright:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
+ top = (*iter).rcInit.top;
+ break;
+ case bottomleft:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.left;
+ top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
+ break;
+ case bottomright:
+ width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
+ height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
+ left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
+ top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
+ break;
+ }
+
+ // Position the child window.
+ CRect rc(left - m_xScrollPos, top - m_yScrollPos, left + width - m_xScrollPos, top + height - m_yScrollPos);
+ if ( rc != (*iter).rcOld)
+ {
+ CWnd* pWnd = FromHandle((*iter).hWnd);
+ CWnd *pWndPrev = pWnd->GetWindow(GW_HWNDPREV); // Trick to maintain the original tab order.
+ HWND hWnd = pWndPrev ? pWndPrev->GetHwnd():NULL;
+ pWnd->SetWindowPos(hWnd, rc, SWP_NOCOPYBITS);
+ (*iter).rcOld = rc;
+ }
+ }
+ }
+
+#endif // #ifndef _WIN32_WCE
+
+} // namespace Win32xx
+
+
+
+#endif // _WIN32XX_DIALOG_H_
+
diff --git a/external/win32cpp/include/docking.h b/external/win32cpp/include/docking.h
new file mode 100644
index 0000000..9e7c448
--- /dev/null
+++ b/external/win32cpp/include/docking.h
@@ -0,0 +1,4214 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// docking.h
+// Declaration of the CDocker class
+
+#ifndef _WIN32XX_DOCKING_H_
+#define _WIN32XX_DOCKING_H_
+
+
+#include "wincore.h"
+#include "gdi.h"
+#include "toolbar.h"
+#include "tab.h"
+#include "frame.h"
+#include "default_resource.h"
+
+
+// Docking Styles
+#define DS_DOCKED_LEFT 0x0001 // Dock the child left
+#define DS_DOCKED_RIGHT 0x0002 // Dock the child right
+#define DS_DOCKED_TOP 0x0004 // Dock the child top
+#define DS_DOCKED_BOTTOM 0x0008 // Dock the child bottom
+#define DS_NO_DOCKCHILD_LEFT 0x0010 // Prevent a child docking left
+#define DS_NO_DOCKCHILD_RIGHT 0x0020 // Prevent a child docking right
+#define DS_NO_DOCKCHILD_TOP 0x0040 // Prevent a child docking at the top
+#define DS_NO_DOCKCHILD_BOTTOM 0x0080 // Prevent a child docking at the bottom
+#define DS_NO_RESIZE 0x0100 // Prevent resizing
+#define DS_NO_CAPTION 0x0200 // Prevent display of caption when docked
+#define DS_NO_CLOSE 0x0400 // Prevent closing of a docker while docked
+#define DS_NO_UNDOCK 0x0800 // Prevent undocking and dock closing
+#define DS_CLIENTEDGE 0x1000 // Has a 3D border when docked
+#define DS_FIXED_RESIZE 0x2000 // Perfomed a fixed resize instead of a proportional resize on dock children
+#define DS_DOCKED_CONTAINER 0x4000 // Dock a container within a container
+#define DS_DOCKED_LEFTMOST 0x10000 // Leftmost outer docking
+#define DS_DOCKED_RIGHTMOST 0x20000 // Rightmost outer docking
+#define DS_DOCKED_TOPMOST 0x40000 // Topmost outer docking
+#define DS_DOCKED_BOTTOMMOST 0x80000 // Bottommost outer docking
+
+// Required for Dev-C++
+#ifndef TME_NONCLIENT
+ #define TME_NONCLIENT 0x00000010
+#endif
+#ifndef TME_LEAVE
+ #define TME_LEAVE 0x000000002
+#endif
+#ifndef WM_NCMOUSELEAVE
+ #define WM_NCMOUSELEAVE 0x000002A2
+#endif
+
+namespace Win32xx
+{
+ // Class declarations
+ class CDockContainer;
+ class CDocker;
+
+ typedef Shared_Ptr DockPtr;
+
+ struct ContainerInfo
+ {
+ TCHAR szTitle[MAX_MENU_STRING];
+ int iImage;
+ CDockContainer* pContainer;
+ };
+
+ ///////////////////////////////////////
+ // Declaration of the CDockContainer class
+ // A CDockContainer is a CTab window. A CTab has a view window, and optionally a toolbar control.
+ // A top level CDockContainer can contain other CDockContainers. The view for each container
+ // (including the top level container) along with possibly its toolbar, is displayed
+ // within the container parent's view page.
+ class CDockContainer : public CTab
+ {
+ public:
+
+ // Nested class. This is the Wnd for the window displayed over the client area
+ // of the tab control. The toolbar and view window are child windows of the
+ // viewpage window. Only the ViewPage of the parent CDockContainer is displayed. It's
+ // contents are updated with the view window of the relevant container whenever
+ // a different tab is selected.
+ class CViewPage : public CWnd
+ {
+
+ public:
+ CViewPage() : m_pView(NULL), m_pTab(NULL) {}
+ virtual ~CViewPage() {}
+ virtual CToolBar& GetToolBar() const {return (CToolBar&)m_ToolBar;}
+ virtual CWnd* GetView() const {return m_pView;}
+ virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void RecalcLayout();
+ virtual void SetView(CWnd& wndView);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ CWnd* GetTabCtrl() const { return m_pTab;}
+
+ private:
+ CToolBar m_ToolBar;
+ tString m_tsTooltip;
+ CWnd* m_pView;
+ CWnd* m_pTab;
+ };
+
+ public:
+ CDockContainer();
+ virtual ~CDockContainer();
+ virtual void AddContainer(CDockContainer* pContainer);
+ virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE);
+ virtual CDockContainer* GetContainerFromIndex(UINT nPage);
+ virtual CDockContainer* GetContainerFromView(CWnd* pView) const;
+ virtual int GetContainerIndex(CDockContainer* pContainer);
+ virtual SIZE GetMaxTabTextSize();
+ virtual CViewPage& GetViewPage() const { return (CViewPage&)m_ViewPage; }
+ virtual void RecalcLayout();
+ virtual void RemoveContainer(CDockContainer* pWnd);
+ virtual void SelectPage(int nPage);
+ virtual void SetTabSize();
+ virtual void SetupToolBar();
+
+ // Attributes
+ CDockContainer* GetActiveContainer() const {return GetContainerFromView(GetActiveView());}
+ CWnd* GetActiveView() const;
+ std::vector& GetAllContainers() const {return m_pContainerParent->m_vContainerInfo;}
+ CDockContainer* GetContainerParent() const { return m_pContainerParent; }
+ CString& GetDockCaption() const { return (CString&)m_csCaption; }
+ HICON GetTabIcon() const { return m_hTabIcon; }
+ LPCTSTR GetTabText() const { return m_tsTabText.c_str(); }
+ virtual CToolBar& GetToolBar() const { return GetViewPage().GetToolBar(); }
+ CWnd* GetView() const { return GetViewPage().GetView(); }
+ void SetActiveContainer(CDockContainer* pContainer);
+ void SetDockCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }
+ void SetTabIcon(HICON hTabIcon) { m_hTabIcon = hTabIcon; }
+ void SetTabIcon(UINT nID_Icon);
+ void SetTabIcon(int i, HICON hIcon) { CTab::SetTabIcon(i, hIcon); }
+ void SetTabText(LPCTSTR szText) { m_tsTabText = szText; }
+ void SetTabText(UINT nTab, LPCTSTR szText);
+ void SetView(CWnd& Wnd);
+
+ protected:
+ virtual void OnCreate();
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ std::vector m_vContainerInfo;
+ tString m_tsTabText;
+ CString m_csCaption;
+ CViewPage m_ViewPage;
+ int m_iCurrentPage;
+ CDockContainer* m_pContainerParent;
+ HICON m_hTabIcon;
+ int m_nTabPressed;
+
+ };
+
+ typedef struct DRAGPOS
+ {
+ NMHDR hdr;
+ POINT ptPos;
+ UINT DockZone;
+ } *LPDRAGPOS;
+
+
+ /////////////////////////////////////////
+ // Declaration of the CDocker class
+ // A CDocker window allows other CDocker windows to be "docked" inside it.
+ // A CDocker can dock on the top, left, right or bottom side of a parent CDocker.
+ // There is no theoretical limit to the number of CDockers within CDockers.
+ class CDocker : public CWnd
+ {
+ public:
+ // A nested class for the splitter bar that seperates the docked panes.
+ class CDockBar : public CWnd
+ {
+ public:
+ CDockBar();
+ virtual ~CDockBar();
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS& wc);
+ virtual void SendNotify(UINT nMessageID);
+ virtual void SetColor(COLORREF color);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ CDocker* GetDock() {return m_pDock;}
+ int GetWidth() {return m_DockBarWidth;}
+ void SetDock(CDocker* pDock) {m_pDock = pDock;}
+ void SetWidth(int nWidth) {m_DockBarWidth = nWidth;}
+
+ private:
+ CDockBar(const CDockBar&); // Disable copy construction
+ CDockBar& operator = (const CDockBar&); // Disable assignment operator
+
+ CDocker* m_pDock;
+ DRAGPOS m_DragPos;
+ CBrush m_brBackground;
+ int m_DockBarWidth;
+ };
+
+ // A nested class for the window inside a CDocker which includes all of this docked client.
+ // It's the remaining part of the CDocker that doesn't belong to the CDocker's children.
+ // The Docker's view window is a child window of CDockClient.
+ class CDockClient : public CWnd
+ {
+ public:
+ CDockClient();
+ virtual ~CDockClient() {}
+ virtual void Draw3DBorder(RECT& Rect);
+ virtual void DrawCaption(WPARAM wParam);
+ virtual void DrawCloseButton(CDC& DrawDC, BOOL bFocus);
+ virtual CRect GetCloseRect();
+ virtual void SendNotify(UINT nMessageID);
+
+ CString& GetCaption() const { return (CString&)m_csCaption; }
+ CWnd* GetView() const { return m_pView; }
+ void SetDock(CDocker* pDock) { m_pDock = pDock;}
+ void SetCaption(LPCTSTR szCaption) { m_csCaption = szCaption; }
+ void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);
+ void SetClosePressed() { m_IsClosePressed = TRUE; }
+ void SetView(CWnd& Wnd) { m_pView = &Wnd; }
+
+ protected:
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual void OnNCCalcSize(WPARAM& wParam, LPARAM& lParam);
+ virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnNCMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCPaint(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual void PreRegisterClass(WNDCLASS& wc);
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CDockClient(const CDockClient&); // Disable copy construction
+ CDockClient& operator = (const CDockClient&); // Disable assignment operator
+
+ CString m_csCaption;
+ CPoint m_Oldpt;
+ CDocker* m_pDock;
+ CWnd* m_pView;
+ BOOL m_IsClosePressed;
+ BOOL m_bOldFocus;
+ BOOL m_bCaptionPressed;
+ BOOL m_IsTracking;
+ COLORREF m_Foregnd1;
+ COLORREF m_Backgnd1;
+ COLORREF m_Foregnd2;
+ COLORREF m_Backgnd2;
+ };
+
+ // This nested class is used to indicate where a window could dock by
+ // displaying a blue tinted window.
+ class CDockHint : public CWnd
+ {
+ public:
+ CDockHint();
+ virtual ~CDockHint();
+ virtual RECT CalcHintRectContainer(CDocker* pDockTarget);
+ virtual RECT CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);
+ virtual RECT CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide);
+ virtual void DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide);
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void ShowHintWindow(CDocker* pDockTarget, CRect rcHint);
+
+ private:
+ CDockHint(const CDockHint&); // Disable copy construction
+ CDockHint& operator = (const CDockHint&); // Disable assignment operator
+
+ CBitmap m_bmBlueTint;
+ UINT m_uDockSideOld;
+ };
+
+ class CTarget : public CWnd
+ {
+ public:
+ CTarget() {}
+ virtual ~CTarget();
+ virtual void OnDraw(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT &cs);
+
+ protected:
+ CBitmap m_bmImage;
+
+ private:
+ CTarget(const CTarget&); // Disable copy construction
+ CTarget& operator = (const CTarget&); // Disable assignment operator
+ };
+
+ class CTargetCentre : public CTarget
+ {
+ public:
+ CTargetCentre();
+ virtual ~CTargetCentre();
+ virtual void OnDraw(CDC* pDC);
+ virtual void OnCreate();
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ BOOL IsOverContainer() { return m_bIsOverContainer; }
+
+ private:
+ CTargetCentre(const CTargetCentre&); // Disable copy construction
+ CTargetCentre& operator = (const CTargetCentre&); // Disable assignment operator
+
+ BOOL m_bIsOverContainer;
+ CDocker* m_pOldDockTarget;
+ };
+
+ class CTargetLeft : public CTarget
+ {
+ public:
+ CTargetLeft() {m_bmImage.LoadImage(IDW_SDLEFT,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+
+ private:
+ CTargetLeft(const CTargetLeft&); // Disable copy construction
+ CTargetLeft& operator = (const CTargetLeft&); // Disable assignment operator
+ };
+
+ class CTargetTop : public CTarget
+ {
+ public:
+ CTargetTop() {m_bmImage.LoadImage(IDW_SDTOP,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ private:
+ CTargetTop(const CTargetTop&); // Disable copy construction
+ CTargetTop& operator = (const CTargetTop&); // Disable assignment operator
+ };
+
+ class CTargetRight : public CTarget
+ {
+ public:
+ CTargetRight() {m_bmImage.LoadImage(IDW_SDRIGHT,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+
+ private:
+ CTargetRight(const CTargetRight&); // Disable copy construction
+ CTargetRight& operator = (const CTargetRight&); // Disable assignment operator
+ };
+
+ class CTargetBottom : public CTarget
+ {
+ public:
+ CTargetBottom() {m_bmImage.LoadImage(IDW_SDBOTTOM,0,0,0);}
+ virtual BOOL CheckTarget(LPDRAGPOS pDragPos);
+ };
+
+ friend class CTargetCentre;
+ friend class CTargetLeft;
+ friend class CTargetTop;
+ friend class CTargetRight;
+ friend class CTargetBottom;
+ friend class CDockClient;
+ friend class CDockContainer;
+
+ public:
+ // Operations
+ CDocker();
+ virtual ~CDocker();
+ virtual CDocker* AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID = 0);
+ virtual CDocker* AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID = 0);
+ virtual void Close();
+ virtual void CloseAllDockers();
+ virtual void Dock(CDocker* pDocker, UINT uDockSide);
+ virtual void DockInContainer(CDocker* pDock, DWORD dwDockStyle);
+ virtual CDockContainer* GetContainer() const;
+ virtual CDocker* GetActiveDocker() const;
+ virtual CDocker* GetDockAncestor() const;
+ virtual CDocker* GetDockFromID(int n_DockID) const;
+ virtual CDocker* GetDockFromPoint(POINT pt) const;
+ virtual CDocker* GetDockFromView(CWnd* pView) const;
+ virtual CDocker* GetTopmostDocker() const;
+ virtual int GetDockSize() const;
+ virtual CTabbedMDI* GetTabbedMDI() const;
+ virtual int GetTextHeight();
+ virtual void Hide();
+ virtual BOOL LoadRegistrySettings(tString tsRegistryKeyName);
+ virtual void RecalcDockLayout();
+ virtual BOOL SaveRegistrySettings(tString tsRegistryKeyName);
+ virtual void Undock(CPoint pt, BOOL bShowUndocked = TRUE);
+ virtual void UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked);
+ virtual BOOL VerifyDockers();
+
+ // Attributes
+ virtual CDockBar& GetDockBar() const {return (CDockBar&)m_DockBar;}
+ virtual CDockClient& GetDockClient() const {return (CDockClient&)m_DockClient;}
+ virtual CDockHint& GetDockHint() const {return m_pDockAncestor->m_DockHint;}
+
+
+ std::vector & GetAllDockers() const {return GetDockAncestor()->m_vAllDockers;}
+ int GetBarWidth() const {return GetDockBar().GetWidth();}
+ CString& GetCaption() const {return GetDockClient().GetCaption();}
+ std::vector & GetDockChildren() const {return (std::vector &)m_vDockChildren;}
+ int GetDockID() const {return m_nDockID;}
+ CDocker* GetDockParent() const {return m_pDockParent;}
+ DWORD GetDockStyle() const {return m_DockStyle;}
+ CWnd* GetView() const {return GetDockClient().GetView();}
+ BOOL IsChildOfDocker(CWnd* pWnd) const;
+ BOOL IsDocked() const;
+ BOOL IsDragAutoResize();
+ BOOL IsRelated(CWnd* pWnd) const;
+ BOOL IsUndocked() const;
+ void SetBarColor(COLORREF color) {GetDockBar().SetColor(color);}
+ void SetBarWidth(int nWidth) {GetDockBar().SetWidth(nWidth);}
+ void SetCaption(LPCTSTR szCaption);
+ void SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2);
+ void SetCaptionHeight(int nHeight);
+ void SetDockStyle(DWORD dwDockStyle);
+ void SetDockSize(int DockSize);
+ void SetDragAutoResize(BOOL bAutoResize);
+ void SetView(CWnd& wndView);
+
+ protected:
+ virtual CDocker* NewDockerFromID(int idDock);
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnCaptionTimer(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual void OnDestroy(WPARAM wParam, LPARAM lParam);
+ virtual void OnDockDestroyed(WPARAM wParam, LPARAM lParam);
+ virtual void OnExitSizeMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnSetFocus(WPARAM wParam, LPARAM lParam);
+ virtual void OnSysColorChange(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnWindowPosChanging(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CDocker(const CDocker&); // Disable copy construction
+ CDocker& operator = (const CDocker&); // Disable assignment operator
+ void CheckAllTargets(LPDRAGPOS pDragPos);
+ void CloseAllTargets();
+ void DockOuter(CDocker* pDocker, DWORD dwDockStyle);
+ void DrawAllCaptions();
+ void DrawHashBar(HWND hBar, POINT Pos);
+ void ConvertToChild(HWND hWndParent);
+ void ConvertToPopup(RECT rc);
+ void MoveDockChildren(CDocker* pDockTarget);
+ void PromoteFirstChild();
+ void RecalcDockChildLayout(CRect rc);
+ void ResizeDockers(LPDRAGPOS pdp);
+ CDocker* SeparateFromDock();
+ void SendNotify(UINT nMessageID);
+ void SetUndockPosition(CPoint pt);
+ std::vector SortDockers();
+
+ CDockBar m_DockBar;
+ CDockHint m_DockHint;
+ CDockClient m_DockClient;
+ CTargetCentre m_TargetCentre;
+ CTargetLeft m_TargetLeft;
+ CTargetTop m_TargetTop;
+ CTargetRight m_TargetRight;
+ CPoint m_OldPoint;
+ CTargetBottom m_TargetBottom;
+ CDocker* m_pDockParent;
+ CDocker* m_pDockAncestor;
+ CDocker* m_pDockActive;
+
+ std::vector m_vDockChildren;
+ std::vector m_vAllDockers; // Only used in DockAncestor
+
+ CRect m_rcBar;
+ CRect m_rcChild;
+
+ BOOL m_BlockMove;
+ BOOL m_Undocking;
+ BOOL m_bIsClosing;
+ BOOL m_bIsDragging;
+ BOOL m_bDragAutoResize;
+ int m_DockStartSize;
+ int m_nDockID;
+ int m_nTimerCount;
+ int m_NCHeight;
+ DWORD m_dwDockZone;
+ double m_DockSizeRatio;
+ DWORD m_DockStyle;
+ HWND m_hOldFocus;
+
+ }; // class CDocker
+
+ struct DockInfo
+ {
+ DWORD DockStyle;
+ int DockSize;
+ int DockID;
+ int DockParentID;
+ RECT Rect;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////
+ // Definitions for the CDockBar class nested within CDocker
+ //
+ inline CDocker::CDockBar::CDockBar() : m_pDock(NULL), m_DockBarWidth(4)
+ {
+ m_brBackground.CreateSolidBrush(RGB(192,192,192));
+ }
+
+ inline CDocker::CDockBar::~CDockBar()
+ {
+ }
+
+ inline void CDocker::CDockBar::OnDraw(CDC* pDC)
+ {
+ CRect rcClient = GetClientRect();
+ pDC->SelectObject(&m_brBackground);
+ pDC->PatBlt(0, 0, rcClient.Width(), rcClient.Height(), PATCOPY);
+ }
+
+ inline void CDocker::CDockBar::PreCreate(CREATESTRUCT &cs)
+ {
+ // Create a child window, initially hidden
+ cs.style = WS_CHILD;
+ }
+
+ inline void CDocker::CDockBar::PreRegisterClass(WNDCLASS& wc)
+ {
+ wc.lpszClassName = _T("Win32++ Bar");
+ wc.hbrBackground = m_brBackground;
+ }
+
+ inline void CDocker::CDockBar::SendNotify(UINT nMessageID)
+ {
+ // Send a splitter bar notification to the parent
+ m_DragPos.hdr.code = nMessageID;
+ m_DragPos.hdr.hwndFrom = m_hWnd;
+ m_DragPos.ptPos = GetCursorPos();
+ m_DragPos.ptPos.x += 1;
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&m_DragPos);
+ }
+
+ inline void CDocker::CDockBar::SetColor(COLORREF color)
+ {
+ // Useful colors:
+ // GetSysColor(COLOR_BTNFACE) // Default Grey
+ // RGB(196, 215, 250) // Default Blue
+
+ m_brBackground.CreateSolidBrush(color);
+ }
+
+ inline LRESULT CDocker::CDockBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ {
+ switch (uMsg)
+ {
+ case WM_SETCURSOR:
+ {
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
+ {
+ HCURSOR hCursor;
+ DWORD dwSide = GetDock()->GetDockStyle() & 0xF;
+ if ((dwSide == DS_DOCKED_LEFT) || (dwSide == DS_DOCKED_RIGHT))
+ hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITH));
+ else
+ hCursor = LoadCursor(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_SPLITV));
+
+ if (hCursor) SetCursor(hCursor);
+ else TRACE(_T("**WARNING** Missing cursor resource for slider bar\n"));
+
+ return TRUE;
+ }
+ else
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ return 0;
+
+ case WM_LBUTTONDOWN:
+ {
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE))
+ {
+ SendNotify(UWM_BAR_START);
+ SetCapture();
+ }
+ }
+ break;
+
+ case WM_LBUTTONUP:
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
+ {
+ SendNotify(UWM_BAR_END);
+ ReleaseCapture();
+ }
+ break;
+
+ case WM_MOUSEMOVE:
+ if (!(m_pDock->GetDockStyle() & DS_NO_RESIZE) && (GetCapture() == this))
+ {
+ SendNotify(UWM_BAR_MOVE);
+ }
+ break;
+ }
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CDockClient class nested within CDocker
+ //
+ inline CDocker::CDockClient::CDockClient() : m_pView(0), m_IsClosePressed(FALSE),
+ m_bOldFocus(FALSE), m_bCaptionPressed(FALSE), m_IsTracking(FALSE)
+ {
+ m_Foregnd1 = RGB(32,32,32);
+ m_Backgnd1 = RGB(190,207,227);
+ m_Foregnd2 = GetSysColor(COLOR_BTNTEXT);
+ m_Backgnd2 = GetSysColor(COLOR_BTNFACE);
+ }
+
+ inline void CDocker::CDockClient::Draw3DBorder(RECT& Rect)
+ {
+ // Imitates the drawing of the WS_EX_CLIENTEDGE extended style
+ // This draws a 2 pixel border around the specified Rect
+ CWindowDC dc(this);
+ CRect rcw = Rect;
+ dc.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
+ dc.MoveTo(0, rcw.Height());
+ dc.LineTo(0, 0);
+ dc.LineTo(rcw.Width(), 0);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DDKSHADOW));
+ dc.MoveTo(1, rcw.Height()-2);
+ dc.LineTo(1, 1);
+ dc.LineTo(rcw.Width()-2, 1);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DHILIGHT));
+ dc.MoveTo(rcw.Width()-1, 0);
+ dc.LineTo(rcw.Width()-1, rcw.Height()-1);
+ dc.LineTo(0, rcw.Height()-1);
+ dc.CreatePen(PS_SOLID,1, GetSysColor(COLOR_3DLIGHT));
+ dc.MoveTo(rcw.Width()-2, 1);
+ dc.LineTo(rcw.Width()-2, rcw.Height()-2);
+ dc.LineTo(1, rcw.Height()-2);
+ }
+
+ inline CRect CDocker::CDockClient::GetCloseRect()
+ {
+ // Calculate the close rect position in screen co-ordinates
+ CRect rcClose;
+
+ int gap = 4;
+ CRect rc = GetWindowRect();
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ int cy = GetSystemMetrics(SM_CYSMICON);
+
+ rcClose.top = 2 + rc.top + m_pDock->m_NCHeight/2 - cy/2;
+ rcClose.bottom = 2 + rc.top + m_pDock->m_NCHeight/2 + cy/2;
+ rcClose.right = rc.right - gap;
+ rcClose.left = rcClose.right - cx;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ {
+ rcClose.left = rc.left + gap;
+ rcClose.right = rcClose.left + cx;
+ }
+#endif
+
+
+ return rcClose;
+ }
+
+ inline void CDocker::CDockClient::DrawCaption(WPARAM wParam)
+ {
+ if (IsWindow() && m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ BOOL bFocus = m_pDock->IsChildOfDocker(GetFocus());
+ m_bOldFocus = FALSE;
+
+ // Acquire the DC for our NonClient painting
+ CDC* pDC;
+ if ((wParam != 1) && (bFocus == m_bOldFocus))
+ pDC = GetDCEx((HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN|DCX_PARENTCLIP);
+ else
+ pDC = GetWindowDC();
+
+ // Create and set up our memory DC
+ CRect rc = GetWindowRect();
+ CMemDC dcMem(pDC);
+ int rcAdjust = (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)? 2 : 0;
+ int Width = MAX(rc.Width() -rcAdjust, 0);
+ int Height = m_pDock->m_NCHeight + rcAdjust;
+ dcMem.CreateCompatibleBitmap(pDC, Width, Height);
+ m_bOldFocus = bFocus;
+
+ // Set the font for the title
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ dcMem.CreateFontIndirect(&info.lfStatusFont);
+
+ // Set the Colours
+ if (bFocus)
+ {
+ dcMem.SetTextColor(m_Foregnd1);
+ dcMem.CreateSolidBrush(m_Backgnd1);
+ dcMem.SetBkColor(m_Backgnd1);
+ }
+ else
+ {
+ dcMem.SetTextColor(m_Foregnd2);
+ dcMem.CreateSolidBrush(m_Backgnd2);
+ dcMem.SetBkColor(m_Backgnd2);
+ }
+
+ // Draw the rectangle
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 150, 140));
+ dcMem.Rectangle(rcAdjust, rcAdjust, rc.Width() -rcAdjust, m_pDock->m_NCHeight +rcAdjust);
+
+ // Display the caption
+ int cx = (m_pDock->GetDockStyle() & DS_NO_CLOSE)? 0 : GetSystemMetrics(SM_CXSMICON);
+ CRect rcText(4 +rcAdjust, rcAdjust, rc.Width() -4 - cx -rcAdjust, m_pDock->m_NCHeight +rcAdjust);
+ dcMem.DrawText(m_csCaption, m_csCaption.GetLength(), rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
+
+ // Draw the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ DrawCloseButton(dcMem, bFocus);
+
+ // Draw the 3D border
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ Draw3DBorder(rc);
+
+ // Copy the Memory DC to the window's DC
+ pDC->BitBlt(rcAdjust, rcAdjust, Width, Height, &dcMem, rcAdjust, rcAdjust, SRCCOPY);
+
+ // Required for Win98/WinME
+ pDC->Destroy();
+ }
+ }
+
+ inline void CDocker::CDockClient::DrawCloseButton(CDC& DrawDC, BOOL bFocus)
+ {
+ // The close button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (m_pDock->IsDocked() && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ // Determine the close button's drawing position relative to the window
+ CRect rcClose = GetCloseRect();
+ UINT uState = GetCloseRect().PtInRect(GetCursorPos())? m_IsClosePressed && IsLeftButtonDown()? 2 : 1 : 0;
+ ScreenToClient(rcClose);
+
+ if (GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ {
+ rcClose.OffsetRect(2, m_pDock->m_NCHeight+2);
+ if (GetWindowRect().Height() < (m_pDock->m_NCHeight+4))
+ rcClose.OffsetRect(-2, -2);
+ }
+ else
+ rcClose.OffsetRect(0, m_pDock->m_NCHeight-2);
+
+ // Draw the outer highlight for the close button
+ if (!IsRectEmpty(&rcClose))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ // Normal button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Popped up button
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Pressed button
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+ break;
+ }
+
+ // Manually Draw Close Button
+ if (bFocus)
+ DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd1);
+ else
+ DrawDC.CreatePen(PS_SOLID, 1, m_Foregnd2);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);
+ }
+ }
+ }
+
+ inline void CDocker::CDockClient::OnNCCalcSize(WPARAM& wParam, LPARAM& lParam)
+ {
+ // Sets the non-client area (and hence sets the client area)
+ // This function modifies lParam
+
+ UNREFERENCED_PARAMETER(wParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ LPRECT rc = (LPRECT)lParam;
+ rc->top += m_pDock->m_NCHeight;
+ }
+ }
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCHitTest(WPARAM wParam, LPARAM lParam)
+ {
+ // Identify which part of the non-client area the cursor is over
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ // Indicate if the point is in the close button (except for Win95)
+ if ((GetWinVersion() > 1400) && (GetCloseRect().PtInRect(pt)))
+ return HTCLOSE;
+
+ ScreenToClient(pt);
+
+ // Indicate if the point is in the caption
+ if (pt.y < 0)
+ return HTCAPTION;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if ((HTCLOSE == wParam) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ m_IsClosePressed = TRUE;
+ SetCapture();
+ }
+
+ m_bCaptionPressed = TRUE;
+ m_Oldpt.x = GET_X_LPARAM(lParam);
+ m_Oldpt.y = GET_Y_LPARAM(lParam);
+ if (m_pDock->IsDocked())
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ ScreenToClient(pt);
+ m_pView->SetFocus();
+
+ // Update the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+
+ return 0L;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCLBUTTONDOWN, wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)))
+ {
+ m_bCaptionPressed = FALSE;
+ if (m_IsClosePressed && GetCloseRect().PtInRect(GetCursorPos()))
+ {
+ // Destroy the docker
+ if (dynamic_cast(m_pDock->GetView()))
+ {
+ CDockContainer* pContainer = ((CDockContainer*)m_pDock->GetView())->GetActiveContainer();
+ CDocker* pDock = m_pDock->GetDockFromView(pContainer);
+ pDock->GetDockClient().SetClosePressed();
+ m_pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);
+ pDock->Destroy();
+ }
+ else
+ {
+ m_pDock->Hide();
+ m_pDock->Destroy();
+ }
+ }
+ }
+ }
+
+ inline void CDocker::CDockClient::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_IsClosePressed = FALSE;
+ ReleaseCapture();
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+
+ inline void CDocker::CDockClient::OnMouseActivate(WPARAM wParam, LPARAM lParam)
+ // Focus changed, so redraw the captions
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ m_pDock->GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ }
+ }
+
+ inline void CDocker::CDockClient::OnMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ OnNCMouseMove(wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnNCMouseLeave(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_IsTracking = FALSE;
+ CWindowDC dc(this);
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & (DS_NO_CAPTION|DS_NO_CLOSE)) && m_pDock->IsDocked())
+ DrawCloseButton(dc, m_bOldFocus);
+
+ m_IsTracking = FALSE;
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ if (!m_IsTracking)
+ {
+ TRACKMOUSEEVENT TrackMouseEventStruct = {0};
+ TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);
+ TrackMouseEventStruct.dwFlags = TME_LEAVE|TME_NONCLIENT;
+ TrackMouseEventStruct.hwndTrack = m_hWnd;
+ _TrackMouseEvent(&TrackMouseEventStruct);
+ m_IsTracking = TRUE;
+ }
+
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ // Discard phantom mouse move messages
+ if ( (m_Oldpt.x == GET_X_LPARAM(lParam) ) && (m_Oldpt.y == GET_Y_LPARAM(lParam)))
+ return 0L;
+
+ if (IsLeftButtonDown() && (wParam == HTCAPTION) && (m_bCaptionPressed))
+ {
+ CDocker* pDock = (CDocker*)GetParent();
+ if (pDock)
+ pDock->Undock(GetCursorPos());
+ }
+
+ // Update the close button
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ }
+ }
+
+ m_bCaptionPressed = FALSE;
+ }
+ return CWnd::WndProcDefault(WM_MOUSEMOVE, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::CDockClient::OnNCPaint(WPARAM wParam, LPARAM lParam)
+ {
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CAPTION))
+ {
+ if (m_pDock->IsDocked())
+ {
+ DefWindowProc(WM_NCPAINT, wParam, lParam);
+ DrawCaption(wParam);
+ return 0;
+ }
+ }
+ return CWnd::WndProcDefault(WM_NCPAINT, wParam, lParam);
+ }
+
+ inline void CDocker::CDockClient::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Reposition the View window to cover the DockClient's client area
+ CRect rc = GetClientRect();
+ m_pView->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+
+ inline void CDocker::CDockClient::PreRegisterClass(WNDCLASS& wc)
+ {
+ wc.lpszClassName = _T("Win32++ DockClient");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDocker::CDockClient::PreCreate(CREATESTRUCT& cs)
+ {
+ DWORD dwStyle = m_pDock->GetDockStyle();
+ if (dwStyle & DS_CLIENTEDGE)
+ cs.dwExStyle = WS_EX_CLIENTEDGE;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (m_pDock->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ cs.dwExStyle |= WS_EX_LAYOUTRTL;
+#endif
+
+ }
+
+ inline void CDocker::CDockClient::SendNotify(UINT nMessageID)
+ {
+ // Fill the DragPos structure with data
+ DRAGPOS DragPos;
+ DragPos.hdr.code = nMessageID;
+ DragPos.hdr.hwndFrom = m_hWnd;
+ DragPos.ptPos = GetCursorPos();
+
+ // Send a DragPos notification to the docker
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
+ }
+
+ inline void CDocker::CDockClient::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF Foregnd2, COLORREF Backgnd2)
+ {
+ // Set the colors used when drawing the caption
+ // m_Foregnd1 Foreground colour (focused). m_Backgnd1 Background colour (focused)
+ // m_Foregnd2 Foreground colour (not focused). m_Backgnd2 Foreground colour (not focused)
+ m_Foregnd1 = Foregnd1;
+ m_Backgnd1 = Backgnd1;
+ m_Foregnd2 = Foregnd2;
+ m_Backgnd2 = Backgnd2;
+ }
+
+ inline LRESULT CDocker::CDockClient::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_LBUTTONUP:
+ {
+ ReleaseCapture();
+ if ((0 != m_pDock) && !(m_pDock->GetDockStyle() & DS_NO_CLOSE))
+ {
+ CWindowDC dc(this);
+ DrawCloseButton(dc, m_bOldFocus);
+ OnLButtonUp(wParam, lParam);
+ }
+ }
+ break;
+
+ case WM_MOUSEACTIVATE:
+ OnMouseActivate(wParam, lParam);
+ break;
+
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+
+ case WM_NCCALCSIZE:
+ OnNCCalcSize(wParam, lParam);
+ break;
+
+ case WM_NCHITTEST:
+ return OnNCHitTest(wParam, lParam);
+
+ case WM_NCLBUTTONDOWN:
+ return OnNCLButtonDown(wParam, lParam);
+
+ case WM_NCMOUSEMOVE:
+ return OnNCMouseMove(wParam, lParam);
+
+ case WM_NCPAINT:
+ return OnNCPaint(wParam, lParam);
+
+ case WM_NCMOUSELEAVE:
+ OnNCMouseLeave(wParam, lParam);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ //////////////////////////////////////////////////////////////
+ // Definitions for the CDockHint class nested within CDocker
+ //
+ inline CDocker::CDockHint::CDockHint() : m_uDockSideOld(0)
+ {
+ }
+
+ inline CDocker::CDockHint::~CDockHint()
+ {
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectContainer(CDocker* pDockTarget)
+ {
+ // Calculate the hint window's position for container docking
+ CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+ pDockTarget->ScreenToClient(rcHint);
+
+ return rcHint;
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectInner(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Calculate the hint window's position for inner docking
+ CRect rcHint = pDockTarget->GetDockClient().GetWindowRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+ pDockTarget->ScreenToClient(rcHint);
+
+ int Width;
+ CRect rcDockDrag = pDockDrag->GetWindowRect();
+ CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
+ if ((uDockSide == DS_DOCKED_LEFT) || (uDockSide == DS_DOCKED_RIGHT))
+ {
+ Width = rcDockDrag.Width();
+ if (Width >= (rcDockTarget.Width() - pDockDrag->GetBarWidth()))
+ Width = MAX(rcDockTarget.Width()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());
+ }
+ else
+ {
+ Width = rcDockDrag.Height();
+ if (Width >= (rcDockTarget.Height() - pDockDrag->GetBarWidth()))
+ Width = MAX(rcDockTarget.Height()/2 - pDockDrag->GetBarWidth(), pDockDrag->GetBarWidth());
+ }
+ switch (uDockSide)
+ {
+ case DS_DOCKED_LEFT:
+ rcHint.right = rcHint.left + Width;
+ break;
+ case DS_DOCKED_RIGHT:
+ rcHint.left = rcHint.right - Width;
+ break;
+ case DS_DOCKED_TOP:
+ rcHint.bottom = rcHint.top + Width;
+ break;
+ case DS_DOCKED_BOTTOM:
+ rcHint.top = rcHint.bottom - Width;
+ break;
+ }
+
+ return rcHint;
+ }
+
+ inline RECT CDocker::CDockHint::CalcHintRectOuter(CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Calculate the hint window's position for outer docking
+ CDocker* pDockTarget = pDockDrag->GetDockAncestor();
+ CRect rcHint = pDockTarget->GetClientRect();
+ if (pDockTarget->GetDockClient().GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+ rcHint.InflateRect(-2, -2);
+
+ int Width;
+ CRect rcDockDrag = pDockDrag->GetWindowRect();
+ CRect rcDockTarget = pDockTarget->GetDockClient().GetWindowRect();
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if ((uDockSide == DS_DOCKED_LEFTMOST) || (uDockSide == DS_DOCKED_RIGHTMOST))
+ {
+ Width = rcDockDrag.Width();
+ int BarWidth = pDockDrag->GetBarWidth();
+ if (Width >= pDockTarget->GetDockClient().GetClientRect().Width() - pDockDrag->GetBarWidth())
+ Width = MAX(pDockTarget->GetDockClient().GetClientRect().Width()/2 - BarWidth, BarWidth);
+ }
+ else
+ {
+ Width = rcDockDrag.Height();
+ int BarWidth = pDockDrag->GetBarWidth();
+ if (Width >= pDockTarget->GetDockClient().GetClientRect().Height() - pDockDrag->GetBarWidth())
+ Width = MAX(pDockTarget->GetDockClient().GetClientRect().Height()/2 - BarWidth, BarWidth);
+ }
+ switch (uDockSide)
+ {
+ case DS_DOCKED_LEFTMOST:
+ rcHint.right = rcHint.left + Width;
+ break;
+ case DS_DOCKED_RIGHTMOST:
+ rcHint.left = rcHint.right - Width;
+ break;
+ case DS_DOCKED_TOPMOST:
+ rcHint.bottom = rcHint.top + Width;
+ break;
+ case DS_DOCKED_BOTTOMMOST:
+ rcHint.top = rcHint.bottom - Width;
+ break;
+ }
+
+ return rcHint;
+ }
+
+ inline void CDocker::CDockHint::DisplayHint(CDocker* pDockTarget, CDocker* pDockDrag, UINT uDockSide)
+ {
+ // Ensure a new hint window is created if dock side changes
+ if (uDockSide != m_uDockSideOld)
+ {
+ Destroy();
+ pDockTarget->RedrawWindow( NULL, NULL, RDW_NOERASE | RDW_UPDATENOW );
+ pDockDrag->RedrawWindow();
+ }
+ m_uDockSideOld = uDockSide;
+
+ if (!IsWindow())
+ {
+ CRect rcHint;
+
+ if (uDockSide & 0xF)
+ rcHint = CalcHintRectInner(pDockTarget, pDockDrag, uDockSide);
+ else if (uDockSide & 0xF0000)
+ rcHint = CalcHintRectOuter(pDockDrag, uDockSide);
+ else if (uDockSide & DS_DOCKED_CONTAINER)
+ rcHint = CalcHintRectContainer(pDockTarget);
+ else
+ return;
+
+ ShowHintWindow(pDockTarget, rcHint);
+ }
+ }
+
+ inline void CDocker::CDockHint::OnDraw(CDC* pDC)
+ {
+ // Display the blue tinted bitmap
+ CRect rc = GetClientRect();
+ CMemDC MemDC(pDC);
+ MemDC.SelectObject(&m_bmBlueTint);
+ pDC->BitBlt(0, 0, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);
+ }
+
+ inline void CDocker::CDockHint::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_POPUP;
+
+ // WS_EX_TOOLWINDOW prevents the window being displayed on the taskbar
+ cs.dwExStyle = WS_EX_TOOLWINDOW;
+
+ cs.lpszClass = _T("Win32++ DockHint");
+ }
+
+ inline void CDocker::CDockHint::ShowHintWindow(CDocker* pDockTarget, CRect rcHint)
+ {
+ // Save the Dock window's blue tinted bitmap
+ CClientDC dcDesktop(NULL);
+ CMemDC dcMem(&dcDesktop);
+ CRect rcBitmap = rcHint;
+ CRect rcTarget = rcHint;
+ pDockTarget->ClientToScreen(rcTarget);
+
+ m_bmBlueTint.CreateCompatibleBitmap(&dcDesktop, rcBitmap.Width(), rcBitmap.Height());
+ CBitmap* pOldBitmap = dcMem.SelectObject(&m_bmBlueTint);
+ dcMem.BitBlt(0, 0, rcBitmap.Width(), rcBitmap.Height(), &dcDesktop, rcTarget.left, rcTarget.top, SRCCOPY);
+ dcMem.SelectObject(pOldBitmap);
+ TintBitmap(&m_bmBlueTint, -64, -24, +128);
+
+ // Create the Hint window
+ if (!IsWindow())
+ {
+ Create(pDockTarget);
+ }
+
+ pDockTarget->ClientToScreen(rcHint);
+ SetWindowPos(NULL, rcHint, SWP_SHOWWINDOW|SWP_NOZORDER|SWP_NOACTIVATE);
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetCentre class nested within CDocker
+ //
+ inline CDocker::CTargetCentre::CTargetCentre() : m_bIsOverContainer(FALSE), m_pOldDockTarget(0)
+ {
+ }
+
+ inline CDocker::CTargetCentre::~CTargetCentre()
+ {
+ }
+
+ inline void CDocker::CTargetCentre::OnDraw(CDC* pDC)
+ {
+ CBitmap bmCentre(IDW_SDCENTER);
+ CBitmap bmLeft(IDW_SDLEFT);
+ CBitmap bmRight(IDW_SDRIGHT);
+ CBitmap bmTop(IDW_SDTOP);
+ CBitmap bmBottom(IDW_SDBOTTOM);
+
+ if (bmCentre.GetHandle()) pDC->DrawBitmap(0, 0, 88, 88, bmCentre, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Centre\n"));
+
+ if (bmLeft.GetHandle()) pDC->DrawBitmap(0, 29, 31, 29, bmLeft, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Left\n"));
+
+ if (bmTop.GetHandle()) pDC->DrawBitmap(29, 0, 29, 31, bmTop, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Top\n"));
+
+ if (bmRight.GetHandle()) pDC->DrawBitmap(55, 29, 31, 29, bmRight, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Right\n"));
+
+ if (bmBottom.GetHandle()) pDC->DrawBitmap(29, 55, 29, 31, bmBottom, RGB(255,0,255));
+ else TRACE(_T("Missing docking resource: Target Bottom\n"));
+
+ if (IsOverContainer())
+ {
+ CBitmap bmMiddle(IDW_SDMIDDLE);
+ pDC->DrawBitmap(31, 31, 25, 26, bmMiddle, RGB(255,0,255));
+ }
+ }
+
+ inline void CDocker::CTargetCentre::OnCreate()
+ {
+ // Use a region to create an irregularly shapped window
+ POINT ptArray[16] = { {0,29}, {22, 29}, {29, 22}, {29, 0},
+ {58, 0}, {58, 22}, {64, 29}, {87, 29},
+ {87, 58}, {64, 58}, {58, 64}, {58, 87},
+ {29, 87}, {29, 64}, {23, 58}, {0, 58} };
+
+ CRgn rgnPoly;
+ rgnPoly.CreatePolygonRgn(ptArray, 16, WINDING);
+ SetWindowRgn(&rgnPoly, FALSE);
+ }
+
+ inline BOOL CDocker::CTargetCentre::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pDragPos->ptPos);
+ if (NULL == pDockTarget) return FALSE;
+
+ if (!IsWindow()) Create();
+ m_bIsOverContainer = (dynamic_cast(pDockTarget->GetView()) != NULL);
+
+ // Redraw the target if the dock target changes
+ if (m_pOldDockTarget != pDockTarget) Invalidate();
+ m_pOldDockTarget = pDockTarget;
+
+ int cxImage = 88;
+ int cyImage = 88;
+
+ CRect rcTarget = pDockTarget->GetDockClient().GetWindowRect();
+ int xMid = rcTarget.left + (rcTarget.Width() - cxImage)/2;
+ int yMid = rcTarget.top + (rcTarget.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+
+ // Create the docking zone rectangles
+ CPoint pt = pDragPos->ptPos;
+ ScreenToClient(pt);
+ CRect rcLeft(0, 29, 31, 58);
+ CRect rcTop(29, 0, 58, 31);
+ CRect rcRight(55, 29, 87, 58);
+ CRect rcBottom(29, 55, 58, 87);
+ CRect rcMiddle(31, 31, 56, 57);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFT);
+ pDockDrag->m_dwDockZone = DS_DOCKED_LEFT;
+ return TRUE;
+ }
+ else if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOP);
+ pDockDrag->m_dwDockZone = DS_DOCKED_TOP;
+ return TRUE;
+ }
+ else if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHT);
+ pDockDrag->m_dwDockZone = DS_DOCKED_RIGHT;
+ return TRUE;
+ }
+ else if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOM);
+ pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOM;
+ return TRUE;
+ }
+ else if ((rcMiddle.PtInRect(pt)) && (IsOverContainer()))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_CONTAINER);
+ pDockDrag->m_dwDockZone = DS_DOCKED_CONTAINER;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTarget class nested within CDocker
+ // CTarget is the base class for a number of CTargetXXX classes
+ inline CDocker::CTarget::~CTarget()
+ {
+ }
+
+ inline void CDocker::CTarget::OnDraw(CDC* pDC)
+ {
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (m_bmImage)
+ pDC->DrawBitmap(0, 0, cxImage, cyImage, m_bmImage, RGB(255,0,255));
+ else
+ TRACE(_T("Missing docking resource\n"));
+ }
+
+ inline void CDocker::CTarget::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_POPUP;
+ cs.dwExStyle = WS_EX_TOPMOST|WS_EX_TOOLWINDOW;
+ cs.lpszClass = _T("Win32++ DockTargeting");
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetLeft class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetLeft::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int yMid = rc.top + (rc.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, rc.left + 10, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcLeft(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcLeft.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_LEFT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_LEFTMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_LEFTMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetTop class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetTop::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int xMid = rc.left + (rc.Width() - cxImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, rc.top + 10, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcTop(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcTop.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_TOP))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_TOPMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_TOPMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetRight class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetRight::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int yMid = rc.top + (rc.Height() - cyImage)/2;
+ SetWindowPos(HWND_TOPMOST, rc.right - 10 - cxImage, yMid, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+
+ CRect rcRight(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcRight.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_RIGHT))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_RIGHTMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_RIGHTMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // Definitions for the CTargetBottom class nested within CDocker
+ //
+ inline BOOL CDocker::CTargetBottom::CheckTarget(LPDRAGPOS pDragPos)
+ {
+ CDocker* pDockDrag = (CDocker*)FromHandle(pDragPos->hdr.hwndFrom);
+ if (NULL == pDockDrag) return FALSE;
+
+ CPoint pt = pDragPos->ptPos;
+ CDocker* pDockTarget = pDockDrag->GetDockFromPoint(pt)->GetTopmostDocker();
+ if (pDockTarget != pDockDrag->GetDockAncestor())
+ {
+ Destroy();
+ return FALSE;
+ }
+
+ BITMAP bm = m_bmImage.GetBitmapData();
+ int cxImage = bm.bmWidth;
+ int cyImage = bm.bmHeight;
+
+ if (!IsWindow())
+ {
+ Create();
+ CRect rc = pDockTarget->GetWindowRect();
+ int xMid = rc.left + (rc.Width() - cxImage)/2;
+ SetWindowPos(HWND_TOPMOST, xMid, rc.bottom - 10 - cyImage, cxImage, cyImage, SWP_NOACTIVATE|SWP_SHOWWINDOW);
+ }
+ CRect rcBottom(0, 0, cxImage, cyImage);
+ ScreenToClient(pt);
+
+ // Test if our cursor is in one of the docking zones
+ if ((rcBottom.PtInRect(pt)) && !(pDockTarget->GetDockStyle() & DS_NO_DOCKCHILD_BOTTOM))
+ {
+ pDockDrag->m_BlockMove = TRUE;
+ pDockTarget->GetDockHint().DisplayHint(pDockTarget, pDockDrag, DS_DOCKED_BOTTOMMOST);
+ pDockDrag->m_dwDockZone = DS_DOCKED_BOTTOMMOST;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+
+ /////////////////////////////////////////
+ // Definitions for the CDocker class
+ //
+ inline CDocker::CDocker() : m_pDockParent(NULL), m_pDockActive(NULL), m_BlockMove(FALSE), m_Undocking(FALSE),
+ m_bIsClosing(FALSE), m_bIsDragging(FALSE), m_bDragAutoResize(TRUE), m_DockStartSize(0), m_nDockID(0),
+ m_nTimerCount(0), m_NCHeight(0), m_dwDockZone(0), m_DockSizeRatio(1.0), m_DockStyle(0), m_hOldFocus(0)
+ {
+ // Assume this docker is the DockAncestor for now.
+ m_pDockAncestor = this;
+ }
+
+ inline CDocker::~CDocker()
+ {
+ GetDockBar().Destroy();
+
+ std::vector ::iterator iter;
+ if (GetDockAncestor() == this)
+ {
+ // Destroy all dock descendants of this dock ancestor
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ (*iter)->Destroy();
+ }
+ }
+ }
+
+ inline CDocker* CDocker::AddDockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, int nDockID /* = 0*/)
+ // This function creates the docker, and adds it to the docker heirachy as docked
+ {
+ // Create the docker window as a child of the frame window.
+ // This pernamently sets the frame window as the docker window's owner,
+ // even when its parent is subsequently changed.
+
+ assert(pDocker);
+
+ // Store the Docker's pointer in the DockAncestor's vector for later deletion
+ GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
+
+ pDocker->SetDockStyle(dwDockStyle);
+ pDocker->m_nDockID = nDockID;
+ pDocker->m_pDockAncestor = GetDockAncestor();
+ pDocker->m_pDockParent = this;
+ pDocker->SetDockSize(DockSize);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pDocker->Create(pFrame);
+ pDocker->SetParent(this);
+
+ // Dock the docker window
+ if (dwDockStyle & DS_DOCKED_CONTAINER)
+ DockInContainer(pDocker, dwDockStyle);
+ else
+ Dock(pDocker, dwDockStyle);
+
+ // Issue TRACE warnings for any missing resources
+ HMODULE hMod= GetApp()->GetResourceHandle();
+
+ if (!(dwDockStyle & DS_NO_RESIZE))
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITH), RT_GROUP_CURSOR))
+ TRACE(_T("**WARNING** Horizontal cursor resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITV), RT_GROUP_CURSOR))
+ TRACE(_T("**WARNING** Vertical cursor resource missing\n"));
+ }
+
+ if (!(dwDockStyle & DS_NO_UNDOCK))
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDCENTER), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking center bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDLEFT), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking left bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDRIGHT), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking right bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDTOP), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking top bitmap resource missing\n"));
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDBOTTOM), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking center bottom resource missing\n"));
+ }
+
+ if (dwDockStyle & DS_DOCKED_CONTAINER)
+ {
+ if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP))
+ TRACE(_T("**WARNING** Docking container bitmap resource missing\n"));
+ }
+
+ return pDocker;
+ }
+
+ inline CDocker* CDocker::AddUndockedChild(CDocker* pDocker, DWORD dwDockStyle, int DockSize, RECT rc, int nDockID /* = 0*/)
+ // This function creates the docker, and adds it to the docker heirachy as undocked
+ {
+ assert(pDocker);
+
+ // Store the Docker's pointer in the DockAncestor's vector for later deletion
+ GetDockAncestor()->m_vAllDockers.push_back(DockPtr(pDocker));
+
+ pDocker->SetDockSize(DockSize);
+ pDocker->SetDockStyle(dwDockStyle & 0XFFFFFF0);
+ pDocker->m_nDockID = nDockID;
+ pDocker->m_pDockAncestor = GetDockAncestor();
+
+ // Initially create the as a child window of the frame
+ // This makes the frame window the owner of our docker
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pDocker->Create(pFrame);
+ pDocker->SetParent(this);
+
+ // Change the Docker to a POPUP window
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;
+ pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDocker->SetRedraw(FALSE);
+ pDocker->SetParent(0);
+ pDocker->SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
+ pDocker->SetRedraw(TRUE);
+ pDocker->RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_ALLCHILDREN);
+ pDocker->SetWindowText(pDocker->GetCaption().c_str());
+
+ return pDocker;
+ }
+
+ inline void CDocker::CheckAllTargets(LPDRAGPOS pDragPos)
+ // Calls CheckTarget for each possible target zone
+ {
+ if (!GetDockAncestor()->m_TargetCentre.CheckTarget(pDragPos))
+ {
+ if (!GetDockAncestor()->m_TargetLeft.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetTop.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetRight.CheckTarget(pDragPos))
+ {
+ if(!GetDockAncestor()->m_TargetBottom.CheckTarget(pDragPos))
+ {
+ // Not in a docking zone, so clean up
+ NMHDR nmhdr = pDragPos->hdr;
+ CDocker* pDockDrag = (CDocker*)FromHandle(nmhdr.hwndFrom);
+ if (pDockDrag)
+ {
+ if (pDockDrag->m_BlockMove)
+ pDockDrag->RedrawWindow(0, 0, RDW_FRAME|RDW_INVALIDATE);
+
+ GetDockHint().Destroy();
+ pDockDrag->m_dwDockZone = 0;
+ pDockDrag->m_BlockMove = FALSE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ inline BOOL CDocker::VerifyDockers()
+ // A diagnostic routine which verifies the integrity of the docking layout
+ {
+ BOOL bResult = TRUE;
+
+ // Check dock ancestor
+ std::vector::iterator iter;
+
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ if (GetDockAncestor() != (*iter)->m_pDockAncestor)
+ {
+ TRACE(_T("Invalid Dock Ancestor\n"));
+ bResult = FALSE;
+ }
+ }
+
+ // Check presence of dock parent
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ if ((*iter)->IsUndocked() && (*iter)->m_pDockParent != 0)
+ {
+ TRACE(_T("Error: Undocked dockers should not have a dock parent\n"));
+ bResult = FALSE;
+ }
+
+ if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0)
+ {
+ TRACE(_T("Error: Docked dockers should have a dock parent\n"));
+ bResult = FALSE;
+ }
+ }
+
+ // Check dock parent/child relationship
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ std::vector::iterator iterChild;
+ for (iterChild = (*iter)->GetDockChildren().begin(); iterChild != (*iter)->GetDockChildren().end(); ++iterChild)
+ {
+ if ((*iterChild)->m_pDockParent != (*iter).get())
+ {
+ TRACE(_T("Error: Docking parent/Child information mismatch\n"));
+ bResult = FALSE;
+ }
+ if ((*iterChild)->GetParent() != (*iter).get())
+ {
+ TRACE(_T("Error: Incorrect windows child parent relationship\n"));
+ bResult = FALSE;
+ }
+ }
+ }
+
+ // Check dock parent chain
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); ++iter)
+ {
+ CDocker* pDockTopLevel = (*iter)->GetTopmostDocker();
+ if (pDockTopLevel->IsDocked())
+ TRACE(_T("Error: Top level parent should be undocked\n"));
+ }
+
+ return bResult;
+ }
+
+ inline void CDocker::Close()
+ {
+ // Destroy the docker
+ Hide();
+ Destroy();
+ }
+
+ inline void CDocker::CloseAllDockers()
+ {
+ assert(this == GetDockAncestor()); // Must call CloseAllDockers from the DockAncestor
+
+ std::vector ::iterator v;
+
+ SetRedraw(FALSE);
+ std::vector AllDockers = GetAllDockers();
+ for (v = AllDockers.begin(); v != AllDockers.end(); ++v)
+ {
+ // The CDocker is destroyed when the window is destroyed
+ (*v)->m_bIsClosing = TRUE;
+ (*v)->Destroy(); // Destroy the window
+ }
+
+ GetDockChildren().clear();
+ SetRedraw(TRUE);
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::CloseAllTargets()
+ {
+ GetDockAncestor()->m_TargetCentre.Destroy();
+ GetDockAncestor()->m_TargetLeft.Destroy();
+ GetDockAncestor()->m_TargetTop.Destroy();
+ GetDockAncestor()->m_TargetRight.Destroy();
+ GetDockAncestor()->m_TargetBottom.Destroy();
+ }
+
+ inline void CDocker::Dock(CDocker* pDocker, UINT DockStyle)
+ // Docks the specified docker inside this docker
+ {
+ assert(pDocker);
+
+ pDocker->m_pDockParent = this;
+ pDocker->m_BlockMove = FALSE;
+ pDocker->SetDockStyle(DockStyle);
+ m_vDockChildren.push_back(pDocker);
+ pDocker->ConvertToChild(m_hWnd);
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if (((DockStyle & 0xF) == DS_DOCKED_LEFT) || ((DockStyle &0xF) == DS_DOCKED_RIGHT))
+ {
+ int Width = GetDockClient().GetWindowRect().Width();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Width - BarWidth))
+ pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Width();
+ }
+ else
+ {
+ int Height = GetDockClient().GetWindowRect().Height();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Height - BarWidth))
+ pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetWindowRect().Height();
+ }
+
+ // Redraw the docked windows
+ GetAncestor()->SetForegroundWindow();
+ GetTopmostDocker()->m_hOldFocus = pDocker->GetView()->GetHwnd();
+ pDocker->GetView()->SetFocus();
+
+ GetTopmostDocker()->SetRedraw(FALSE);
+ RecalcDockLayout();
+ GetTopmostDocker()->SetRedraw(TRUE);
+ GetTopmostDocker()->RedrawWindow();
+ }
+
+ inline void CDocker::DockInContainer(CDocker* pDock, DWORD dwDockStyle)
+ // Add a container to an existing container
+ {
+ if ((dwDockStyle & DS_DOCKED_CONTAINER) && (dynamic_cast(pDock->GetView())))
+ {
+ // Transfer any dock children to this docker
+ pDock->MoveDockChildren(this);
+
+ // Transfer container children to the target container
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ CDockContainer* pContainerSource = (CDockContainer*)pDock->GetView();
+
+ if (pContainerSource->GetAllContainers().size() > 1)
+ {
+ // The container we're about to add has children, so transfer those first
+ std::vector::reverse_iterator riter;
+ std::vector AllContainers = pContainerSource->GetAllContainers();
+ for ( riter = AllContainers.rbegin() ; riter < AllContainers.rend() -1; ++riter )
+ {
+ // Remove child container from pContainerSource
+ CDockContainer* pContainerChild = (*riter).pContainer;
+ pContainerChild->ShowWindow(SW_HIDE);
+ pContainerSource->RemoveContainer(pContainerChild);
+
+ // Add child container to this container
+ pContainer->AddContainer(pContainerChild);
+
+ CDocker* pDockChild = GetDockFromView(pContainerChild);
+ pDockChild->SetParent(this);
+ pDockChild->m_pDockParent = this;
+ }
+ }
+
+ pContainer->AddContainer((CDockContainer*)pDock->GetView());
+ pDock->m_pDockParent = this;
+ pDock->m_BlockMove = FALSE;
+ pDock->ShowWindow(SW_HIDE);
+ pDock->SetWindowLongPtr(GWL_STYLE, WS_CHILD);
+ pDock->SetDockStyle(dwDockStyle);
+ pDock->SetParent(this);
+ }
+ }
+
+ inline void CDocker::DockOuter(CDocker* pDocker, DWORD dwDockStyle)
+ // Docks the specified docker inside the dock ancestor
+ {
+ assert(pDocker);
+
+ pDocker->m_pDockParent = GetDockAncestor();
+
+ DWORD OuterDocking = dwDockStyle & 0xF0000;
+ DWORD DockSide = OuterDocking / 0x10000;
+ dwDockStyle &= 0xFFF0FFFF;
+ dwDockStyle |= DockSide;
+
+ // Set the dock styles
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+ pDocker->m_BlockMove = FALSE;
+ pDocker->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDocker->ShowWindow(SW_HIDE);
+ pDocker->SetDockStyle(dwDockStyle);
+
+ // Set the docking relationships
+ std::vector::iterator iter = GetDockAncestor()->m_vDockChildren.begin();
+ GetDockAncestor()->m_vDockChildren.insert(iter, pDocker);
+ pDocker->SetParent(GetDockAncestor());
+ pDocker->GetDockBar().SetParent(GetDockAncestor());
+
+ // Limit the docked size to half the parent's size if it won't fit inside parent
+ if (((dwDockStyle & 0xF) == DS_DOCKED_LEFT) || ((dwDockStyle &0xF) == DS_DOCKED_RIGHT))
+ {
+ int Width = GetDockAncestor()->GetDockClient().GetWindowRect().Width();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Width - BarWidth))
+ pDocker->SetDockSize(MAX(Width/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Width();
+ }
+ else
+ {
+ int Height = GetDockAncestor()->GetDockClient().GetWindowRect().Height();
+ int BarWidth = pDocker->GetBarWidth();
+ if (pDocker->m_DockStartSize >= (Height - BarWidth))
+ pDocker->SetDockSize(MAX(Height/2 - BarWidth, BarWidth));
+
+ pDocker->m_DockSizeRatio = ((double)pDocker->m_DockStartSize) / (double)GetDockAncestor()->GetWindowRect().Height();
+ }
+
+ // Redraw the docked windows
+ GetAncestor()->SetFocus();
+ pDocker->GetView()->SetFocus();
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::DrawAllCaptions()
+ {
+ std::vector::iterator iter;
+ for (iter = GetAllDockers().begin(); iter != GetAllDockers().end(); iter++)
+ {
+ if ((*iter)->IsDocked())
+ (*iter)->GetDockClient().DrawCaption((WPARAM)1);
+ }
+ }
+
+ inline void CDocker::DrawHashBar(HWND hBar, POINT Pos)
+ // Draws a hashed bar while the splitter bar is being dragged
+ {
+ CDocker* pDock = ((CDockBar*)FromHandle(hBar))->GetDock();
+ if (NULL == pDock) return;
+
+ BOOL bVertical = ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_LEFT) || ((pDock->GetDockStyle() & 0xF) == DS_DOCKED_RIGHT);
+
+ CClientDC dcBar(this);
+
+ WORD HashPattern[] = {0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA};
+ CBitmap bmHash;
+ CBrush brDithered;
+ bmHash.CreateBitmap(8, 8, 1, 1, HashPattern);
+ brDithered.CreatePatternBrush(&bmHash);
+ dcBar.SelectObject(&brDithered);
+
+ CRect rc = FromHandle(hBar)->GetWindowRect();
+ ScreenToClient(rc);
+ int cx = rc.Width();
+ int cy = rc.Height();
+ int BarWidth = pDock->GetDockBar().GetWidth();
+
+ if (bVertical)
+ dcBar.PatBlt(Pos.x - BarWidth/2, rc.top, BarWidth, cy, PATINVERT);
+ else
+ dcBar.PatBlt(rc.left, Pos.y - BarWidth/2, cx, BarWidth, PATINVERT);
+ }
+
+ inline CDockContainer* CDocker::GetContainer() const
+ {
+ CDockContainer* pContainer = NULL;
+ if (dynamic_cast(GetView()))
+ pContainer = (CDockContainer*)GetView();
+
+ return pContainer;
+ }
+
+ inline CDocker* CDocker::GetActiveDocker() const
+ // Returns the docker whose child window has focus
+ {
+ CWnd* pWnd = GetFocus();
+ CDocker* pDock= NULL;
+ while (pWnd && (pDock == NULL))
+ {
+ if (IsRelated(pWnd))
+ pDock = (CDocker*)pWnd;
+
+ pWnd = pWnd->GetParent();
+ }
+
+ return pDock;
+ }
+
+ inline CDocker* CDocker::GetDockAncestor() const
+ // The GetDockAncestor function retrieves the pointer to the
+ // ancestor (root docker parent) of the Docker.
+ {
+ return m_pDockAncestor;
+ }
+
+ inline CDocker* CDocker::GetDockFromPoint(POINT pt) const
+ // Retrieves the Docker whose view window contains the specified point
+ {
+ // Step 1: Find the top level Docker the point is over
+ CDocker* pDockTop = NULL;
+ CWnd* pAncestor = GetDockAncestor()->GetAncestor();
+
+ // Iterate through all top level windows
+ CWnd* pWnd = GetWindow(GW_HWNDFIRST);
+ while(pWnd)
+ {
+ if (IsRelated(pWnd) || pWnd == pAncestor)
+ {
+ CDocker* pDockTest;
+ if (pWnd == pAncestor)
+ pDockTest = GetDockAncestor();
+ else
+ pDockTest = (CDocker*)pWnd;
+
+ CRect rc = pDockTest->GetClientRect();
+ pDockTest->ClientToScreen(rc);
+ if ((this != pDockTest) && rc.PtInRect(pt))
+ {
+ pDockTop = pDockTest;
+ break;
+ }
+ }
+
+ pWnd = pWnd->GetWindow(GW_HWNDNEXT);
+ }
+
+ // Step 2: Find the docker child whose view window has the point
+ CDocker* pDockTarget = NULL;
+ if (pDockTop)
+ {
+ CDocker* pDockParent = pDockTop;
+ CDocker* pDockTest = pDockParent;
+
+ while (IsRelated(pDockTest))
+ {
+ pDockParent = pDockTest;
+ CPoint ptLocal = pt;
+ pDockParent->ScreenToClient(ptLocal);
+ pDockTest = (CDocker*)pDockParent->ChildWindowFromPoint(ptLocal);
+ assert (pDockTest != pDockParent);
+ }
+
+ CRect rc = pDockParent->GetDockClient().GetWindowRect();
+ if (rc.PtInRect(pt)) pDockTarget = pDockParent;
+ }
+
+ return pDockTarget;
+ }
+
+ inline CDocker* CDocker::GetDockFromID(int n_DockID) const
+ {
+ std::vector ::iterator v;
+
+ if (GetDockAncestor())
+ {
+ for (v = GetDockAncestor()->m_vAllDockers.begin(); v != GetDockAncestor()->m_vAllDockers.end(); v++)
+ {
+ if (n_DockID == (*v)->GetDockID())
+ return (*v).get();
+ }
+ }
+
+ return 0;
+ }
+
+ inline CDocker* CDocker::GetDockFromView(CWnd* pView) const
+ {
+ CDocker* pDock = 0;
+ std::vector::iterator iter;
+ std::vector AllDockers = GetAllDockers();
+ for (iter = AllDockers.begin(); iter != AllDockers.end(); ++iter)
+ {
+ if ((*iter)->GetView() == pView)
+ pDock = (*iter).get();
+ }
+
+ return pDock;
+ }
+
+ inline int CDocker::GetDockSize() const
+ {
+ // Returns the size of the docker to be used if it is redocked
+ // Note: This function returns 0 if the docker has the DS_DOCKED_CONTAINER style
+
+ CRect rcParent;
+ if (GetDockParent())
+ rcParent = GetDockParent()->GetWindowRect();
+ else
+ rcParent = GetDockAncestor()->GetWindowRect();
+
+ double DockSize = 0;
+ if ((GetDockStyle() & DS_DOCKED_LEFT) || (GetDockStyle() & DS_DOCKED_RIGHT))
+ DockSize = (double)(rcParent.Width()*m_DockSizeRatio);
+ else if ((GetDockStyle() & DS_DOCKED_TOP) || (GetDockStyle() & DS_DOCKED_BOTTOM))
+ DockSize = (double)(rcParent.Height()*m_DockSizeRatio);
+ else if ((GetDockStyle() & DS_DOCKED_CONTAINER))
+ DockSize = 0;
+
+ return (int)DockSize;
+ }
+
+ inline CDocker* CDocker::GetTopmostDocker() const
+ // Returns the docker's parent at the top of the Z order.
+ // Could be the dock ancestor or an undocked docker.
+ {
+ CDocker* pDockTopLevel = (CDocker* const)this;
+
+ while(pDockTopLevel->GetDockParent())
+ {
+ assert (pDockTopLevel != pDockTopLevel->GetDockParent());
+ pDockTopLevel = pDockTopLevel->GetDockParent();
+ }
+
+ return pDockTopLevel;
+ }
+
+ inline CTabbedMDI* CDocker::GetTabbedMDI() const
+ {
+ CTabbedMDI* pTabbedMDI = NULL;
+ if (dynamic_cast(GetView()))
+ pTabbedMDI = (CTabbedMDI*)GetView();
+
+ return pTabbedMDI;
+ }
+
+ inline int CDocker::GetTextHeight()
+ {
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
+ LOGFONT lf = nm.lfStatusFont;
+
+ CClientDC dc(this);
+ dc.CreateFontIndirect(&lf);
+ CSize szText = dc.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));
+ return szText.cy;
+ }
+
+ inline void CDocker::Hide()
+ {
+ // Undocks a docker (if needed) and hides it.
+ // Do unhide the docker, dock it.
+
+ if (IsDocked())
+ {
+ if (dynamic_cast(GetView()))
+ {
+ CDockContainer* pContainer = GetContainer();
+ CDocker* pDock = GetDockFromView(pContainer->GetContainerParent());
+ pDock->UndockContainer(pContainer, GetCursorPos(), FALSE);
+ }
+ else
+ {
+ CDocker* pDockUndockedFrom = SeparateFromDock();
+ pDockUndockedFrom->RecalcDockLayout();
+ }
+ }
+
+ ShowWindow(SW_HIDE);
+ }
+
+ inline BOOL CDocker::IsChildOfDocker(CWnd* pWnd) const
+ // returns true if the specified window is a child of this docker
+ {
+ while ((pWnd != NULL) && (pWnd != GetDockAncestor()))
+ {
+ if (pWnd == (CWnd*)this) return TRUE;
+ if (IsRelated(pWnd)) break;
+ pWnd = pWnd->GetParent();
+ }
+
+ return FALSE;
+ }
+
+ inline BOOL CDocker::IsDocked() const
+ {
+ return (((m_DockStyle&0xF) || (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
+ }
+
+ inline BOOL CDocker::IsDragAutoResize()
+ {
+ return m_bDragAutoResize;
+ }
+
+ inline BOOL CDocker::IsRelated(CWnd* pWnd) const
+ // Returns TRUE if the hWnd is a docker within this dock family
+ {
+ if (GetDockAncestor() == pWnd) return TRUE;
+
+ std::vector::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ if ((*iter).get() == pWnd) return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ inline BOOL CDocker::IsUndocked() const
+ {
+ return (!((m_DockStyle&0xF)|| (m_DockStyle & DS_DOCKED_CONTAINER)) && !m_Undocking); // Boolean expression
+ }
+
+ inline BOOL CDocker::LoadRegistrySettings(tString tsRegistryKeyName)
+ // Recreates the docker layout based on information stored in the registry.
+ // Assumes the DockAncestor window is already created.
+ {
+ BOOL bResult = FALSE;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ std::vector vDockList;
+ std::vector vActiveContainers;
+ tString tsKey = _T("Software\\") + tsRegistryKeyName + _T("\\Dock Windows");
+ HKEY hKey = 0;
+ RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey);
+ if (hKey)
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(DockInfo);
+ DockInfo di;
+ int i = 0;
+ TCHAR szNumber[20];
+ tString tsSubKey = _T("DockChild");
+ tsSubKey += _itot(i, szNumber, 10);
+
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&di, &BufferSize))
+ {
+ vDockList.push_back(di);
+ i++;
+ tsSubKey = _T("DockChild");
+ tsSubKey += _itot(i, szNumber, 10);
+ }
+
+ dwType = REG_DWORD;
+ BufferSize = sizeof(int);
+ int nID;
+ i = 0;
+ tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i, szNumber, 10);
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&nID, &BufferSize))
+ {
+ vActiveContainers.push_back(nID);
+ i++;
+ tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i, szNumber, 10);
+ }
+
+ RegCloseKey(hKey);
+ if (vDockList.size() > 0) bResult = TRUE;
+ }
+
+ // Add dockers without parents first
+ std::vector::iterator iter;
+ for (iter = vDockList.begin(); iter < vDockList.end() ; ++iter)
+ {
+ DockInfo di = (*iter);
+ if (di.DockParentID == 0)
+ {
+ CDocker* pDocker = NewDockerFromID(di.DockID);
+ if (pDocker)
+ {
+ if (di.DockStyle & 0xF)
+ AddDockedChild(pDocker, di.DockStyle, di.DockSize, di.DockID);
+ else
+ AddUndockedChild(pDocker, di.DockStyle, di.DockSize, di.Rect, di.DockID);
+ }
+ else
+ {
+ TRACE(_T("Failed to add dockers without parents from registry"));
+ bResult = FALSE;
+ }
+ }
+ }
+
+ // Remove dockers without parents from vDockList
+ for (UINT n = (UINT)vDockList.size(); n > 0; --n)
+ {
+ iter = vDockList.begin() + n-1;
+ if ((*iter).DockParentID == 0)
+ vDockList.erase(iter);
+ }
+
+ // Add remaining dockers
+ while (vDockList.size() > 0)
+ {
+ bool bFound = false;
+ std::vector::iterator iter;
+ for (iter = vDockList.begin(); iter < vDockList.end(); ++iter)
+ {
+ DockInfo di = *iter;
+ CDocker* pDockParent = GetDockFromID(di.DockParentID);
+
+ if (pDockParent != 0)
+ {
+ CDocker* pDock = NewDockerFromID(di.DockID);
+ if(pDock)
+ {
+ pDockParent->AddDockedChild(pDock, di.DockStyle, di.DockSize, di.DockID);
+ bFound = true;
+ }
+ else
+ {
+ TRACE(_T("Failed to add dockers with parents from registry"));
+ bResult = FALSE;
+ }
+
+ vDockList.erase(iter);
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ TRACE(_T("Orphaned dockers stored in registry "));
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ std::vector::iterator iterID;
+ for (iterID = vActiveContainers.begin(); iterID < vActiveContainers.end(); ++iterID)
+ {
+ CDocker* pDocker = GetDockFromID(*iterID);
+ if (pDocker)
+ {
+ CDockContainer* pContainer = pDocker->GetContainer();
+ if (pContainer)
+ {
+ int nPage = pContainer->GetContainerIndex(pContainer);
+ if (nPage >= 0)
+ pContainer->SelectPage(nPage);
+ }
+ }
+ }
+ }
+
+ if (!bResult) CloseAllDockers();
+ return bResult;
+ }
+
+ inline void CDocker::MoveDockChildren(CDocker* pDockTarget)
+ // Used internally by Dock and Undock
+ {
+ assert(pDockTarget);
+
+ // Transfer any dock children from the current docker to the target docker
+ std::vector::iterator iter;
+ for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)
+ {
+ pDockTarget->GetDockChildren().push_back(*iter);
+ (*iter)->m_pDockParent = pDockTarget;
+ (*iter)->SetParent(pDockTarget);
+ (*iter)->GetDockBar().SetParent(pDockTarget);
+ }
+ GetDockChildren().clear();
+ }
+
+ inline CDocker* CDocker::NewDockerFromID(int nID)
+ // Used in LoadRegistrySettings. Creates a new Docker from the specified ID
+ {
+ UNREFERENCED_PARAMETER(nID);
+
+ // Override this function to create the Docker objects as shown below
+
+ CDocker* pDock = NULL;
+ /* switch(nID)
+ {
+ case ID_CLASSES:
+ pDock = new CDockClasses;
+ break;
+ case ID_FILES:
+ pDock = new CDockFiles;
+ break;
+ default:
+ TRACE(_T("Unknown Dock ID\n"));
+ break;
+ } */
+
+ return pDock;
+ }
+
+ inline void CDocker::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Only top level undocked dockers get this message
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ GetTopmostDocker()->m_hOldFocus = ::GetFocus();
+
+ // Send a notification of focus lost
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMELOSTFOCUS;
+ SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CDocker::OnCaptionTimer(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (this == GetDockAncestor())
+ {
+ if (wParam == 1)
+ {
+ DrawAllCaptions();
+ m_nTimerCount++;
+ if (m_nTimerCount == 10)
+ {
+ KillTimer(wParam);
+ m_nTimerCount = 0;
+ }
+ }
+ }
+ }
+
+ inline void CDocker::OnCreate()
+ {
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ if (GetParent()->GetWindowLongPtr(GWL_EXSTYLE) & WS_EX_LAYOUTRTL)
+ {
+ DWORD dwExStyle = GetWindowLongPtr(GWL_EXSTYLE);
+ SetWindowLongPtr(GWL_EXSTYLE, dwExStyle | WS_EX_LAYOUTRTL);
+ }
+#endif
+
+ // Create the various child windows
+ GetDockClient().SetDock(this);
+ GetDockClient().Create(this);
+
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(&GetDockClient());
+
+ // Create the slider bar belonging to this docker
+ GetDockBar().SetDock(this);
+ if (GetDockAncestor() != this)
+ GetDockBar().Create(GetParent());
+
+ // Now remove the WS_POPUP style. It was required to allow this window
+ // to be owned by the frame window.
+ SetWindowLongPtr(GWL_STYLE, WS_CHILD);
+ SetParent(GetParent()); // Reinstate the window's parent
+
+ // Set the default colour for the splitter bar
+ COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->clrBkgnd2 != 0)
+ rgbColour =pTheme->clrBkgnd2;
+
+ SetBarColor(rgbColour);
+
+ // Set the caption height based on text height
+ m_NCHeight = MAX(20, GetTextHeight() + 5);
+ }
+
+ inline void CDocker::OnDestroy(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Destroy any dock children first
+ std::vector::iterator iter;
+ for (iter = GetDockChildren().begin(); iter < GetDockChildren().end(); ++iter)
+ {
+ (*iter)->Destroy();
+ }
+
+ if (dynamic_cast(GetView()) && IsUndocked())
+ {
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ if (pContainer->GetAllContainers().size() > 1)
+ {
+ // This container has children, so destroy them now
+ std::vector AllContainers = pContainer->GetAllContainers();
+ std::vector::iterator iter;
+ for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter)
+ {
+ if ((*iter).pContainer != pContainer)
+ {
+ // Reset container parent before destroying the dock window
+ CDocker* pDock = GetDockFromView((*iter).pContainer);
+ if (pContainer->IsWindow())
+ pContainer->SetParent(&pDock->GetDockClient());
+
+ pDock->Destroy();
+ }
+ }
+ }
+ }
+
+ GetDockBar().Destroy();
+
+ // Post a destroy docker message
+ if ( GetDockAncestor()->IsWindow() )
+ GetDockAncestor()->PostMessage(UWM_DOCK_DESTROYED, (WPARAM)this, 0L);
+ }
+
+ inline void CDocker::OnDockDestroyed(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ CDocker* pDock = (CDocker*)wParam;
+
+ assert( this == GetDockAncestor() );
+ std::vector::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ {
+ if ((*iter).get() == pDock)
+ {
+ GetAllDockers().erase(iter);
+ break;
+ }
+ }
+ }
+
+ inline void CDocker::OnExitSizeMove(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ m_BlockMove = FALSE;
+ m_bIsDragging = FALSE;
+ SendNotify(UWM_DOCK_END);
+ }
+
+ inline LRESULT CDocker::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ LPDRAGPOS pdp = (LPDRAGPOS)lParam;
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case UWM_DOCK_START:
+ {
+ if (IsDocked())
+ {
+ Undock(GetCursorPos());
+ SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pdp->ptPos.x, pdp->ptPos.y));
+ }
+ }
+ break;
+
+ case UWM_DOCK_MOVE:
+ {
+ CheckAllTargets((LPDRAGPOS)lParam);
+ }
+ break;
+
+ case UWM_DOCK_END:
+ {
+ CDocker* pDock = (CDocker*)FromHandle(pdp->hdr.hwndFrom);
+ if (NULL == pDock) break;
+
+ UINT DockZone = pdp->DockZone;
+ CRect rc = pDock->GetWindowRect();
+
+ switch(DockZone)
+ {
+ case DS_DOCKED_LEFT:
+ case DS_DOCKED_RIGHT:
+ pDock->SetDockSize(rc.Width());
+ Dock(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_TOP:
+ case DS_DOCKED_BOTTOM:
+ pDock->SetDockSize(rc.Height());
+ Dock(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_CONTAINER:
+ {
+ DockInContainer(pDock, pDock->GetDockStyle() | DockZone);
+ CDockContainer* pContainer = (CDockContainer*)GetView();
+ int nPage = pContainer->GetContainerIndex((CDockContainer*)pDock->GetView());
+ pContainer->SelectPage(nPage);
+ }
+ break;
+ case DS_DOCKED_LEFTMOST:
+ case DS_DOCKED_RIGHTMOST:
+ pDock->SetDockSize(rc.Width());
+ DockOuter(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ case DS_DOCKED_TOPMOST:
+ case DS_DOCKED_BOTTOMMOST:
+ pDock->SetDockSize(rc.Height());
+ DockOuter(pDock, pDock->GetDockStyle() | DockZone);
+ break;
+ }
+
+ GetDockHint().Destroy();
+ CloseAllTargets();
+ }
+ break;
+
+ case UWM_BAR_START:
+ {
+ CPoint pt = pdp->ptPos;
+ ScreenToClient(pt);
+ if (!IsDragAutoResize())
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+ m_OldPoint = pt;
+ }
+ break;
+
+ case UWM_BAR_MOVE:
+ {
+ CPoint pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ if (pt != m_OldPoint)
+ {
+ if (IsDragAutoResize())
+ ResizeDockers(pdp);
+ else
+ {
+ DrawHashBar(pdp->hdr.hwndFrom, m_OldPoint);
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+ }
+
+ m_OldPoint = pt;
+ }
+ }
+ break;
+
+ case UWM_BAR_END:
+ {
+ POINT pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ if (!IsDragAutoResize())
+ DrawHashBar(pdp->hdr.hwndFrom, pt);
+
+ ResizeDockers(pdp);
+ }
+ break;
+ case NM_SETFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ break;
+ case UWM_FRAMEGOTFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, wParam, lParam);
+ break;
+ case UWM_FRAMELOSTFOCUS:
+ if (GetDockAncestor()->IsWindow())
+ GetDockAncestor()->PostMessage(UWM_DOCK_ACTIVATED, 0, 0);
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, wParam, lParam);
+ break;
+ }
+ return 0L;
+ }
+
+ inline void CDocker::ResizeDockers(LPDRAGPOS pdp)
+ // Called when the docker's splitter bar is dragged
+ {
+ assert(pdp);
+
+ POINT pt = pdp->ptPos;
+ ScreenToClient(pt);
+
+ CDocker* pDock = ((CDockBar*)FromHandle(pdp->hdr.hwndFrom))->GetDock();
+ if (NULL == pDock) return;
+
+ RECT rcDock = pDock->GetWindowRect();
+ ScreenToClient(rcDock);
+
+ double dBarWidth = pDock->GetDockBar().GetWidth();
+ int iBarWidth = pDock->GetDockBar().GetWidth();
+ int DockSize;
+
+ switch (pDock->GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ DockSize = MAX(pt.x, iBarWidth/2) - rcDock.left - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_RIGHT:
+ DockSize = rcDock.right - MAX(pt.x, iBarWidth/2) - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_TOP:
+ DockSize = MAX(pt.y, iBarWidth/2) - rcDock.top - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());
+ break;
+ case DS_DOCKED_BOTTOM:
+ DockSize = rcDock.bottom - MAX(pt.y, iBarWidth/2) - (int)(.5* dBarWidth);
+ DockSize = MAX(-iBarWidth, DockSize);
+ pDock->SetDockSize(DockSize);
+ pDock->m_DockSizeRatio = ((double)pDock->m_DockStartSize)/((double)pDock->m_pDockParent->GetWindowRect().Height());
+ break;
+ }
+
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::OnSetFocus(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (IsUndocked() && m_hOldFocus)
+ ::SetFocus(m_hOldFocus);
+ else
+ // Pass focus on the the view window
+ GetView()->SetFocus();
+
+ if ((this == GetTopmostDocker()) && (this != GetDockAncestor()))
+ {
+ // Send a notification to top level window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = NM_SETFOCUS;
+ SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CDocker::OnSysColorChange(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (this == GetDockAncestor())
+ {
+ COLORREF rgbColour = GetSysColor(COLOR_BTNFACE);
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ ReBarTheme* pTheme = (ReBarTheme*)pFrame->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->clrBand2 != 0)
+ rgbColour = pTheme->clrBkgnd2;
+ else
+ rgbColour = GetSysColor(COLOR_BTNFACE);
+
+ // Set the splitter bar colour for each docker decendant
+ std::vector::iterator iter;
+ for (iter = GetAllDockers().begin(); iter < GetAllDockers().end(); ++iter)
+ (*iter)->SetBarColor(rgbColour);
+
+ // Set the splitter bar colour for the docker ancestor
+ SetBarColor(rgbColour);
+ }
+ }
+
+ inline LRESULT CDocker::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ switch(wParam&0xFFF0)
+ {
+ case SC_MOVE:
+ // An undocked docker is being moved
+ {
+ BOOL bResult = FALSE;
+ m_bIsDragging = TRUE;
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ if (SystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, &bResult, 0))
+ {
+ // Turn on DragFullWindows for this move
+ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, TRUE, 0, 0);
+
+ // Process this message
+ DefWindowProc(WM_SYSCOMMAND, wParam, lParam);
+
+ // Return DragFullWindows to its previous state
+ SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, bResult, 0, 0);
+ return 0L;
+ }
+ }
+ break;
+ case SC_CLOSE:
+ // The close button is pressed on an undocked docker
+ m_bIsClosing = TRUE;
+ break;
+ }
+ return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
+ }
+
+ inline LRESULT CDocker::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
+ {
+ // Suspend dock drag moving while over dock zone
+ if (m_BlockMove)
+ {
+ LPWINDOWPOS pWndPos = (LPWINDOWPOS)lParam;
+ pWndPos->flags |= SWP_NOMOVE|SWP_FRAMECHANGED;
+ return 0;
+ }
+
+ return CWnd::WndProcDefault(WM_WINDOWPOSCHANGING, wParam, lParam);
+ }
+
+ inline void CDocker::OnWindowPosChanged(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ if (m_bIsDragging)
+ {
+ // Send a Move notification to the parent
+ if ( IsLeftButtonDown() )
+ {
+ LPWINDOWPOS wPos = (LPWINDOWPOS)lParam;
+ if ((!(wPos->flags & SWP_NOMOVE)) || m_BlockMove)
+ SendNotify(UWM_DOCK_MOVE);
+ }
+ else
+ {
+ CloseAllTargets();
+ m_BlockMove = FALSE;
+ }
+ }
+ else if (this == GetTopmostDocker())
+ {
+ // Reposition the dock children
+ if (IsUndocked() && IsWindowVisible() && !m_bIsClosing) RecalcDockLayout();
+ }
+ }
+
+ inline void CDocker::PreCreate(CREATESTRUCT &cs)
+ {
+ // Specify the WS_POPUP style to have this window owned
+ if (this != GetDockAncestor())
+ cs.style = WS_POPUP;
+
+ cs.dwExStyle = WS_EX_TOOLWINDOW;
+ }
+
+ inline void CDocker::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = _T("Win32++ Docker");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDocker::RecalcDockChildLayout(CRect rc)
+ {
+ // This function positions the Docker's dock children, the Dockers client area
+ // and draws the dockbar bars.
+
+ // Notes:
+ // 1) This function is called recursively.
+ // 2) The client area and child dockers are positioned simultaneously with
+ // DeferWindowPos to avoid drawing errors in complex docker arrangements.
+ // 3) The docker's client area contains the docker's caption (if any) and the docker's view window.
+
+ // Note: All top level dockers are undocked, including the dock ancestor.
+ if (IsDocked())
+ {
+ rc.OffsetRect(-rc.left, -rc.top);
+ }
+
+ HDWP hdwp = BeginDeferWindowPos((int)m_vDockChildren.size() +2);
+
+ // Step 1: Calculate the position of each Docker child, DockBar, and Client window.
+ // The Client area = the docker rect minus the area of dock children and the dock bar (splitter bar).
+ for (UINT u = 0; u < m_vDockChildren.size(); ++u)
+ {
+ CRect rcChild = rc;
+ double DockSize = m_vDockChildren[u]->m_DockStartSize;;
+
+ // Calculate the size of the Docker children
+ switch (m_vDockChildren[u]->GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());
+ rcChild.right = rcChild.left + (int)DockSize;
+ break;
+ case DS_DOCKED_RIGHT:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Width()), rcChild.Width());
+ rcChild.left = rcChild.right - (int)DockSize;
+ break;
+ case DS_DOCKED_TOP:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());
+ rcChild.bottom = rcChild.top + (int)DockSize;
+ break;
+ case DS_DOCKED_BOTTOM:
+ if (!(GetDockStyle() & DS_FIXED_RESIZE))
+ DockSize = MIN(m_vDockChildren[u]->m_DockSizeRatio*(GetWindowRect().Height()), rcChild.Height());
+ rcChild.top = rcChild.bottom - (int)DockSize;
+ break;
+ }
+
+ if (m_vDockChildren[u]->IsDocked())
+ {
+ // Position this docker's children
+ hdwp = m_vDockChildren[u]->DeferWindowPos(hdwp, NULL, rcChild, SWP_SHOWWINDOW|SWP_FRAMECHANGED);
+ m_vDockChildren[u]->m_rcChild = rcChild;
+
+ rc.SubtractRect(rc, rcChild);
+
+ // Calculate the dimensions of the splitter bar
+ CRect rcBar = rc;
+ DWORD DockSide = m_vDockChildren[u]->GetDockStyle() & 0xF;
+
+ if (DS_DOCKED_LEFT == DockSide) rcBar.right = rcBar.left + m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_RIGHT == DockSide) rcBar.left = rcBar.right - m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_TOP == DockSide) rcBar.bottom = rcBar.top + m_vDockChildren[u]->GetBarWidth();
+ if (DS_DOCKED_BOTTOM == DockSide) rcBar.top = rcBar.bottom - m_vDockChildren[u]->GetBarWidth();
+
+ // Save the splitter bar position. We will reposition it later.
+ m_vDockChildren[u]->m_rcBar = rcBar;
+ rc.SubtractRect(rc, rcBar);
+ }
+ }
+
+ // Step 2: Position the Dock client and dock bar
+ hdwp = GetDockClient().DeferWindowPos(hdwp, NULL, rc, SWP_SHOWWINDOW |SWP_FRAMECHANGED);
+ EndDeferWindowPos(hdwp);
+
+ // Position the dockbar. Only docked dockers have a dock bar.
+ if (IsDocked())
+ {
+ // The SWP_NOCOPYBITS forces a redraw of the dock bar.
+ GetDockBar().SetWindowPos(NULL, m_rcBar, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOCOPYBITS );
+ }
+
+ // Step 3: Now recurse through the docker's children. They might have children of their own.
+ for (UINT v = 0; v < m_vDockChildren.size(); ++v)
+ {
+ m_vDockChildren[v]->RecalcDockChildLayout(m_vDockChildren[v]->m_rcChild);
+ }
+ }
+
+ inline void CDocker::RecalcDockLayout()
+ // Repositions the dock children of a top level docker
+ {
+ if (GetDockAncestor()->IsWindow())
+ {
+ CRect rc = GetTopmostDocker()->GetClientRect();
+ GetTopmostDocker()->RecalcDockChildLayout(rc);
+ GetTopmostDocker()->UpdateWindow();
+ }
+ }
+
+ inline std::vector CDocker::SortDockers()
+ // Returns a vector of sorted dockers, used by SaveRegistrySettings.
+ {
+ std::vector vSorted;
+ std::vector::iterator itSort;
+ std::vector::iterator itAll;
+
+ // Add undocked top level dockers
+ for (itAll = GetAllDockers().begin(); itAll < GetAllDockers().end(); ++itAll)
+ {
+ if (!(*itAll)->GetDockParent())
+ vSorted.push_back((*itAll).get());
+ }
+
+ // Add dock ancestor's children
+ vSorted.insert(vSorted.end(), GetDockAncestor()->GetDockChildren().begin(), GetDockAncestor()->GetDockChildren().end());
+
+ // Add other dock children
+ int index = 0;
+ itSort = vSorted.begin();
+ while (itSort < vSorted.end())
+ {
+ vSorted.insert(vSorted.end(), (*itSort)->GetDockChildren().begin(), (*itSort)->GetDockChildren().end());
+ itSort = vSorted.begin() + (++index);
+ }
+
+ // Add dockers docked in containers
+ std::vector vDockContainers;
+ for (itSort = vSorted.begin(); itSort< vSorted.end(); ++itSort)
+ {
+ if ((*itSort)->GetContainer())
+ vDockContainers.push_back(*itSort);
+ }
+
+ for (itSort = vDockContainers.begin(); itSort < vDockContainers.end(); ++itSort)
+ {
+ CDockContainer* pContainer = (*itSort)->GetContainer();
+
+ for (UINT i = 1; i < pContainer->GetAllContainers().size(); ++i)
+ {
+ CDockContainer* pChild = pContainer->GetContainerFromIndex(i);
+ CDocker* pDock = GetDockFromView(pChild);
+ vSorted.push_back(pDock);
+ }
+ }
+
+ return vSorted;
+ }
+
+ inline BOOL CDocker::SaveRegistrySettings(tString tsRegistryKeyName)
+ // Stores the docking configuration in the registry
+ // NOTE: This function assumes that each docker has a unique DockID
+ {
+ assert(VerifyDockers());
+
+ std::vector vSorted = SortDockers();
+ std::vector::iterator iter;
+ std::vector vDockInfo;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ // Fill the DockInfo vector with the docking information
+ for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
+ {
+ DockInfo di = {0};
+ di.DockID = (*iter)->GetDockID();
+ di.DockStyle = (*iter)->GetDockStyle();
+ di.DockSize = (*iter)->GetDockSize();
+ di.Rect = (*iter)->GetWindowRect();
+ if ((*iter)->GetDockParent())
+ di.DockParentID = (*iter)->GetDockParent()->GetDockID();
+
+ vDockInfo.push_back(di);
+ }
+
+ tString tsKeyName = _T("Software\\") + tsRegistryKeyName;
+ HKEY hKey = NULL;
+ HKEY hKeyDock = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ RegDeleteKey(hKey, _T("Dock Windows"));
+ if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("Dock Windows"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyDock, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ // Add the Dock windows information to the registry
+ for (UINT u = 0; u < vDockInfo.size(); ++u)
+ {
+ DockInfo di = vDockInfo[u];
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("DockChild");
+ tsSubKey += _itot((int)u, szNumber, 10);
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, tsSubKey.c_str(), 0, REG_BINARY, (LPBYTE)&di, sizeof(DockInfo)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+ }
+
+ // Add Active Container to the registry
+ int i = 0;
+ for (iter = vSorted.begin(); iter < vSorted.end(); ++iter)
+ {
+ CDockContainer* pContainer = (*iter)->GetContainer();
+
+ if (pContainer && (pContainer == pContainer->GetActiveContainer()))
+ {
+ TCHAR szNumber[20];
+ tString tsSubKey = _T("ActiveContainer");
+ tsSubKey += _itot(i++, szNumber, 10);
+ int nID = GetDockFromView(pContainer)->GetDockID();
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, tsSubKey.c_str(), 0, REG_DWORD, (LPBYTE)&nID, sizeof(int)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+ }
+ }
+
+ RegCloseKey(hKeyDock);
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ // Roll back the registry changes by deleting the subkeys
+ if (hKey)
+ {
+ if (hKeyDock)
+ {
+ RegDeleteKey(hKeyDock, _T("Dock Windows"));
+ RegCloseKey(hKeyDock);
+ }
+
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CDocker::SendNotify(UINT nMessageID)
+ // Sends a docking notification to the docker below the cursor
+ {
+ DRAGPOS DragPos;
+ DragPos.hdr.code = nMessageID;
+ DragPos.hdr.hwndFrom = m_hWnd;
+ DragPos.ptPos = GetCursorPos();
+ DragPos.DockZone = m_dwDockZone;
+ m_dwDockZone = 0;
+
+ CDocker* pDock = GetDockFromPoint(DragPos.ptPos);
+
+ if (pDock)
+ pDock->SendMessage(WM_NOTIFY, 0L, (LPARAM)&DragPos);
+ else
+ {
+ if (GetDockHint().IsWindow()) GetDockHint().Destroy();
+ CloseAllTargets();
+ m_BlockMove = FALSE;
+ }
+ }
+
+ inline void CDocker::SetDockStyle(DWORD dwDockStyle)
+ {
+ if (IsWindow())
+ {
+ if ((dwDockStyle & DS_CLIENTEDGE) != (m_DockStyle & DS_CLIENTEDGE))
+ {
+ if (dwDockStyle & DS_CLIENTEDGE)
+ {
+ DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE)|WS_EX_CLIENTEDGE;
+ GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);
+ GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
+ }
+ else
+ {
+ DWORD dwExStyle = (DWORD)GetDockClient().GetWindowLongPtr(GWL_EXSTYLE);
+ dwExStyle &= ~WS_EX_CLIENTEDGE;
+ GetDockClient().SetWindowLongPtr(GWL_EXSTYLE, dwExStyle);
+ GetDockClient().RedrawWindow(0, 0, RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE|RDW_FRAME);
+ }
+ }
+
+ RecalcDockLayout();
+ }
+
+ m_DockStyle = dwDockStyle;
+ }
+
+ inline void CDocker::SetCaption(LPCTSTR szCaption)
+ // Sets the caption text
+ {
+ GetDockClient().SetCaption(szCaption);
+
+ if (IsWindow())
+ SetWindowText(szCaption);
+ }
+
+ inline void CDocker::SetCaptionColors(COLORREF Foregnd1, COLORREF Backgnd1, COLORREF ForeGnd2, COLORREF BackGnd2)
+ {
+ GetDockClient().SetCaptionColors(Foregnd1, Backgnd1, ForeGnd2, BackGnd2);
+ }
+
+ inline void CDocker::SetCaptionHeight(int nHeight)
+ // Sets the height of the caption
+ {
+ m_NCHeight = nHeight;
+ RedrawWindow();
+ RecalcDockLayout();
+ }
+
+ inline void CDocker::SetDockSize(int DockSize)
+ // Sets the size of a docked docker
+ {
+ if (IsDocked())
+ {
+ assert (m_pDockParent);
+ switch (GetDockStyle() & 0xF)
+ {
+ case DS_DOCKED_LEFT:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_RIGHT:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Width());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Width());
+ break;
+ case DS_DOCKED_TOP:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());
+ break;
+ case DS_DOCKED_BOTTOM:
+ m_DockStartSize = MIN(DockSize,m_pDockParent->GetWindowRect().Height());
+ m_DockSizeRatio = ((double)m_DockStartSize)/((double)m_pDockParent->GetWindowRect().Height());
+ break;
+ }
+
+ RecalcDockLayout();
+ }
+ else
+ {
+ m_DockStartSize = DockSize;
+ m_DockSizeRatio = 1.0;
+ }
+ }
+
+ inline void CDocker::SetDragAutoResize(BOOL bAutoResize)
+ {
+ m_bDragAutoResize = bAutoResize;
+ }
+
+ inline void CDocker::SetView(CWnd& wndView)
+ // Assigns the view window to the docker
+ {
+ CWnd* pWnd = &wndView;
+ GetDockClient().SetView(wndView);
+ if (dynamic_cast(pWnd))
+ {
+ CDockContainer* pContainer = (CDockContainer*)&wndView;
+ SetCaption(pContainer->GetDockCaption().c_str());
+ }
+ }
+
+ inline void CDocker::PromoteFirstChild()
+ // One of the steps required for undocking
+ {
+ // Promote our first child to replace ourself
+ if (m_pDockParent)
+ {
+ for (UINT u = 0 ; u < m_pDockParent->m_vDockChildren.size(); ++u)
+ {
+ if (m_pDockParent->m_vDockChildren[u] == this)
+ {
+ if (m_vDockChildren.size() > 0)
+ // swap our first child for ourself as a child of the parent
+ m_pDockParent->m_vDockChildren[u] = m_vDockChildren[0];
+ else
+ // remove ourself as a child of the parent
+ m_pDockParent->m_vDockChildren.erase(m_pDockParent->m_vDockChildren.begin() + u);
+ break;
+ }
+ }
+ }
+
+ // Transfer styles and data and children to the child docker
+ CDocker* pDockFirstChild = NULL;
+ if (m_vDockChildren.size() > 0)
+ {
+ pDockFirstChild = m_vDockChildren[0];
+ pDockFirstChild->m_DockStyle = (pDockFirstChild->m_DockStyle & 0xFFFFFFF0 ) | (m_DockStyle & 0xF);
+ pDockFirstChild->m_DockStartSize = m_DockStartSize;
+ pDockFirstChild->m_DockSizeRatio = m_DockSizeRatio;
+
+ if (m_pDockParent)
+ {
+ pDockFirstChild->m_pDockParent = m_pDockParent;
+ pDockFirstChild->SetParent(m_pDockParent);
+ pDockFirstChild->GetDockBar().SetParent(m_pDockParent);
+ }
+ else
+ {
+ std::vector::iterator iter;
+ for (iter = GetDockChildren().begin() + 1; iter < GetDockChildren().end(); ++iter)
+ (*iter)->ShowWindow(SW_HIDE);
+
+ pDockFirstChild->ConvertToPopup(GetWindowRect());
+ pDockFirstChild->GetDockBar().ShowWindow(SW_HIDE);
+ }
+
+ m_vDockChildren.erase(m_vDockChildren.begin());
+ MoveDockChildren(pDockFirstChild);
+ }
+ }
+
+ inline void CDocker::ConvertToChild(HWND hWndParent)
+ {
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE;
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+ SetParent(FromHandle(hWndParent));
+ GetDockBar().SetParent(FromHandle(hWndParent));
+ }
+
+ inline void CDocker::ConvertToPopup(RECT rc)
+ {
+ // Change the window to an "undocked" style
+ ShowWindow(SW_HIDE);
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+
+ // Change the window's parent and reposition it
+ GetDockBar().ShowWindow(SW_HIDE);
+ SetWindowPos(0, 0, 0, 0, 0, SWP_NOSENDCHANGING|SWP_HIDEWINDOW|SWP_NOREDRAW);
+ m_pDockParent = 0;
+ SetParent(0);
+ SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED|SWP_NOOWNERZORDER);
+ GetDockClient().SetWindowPos(NULL, GetClientRect(), SWP_SHOWWINDOW);
+
+ SetWindowText(GetCaption().c_str());
+ }
+
+ inline CDocker* CDocker::SeparateFromDock()
+ {
+ // This performs some of the tasks required for undocking.
+ // It is also used when a docker is hidden.
+ CDocker* pDockUndockedFrom = GetDockParent();
+ if (!pDockUndockedFrom && (GetDockChildren().size() > 0))
+ pDockUndockedFrom = GetDockChildren()[0];
+
+ GetTopmostDocker()->m_hOldFocus = 0;
+ PromoteFirstChild();
+ m_pDockParent = 0;
+
+ GetDockBar().ShowWindow(SW_HIDE);
+ m_DockStyle = m_DockStyle & 0xFFFFFFF0;
+ m_DockStyle &= ~DS_DOCKED_CONTAINER;
+
+ return pDockUndockedFrom;
+ }
+
+ inline void CDocker::SetUndockPosition(CPoint pt)
+ {
+ m_Undocking = TRUE;
+ CRect rc;
+ rc = GetDockClient().GetWindowRect();
+ CRect rcTest = rc;
+ rcTest.bottom = MIN(rcTest.bottom, rcTest.top + m_NCHeight);
+ if ( !rcTest.PtInRect(pt))
+ rc.SetRect(pt.x - rc.Width()/2, pt.y - m_NCHeight/2, pt.x + rc.Width()/2, pt.y - m_NCHeight/2 + rc.Height());
+
+ ConvertToPopup(rc);
+ m_Undocking = FALSE;
+
+ // Send the undock notification to the frame
+ NMHDR nmhdr = {0};
+ nmhdr.hwndFrom = m_hWnd;
+ nmhdr.code = UWM_UNDOCKED;
+ nmhdr.idFrom = m_nDockID;
+ CWnd* pFrame = GetDockAncestor()->GetAncestor();
+ pFrame->SendMessage(WM_NOTIFY, m_nDockID, (LPARAM)&nmhdr);
+
+ // Initiate the window move
+ SetCursorPos(pt.x, pt.y);
+ ScreenToClient(pt);
+ PostMessage(WM_SYSCOMMAND, (WPARAM)(SC_MOVE|0x0002), MAKELPARAM(pt.x, pt.y));
+ }
+
+ inline void CDocker::Undock(CPoint pt, BOOL bShowUndocked)
+ {
+ // Return if we shouldn't undock
+ if (GetDockStyle() & DS_NO_UNDOCK) return;
+
+ // Undocking isn't supported on Win95
+ if (1400 == GetWinVersion()) return;
+
+ CDocker* pDockUndockedFrom = SeparateFromDock();
+
+ // Position and draw the undocked window, unless it is about to be closed
+ if (bShowUndocked)
+ {
+ SetUndockPosition(pt);
+ }
+
+ RecalcDockLayout();
+ if ((pDockUndockedFrom) && (pDockUndockedFrom->GetTopmostDocker() != GetTopmostDocker()))
+ pDockUndockedFrom->RecalcDockLayout();
+ }
+
+ inline void CDocker::UndockContainer(CDockContainer* pContainer, CPoint pt, BOOL bShowUndocked)
+ {
+ assert(pContainer);
+ assert(this == GetDockFromView(pContainer->GetContainerParent()));
+
+ // Return if we shouldn't undock
+ if (GetDockFromView(pContainer)->GetDockStyle() & DS_NO_UNDOCK) return;
+
+ // Undocking isn't supported on Win95
+ if (1400 == GetWinVersion()) return;
+
+ GetTopmostDocker()->m_hOldFocus = 0;
+ CDocker* pDockUndockedFrom = GetDockFromView(pContainer->GetContainerParent());
+ pDockUndockedFrom->ShowWindow(SW_HIDE);
+ if (GetView() == pContainer)
+ {
+ // The parent container is being undocked, so we need
+ // to transfer our child containers to a different docker
+
+ // Choose a new docker from among the dockers for child containers
+ CDocker* pDockNew = 0;
+ CDocker* pDockOld = GetDockFromView(pContainer);
+ std::vector AllContainers = pContainer->GetAllContainers();
+ std::vector::iterator iter = AllContainers.begin();
+ while ((0 == pDockNew) && (iter < AllContainers.end()))
+ {
+ if ((*iter).pContainer != pContainer)
+ pDockNew = (CDocker*)FromHandle(::GetParent((*iter).pContainer->GetParent()->GetHwnd()));
+
+ ++iter;
+ }
+
+ if (pDockNew)
+ {
+ // Move containers from the old docker to the new docker
+ CDockContainer* pContainerNew = (CDockContainer*)pDockNew->GetView();
+ for (iter = AllContainers.begin(); iter != AllContainers.end(); ++iter)
+ {
+ if ((*iter).pContainer != pContainer)
+ {
+ CDockContainer* pChildContainer = (CDockContainer*)(*iter).pContainer;
+ pContainer->RemoveContainer(pChildContainer);
+ if (pContainerNew != pChildContainer)
+ {
+ pContainerNew->AddContainer(pChildContainer);
+ CDocker* pDock = GetDockFromView(pChildContainer);
+ pDock->SetParent(pDockNew);
+ pDock->m_pDockParent = pDockNew;
+ }
+ }
+ }
+
+ // Now transfer the old docker's settings to the new one.
+ pDockUndockedFrom = pDockNew;
+ pDockNew->m_DockStyle = pDockOld->m_DockStyle;
+ pDockNew->m_DockStartSize = pDockOld->m_DockStartSize;
+ pDockNew->m_DockSizeRatio = pDockOld->m_DockSizeRatio;
+ if (pDockOld->IsDocked())
+ {
+ pDockNew->m_pDockParent = pDockOld->m_pDockParent;
+ pDockNew->SetParent(pDockOld->GetParent());
+ }
+ else
+ {
+ CRect rc = pDockOld->GetWindowRect();
+ pDockNew->ShowWindow(SW_HIDE);
+ DWORD dwStyle = WS_POPUP| WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE;
+ pDockNew->SetWindowLongPtr(GWL_STYLE, dwStyle);
+ pDockNew->m_pDockParent = 0;
+ pDockNew->SetParent(0);
+ pDockNew->SetWindowPos(NULL, rc, SWP_SHOWWINDOW|SWP_FRAMECHANGED| SWP_NOOWNERZORDER);
+ }
+ pDockNew->GetDockBar().SetParent(pDockOld->GetParent());
+ pDockNew->GetView()->SetFocus();
+
+ // Transfer the Dock children to the new docker
+ pDockOld->MoveDockChildren(pDockNew);
+
+ // insert pDockNew into its DockParent's DockChildren vector
+ if (pDockNew->m_pDockParent)
+ {
+ std::vector::iterator p;
+ for (p = pDockNew->m_pDockParent->m_vDockChildren.begin(); p != pDockNew->m_pDockParent->m_vDockChildren.end(); ++p)
+ {
+ if (*p == this)
+ {
+ pDockNew->m_pDockParent->m_vDockChildren.insert(p, pDockNew);
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ // This is a child container, so simply remove it from the parent
+ CDockContainer* pContainerParent = (CDockContainer*)GetView();
+ pContainerParent->RemoveContainer(pContainer);
+ pContainerParent->SetTabSize();
+ pContainerParent->SetFocus();
+ pContainerParent->GetViewPage().SetParent(pContainerParent);
+ }
+
+ // Finally do the actual undocking
+ CDocker* pDock = GetDockFromView(pContainer);
+ CRect rc = GetDockClient().GetWindowRect();
+ ScreenToClient(rc);
+ pDock->GetDockClient().SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ pDock->Undock(pt, bShowUndocked);
+ pDockUndockedFrom->ShowWindow();
+ pDockUndockedFrom->RecalcDockLayout();
+ pDock->BringWindowToTop();
+ }
+
+ inline LRESULT CDocker::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ break;
+ case WM_SYSCOMMAND:
+ return OnSysCommand(wParam, lParam);
+
+ case WM_EXITSIZEMOVE:
+ OnExitSizeMove(wParam, lParam);
+ break;
+ case WM_WINDOWPOSCHANGING:
+ return OnWindowPosChanging(wParam, lParam);
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ case WM_DESTROY:
+ OnDestroy(wParam, lParam);
+ break;
+ case WM_SETFOCUS:
+ OnSetFocus(wParam, lParam);
+ break;
+ case WM_TIMER:
+ OnCaptionTimer(wParam, lParam);
+ break;
+ case UWM_DOCK_DESTROYED:
+ OnDockDestroyed(wParam, lParam);
+ break;
+ case UWM_DOCK_ACTIVATED:
+ DrawAllCaptions();
+ SetTimer(1, 100, NULL);
+ break;
+ case WM_SYSCOLORCHANGE:
+ OnSysColorChange(wParam, lParam);
+ break;
+ case WM_NCLBUTTONDBLCLK :
+ m_bIsDragging = FALSE;
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ //////////////////////////////////////
+ // Declaration of the CDockContainer class
+ inline CDockContainer::CDockContainer() : m_iCurrentPage(0), m_hTabIcon(0), m_nTabPressed(-1)
+ {
+ m_pContainerParent = this;
+ }
+
+ inline CDockContainer::~CDockContainer()
+ {
+ if (m_hTabIcon)
+ DestroyIcon(m_hTabIcon);
+ }
+
+ inline void CDockContainer::AddContainer(CDockContainer* pContainer)
+ {
+ assert(pContainer);
+
+ if (this == m_pContainerParent)
+ {
+ ContainerInfo ci = {0};
+ ci.pContainer = pContainer;
+ lstrcpy(ci.szTitle, pContainer->GetTabText());
+ ci.iImage = ImageList_AddIcon(GetImageList(), pContainer->GetTabIcon());
+ int iNewPage = (int)m_vContainerInfo.size();
+ m_vContainerInfo.push_back(ci);
+
+ if (m_hWnd)
+ {
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = ci.iImage;
+ tie.pszText = m_vContainerInfo[iNewPage].szTitle;
+ TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);
+
+ SetTabSize();
+ }
+
+ pContainer->m_pContainerParent = this;
+ if (pContainer->IsWindow())
+ {
+ // Set the parent container relationships
+ pContainer->GetViewPage().SetParent(this);
+ pContainer->GetViewPage().ShowWindow(SW_HIDE);
+ }
+ }
+ }
+
+ inline void CDockContainer::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE */)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ GetToolBar().AddButton(nID, bEnabled);
+ }
+
+ inline CDockContainer* CDockContainer::GetContainerFromIndex(UINT nPage)
+ {
+ CDockContainer* pContainer = NULL;
+ if (nPage < m_vContainerInfo.size())
+ pContainer = (CDockContainer*)m_vContainerInfo[nPage].pContainer;
+
+ return pContainer;
+ }
+
+ inline CWnd* CDockContainer::GetActiveView() const
+ // Returns a pointer to the active view window, or NULL if there is no active veiw.
+ {
+ CWnd* pWnd = NULL;
+ if (m_pContainerParent->m_vContainerInfo.size() > 0)
+ {
+ CDockContainer* pActiveContainer = m_pContainerParent->m_vContainerInfo[m_pContainerParent->m_iCurrentPage].pContainer;
+ if (pActiveContainer->GetViewPage().GetView()->IsWindow())
+ pWnd = pActiveContainer->GetViewPage().GetView();
+ }
+
+ return pWnd;
+ }
+
+ inline CDockContainer* CDockContainer::GetContainerFromView(CWnd* pView) const
+ {
+ assert(pView);
+
+ std::vector::iterator iter;
+ CDockContainer* pViewContainer = 0;
+ for (iter = GetAllContainers().begin(); iter != GetAllContainers().end(); ++iter)
+ {
+ CDockContainer* pContainer = (*iter).pContainer;
+ if (pContainer->GetView() == pView)
+ pViewContainer = pContainer;
+ }
+
+ return pViewContainer;
+ }
+
+ inline int CDockContainer::GetContainerIndex(CDockContainer* pContainer)
+ {
+ assert(pContainer);
+ int iReturn = -1;
+
+ for (int i = 0; i < (int)m_pContainerParent->m_vContainerInfo.size(); ++i)
+ {
+ if (m_pContainerParent->m_vContainerInfo[i].pContainer == pContainer)
+ iReturn = i;
+ }
+
+ return iReturn;
+ }
+
+ inline SIZE CDockContainer::GetMaxTabTextSize()
+ {
+ CSize Size;
+
+ // Allocate an iterator for the ContainerInfo vector
+ std::vector::iterator iter;
+
+ for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
+ {
+ CSize TempSize;
+ CClientDC dc(this);
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ dc.CreateFontIndirect(&info.lfStatusFont);
+ TempSize = dc.GetTextExtentPoint32(iter->szTitle, lstrlen(iter->szTitle));
+ if (TempSize.cx > Size.cx)
+ Size = TempSize;
+ }
+
+ return Size;
+ }
+
+ inline void CDockContainer::SetupToolBar()
+ {
+ // Use this function to set the Resource IDs for the toolbar(s).
+
+/* // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( IDM_FILE_NEW );
+ AddToolBarButton( IDM_FILE_OPEN );
+ AddToolBarButton( IDM_FILE_SAVE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_EDIT_CUT );
+ AddToolBarButton( IDM_EDIT_COPY );
+ AddToolBarButton( IDM_EDIT_PASTE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_FILE_PRINT );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_HELP_ABOUT );
+*/
+ }
+
+ inline void CDockContainer::OnCreate()
+ {
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+
+ ContainerInfo ci = {0};
+ ci.pContainer = this;
+ lstrcpy(ci.szTitle, GetTabText());
+ ci.iImage = ImageList_AddIcon(GetImageList(), GetTabIcon());
+ m_vContainerInfo.push_back(ci);
+
+ // Create the page window
+ GetViewPage().Create(this);
+
+ // Create the toolbar
+ GetToolBar().Create(&GetViewPage());
+ DWORD style = (DWORD)GetToolBar().GetWindowLongPtr(GWL_STYLE);
+ style |= CCS_NODIVIDER ;
+ GetToolBar().SetWindowLongPtr(GWL_STYLE, style);
+ SetupToolBar();
+ if (GetToolBar().GetToolBarData().size() > 0)
+ {
+ // Set the toolbar images
+ // A mask of 192,192,192 is compatible with AddBitmap (for Win95)
+ if (!GetToolBar().SendMessage(TB_GETIMAGELIST, 0L, 0L))
+ GetToolBar().SetImages(RGB(192,192,192), IDW_MAIN, 0, 0);
+
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+ }
+ else
+ GetToolBar().Destroy();
+
+ SetFixedWidth(TRUE);
+ SetOwnerDraw(TRUE);
+
+ // Add tabs for each container.
+ for (int i = 0; i < (int)m_vContainerInfo.size(); ++i)
+ {
+ // Add tabs for each view.
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = i;
+ tie.pszText = m_vContainerInfo[i].szTitle;
+ TabCtrl_InsertItem(m_hWnd, i, &tie);
+ }
+ }
+
+ inline void CDockContainer::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnLButtonDown
+
+ UNREFERENCED_PARAMETER(wParam);
+
+ CPoint pt((DWORD)lParam);
+ TCHITTESTINFO info = {0};
+ info.pt = pt;
+ m_nTabPressed = HitTest(info);
+ }
+
+ inline void CDockContainer::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnLButtonUp and takes no action
+
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+ }
+
+ inline void CDockContainer::OnMouseLeave(WPARAM wParam, LPARAM lParam)
+ {
+ // Overrides CTab::OnMouseLeave
+
+ if (IsLeftButtonDown() && (m_nTabPressed >= 0))
+ {
+ CDocker* pDock = (CDocker*)FromHandle(::GetParent(GetParent()->GetHwnd()));
+ if (dynamic_cast(pDock))
+ {
+ CDockContainer* pContainer = GetContainerFromIndex(m_iCurrentPage);
+ pDock->UndockContainer(pContainer, GetCursorPos(), TRUE);
+ }
+ }
+
+ m_nTabPressed = -1;
+ CTab::OnMouseLeave(wParam, lParam);
+ }
+
+ inline LRESULT CDockContainer::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGE:
+ {
+ // Display the newly selected tab page
+ int nPage = GetCurSel();
+ SelectPage(nPage);
+ }
+ break;
+ }
+
+ return 0L;
+ }
+
+ inline void CDockContainer::PreCreate(CREATESTRUCT &cs)
+ {
+ // For Tabs on the bottom, add the TCS_BOTTOM style
+ CTab::PreCreate(cs);
+ cs.style |= TCS_BOTTOM;
+ }
+
+ inline void CDockContainer::RecalcLayout()
+ {
+ if (GetContainerParent() == this)
+ {
+ // Set the tab sizes
+ SetTabSize();
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+ CDockContainer* pContainer = m_vContainerInfo[m_iCurrentPage].pContainer;
+ pContainer->GetViewPage().SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ }
+ }
+
+ inline void CDockContainer::RemoveContainer(CDockContainer* pWnd)
+ {
+ assert(pWnd);
+
+ // Remove the tab
+ int iTab = GetContainerIndex(pWnd);
+ if (iTab > 0)
+ {
+ // DeleteItem(iTab);
+ TabCtrl_DeleteItem(m_hWnd, iTab);
+ }
+
+ // Remove the ContainerInfo entry
+ std::vector::iterator iter;
+ int iImage = -1;
+ for (iter = m_vContainerInfo.begin(); iter != m_vContainerInfo.end(); ++iter)
+ {
+ if (iter->pContainer == pWnd)
+ {
+ iImage = (*iter).iImage;
+ if (iImage >= 0)
+ TabCtrl_RemoveImage(m_hWnd, iImage);
+
+ m_vContainerInfo.erase(iter);
+ break;
+ }
+ }
+
+ // Set the parent container relationships
+ pWnd->GetViewPage().SetParent(pWnd);
+ pWnd->m_pContainerParent = pWnd;
+
+ // Display the first page
+ m_iCurrentPage = 0;
+ if (IsWindow())
+ SelectPage(0);
+ }
+
+ inline void CDockContainer::SelectPage(int nPage)
+ {
+ if (this != m_pContainerParent)
+ m_pContainerParent->SelectPage(nPage);
+ else
+ {
+ if ((nPage >= 0) && (nPage < (int)m_vContainerInfo.size() ))
+ {
+ if (GetCurSel() != nPage)
+ SetCurSel(nPage);
+
+ // Create the new container window if required
+ if (!m_vContainerInfo[nPage].pContainer->IsWindow())
+ {
+ CDockContainer* pContainer = m_vContainerInfo[nPage].pContainer;
+ pContainer->Create(GetParent());
+ pContainer->GetViewPage().SetParent(this);
+ }
+
+ // Determine the size of the tab page's view area
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+
+ // Swap the pages over
+ CDockContainer* pOldContainer = m_vContainerInfo[m_iCurrentPage].pContainer;
+ CDockContainer* pNewContainer = m_vContainerInfo[nPage].pContainer;
+ pOldContainer->GetViewPage().ShowWindow(SW_HIDE);
+ pNewContainer->GetViewPage().SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ pNewContainer->GetViewPage().GetView()->SetFocus();
+
+ // Adjust the docking caption
+ CDocker* pDock = (CDocker*)FromHandle(::GetParent(::GetParent(m_hWnd)));
+ if (dynamic_cast(pDock))
+ {
+ pDock->SetCaption(pNewContainer->GetDockCaption().c_str());
+ pDock->RedrawWindow();
+ }
+
+ m_iCurrentPage = nPage;
+ }
+ }
+ }
+
+ inline void CDockContainer::SetActiveContainer(CDockContainer* pContainer)
+ {
+ int nPage = GetContainerIndex(pContainer);
+ assert (0 <= nPage);
+ SelectPage(nPage);
+ }
+
+ inline void CDockContainer::SetTabIcon(UINT nID_Icon)
+ {
+ HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID_Icon), IMAGE_ICON, 0, 0, LR_SHARED);
+ SetTabIcon(hIcon);
+ }
+
+ inline void CDockContainer::SetTabSize()
+ {
+ CRect rc = GetClientRect();
+ AdjustRect(FALSE, &rc);
+ if (rc.Width() < 0 )
+ rc.SetRectEmpty();
+
+ int nItemWidth = MIN(25 + GetMaxTabTextSize().cx, (rc.Width()-2)/(int)m_vContainerInfo.size());
+ int nItemHeight = MAX(20, GetTextHeight() + 5);
+ SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, nItemHeight));
+ }
+
+ inline void CDockContainer::SetTabText(UINT nTab, LPCTSTR szText)
+ {
+ CDockContainer* pContainer = GetContainerParent()->GetContainerFromIndex(nTab);
+ pContainer->SetTabText(szText);
+
+ CTab::SetTabText(nTab, szText);
+ }
+
+ inline void CDockContainer::SetView(CWnd& Wnd)
+ {
+ GetViewPage().SetView(Wnd);
+ }
+
+ inline LRESULT CDockContainer::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ return 0;
+
+ // The following are called in CTab::WndProcDefault
+ // case WM_LBUTTONDOWN:
+ // OnLButtonDown(wParam, lParam);
+ // break;
+ // case WM_LBUTTONUP:
+ // OnLButtonUp(wParam, lParam);
+ // break;
+ // case WM_MOUSELEAVE:
+ // OnMouseLeave(wParam, lParam);
+ // break;
+
+ case WM_SETFOCUS:
+ {
+ // Pass focus on to the current view
+ GetActiveView()->SetFocus();
+ }
+ break;
+ }
+
+ // pass unhandled messages on to CTab for processing
+ return CTab::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ ///////////////////////////////////////////
+ // Declaration of the nested CViewPage class
+ inline BOOL CDockContainer::CViewPage::OnCommand(WPARAM wParam, LPARAM lParam)
+ {
+ CDockContainer* pContainer = (CDockContainer*)GetParent();
+ BOOL bResult = FALSE;
+ if (pContainer && pContainer->GetActiveContainer())
+ bResult = (BOOL)pContainer->GetActiveContainer()->SendMessage(WM_COMMAND, wParam, lParam);
+
+ return bResult;
+ }
+
+ inline void CDockContainer::CViewPage::OnCreate()
+ {
+ if (m_pView)
+ m_pView->Create(this);
+ }
+
+ inline LRESULT CDockContainer::CViewPage::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+
+ // Display tooltips for the toolbar
+ case TTN_GETDISPINFO:
+ {
+ int iIndex = GetToolBar().HitTest();
+ LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
+ if (iIndex >= 0)
+ {
+ int nID = GetToolBar().GetCommandID(iIndex);
+ if (nID > 0)
+ {
+ m_tsTooltip = LoadString(nID);
+ lpDispInfo->lpszText = (LPTSTR)m_tsTooltip.c_str();
+ }
+ else
+ m_tsTooltip = _T("");
+ }
+ }
+ break;
+ } // switch LPNMHDR
+
+ return 0L;
+ }
+
+ inline void CDockContainer::CViewPage::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = _T("Win32++ TabPage");
+ wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
+ }
+
+ inline void CDockContainer::CViewPage::RecalcLayout()
+ {
+ CRect rc = GetClientRect();
+ if (GetToolBar().IsWindow())
+ {
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+ CRect rcToolBar = m_ToolBar.GetClientRect();
+ rc.top += rcToolBar.Height();
+ }
+
+ GetView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+
+ inline void CDockContainer::CViewPage::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ if (!m_pView->IsWindow())
+ {
+ // The container is already created, so create and position the new view too
+ GetView()->Create(this);
+ }
+
+ RecalcLayout();
+ }
+ }
+
+ inline LRESULT CDockContainer::CViewPage::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_SIZE:
+ RecalcLayout();
+ break;
+ case WM_NOTIFY:
+ switch (((LPNMHDR)lParam)->code)
+ {
+ // Send the focus change notifications to the grandparent
+ case NM_KILLFOCUS:
+ case NM_SETFOCUS:
+ case UWM_FRAMELOSTFOCUS:
+ ::SendMessage(::GetParent(::GetParent(m_hWnd)), WM_NOTIFY, wParam, lParam);
+ break;
+ }
+
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_DOCKING_H_
+
diff --git a/external/win32cpp/include/file.h b/external/win32cpp/include/file.h
new file mode 100644
index 0000000..4316dc9
--- /dev/null
+++ b/external/win32cpp/include/file.h
@@ -0,0 +1,392 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_FILE_H_
+#define _WIN32XX_FILE_H_
+
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ class CFile
+ {
+ public:
+ CFile();
+ CFile(HANDLE hFile);
+ CFile(LPCTSTR pszFileName, UINT nOpenFlags);
+ ~CFile();
+ operator HANDLE() const;
+
+ BOOL Close();
+ BOOL Flush();
+ HANDLE GetHandle() const;
+ ULONGLONG GetLength() const;
+ const CString& GetFileName() const;
+ const CString& GetFilePath() const;
+ const CString& GetFileTitle() const;
+ ULONGLONG GetPosition() const;
+ BOOL LockRange(ULONGLONG Pos, ULONGLONG Count);
+ BOOL Open(LPCTSTR pszFileName, UINT nOpenFlags);
+ CString OpenFileDialog(LPCTSTR pszFilePathName = NULL,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR pszFilter = NULL,
+ CWnd* pOwnerWnd = NULL);
+ UINT Read(void* pBuf, UINT nCount);
+ static BOOL Remove(LPCTSTR pszFileName);
+ static BOOL Rename(LPCTSTR pszOldName, LPCTSTR pszNewName);
+ CString SaveFileDialog(LPCTSTR pszFilePathName = NULL,
+ DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR pszFilter = NULL,
+ LPCTSTR pszDefExt = NULL, CWnd* pOwnerWnd = NULL);
+ ULONGLONG Seek(LONGLONG lOff, UINT nFrom);
+ void SeekToBegin();
+ ULONGLONG SeekToEnd();
+ void SetFilePath(LPCTSTR pszNewName);
+ BOOL SetLength(ULONGLONG NewLen);
+ BOOL UnlockRange(ULONGLONG Pos, ULONGLONG Count);
+ BOOL Write(const void* pBuf, UINT nCount);
+
+ private:
+ CFile(const CFile&); // Disable copy construction
+ CFile& operator = (const CFile&); // Disable assignment operator
+ CString m_FileName;
+ CString m_FilePath;
+ CString m_FileTitle;
+ HANDLE m_hFile;
+ };
+
+}
+
+
+
+namespace Win32xx
+{
+ inline CFile::CFile() : m_hFile(0)
+ {
+ }
+
+ inline CFile::CFile(HANDLE hFile) : m_hFile(hFile)
+ {
+ }
+
+ inline CFile::CFile(LPCTSTR pszFileName, UINT nOpenFlags) : m_hFile(0)
+ {
+ assert(pszFileName);
+ Open(pszFileName, nOpenFlags);
+ assert(m_hFile);
+ }
+
+ inline CFile::~CFile()
+ {
+ Close();
+ }
+
+ inline CFile::operator HANDLE() const
+ {
+ return m_hFile;
+ }
+
+ inline BOOL CFile::Close()
+ // Closes the file associated with this object. Closed file can no longer be read or written to.
+ {
+ BOOL bResult = TRUE;
+ if (m_hFile)
+ bResult = CloseHandle(m_hFile);
+
+ m_hFile = 0;
+ return bResult;
+ }
+
+ inline BOOL CFile::Flush()
+ // Causes any remaining data in the file buffer to be written to the file.
+ {
+ assert(m_hFile);
+ return FlushFileBuffers(m_hFile);
+ }
+
+ inline HANDLE CFile::GetHandle() const
+ {
+ return m_hFile;
+ }
+
+ inline ULONGLONG CFile::GetLength( ) const
+ // Returns the length of the file in bytes.
+ {
+ assert(m_hFile);
+
+ LONG High = 0;
+ DWORD LowPos = SetFilePointer(m_hFile, 0, &High, FILE_END);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline const CString& CFile::GetFileName() const
+ // Returns the filename of the file associated with this object.
+ {
+ return (const CString&)m_FileName;
+ }
+
+ inline const CString& CFile::GetFilePath() const
+ // Returns the full filename including the directory of the file associated with this object.
+ {
+ return (const CString&)m_FilePath;
+ }
+
+ inline const CString& CFile::GetFileTitle() const
+ // Returns the filename of the file associated with this object, excluding the path and the file extension
+ {
+ return (const CString&)m_FileTitle;
+ }
+
+ inline ULONGLONG CFile::GetPosition() const
+ // Returns the current value of the file pointer, which can be used in subsequent calls to Seek.
+ {
+ assert(m_hFile);
+ LONG High = 0;
+ DWORD LowPos = SetFilePointer(m_hFile, 0, &High, FILE_CURRENT);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline BOOL CFile::LockRange(ULONGLONG Pos, ULONGLONG Count)
+ // Locks a range of bytes in and open file.
+ {
+ assert(m_hFile);
+
+ DWORD dwPosHigh = (DWORD)(Pos >> 32);
+ DWORD dwPosLow = (DWORD)(Pos & 0xFFFFFFFF);
+ DWORD dwCountHigh = (DWORD)(Count >> 32);
+ DWORD dwCountLow = (DWORD)(Count & 0xFFFFFFFF);
+
+ return ::LockFile(m_hFile, dwPosLow, dwPosHigh, dwCountLow, dwCountHigh);
+ }
+
+ inline BOOL CFile::Open(LPCTSTR pszFileName, UINT nOpenFlags)
+ // Prepares a file to be written to or read from.
+ {
+ if (m_hFile) Close();
+
+ m_hFile = ::CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, nOpenFlags, FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (INVALID_HANDLE_VALUE == m_hFile)
+ {
+ TRACE(_T("Failed\n"));
+ m_hFile = 0;
+ }
+
+ if (m_hFile)
+ {
+ SetFilePath(pszFileName);
+ }
+
+ return (m_hFile != 0);
+ }
+
+ inline CString CFile::OpenFileDialog(LPCTSTR pszFilePathName, DWORD dwFlags, LPCTSTR pszFilter, CWnd* pOwnerWnd)
+ // Displays the file open dialog.
+ // Returns a CString containing either the selected file name or an empty CString.
+ {
+ CString str;
+ if (pszFilePathName)
+ str = pszFilePathName;
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+
+#if defined OPENFILENAME_SIZE_VERSION_400
+ if (GetWinVersion() < 2500)
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#endif
+
+ ofn.hwndOwner = pOwnerWnd? pOwnerWnd->GetHwnd() : NULL;
+ ofn.hInstance = GetApp()->GetInstanceHandle();
+ ofn.lpstrFilter = pszFilter;
+ ofn.lpstrTitle = _T("Open File");
+ ofn.Flags = dwFlags;
+ ofn.nMaxFile = _MAX_PATH;
+
+ ofn.lpstrFile = (LPTSTR)str.GetBuffer(_MAX_PATH);
+ ::GetOpenFileName(&ofn);
+ str.ReleaseBuffer();
+
+ return str;
+ }
+
+ inline UINT CFile::Read(void* pBuf, UINT nCount)
+ // Reads from the file, storing the contents in the specified buffer.
+ {
+ assert(m_hFile);
+ DWORD dwRead = 0;
+
+ if (!::ReadFile(m_hFile, pBuf, nCount, &dwRead, NULL))
+ dwRead = 0;
+
+ return dwRead;
+ }
+
+ inline BOOL CFile::Rename(LPCTSTR pszOldName, LPCTSTR pszNewName)
+ // Renames the specified file.
+ {
+ return ::MoveFile(pszOldName, pszNewName);
+ }
+
+ inline BOOL CFile::Remove(LPCTSTR pszFileName)
+ // Deletes the specified file.
+ {
+ return ::DeleteFile(pszFileName);
+ }
+
+ inline CString CFile::SaveFileDialog(LPCTSTR pszFilePathName, DWORD dwFlags, LPCTSTR pszFilter, LPCTSTR pszDefExt, CWnd* pOwnerWnd)
+ // Displays the SaveFileDialog.
+ // Returns a CString containing either the selected file name or an empty CString
+ {
+ CString str;
+ if (pszFilePathName)
+ str = pszFilePathName;
+
+ OPENFILENAME ofn = {0};
+ ofn.lStructSize = sizeof(OPENFILENAME);
+
+#if defined OPENFILENAME_SIZE_VERSION_400
+ if (GetWinVersion() < 2500)
+ ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
+#endif
+
+ ofn.hwndOwner = pOwnerWnd? pOwnerWnd->GetHwnd() : NULL;
+ ofn.hInstance = GetApp()->GetInstanceHandle();
+ ofn.lpstrFilter = pszFilter;
+ ofn.lpstrFile = (LPTSTR)pszFilePathName;
+ ofn.lpstrFileTitle = (LPTSTR)pszFilePathName;
+ ofn.lpstrDefExt = pszDefExt;
+ ofn.nMaxFile = lstrlen(pszFilePathName);
+ ofn.lpstrTitle = _T("Save File");
+ ofn.Flags = dwFlags;
+ ofn.nMaxFile = _MAX_PATH;
+ ofn.lpstrFile = (LPTSTR)str.GetBuffer(_MAX_PATH);
+ ::GetSaveFileName(&ofn);
+ str.ReleaseBuffer();
+
+ return str;
+ }
+
+ inline ULONGLONG CFile::Seek(LONGLONG lOff, UINT nFrom)
+ // Positions the current file pointer.
+ // Permitted values for nFrom are: FILE_BEGIN, FILE_CURRENT, or FILE_END.
+ {
+ assert(m_hFile);
+ assert(nFrom == FILE_BEGIN || nFrom == FILE_CURRENT || nFrom == FILE_END);
+
+ LONG High = LONG(lOff >> 32);
+ LONG Low = (LONG)(lOff & 0xFFFFFFFF);
+
+ DWORD LowPos = SetFilePointer(m_hFile, Low, &High, nFrom);
+
+ ULONGLONG Result = ((ULONGLONG)High << 32) + LowPos;
+ return Result;
+ }
+
+ inline void CFile::SeekToBegin()
+ // Sets the current file pointer to the beginning of the file.
+ {
+ assert(m_hFile);
+ Seek(0, FILE_BEGIN);
+ }
+
+ inline ULONGLONG CFile::SeekToEnd()
+ // Sets the current file pointer to the end of the file.
+ {
+ assert(m_hFile);
+ return Seek(0, FILE_END);
+ }
+
+ inline void CFile::SetFilePath(LPCTSTR pszFileName)
+ // Specifies the full file name, including its path
+ {
+ TCHAR* pFileName = NULL;
+ int nBuffSize = ::GetFullPathName(pszFileName, 0, 0, 0);
+ if (nBuffSize > 0)
+ {
+ TCHAR* pBuff = m_FilePath.GetBuffer(nBuffSize);
+ ::GetFullPathName(pszFileName, nBuffSize, pBuff, &pFileName);
+ m_FilePath.ReleaseBuffer();
+ m_FileName = pFileName;
+ int nPos = m_FileName.ReverseFind(_T("."));
+ if (nPos >= 0)
+ m_FileTitle = m_FileName.Left(nPos);
+ }
+ }
+
+ inline BOOL CFile::SetLength(ULONGLONG NewLen)
+ // Changes the length of the file to the specified value.
+ {
+ assert(m_hFile);
+
+ Seek(NewLen, FILE_BEGIN);
+ return ::SetEndOfFile(m_hFile);
+ }
+
+ inline BOOL CFile::UnlockRange(ULONGLONG Pos, ULONGLONG Count)
+ // Unlocks a range of bytes in an open file.
+ {
+ assert(m_hFile);
+
+ DWORD dwPosHigh = (DWORD)(Pos >> 32);
+ DWORD dwPosLow = (DWORD)(Pos & 0xFFFFFFFF);
+ DWORD dwCountHigh = (DWORD)(Count >> 32);
+ DWORD dwCountLow = (DWORD)(Count & 0xFFFFFFFF);
+
+ return ::UnlockFile(m_hFile, dwPosLow, dwPosHigh, dwCountLow, dwCountHigh);
+ }
+
+ inline BOOL CFile::Write(const void* pBuf, UINT nCount)
+ // Writes the specified buffer to the file.
+ {
+ assert(m_hFile);
+ DWORD dwWritten = 0;
+ BOOL bResult = ::WriteFile(m_hFile, pBuf, nCount, &dwWritten, NULL);
+ if (dwWritten != nCount)
+ bResult = FALSE;
+
+ return bResult;
+ }
+
+
+} // namespace Win32xx
+
+#endif
diff --git a/external/win32cpp/include/frame.h b/external/win32cpp/include/frame.h
new file mode 100644
index 0000000..1f439fd
--- /dev/null
+++ b/external/win32cpp/include/frame.h
@@ -0,0 +1,3303 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// frame.h
+// Declaration of the CFrame and CMenuBar classes
+
+// The classes declared in this file support SDI (Single Document Interface)
+// frames on Win32/Win64 operating systems (not Windows CE). For Windows CE,
+// use wceframe.h instead. SDI frames are a simple frame which supports a
+// single view window. Refer to mdi.h for frames that support several
+// child windows.
+
+// CFrame also includes each of the following classes as members:
+// * CReBar for managing the frame's rebar control.
+// * CMenuBar for managing the menu inside the rebar.
+// * CToolBar for managing the frame's toolbar.
+// * CStatusBar for managing the frame's status bar.
+// In each case these members are exposed by a GetXXX function, allowing
+// them to be accessed or sent messages.
+
+// CFrame is responsible for creating a "frame" window. This window has a
+// menu and and several child windows, including a toolbar (usualy hosted
+// within a rebar), a status bar, and a view positioned over the frame
+// window's non-client area. The "view" window is a seperate CWnd object
+// assigned to the frame with the SetView function.
+
+// When compiling an application with these classes, it will need to be linked
+// with Comctl32.lib.
+
+// To create a SDI frame application, inherit a CMainFrame class from CFrame.
+// Use the Frame sample application as the starting point for your own frame
+// applications.
+// Refer to the Notepad and Scribble samples for examples on how to use these
+// classes to create a frame application.
+
+
+#ifndef _WIN32XX_FRAME_H_
+#define _WIN32XX_FRAME_H_
+
+#include "wincore.h"
+#include "dialog.h"
+#include "gdi.h"
+#include "statusbar.h"
+#include "toolbar.h"
+#include "rebar.h"
+#include "default_resource.h"
+
+#ifndef RBN_MINMAX
+ #define RBN_MINMAX (RBN_FIRST - 21)
+#endif
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////////////
+ // Declarations for structures for themes
+ //
+ struct MenuTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrHot1; // Colour 1 for top menu. Color of selected menu item
+ COLORREF clrHot2; // Colour 2 for top menu. Color of checkbox
+ COLORREF clrPressed1; // Colour 1 for pressed top menu and side bar
+ COLORREF clrPressed2; // Colour 2 for pressed top menu and side bar
+ COLORREF clrOutline; // Colour for border outline
+ };
+
+
+ // Forward declaration of CFrame. Its defined later.
+ class CFrame;
+
+
+ ////////////////////////////////////
+ // Declaration of the CMenuBar class
+ //
+ class CMenuBar : public CToolBar
+ {
+ friend class CFrame;
+
+ public:
+ CMenuBar();
+ virtual ~CMenuBar();
+ virtual void SetMenu(HMENU hMenu);
+ virtual void SetMenuBarTheme(MenuTheme& Theme);
+
+ HMENU GetMenu() const {return m_hTopMenu;}
+ MenuTheme& GetMenuBarTheme() {return m_ThemeMenu;}
+
+ protected:
+ //Overridables
+ virtual void OnCreate();
+ virtual LRESULT OnCustomDraw(NMHDR* pNMHDR);
+ virtual void OnKeyDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMenuChar(WPARAM wParam, LPARAM lParam);
+ virtual BOOL OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave();
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged();
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMenuBar(const CMenuBar&); // Disable copy construction
+ CMenuBar& operator = (const CMenuBar&); // Disable assignment operator
+ void DoAltKey(WORD KeyCode);
+ void DoPopupMenu();
+ void DrawAllMDIButtons(CDC& DrawDC);
+ void DrawMDIButton(CDC& DrawDC, int iButton, UINT uState);
+ void ExitMenu();
+ HWND GetActiveMDIChild();
+ void GrabFocus();
+ BOOL IsMDIChildMaxed() const;
+ BOOL IsMDIFrame() const;
+ void ReleaseFocus();
+ void SetHotItem(int nHot);
+ static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
+
+ enum MDIButtonType
+ {
+ MDI_MIN = 0,
+ MDI_RESTORE = 1,
+ MDI_CLOSE = 2,
+ };
+
+ BOOL m_bExitAfter; // Exit after Popup menu ends
+ BOOL m_bKeyMode; // keyboard navigation mode
+ BOOL m_bMenuActive; // popup menu active
+ BOOL m_bSelPopup; // a popup (cascade) menu is selected
+ HMENU m_hPopupMenu; // handle to the popup menu
+ HMENU m_hSelMenu; // handle to the casceded popup menu
+ HMENU m_hTopMenu; // handle to the top level menu
+ HWND m_hPrevFocus; // handle to window which had focus
+ CRect m_MDIRect[3]; // array of CRect for MDI buttons
+ int m_nHotItem; // hot item
+ int m_nMDIButton; // the MDI button (MDIButtonType) pressed
+ CPoint m_OldMousePos; // old Mouse position
+ MenuTheme m_ThemeMenu; // Theme structure
+ CFrame* m_pFrame; // Pointer to the frame
+
+ }; // class CMenuBar
+
+
+
+ //////////////////////////////////
+ // Declaration of the CFrame class
+ //
+ class CFrame : public CWnd
+ {
+ friend class CMenuBar;
+
+ struct ItemData
+ // Each Dropdown menu item has this data
+ {
+ HMENU hMenu;
+ UINT nPos;
+ UINT fType;
+ std::vector vItemText;
+ HMENU hSubMenu;
+
+ ItemData() : hMenu(0), nPos(0), fType(0), hSubMenu(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); }
+ LPTSTR GetItemText() {return &vItemText[0];}
+ };
+
+ typedef Shared_Ptr ItemDataPtr;
+
+ public:
+ CFrame();
+ virtual ~CFrame();
+
+ // Override these functions as required
+ virtual void AdjustFrameRect(RECT rcView) const;
+ virtual CRect GetViewRect() const;
+ virtual BOOL IsMDIFrame() const { return FALSE; }
+ virtual void SetStatusIndicators();
+ virtual void SetStatusText();
+ virtual void RecalcLayout();
+ virtual MenuTheme& GetMenuTheme() const { return (MenuTheme&) m_ThemeMenu; }
+ virtual ReBarTheme& GetReBarTheme() const { return (ReBarTheme&)GetReBar().GetReBarTheme(); }
+ virtual ToolBarTheme& GetToolBarTheme() const { return (ToolBarTheme&)GetToolBar().GetToolBarTheme(); }
+
+ // Virtual Attributes
+ // If you need to modify the default behaviour of the menubar, rebar,
+ // statusbar or toolbar, inherit from those classes, and override
+ // the following attribute functions.
+ virtual CMenuBar& GetMenuBar() const { return (CMenuBar&)m_MenuBar; }
+ virtual CReBar& GetReBar() const { return (CReBar&)m_ReBar; }
+ virtual CStatusBar& GetStatusBar() const { return (CStatusBar&)m_StatusBar; }
+ virtual CToolBar& GetToolBar() const { return (CToolBar&)m_ToolBar; }
+
+ // These functions aren't virtual, and shouldn't be overridden
+ HACCEL GetFrameAccel() const { return m_hAccel; }
+ CMenu& GetFrameMenu() const { return (CMenu&)m_Menu; }
+ std::vector GetMRUEntries() const { return m_vMRUEntries; }
+ tString GetRegistryKeyName() const { return m_tsKeyName; }
+ CWnd* GetView() const { return m_pView; }
+ tString GetMRUEntry(UINT nIndex);
+ void SetFrameMenu(INT ID_MENU);
+ void SetFrameMenu(HMENU hMenu);
+ void SetMenuTheme(MenuTheme& Theme);
+ void SetView(CWnd& wndView);
+ BOOL IsMenuBarUsed() const { return (GetMenuBar() != 0); }
+ BOOL IsReBarSupported() const { return (GetComCtlVersion() >= 470); }
+ BOOL IsReBarUsed() const { return (GetReBar() != 0); }
+
+ protected:
+ // Override these functions as required
+ virtual BOOL AddMenuIcon(int nID_MenuItem, HICON hIcon, int cx = 16, int cy = 16);
+ virtual UINT AddMenuIcons(const std::vector& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
+ virtual void AddMenuBarBand();
+ virtual void AddMRUEntry(LPCTSTR szMRUEntry);
+ virtual void AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID);
+ virtual void AddToolBarButton(UINT nID, BOOL bEnabled = TRUE, LPCTSTR szText = 0);
+ virtual void CreateToolBar();
+ virtual void DrawCheckmark(LPDRAWITEMSTRUCT pdis, CDC& DrawDC);
+ virtual void DrawMenuIcon(LPDRAWITEMSTRUCT pdis, CDC& DrawDC, BOOL bDisabled);
+ virtual void DrawMenuText(CDC& DrawDC, LPCTSTR ItemText, CRect& rc, COLORREF colorText);
+ virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem);
+ virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName);
+ virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0);
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnClose();
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual LRESULT OnDrawItem(WPARAM wParam, LPARAM lParam);
+ virtual void OnExitMenuLoop();
+ virtual void OnHelp();
+ virtual void OnInitMenuPopup(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnMeasureItem(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnMenuChar(WPARAM wParam, LPARAM lParam);
+ virtual void OnMenuSelect(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnSetFocus();
+ virtual void OnSysColorChange();
+ virtual LRESULT OnSysCommand(WPARAM wParam, LPARAM lParam);
+ virtual void OnTimer(WPARAM wParam);
+ virtual void OnViewStatusBar();
+ virtual void OnViewToolBar();
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void RemoveMRUEntry(LPCTSTR szMRUEntry);
+ virtual BOOL SaveRegistrySettings();
+ virtual void SetMenuBarBandSize();
+ virtual UINT SetMenuIcons(const std::vector& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID);
+ virtual void SetupToolBar();
+ virtual void SetTheme();
+ virtual void SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID);
+ virtual void ShowMenu(BOOL bShow);
+ virtual void ShowStatusBar(BOOL bShow);
+ virtual void ShowToolBar(BOOL bShow);
+ virtual void UpdateMRUMenu();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ enum Constants
+ {
+ ID_STATUS_TIMER = 1,
+ POST_TEXT_GAP = 16, // for owner draw menu item
+ };
+
+ tString m_tsStatusText; // TCHAR std::string for status text
+ BOOL m_bShowIndicatorStatus; // set to TRUE to see indicators in status bar
+ BOOL m_bShowMenuStatus; // set to TRUE to see menu and toolbar updates in status bar
+ BOOL m_bUseReBar; // set to TRUE if ReBars are to be used
+ BOOL m_bUseThemes; // set to TRUE if themes are to be used
+ BOOL m_bUpdateTheme; // set to TRUE to run SetThemes when theme changes
+ BOOL m_bUseToolBar; // set to TRUE if the toolbar is used
+ BOOL m_bUseCustomDraw; // set to TRUE to perform custom drawing on menu items
+ BOOL m_bShowStatusBar; // A flag to indicate if the StatusBar should be displayed
+ BOOL m_bShowToolBar; // A flag to indicate if the ToolBar should be displayed
+ MenuTheme m_ThemeMenu; // Theme structure for popup menus
+ HIMAGELIST m_himlMenu; // Imagelist of menu icons
+ HIMAGELIST m_himlMenuDis; // Imagelist of disabled menu icons
+
+ private:
+ CFrame(const CFrame&); // Disable copy construction
+ CFrame& operator = (const CFrame&); // Disable assignment operator
+ void LoadCommonControls();
+
+ std::vector m_vMenuItemData;// vector of ItemData pointers
+ std::vector m_vMenuIcons; // vector of menu icon resource IDs
+ std::vector m_vMRUEntries; // Vector of tStrings for MRU entires
+ CDialog m_AboutDialog; // Help about dialog
+ CMenuBar m_MenuBar; // CMenuBar object
+ CReBar m_ReBar; // CReBar object
+ CStatusBar m_StatusBar; // CStatusBar object
+ CToolBar m_ToolBar; // CToolBar object
+ CMenu m_Menu; // handle to the frame menu
+ HACCEL m_hAccel; // handle to the frame's accelerator table
+ CWnd* m_pView; // pointer to the View CWnd object
+ LPCTSTR m_OldStatus[3]; // Array of TCHAR pointers;
+ tString m_tsKeyName; // TCHAR std::string for Registry key name
+ tString m_tsTooltip; // TCHAR std::string for tool tips
+ UINT m_nMaxMRU; // maximum number of MRU entries
+ CRect m_rcPosition; // CRect of the starting window position
+ HWND m_hOldFocus; // The window which had focus prior to the app'a deactivation
+ int m_nOldID; // The previous ToolBar ID displayed in the statusbar
+
+ }; // class CFrame
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////
+ // Definitions for the CMenuBar class
+ //
+ inline CMenuBar::CMenuBar()
+ {
+ m_bExitAfter = FALSE;
+ m_hTopMenu = NULL;
+ m_nHotItem = -1;
+ m_bSelPopup = FALSE;
+ m_hSelMenu = NULL;
+ m_bMenuActive = FALSE;
+ m_bKeyMode = FALSE;
+ m_hPrevFocus = NULL;
+ m_nMDIButton = 0;
+ m_hPopupMenu = 0;
+
+ ZeroMemory(&m_ThemeMenu, sizeof(MenuTheme));
+ }
+
+ inline CMenuBar::~CMenuBar()
+ {
+ }
+
+ inline void CMenuBar::DoAltKey(WORD KeyCode)
+ {
+ //Handle key pressed with Alt held down
+ UINT ID;
+ if (SendMessage(TB_MAPACCELERATOR, KeyCode, (LPARAM) &ID))
+ {
+ GrabFocus();
+ m_bKeyMode = TRUE;
+ SetHotItem(ID);
+ m_bMenuActive = TRUE;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ else
+ ::MessageBeep(MB_OK);
+ }
+
+ inline void CMenuBar::DoPopupMenu()
+ {
+ if (m_bKeyMode)
+ // Simulate a down arrow key press
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+
+ m_bKeyMode = FALSE;
+ m_bExitAfter = FALSE;
+ m_OldMousePos = GetCursorPos();
+
+ HWND hMaxMDIChild = NULL;
+ if (IsMDIChildMaxed())
+ hMaxMDIChild = GetActiveMDIChild();
+
+ // Load the submenu
+ int nMaxedOffset = IsMDIChildMaxed()? 1:0;
+ m_hPopupMenu = ::GetSubMenu(m_hTopMenu, m_nHotItem - nMaxedOffset);
+ if (IsMDIChildMaxed() && (0 == m_nHotItem) )
+ m_hPopupMenu = ::GetSystemMenu(hMaxMDIChild, FALSE);
+
+ // Retrieve the bounding rectangle for the toolbar button
+ CRect rc = GetItemRect(m_nHotItem);
+
+ // convert rectangle to desktop coordinates
+ ClientToScreen(rc);
+
+ // Position popup above toolbar if it won't fit below
+ TPMPARAMS tpm;
+ tpm.cbSize = sizeof(TPMPARAMS);
+ tpm.rcExclude = rc;
+
+ // Set the hot button
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(TRUE, 0));
+
+ m_bSelPopup = FALSE;
+ m_hSelMenu = NULL;
+ m_bMenuActive = TRUE;
+
+ // We hook mouse input to process mouse and keyboard input during
+ // the popup menu. Messages are sent to StaticMsgHook.
+
+ // Remove any remaining hook first
+ TLSData* pTLSData = (TLSData*)::TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->pMenuBar = this;
+ if (pTLSData->hHook != NULL)
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+
+ // Hook messages about to be processed by the shortcut menu
+ pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
+
+ // Display the shortcut menu
+ BOOL bRightToLeft = FALSE;
+
+#if defined(WINVER) && defined (WS_EX_LAYOUTRTL) && (WINVER >= 0x0500)
+ bRightToLeft = ((GetAncestor()->GetWindowLongPtr(GWL_EXSTYLE)) & WS_EX_LAYOUTRTL);
+#endif
+
+ int xPos = bRightToLeft? rc.right : rc.left;
+ UINT nID = ::TrackPopupMenuEx(m_hPopupMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL,
+ xPos, rc.bottom, m_hWnd, &tpm);
+
+ // We get here once the TrackPopupMenuEx has ended
+ m_bMenuActive = FALSE;
+
+ // Remove the message hook
+ ::UnhookWindowsHookEx(pTLSData->hHook);
+ pTLSData->hHook = NULL;
+
+ // Process MDI Child system menu
+ if (IsMDIChildMaxed())
+ {
+ if (::GetSystemMenu(hMaxMDIChild, FALSE) == m_hPopupMenu )
+ {
+ if (nID)
+ ::SendMessage(hMaxMDIChild, WM_SYSCOMMAND, nID, 0L);
+ }
+ }
+
+ // Resestablish Focus
+ if (m_bKeyMode)
+ GrabFocus();
+ }
+
+ inline void CMenuBar::DrawAllMDIButtons(CDC& DrawDC)
+ {
+ if (!IsMDIFrame())
+ return;
+
+ if (IsMDIChildMaxed())
+ {
+ int cx = GetSystemMetrics(SM_CXSMICON);
+ int cy = GetSystemMetrics(SM_CYSMICON);
+ CRect rc = GetClientRect();
+ int gap = 4;
+ rc.right -= gap;
+
+ // Assign values to each element of the CRect array
+ for (int i = 0 ; i < 3 ; ++i)
+ {
+ int left = rc.right - (i+1)*cx - gap*(i+1);
+ int top = rc.bottom/2 - cy/2;
+ int right = rc.right - i*cx - gap*(i+1);
+ int bottom = rc.bottom/2 + cy/2;
+ ::SetRect(&m_MDIRect[2 - i], left, top, right, bottom);
+ }
+
+ // Hide the MDI button if it won't fit
+ for (int k = 0 ; k <= 2 ; ++k)
+ {
+
+ if (m_MDIRect[k].left < GetMaxSize().cx)
+ {
+ ::SetRectEmpty(&m_MDIRect[k]);
+ }
+ }
+
+ DrawMDIButton(DrawDC, MDI_MIN, 0);
+ DrawMDIButton(DrawDC, MDI_RESTORE, 0);
+ DrawMDIButton(DrawDC, MDI_CLOSE, 0);
+ }
+ }
+
+ inline void CMenuBar::DrawMDIButton(CDC& DrawDC, int iButton, UINT uState)
+ {
+ if (!IsRectEmpty(&m_MDIRect[iButton]))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ // Draw a grey outline
+ DrawDC.CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNFACE));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+ break;
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].bottom);
+ DrawDC.LineTo(m_MDIRect[iButton].right, m_MDIRect[iButton].top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].top);
+ DrawDC.LineTo(m_MDIRect[iButton].left, m_MDIRect[iButton].bottom);
+ }
+ break;
+ }
+
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+
+ switch (iButton)
+ {
+ case MDI_MIN:
+ // Manually Draw Minimise button
+ DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -4);
+ DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 4);
+
+ DrawDC.MoveTo(m_MDIRect[0].left + 4, m_MDIRect[0].bottom -5);
+ DrawDC.LineTo(m_MDIRect[0].right - 4, m_MDIRect[0].bottom - 5);
+ break;
+ case MDI_RESTORE:
+ // Manually Draw Restore Button
+ DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].bottom -4);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -4);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 7);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 3, m_MDIRect[1].top + 8);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].top + 8);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 7);
+ DrawDC.LineTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 4);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 4);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].bottom -6);
+ DrawDC.LineTo(m_MDIRect[1].right - 6, m_MDIRect[1].bottom -6);
+
+ DrawDC.MoveTo(m_MDIRect[1].left + 5, m_MDIRect[1].top + 5);
+ DrawDC.LineTo(m_MDIRect[1].right - 4, m_MDIRect[1].top + 5);
+ break;
+ case MDI_CLOSE:
+ // Manually Draw Close Button
+ DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].left + 5, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].right - 4, m_MDIRect[2].bottom -4);
+
+ DrawDC.MoveTo(m_MDIRect[2].left + 4, m_MDIRect[2].top +6);
+ DrawDC.LineTo(m_MDIRect[2].right - 5, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -5, m_MDIRect[2].top +6);
+ DrawDC.LineTo(m_MDIRect[2].left + 4, m_MDIRect[2].bottom -3);
+
+ DrawDC.MoveTo(m_MDIRect[2].right -6, m_MDIRect[2].top +5);
+ DrawDC.LineTo(m_MDIRect[2].left + 3, m_MDIRect[2].bottom -4);
+ break;
+ }
+ }
+ }
+
+ inline void CMenuBar::ExitMenu()
+ {
+ ReleaseFocus();
+ m_bKeyMode = FALSE;
+ m_bMenuActive = FALSE;
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, (LPARAM) MAKELONG (FALSE, 0));
+ SetHotItem(-1);
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ // Update mouse mouse position for hot tracking
+ SendMessage(WM_MOUSEMOVE, 0L, MAKELONG(pt.x, pt.y));
+ }
+
+ inline HWND CMenuBar::GetActiveMDIChild()
+ {
+ HWND hwndMDIChild = NULL;
+ if (IsMDIFrame())
+ {
+ hwndMDIChild = (HWND)::SendMessage(m_pFrame->GetView()->GetHwnd(), WM_MDIGETACTIVE, 0L, 0L);
+ }
+
+ return hwndMDIChild;
+ }
+
+ inline void CMenuBar::GrabFocus()
+ {
+ if (::GetFocus() != m_hWnd)
+ m_hPrevFocus = ::SetFocus(m_hWnd);
+ ::SetCapture(m_hWnd);
+ ::SetCursor(::LoadCursor(NULL, IDC_ARROW));
+ }
+
+ inline BOOL CMenuBar::IsMDIChildMaxed() const
+ {
+ BOOL bMaxed = FALSE;
+
+ if (IsMDIFrame() && m_pFrame->GetView()->IsWindow())
+ {
+ m_pFrame->GetView()->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);
+ }
+
+ return bMaxed;
+ }
+
+ inline BOOL CMenuBar::IsMDIFrame() const
+ {
+ return (m_pFrame->IsMDIFrame());
+ }
+
+ inline void CMenuBar::OnMenuChar(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ if (!m_bMenuActive)
+ DoAltKey(LOWORD(wParam));
+ }
+
+ inline void CMenuBar::OnCreate()
+ {
+ // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message
+ SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L);
+
+ m_pFrame = (CFrame*)GetAncestor();
+ assert(m_pFrame);
+ }
+
+ inline LRESULT CMenuBar::OnCustomDraw(NMHDR* pNMHDR)
+ // CustomDraw is used to render the MenuBar's toolbar buttons
+ {
+ if (m_ThemeMenu.UseThemes)
+ {
+ LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;
+
+ switch (lpNMCustomDraw->nmcd.dwDrawStage)
+ {
+ // Begin paint cycle
+ case CDDS_PREPAINT:
+ // Send NM_CUSTOMDRAW item draw, and post-paint notification messages.
+ return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
+
+ // An item is about to be drawn
+ case CDDS_ITEMPREPAINT:
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ CRect rcRect = lpNMCustomDraw->nmcd.rc;
+ int nState = lpNMCustomDraw->nmcd.uItemState;
+ DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec;
+
+ // Leave a pixel gap above and below the drawn rectangle
+ if (IsAeroThemed())
+ rcRect.InflateRect(0, -2);
+ else
+ rcRect.InflateRect(0, -1);
+
+ if (IsMDIChildMaxed() && (0 == dwItem))
+ // Draw over MDI Max button
+ {
+ HICON hIcon = (HICON)::SendMessage(GetActiveMDIChild(), WM_GETICON, ICON_SMALL, 0L);
+ if (NULL == hIcon)
+ hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
+
+ int cx = ::GetSystemMetrics (SM_CXSMICON);
+ int cy = ::GetSystemMetrics (SM_CYSMICON);
+ int y = 1 + (GetWindowRect().Height() - cy)/2;
+ int x = (rcRect.Width() - cx)/2;
+ pDrawDC->DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL);
+
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+
+ else if (nState & (CDIS_HOT | CDIS_SELECTED))
+ {
+ if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED))
+ {
+ pDrawDC->GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE);
+ }
+ else if (nState & CDIS_HOT)
+ {
+ pDrawDC->GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE);
+ }
+
+ // Draw border
+ pDrawDC->CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline);
+ pDrawDC->MoveTo(rcRect.left, rcRect.bottom);
+ pDrawDC->LineTo(rcRect.left, rcRect.top);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.top);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.bottom);
+ pDrawDC->MoveTo(rcRect.right-1, rcRect.bottom);
+ pDrawDC->LineTo(rcRect.left, rcRect.bottom);
+
+ TCHAR str[80] = _T("");
+ int nLength = (int)SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, 0L);
+ if ((nLength > 0) && (nLength < 80))
+ SendMessage(TB_GETBUTTONTEXT, lpNMCustomDraw->nmcd.dwItemSpec, (LPARAM)str);
+
+ // Draw highlight text
+ pDrawDC->SelectObject(GetFont());
+ rcRect.bottom += 1;
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ pDrawDC->DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
+
+ pDrawDC->SetBkMode(iMode);
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+ }
+ return CDRF_DODEFAULT ; // Do default drawing
+
+ // Painting cycle has completed
+ case CDDS_POSTPAINT:
+ // Draw MDI Minimise, Restore and Close buttons
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ DrawAllMDIButtons(*pDrawDC);
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ }
+ break;
+ }
+ }
+ return 0L;
+ }
+
+ inline void CMenuBar::OnKeyDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(lParam);
+
+ switch (wParam)
+ {
+ case VK_ESCAPE:
+ ExitMenu();
+ break;
+
+ case VK_SPACE:
+ ExitMenu();
+ // Bring up the system menu
+ GetAncestor()->PostMessage(WM_SYSCOMMAND, SC_KEYMENU, VK_SPACE);
+ break;
+
+ // Handle VK_DOWN,VK_UP and VK_RETURN together
+ case VK_DOWN:
+ case VK_UP:
+ case VK_RETURN:
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ break;
+
+ case VK_LEFT:
+ // Move left to next topmenu item
+ (m_nHotItem > 0)? SetHotItem(m_nHotItem -1) : SetHotItem(GetButtonCount()-1);
+ break;
+
+ case VK_RIGHT:
+ // Move right to next topmenu item
+ (m_nHotItem < GetButtonCount() -1)? SetHotItem(m_nHotItem +1) : SetHotItem(0);
+ break;
+
+ default:
+ // Handle Accelerator keys with Alt toggled down
+ if (m_bKeyMode)
+ {
+ UINT ID;
+ if (SendMessage(TB_MAPACCELERATOR, wParam, (LPARAM) &ID))
+ {
+ m_nHotItem = ID;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ else
+ ::MessageBeep(MB_OK);
+ }
+ break;
+ } // switch (wParam)
+ }
+
+ inline void CMenuBar::OnLButtonDown(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ GrabFocus();
+ m_nMDIButton = 0;
+ CPoint pt;
+
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+ m_nMDIButton = -1;
+
+ if (m_MDIRect[0].PtInRect(pt)) m_nMDIButton = 0;
+ if (m_MDIRect[1].PtInRect(pt)) m_nMDIButton = 1;
+ if (m_MDIRect[2].PtInRect(pt)) m_nMDIButton = 2;
+
+ if (m_nMDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, (0 == m_nMDIButton)? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == m_nMDIButton)? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == m_nMDIButton)? 2 : 0);
+ }
+
+ // Bring up the MDI Child window's system menu when the icon is pressed
+ if (0 == HitTest())
+ {
+ m_nHotItem = 0;
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ }
+ }
+ }
+
+ inline void CMenuBar::OnLButtonUp(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ HWND MDIClient = m_pFrame->GetView()->GetHwnd();
+ HWND MDIChild = GetActiveMDIChild();
+
+ if (IsMDIChildMaxed())
+ {
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ // Process the MDI button action when the left mouse button is up
+ if (m_MDIRect[0].PtInRect(pt))
+ {
+ if (MDI_MIN == m_nMDIButton)
+ ::ShowWindow(MDIChild, SW_MINIMIZE);
+ }
+
+ if (m_MDIRect[1].PtInRect(pt))
+ {
+ if (MDI_RESTORE == m_nMDIButton)
+ ::PostMessage(MDIClient, WM_MDIRESTORE, (WPARAM)MDIChild, 0L);
+ }
+
+ if (m_MDIRect[2].PtInRect(pt))
+ {
+ if (MDI_CLOSE == m_nMDIButton)
+ ::PostMessage(MDIChild, WM_CLOSE, 0L, 0L);
+ }
+ }
+ }
+ m_nMDIButton = 0;
+ ExitMenu();
+ }
+
+ inline BOOL CMenuBar::OnMenuInput(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // When a popup menu is active, StaticMsgHook directs all menu messages here
+ {
+ switch(uMsg)
+ {
+ case WM_KEYDOWN:
+ m_bExitAfter = FALSE;
+ {
+ switch (wParam)
+ {
+ case VK_ESCAPE:
+ // Use default processing if inside a Sub Menu
+ if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
+ return FALSE;
+
+ m_bMenuActive = FALSE;
+ m_bKeyMode = TRUE;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ break;
+
+ case VK_LEFT:
+ // Use default processing if inside a Sub Menu
+ if ((m_hSelMenu) &&(m_hSelMenu != m_hPopupMenu))
+ return FALSE;
+
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+
+ // Move left to next topmenu item
+ (m_nHotItem > 0)? --m_nHotItem : m_nHotItem = GetButtonCount()-1;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+ break;
+
+ case VK_RIGHT:
+ // Use default processing to open Sub Menu
+ if (m_bSelPopup)
+ return FALSE;
+
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+
+ // Move right to next topmenu item
+ (m_nHotItem < GetButtonCount()-1)? ++m_nHotItem : m_nHotItem = 0;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ PostMessage(WM_KEYDOWN, VK_DOWN, 0L);
+ break;
+
+ case VK_RETURN:
+ m_bExitAfter = TRUE;
+ break;
+
+ } // switch (wParam)
+
+ } // case WM_KEYDOWN
+
+ return FALSE;
+
+ case WM_CHAR:
+ m_bExitAfter = TRUE;
+ return FALSE;
+
+ case WM_LBUTTONDOWN:
+ {
+ m_bExitAfter = TRUE;
+ if (HitTest() >= 0)
+ {
+ // Cancel popup when we hit a button a second time
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+ return TRUE;
+ }
+ }
+ return FALSE;
+
+ case WM_LBUTTONDBLCLK:
+ // Perform default action for DblClick on MDI Maxed icon
+ if (IsMDIChildMaxed() && (0 == HitTest()))
+ {
+ CWnd* pMDIChild = FromHandle(GetActiveMDIChild());
+ CMenu* pChildMenu = pMDIChild->GetSystemMenu(FALSE);
+
+ UINT nID = pChildMenu->GetDefaultItem(FALSE, 0);
+ if (nID)
+ pMDIChild->PostMessage(WM_SYSCOMMAND, nID, 0L);
+ }
+
+ m_bExitAfter = TRUE;
+ return FALSE;
+
+ case WM_MENUSELECT:
+ {
+ // store info about selected item
+ m_hSelMenu = (HMENU)lParam;
+ m_bSelPopup = ((HIWORD(wParam) & MF_POPUP) != 0);
+
+ // Reflect message back to the frame window
+ GetAncestor()->SendMessage(WM_MENUSELECT, wParam, lParam);
+ }
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ {
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ // Skip if mouse hasn't moved
+ if ((pt.x == m_OldMousePos.x) && (pt.y == m_OldMousePos.y))
+ return FALSE;
+
+ m_OldMousePos.x = pt.x;
+ m_OldMousePos.y = pt.y;
+ ScreenToClient(pt);
+
+ // Reflect messages back to the MenuBar for hot tracking
+ SendMessage(WM_MOUSEMOVE, 0L, MAKELPARAM(pt.x, pt.y));
+ }
+ break;
+
+ }
+ return FALSE;
+ }
+
+ inline void CMenuBar::OnMouseLeave()
+ {
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ }
+
+ inline void CMenuBar::OnMouseMove(WPARAM wParam, LPARAM lParam)
+ {
+ CPoint pt;
+ pt.x = GET_X_LPARAM(lParam);
+ pt.y = GET_Y_LPARAM(lParam);
+
+ if (IsMDIFrame())
+ {
+ if (IsMDIChildMaxed())
+ {
+ CClientDC MenuBarDC(this);
+ int MDIButton = -1;
+ if (m_MDIRect[0].PtInRect(pt)) MDIButton = 0;
+ if (m_MDIRect[1].PtInRect(pt)) MDIButton = 1;
+ if (m_MDIRect[2].PtInRect(pt)) MDIButton = 2;
+
+ if (MK_LBUTTON == wParam) // mouse moved with left mouse button is held down
+ {
+ // toggle the MDI button image pressed/unpressed as required
+ if (MDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, ((0 == MDIButton) && (0 == m_nMDIButton))? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, ((1 == MDIButton) && (1 == m_nMDIButton))? 2 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, ((2 == MDIButton) && (2 == m_nMDIButton))? 2 : 0);
+ }
+ else
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ else // mouse moved without left mouse button held down
+ {
+ if (MDIButton >= 0)
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, (0 == MDIButton)? 1 : 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, (1 == MDIButton)? 1 : 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, (2 == MDIButton)? 1 : 0);
+ }
+ else
+ {
+ DrawMDIButton(MenuBarDC, MDI_MIN, 0);
+ DrawMDIButton(MenuBarDC, MDI_RESTORE, 0);
+ DrawMDIButton(MenuBarDC, MDI_CLOSE, 0);
+ }
+ }
+ }
+ }
+ }
+
+ inline LRESULT CMenuBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case NM_CUSTOMDRAW:
+ {
+ return OnCustomDraw((LPNMHDR) lParam);
+ }
+
+ case TBN_DROPDOWN:
+ // Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ break;
+
+ case TBN_HOTITEMCHANGE:
+ // This is the notification that a hot item change is about to occur
+ // This is used to bring up a new popup menu when required
+ {
+ CPoint pt = GetCursorPos();
+ if (this == WindowFromPoint(pt)) // MenuBar window must be on top
+ {
+ DWORD flag = ((LPNMTBHOTITEM)lParam)->dwFlags;
+ if ((flag & HICF_MOUSE) && !(flag & HICF_LEAVING))
+ {
+ int nButton = HitTest();
+ if ((m_bMenuActive) && (nButton != m_nHotItem))
+ {
+ SendMessage(TB_PRESSBUTTON, m_nHotItem, MAKELONG(FALSE, 0));
+ m_nHotItem = nButton;
+ SendMessage(WM_CANCELMODE, 0L, 0L);
+
+ //Always use PostMessage for USER_POPUPMENU (not SendMessage)
+ PostMessage(UWM_POPUPMENU, 0L, 0L);
+ }
+ m_nHotItem = nButton;
+ }
+
+ // Handle escape from popup menu
+ if ((flag & HICF_LEAVING) && m_bKeyMode)
+ {
+ m_nHotItem = ((LPNMTBHOTITEM)lParam)->idOld;
+ PostMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ }
+
+ }
+ break;
+ } //case TBN_HOTITEMCHANGE:
+
+ } // switch(((LPNMHDR)lParam)->code)
+ return 0L;
+ } // CMenuBar::OnNotify(...)
+
+ inline void CMenuBar::OnWindowPosChanged()
+ {
+ InvalidateRect(&m_MDIRect[0], TRUE);
+ InvalidateRect(&m_MDIRect[1], TRUE);
+ InvalidateRect(&m_MDIRect[2], TRUE);
+ {
+ CClientDC MenuBarDC(this);
+ DrawAllMDIButtons(MenuBarDC);
+ }
+ }
+
+ inline void CMenuBar::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_LIST | TBSTYLE_FLAT | CCS_NODIVIDER | CCS_NORESIZE;
+ }
+
+ inline void CMenuBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = TOOLBARCLASSNAME;
+ }
+
+ inline void CMenuBar::ReleaseFocus()
+ {
+ if (m_hPrevFocus)
+ ::SetFocus(m_hPrevFocus);
+
+ m_hPrevFocus = NULL;
+ ::ReleaseCapture();
+ }
+
+ inline void CMenuBar::SetHotItem(int nHot)
+ {
+ m_nHotItem = nHot;
+ SendMessage(TB_SETHOTITEM, m_nHotItem, 0L);
+ }
+
+ inline void CMenuBar::SetMenu(HMENU hMenu)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ m_hTopMenu = hMenu;
+ int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
+
+ // Remove any existing buttons
+ while (SendMessage(TB_BUTTONCOUNT, 0L, 0L) > 0)
+ {
+ if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))
+ break;
+ }
+
+ // Set the Bitmap size to zero
+ SendMessage(TB_SETBITMAPSIZE, 0L, MAKELPARAM(0, 0));
+
+ if (IsMDIChildMaxed())
+ {
+ // Create an extra button for the MDI child system menu
+ // Later we will custom draw the window icon over this button
+ TBBUTTON tbb = {0};
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE ;
+ tbb.iString = (INT_PTR)_T(" ");
+ SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
+ SetButtonText(0, _T(" "));
+ }
+
+ for (int i = 0 ; i < ::GetMenuItemCount(hMenu); ++i)
+ {
+ // Assign the ToolBar Button struct
+ TBBUTTON tbb = {0};
+ tbb.idCommand = i + nMaxedOffset; // Each button needs a unique ID
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE | TBSTYLE_DROPDOWN;
+ tbb.iString = (INT_PTR)_T(" ");
+ SendMessage(TB_ADDBUTTONS, 1, (WPARAM)&tbb);
+
+ // Add the menu title to the string table
+ std::vector vMenuName( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szMenuName = &vMenuName[0];
+ GetMenuString(hMenu, i, szMenuName, MAX_MENU_STRING, MF_BYPOSITION);
+ SetButtonText(i + nMaxedOffset, szMenuName);
+ }
+ }
+
+ inline void CMenuBar::SetMenuBarTheme(MenuTheme& Theme)
+ {
+ m_ThemeMenu.UseThemes = Theme.UseThemes;
+ m_ThemeMenu.clrHot1 = Theme.clrHot1;
+ m_ThemeMenu.clrHot2 = Theme.clrHot2;
+ m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
+ m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
+ m_ThemeMenu.clrOutline = Theme.clrOutline;
+
+ if (IsWindow())
+ Invalidate();
+ }
+
+ inline LRESULT CALLBACK CMenuBar::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
+ {
+ assert(GetApp());
+ MSG* pMsg = (MSG*)lParam;
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+ CMenuBar* pMenuBar = (CMenuBar*)pTLSData->pMenuBar;
+
+ if (pMenuBar && (MSGF_MENU == nCode))
+ {
+ // process menu message
+ if (pMenuBar->OnMenuInput(pMsg->message, pMsg->wParam, pMsg->lParam))
+ {
+ return TRUE;
+ }
+ }
+
+ return CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
+ }
+
+ inline void CMenuBar::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ if (SC_KEYMENU == wParam)
+ {
+ if (0 == lParam)
+ {
+ // Alt/F10 key toggled
+ GrabFocus();
+ m_bKeyMode = TRUE;
+ int nMaxedOffset = (IsMDIChildMaxed()? 1:0);
+ SetHotItem(nMaxedOffset);
+ }
+ else
+ // Handle key pressed with Alt held down
+ DoAltKey((WORD)lParam);
+ }
+ }
+
+ inline LRESULT CMenuBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_CHAR:
+ return 0L; // Discard these messages
+ case WM_DRAWITEM:
+ m_pFrame->OnDrawItem(wParam, lParam);
+ return TRUE; // handled
+ case WM_EXITMENULOOP:
+ if (m_bExitAfter)
+ ExitMenu();
+ m_pFrame->OnExitMenuLoop();
+ break;
+ case WM_INITMENUPOPUP:
+ m_pFrame->OnInitMenuPopup(wParam, lParam);
+ break;
+ case WM_KEYDOWN:
+ OnKeyDown(wParam, lParam);
+ return 0L; // Discard these messages
+ case WM_KILLFOCUS:
+ ExitMenu();
+ return 0L;
+ case WM_LBUTTONDOWN:
+ // Do default processing first
+ CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);
+
+ OnLButtonDown(wParam, lParam);
+ return 0L;
+ case WM_LBUTTONUP:
+ OnLButtonUp(wParam, lParam);
+ break;
+ case WM_MEASUREITEM:
+ m_pFrame->OnMeasureItem(wParam, lParam);
+ return TRUE; // handled
+ case WM_MOUSELEAVE:
+ OnMouseLeave();
+ break;
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+ case UWM_POPUPMENU:
+ DoPopupMenu();
+ return 0L;
+ case WM_SYSKEYDOWN:
+ if ((VK_MENU == wParam) || (VK_F10 == wParam))
+ return 0L;
+ break;
+ case WM_SYSKEYUP:
+ if ((VK_MENU == wParam) || (VK_F10 == wParam))
+ {
+ ExitMenu();
+ return 0L;
+ }
+ break;
+ case UWM_GETMENUTHEME:
+ {
+ MenuTheme& tm = GetMenuBarTheme();
+ return (LRESULT)&tm;
+ }
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged();
+ break;
+ case WM_WINDOWPOSCHANGING:
+ // Bypass CToolBar::WndProcDefault for this message
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+
+ } // switch (uMsg)
+
+ return CToolBar::WndProcDefault(uMsg, wParam, lParam);
+ } // LRESULT CMenuBar::WndProcDefault(...)
+
+
+
+ ///////////////////////////////////
+ // Definitions for the CFrame class
+ //
+ inline CFrame::CFrame() : m_tsStatusText(_T("Ready")), m_bShowIndicatorStatus(TRUE), m_bShowMenuStatus(TRUE),
+ m_bUseReBar(FALSE), m_bUseThemes(TRUE), m_bUpdateTheme(FALSE), m_bUseToolBar(TRUE), m_bUseCustomDraw(TRUE),
+ m_bShowStatusBar(TRUE), m_bShowToolBar(TRUE), m_himlMenu(NULL), m_himlMenuDis(NULL),
+ m_AboutDialog(IDW_ABOUT), m_pView(NULL), m_nMaxMRU(0), m_hOldFocus(0), m_nOldID(-1)
+ {
+ ZeroMemory(&m_ThemeMenu, sizeof(m_ThemeMenu));
+
+ // Do either InitCommonControls or InitCommonControlsEx
+ LoadCommonControls();
+
+ // By default, we use the rebar if we can
+ if (GetComCtlVersion() >= 470)
+ m_bUseReBar = TRUE;
+
+ for (int i = 0 ; i < 3 ; ++i)
+ m_OldStatus[i] = _T('\0');
+ }
+
+ inline CFrame::~CFrame()
+ {
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ }
+
+ inline BOOL CFrame::AddMenuIcon(int nID_MenuItem, HICON hIcon, int cx /*= 16*/, int cy /*= 16*/)
+ {
+ // Get ImageList image size
+ int cxOld = 0;
+ int cyOld = 0;
+ ImageList_GetIconSize(m_himlMenu, &cxOld, &cyOld );
+
+ // Create a new ImageList if required
+ if ((cx != cxOld) || (cy != cyOld) || (NULL == m_himlMenu))
+ {
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ m_himlMenu = ImageList_Create(cx, cy, ILC_COLOR32 | ILC_MASK, 1, 0);
+ m_vMenuIcons.clear();
+ }
+
+ if (ImageList_AddIcon(m_himlMenu, hIcon) != -1)
+ {
+ m_vMenuIcons.push_back(nID_MenuItem);
+
+ // Recreate the Disabled imagelist
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = NULL;
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ inline UINT CFrame::AddMenuIcons(const std::vector& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
+ // Adds the icons from a bitmap resouce to an internal ImageList for use with popup menu items.
+ // Note: If existing are a different size to the new ones, the old ones will be removed!
+ // The ToolBarDisabledID is ignored unless ToolBarID and ToolBarDisabledID bitmaps are the same size.
+ {
+ // Count the MenuData entries excluding seperators
+ int iImages = 0;
+ for (UINT i = 0 ; i < MenuData.size(); ++i)
+ {
+ if (MenuData[i] != 0) // Don't count seperators
+ {
+ ++iImages;
+ }
+ }
+
+ // Load the button images from Resouce ID
+ CBitmap Bitmap(ToolBarID);
+
+ if ((0 == iImages) || (!Bitmap))
+ return (UINT)m_vMenuIcons.size(); // No valid images, so nothing to do!
+
+ BITMAP bm = Bitmap.GetBitmapData();
+ int iImageWidth = bm.bmWidth / iImages;
+ int iImageHeight = bm.bmHeight;
+
+ // Create the ImageList if required
+ if (NULL == m_himlMenu)
+ {
+ m_himlMenu = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
+ m_vMenuIcons.clear();
+ }
+ else
+ {
+ int Oldcx;
+ int Oldcy;
+
+ ImageList_GetIconSize(m_himlMenu, &Oldcx, &Oldcy);
+ if (iImageHeight != Oldcy)
+ {
+ TRACE(_T("Unable to add icons. The new icons are a different size to the old ones\n"));
+ return (UINT)m_vMenuIcons.size();
+ }
+ }
+
+ // Add the resource IDs to the m_vMenuIcons vector
+ for (UINT j = 0 ; j < MenuData.size(); ++j)
+ {
+ if (MenuData[j] != 0)
+ {
+ m_vMenuIcons.push_back(MenuData[j]);
+ }
+ }
+
+ // Add the images to the ImageList
+ ImageList_AddMasked(m_himlMenu, Bitmap, crMask);
+
+ // Create the Disabled imagelist
+ if (ToolBarDisabledID)
+ {
+ if (0 != m_himlMenuDis)
+ m_himlMenuDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iImages, 0);
+
+ CBitmap BitmapDisabled(ToolBarDisabledID);
+ BITMAP bmDis = BitmapDisabled.GetBitmapData();
+
+ int iImageWidthDis = bmDis.bmWidth / iImages;
+ int iImageHeightDis = bmDis.bmHeight;
+
+ // Normal and Disabled icons must be the same size
+ if ((iImageWidthDis == iImageWidth) && (iImageHeightDis == iImageHeight))
+ {
+ ImageList_AddMasked(m_himlMenu, BitmapDisabled, crMask);
+ }
+ else
+ {
+ ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+ }
+ }
+ else
+ {
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenuDis = CreateDisabledImageList(m_himlMenu);
+ }
+
+ // return the number of menu icons
+ return (UINT)m_vMenuIcons.size();
+ }
+
+ inline void CFrame::AddMenuBarBand()
+ {
+ // Adds a MenuBar to the rebar control
+ REBARBANDINFO rbbi = {0};
+ CSize sz = GetMenuBar().GetMaxSize();
+
+ // Calculate the MenuBar height from the menu font
+ CSize csMenuBar;
+ CClientDC dcMenuBar(&GetMenuBar());
+ dcMenuBar.SelectObject(GetMenuBar().GetFont());
+ csMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText")));
+ int MenuBar_Height = csMenuBar.cy + 6;
+
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
+ rbbi.cxMinChild = sz.cx;
+ rbbi.cx = sz.cx;
+ rbbi.cyMinChild = MenuBar_Height;
+ rbbi.cyMaxChild = MenuBar_Height;
+ rbbi.fStyle = RBBS_BREAK | RBBS_VARIABLEHEIGHT | RBBS_GRIPPERALWAYS ;
+ rbbi.hwndChild = GetMenuBar();
+ rbbi.wID = IDW_MENUBAR;
+
+ // Note: rbbi.cbSize is set inside the InsertBand function
+ GetReBar().InsertBand(-1, rbbi);
+ SetMenuBarBandSize();
+ GetReBar().SetMenuBar(GetMenuBar());
+
+ if (GetReBar().GetReBarTheme().LockMenuBand)
+ GetReBar().ShowGripper(GetReBar().GetBand(GetMenuBar()), FALSE);
+ }
+
+ inline void CFrame::AddMRUEntry(LPCTSTR szMRUEntry)
+ {
+ // Erase possible duplicate entries from vector
+ RemoveMRUEntry(szMRUEntry);
+
+ // Insert the entry at the beginning of the vector
+ m_vMRUEntries.insert(m_vMRUEntries.begin(), szMRUEntry);
+
+ // Delete excessive MRU entries
+ if (m_vMRUEntries.size() > m_nMaxMRU)
+ m_vMRUEntries.erase(m_vMRUEntries.begin() + m_nMaxMRU, m_vMRUEntries.end());
+
+ UpdateMRUMenu();
+ }
+
+ inline void CFrame::AddToolBarBand(CToolBar& TB, DWORD dwStyle, UINT nID)
+ {
+ // Adds a ToolBar to the rebar control
+
+ // Create the ToolBar Window
+ TB.Create(&GetReBar());
+
+ // Fill the REBARBAND structure
+ REBARBANDINFO rbbi = {0};
+ CSize sz = TB.GetMaxSize();
+
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CHILD | RBBIM_SIZE | RBBIM_ID;
+ rbbi.cyMinChild = sz.cy;
+ rbbi.cyMaxChild = sz.cy;
+ rbbi.cx = sz.cx +2;
+ rbbi.cxMinChild = sz.cx +2;
+
+ rbbi.fStyle = dwStyle;
+ rbbi.hwndChild = TB;
+ rbbi.wID = nID;
+
+ // Note: rbbi.cbSize is set inside the InsertBand function
+ GetReBar().InsertBand(-1, rbbi);
+ }
+
+ inline void CFrame::AddToolBarButton(UINT nID, BOOL bEnabled /* = TRUE*/, LPCTSTR szText)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ GetToolBar().AddButton(nID, bEnabled);
+
+ if(0 != szText)
+ GetToolBar().SetButtonText(nID, szText);
+
+ if (!IsWindow()) TRACE(_T("Warning ... Resource IDs for toolbars should be added in SetupToolBar\n"));
+ }
+
+ inline void CFrame::AdjustFrameRect(RECT rcView) const
+ // Adjust the size of the frame to accommodate the View window's dimensions
+ {
+ // Adjust for the view styles
+ CRect rc = rcView;
+ DWORD dwStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_STYLE);
+ DWORD dwExStyle = (DWORD)GetView()->GetWindowLongPtr(GWL_EXSTYLE);
+ AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
+
+ // Calculate the new frame height
+ CRect rcFrameBefore = GetWindowRect();
+ CRect rcViewBefore = GetViewRect();
+ int Height = rc.Height() + rcFrameBefore.Height() - rcViewBefore.Height();
+
+ // Adjust for the frame styles
+ dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ dwExStyle = (DWORD)GetWindowLongPtr(GWL_EXSTYLE);
+ AdjustWindowRectEx(&rc, dwStyle, FALSE, dwExStyle);
+
+ // Calculate final rect size, and reposition frame
+ SetWindowPos(NULL, 0, 0, rc.Width(), Height, SWP_NOMOVE);
+ }
+
+ inline void CFrame::CreateToolBar()
+ {
+ if (IsReBarSupported() && m_bUseReBar)
+ AddToolBarBand(GetToolBar(), RBBS_BREAK, IDW_TOOLBAR); // Create the toolbar inside rebar
+ else
+ GetToolBar().Create(this); // Create the toolbar without a rebar
+
+ SetupToolBar();
+
+ if (IsReBarSupported() && m_bUseReBar)
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().LockMenuBand)
+ {
+ // Hide gripper for single toolbar
+ if (GetReBar().GetBandCount() <= 2)
+ GetReBar().ShowGripper(GetReBar().GetBand(GetToolBar()), FALSE);
+ }
+ }
+
+ if (GetToolBar().GetToolBarData().size() > 0)
+ {
+ // Set the toolbar images (if not already set in SetupToolBar)
+ // A mask of 192,192,192 is compatible with AddBitmap (for Win95)
+ if (!GetToolBar().SendMessage(TB_GETIMAGELIST, 0L, 0L))
+ SetToolBarImages(RGB(192,192,192), IDW_MAIN, 0, 0);
+
+ // Add the icons for popup menu
+ AddMenuIcons(GetToolBar().GetToolBarData(), RGB(192, 192, 192), IDW_MAIN, 0);
+ }
+ else
+ {
+ TRACE(_T("Warning ... No resource IDs assigned to the toolbar\n"));
+ }
+ }
+
+ inline void CFrame::DrawCheckmark(LPDRAWITEMSTRUCT pdis, CDC& DrawDC)
+ // Draws the checkmark or radiocheck transparently
+ {
+ CRect rc = pdis->rcItem;
+ UINT fType = ((ItemData*)pdis->itemData)->fType;
+ MenuTheme tm = GetMenuTheme();
+ CRect rcBk;
+
+ // Draw the checkmark's background rectangle first
+ int Iconx = 16, Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = Iconx + 8;
+ int left = (BarWidth - Iconx)/2;
+ int top = rc.top + (rc.Height() - Icony)/2;
+ rcBk.SetRect(left, top, left + Iconx, top + Icony);
+
+ if (tm.UseThemes)
+ {
+ DrawDC.CreateSolidBrush(tm.clrHot2);
+ DrawDC.CreatePen(PS_SOLID, 1, tm.clrOutline);
+
+ // Draw the checkmark's background rectangle
+ DrawDC.Rectangle(rcBk.left, rcBk.top, rcBk.right, rcBk.bottom);
+ }
+
+ CMemDC MemDC(FromHandle(pdis->hDC));
+ int cxCheck = ::GetSystemMetrics(SM_CXMENUCHECK);
+ int cyCheck = ::GetSystemMetrics(SM_CYMENUCHECK);
+ MemDC.CreateBitmap(cxCheck, cyCheck, 1, 1, NULL);
+ CRect rcCheck( 0, 0, cxCheck, cyCheck);
+
+ // Copy the check mark bitmap to hdcMem
+ if (MFT_RADIOCHECK == fType)
+ MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUBULLET);
+ else
+ MemDC.DrawFrameControl(rcCheck, DFC_MENU, DFCS_MENUCHECK);
+
+ int xoffset = (rcBk.Width() - rcCheck.Width()-1)/2;
+ int yoffset = (rcBk.Height() - rcCheck.Height()-1)/2;
+
+ if (tm.UseThemes)
+ xoffset += 2;
+
+ // Draw a white or black check mark as required
+ // Unfortunately MaskBlt isn't supported on Win95, 98 or ME, so we do it the hard way
+ CMemDC MaskDC(FromHandle(pdis->hDC));
+ MaskDC.CreateCompatibleBitmap(FromHandle(pdis->hDC), cxCheck, cyCheck);
+ MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MaskDC, 0, 0, WHITENESS);
+
+ if ((pdis->itemState & ODS_SELECTED) && (!tm.UseThemes))
+ {
+ // Draw a white checkmark
+ MemDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, DSTINVERT);
+ MaskDC.BitBlt(0, 0, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
+ DrawDC.BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCPAINT);
+ }
+ else
+ {
+ // Draw a black checkmark
+ int BullitOffset = ((MFT_RADIOCHECK == fType) && tm.UseThemes)? 1 : 0;
+ MaskDC.BitBlt( -BullitOffset, BullitOffset, cxCheck, cyCheck, &MemDC, 0, 0, SRCAND);
+ DrawDC.BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCAND);
+ }
+ }
+
+ inline void CFrame::DrawMenuIcon(LPDRAWITEMSTRUCT pdis, CDC& DrawDC, BOOL bDisabled)
+ {
+ if (!m_himlMenu)
+ return;
+ // Get icon size
+ int Iconx;
+ int Icony;
+ ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = Iconx + 8;
+
+ // get the drawing rectangle
+ CRect rc = pdis->rcItem;
+ int left = (BarWidth - Iconx)/2;
+ int top = rc.top + (rc.Height() - Icony)/2;
+ rc.SetRect(left, top, left + Iconx, top + Icony);
+
+ // get the icon's location in the imagelist
+ int iImage = -1;
+ for (int i = 0 ; i < (int)m_vMenuIcons.size(); ++i)
+ {
+ if (pdis->itemID == m_vMenuIcons[i])
+ iImage = i;
+ }
+
+ // draw the image
+ if (iImage >= 0 )
+ {
+ if ((bDisabled) && (m_himlMenuDis))
+ ImageList_Draw(m_himlMenuDis, iImage, DrawDC, rc.left, rc.top, ILD_TRANSPARENT);
+ else
+ ImageList_Draw(m_himlMenu, iImage, DrawDC, rc.left, rc.top, ILD_TRANSPARENT);
+ }
+ }
+
+ inline void CFrame::DrawMenuText(CDC& DrawDC, LPCTSTR ItemText, CRect& rc, COLORREF colorText)
+ {
+ // find the position of tab character
+ int nTab = -1;
+ for(int i = 0; i < lstrlen(ItemText); ++i)
+ {
+ if(_T('\t') == ItemText[i])
+ {
+ nTab = i;
+ break;
+ }
+ }
+
+ // Draw the item text
+ DrawDC.SetTextColor(colorText);
+ DrawDC.DrawText(ItemText, nTab, rc, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
+
+ // Draw text after tab, right aligned
+ if(nTab != -1)
+ DrawDC.DrawText( &ItemText[nTab + 1], -1, rc, DT_SINGLELINE | DT_RIGHT | DT_VCENTER);
+ }
+
+ inline int CFrame::GetMenuItemPos(HMENU hMenu, LPCTSTR szItem)
+ // Returns the position of the menu item, given it's name
+ {
+ int nMenuItemCount = GetMenuItemCount(hMenu);
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ for (int nItem = 0 ; nItem < nMenuItemCount; ++nItem)
+ {
+ std::vector vTChar( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szStr = &vTChar[0];
+
+ std::vector vStripped( MAX_MENU_STRING+1, _T('\0') );
+ TCHAR* szStripped = &vStripped[0];
+
+ mii.fMask = MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = szStr;
+ mii.cch = MAX_MENU_STRING;
+
+ // Fill the contents of szStr from the menu item
+ if (::GetMenuItemInfo(hMenu, nItem, TRUE, &mii) && (lstrlen(szStr) <= MAX_MENU_STRING))
+ {
+ // Strip out any & characters
+ int j = 0;
+ for (int i = 0; i < lstrlen(szStr); ++i)
+ {
+ if (szStr[i] != _T('&'))
+ szStripped[j++] = szStr[i];
+ }
+ szStripped[j] = _T('\0'); // Append null tchar
+
+ // Compare the strings
+ if (0 == lstrcmp(szStripped, szItem))
+ return nItem;
+ }
+ }
+
+ return -1;
+ }
+
+ inline tString CFrame::GetMRUEntry(UINT nIndex)
+ {
+ tString tsPathName;
+ if (nIndex < m_vMRUEntries.size())
+ {
+ tsPathName = m_vMRUEntries[nIndex];
+
+ // Now put the selected entry at Index 0
+ AddMRUEntry(tsPathName.c_str());
+ }
+ return tsPathName;
+ }
+
+ inline CRect CFrame::GetViewRect() const
+ {
+ // Get the frame's client area
+ CRect rcFrame = GetClientRect();
+
+ // Get the statusbar's window area
+ CRect rcStatus;
+ if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
+ rcStatus = GetStatusBar().GetWindowRect();
+
+ // Get the top rebar or toolbar's window area
+ CRect rcTop;
+ if (IsReBarSupported() && m_bUseReBar)
+ rcTop = GetReBar().GetWindowRect();
+ else
+ if (GetToolBar().IsWindow() && GetToolBar().IsWindowVisible())
+ rcTop = GetToolBar().GetWindowRect();
+
+ // Return client size less the rebar and status windows
+ int top = rcFrame.top + rcTop.Height();
+ int left = rcFrame.left;
+ int right = rcFrame.right;
+ int bottom = rcFrame.Height() - (rcStatus.Height());
+ if ((bottom <= top) ||( right <= left))
+ top = left = right = bottom = 0;
+
+ CRect rcView(left, top, right, bottom);
+ return rcView;
+ }
+
+ inline void CFrame::LoadCommonControls()
+ {
+ HMODULE hComCtl;
+
+ try
+ {
+ // Load the Common Controls DLL
+ hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
+ if (!hComCtl)
+ throw CWinException(_T("Failed to load COMCTL32.DLL"));
+
+ if (GetComCtlVersion() > 470)
+ {
+ // Declare a pointer to the InItCommonControlsEx function
+ typedef BOOL WINAPI INIT_EX(INITCOMMONCONTROLSEX*);
+ INIT_EX* pfnInit = (INIT_EX*)::GetProcAddress(hComCtl, "InitCommonControlsEx");
+
+ // Load the full set of common controls
+ INITCOMMONCONTROLSEX InitStruct = {0};
+ InitStruct.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ InitStruct.dwICC = ICC_COOL_CLASSES|ICC_DATE_CLASSES|ICC_INTERNET_CLASSES|ICC_NATIVEFNTCTL_CLASS|
+ ICC_PAGESCROLLER_CLASS|ICC_USEREX_CLASSES|ICC_WIN95_CLASSES;
+
+ // Call InitCommonControlsEx
+ if(!((*pfnInit)(&InitStruct)))
+ throw CWinException(_T("InitCommonControlsEx failed"));
+ }
+ else
+ {
+ ::InitCommonControls();
+ }
+
+ ::FreeLibrary(hComCtl);
+ }
+
+ catch (const CWinException &e)
+ {
+ e.what();
+ if (hComCtl)
+ ::FreeLibrary(hComCtl);
+
+ throw;
+ }
+ }
+
+ inline BOOL CFrame::LoadRegistryMRUSettings(UINT nMaxMRU /*= 0*/)
+ {
+ // Load the MRU list from the registry
+
+ assert(!m_tsKeyName.empty()); // KeyName must be set before calling LoadRegistryMRUSettings
+ HKEY hKey = NULL;
+ BOOL bRet = FALSE;
+
+ try
+ {
+ m_nMaxMRU = MIN(nMaxMRU, 16);
+ std::vector vMRUEntries;
+ tString tsKey = _T("Software\\") + m_tsKeyName + _T("\\Recent Files");
+
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey))
+ {
+ for (UINT i = 0; i < m_nMaxMRU; ++i)
+ {
+ DWORD dwType = REG_SZ;
+ DWORD dwBufferSize = 0;
+ TCHAR szSubKey[10] = _T("");
+ wsprintf(szSubKey, _T("File %d\0"), i+1);
+
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, NULL, &dwBufferSize))
+ throw CWinException(_T("RegQueryValueEx failed\n"));
+
+ std::vector PathName( dwBufferSize, _T('\0') );
+ TCHAR* pTCharArray = &PathName[0];
+
+ // load the entry from the registry
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, szSubKey, NULL, &dwType, (LPBYTE)pTCharArray, &dwBufferSize))
+ throw CWinException(_T("RegQueryValueEx failed\n"));
+
+ if ( lstrlen( pTCharArray ) )
+ vMRUEntries.push_back( pTCharArray );
+ }
+
+ // successfully loaded all MRU values, so store them
+ m_vMRUEntries = vMRUEntries;
+ RegCloseKey(hKey);
+ bRet = TRUE;
+ }
+ }
+
+ catch(const CWinException& e)
+ {
+ TRACE(_T("Failed to load MRU values from registry\n"));
+ e.what();
+
+ if (hKey)
+ RegCloseKey(hKey);
+ }
+
+ return bRet;
+ }
+
+ inline BOOL CFrame::LoadRegistrySettings(LPCTSTR szKeyName)
+ {
+ assert (NULL != szKeyName);
+ m_tsKeyName = szKeyName;
+
+ tString tsKey = _T("Software\\") + m_tsKeyName + _T("\\Frame Settings");
+ HKEY hKey = 0;
+ BOOL bRet = FALSE;
+
+ try
+ {
+ if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey))
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(DWORD);
+ DWORD dwTop, dwLeft, dwWidth, dwHeight, dwStatusBar, dwToolBar;
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Top"), NULL, &dwType, (LPBYTE)&dwTop, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Left"), NULL, &dwType, (LPBYTE)&dwLeft, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Width"), NULL, &dwType, (LPBYTE)&dwWidth, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("Height"), NULL, &dwType, (LPBYTE)&dwHeight, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("StatusBar"), NULL, &dwType, (LPBYTE)&dwStatusBar, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+ if (ERROR_SUCCESS != RegQueryValueEx(hKey, _T("ToolBar"), NULL, &dwType, (LPBYTE)&dwToolBar, &BufferSize))
+ throw CWinException(_T("RegQueryValueEx Failed"));
+
+ m_rcPosition.top = dwTop;
+ m_rcPosition.left = dwLeft;
+ m_rcPosition.bottom = m_rcPosition.top + dwHeight;
+ m_rcPosition.right = m_rcPosition.left + dwWidth;
+ m_bShowStatusBar = dwStatusBar & 1;
+ m_bShowToolBar = dwToolBar & 1;
+
+ RegCloseKey(hKey);
+ bRet = TRUE;
+ }
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to load values from registry, using defaults!\n"));
+ e.what();
+
+ if (hKey)
+ RegCloseKey(hKey);
+ }
+
+ return bRet;
+ }
+
+ inline void CFrame::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+ // Do default processing first
+ DefWindowProc(WM_ACTIVATE, wParam, lParam);
+
+ if (LOWORD(wParam) == WA_INACTIVE)
+ {
+ // Save the hwnd of the window which currently has focus
+ // (this must be CFrame window itself or a child window
+ if (!IsIconic()) m_hOldFocus = ::GetFocus();
+
+ // Send a notification to the view window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMELOSTFOCUS;
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ else
+ {
+ // Now set the focus to the appropriate child window
+ if (m_hOldFocus) ::SetFocus(m_hOldFocus);
+
+ // Send a notification to the view window
+ int idCtrl = ::GetDlgCtrlID(m_hOldFocus);
+ NMHDR nhdr={0};
+ nhdr.hwndFrom = m_hOldFocus;
+ nhdr.idFrom = idCtrl;
+ nhdr.code = UWM_FRAMEGOTFOCUS;
+ if (GetView()->IsWindow())
+ GetView()->SendMessage(WM_NOTIFY, (WPARAM)idCtrl, (LPARAM)&nhdr);
+ }
+ }
+
+ inline void CFrame::OnClose()
+ {
+ // Called in response to a WM_CLOSE message for the frame.
+ ShowWindow(SW_HIDE);
+ SaveRegistrySettings();
+
+ GetMenuBar().Destroy();
+ GetToolBar().Destroy();
+ GetReBar().Destroy();
+ GetStatusBar().Destroy();
+ GetView()->Destroy();
+ }
+
+ inline void CFrame::OnCreate()
+ {
+ // This is called when the frame window is being created.
+ // Override this in CMainFrame if you wish to modify what happens here
+
+ // Set the icon
+ SetIconLarge(IDW_MAIN);
+ SetIconSmall(IDW_MAIN);
+
+ // Set the keyboard accelerators
+ m_hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ GetApp()->SetAccelerators(m_hAccel, this);
+
+ // Set the Caption
+ SetWindowText(LoadString(IDW_MAIN));
+
+ // Set the theme for the frame elements
+ SetTheme();
+
+ // Create the rebar and menubar
+ if (IsReBarSupported() && m_bUseReBar)
+ {
+ // Create the rebar
+ GetReBar().Create(this);
+
+ // Create the menu inside rebar
+ GetMenuBar().Create(&GetReBar());
+ AddMenuBarBand();
+ }
+
+ // Setup the menu
+ SetFrameMenu(IDW_MAIN);
+ UpdateMRUMenu();
+
+ // Create the ToolBar
+ if (m_bUseToolBar)
+ {
+ CreateToolBar();
+ ShowToolBar(m_bShowToolBar);
+ }
+ else
+ {
+ ::CheckMenuItem(GetFrameMenu(), IDW_VIEW_TOOLBAR, MF_UNCHECKED);
+ ::EnableMenuItem(GetFrameMenu(), IDW_VIEW_TOOLBAR, MF_GRAYED);
+ }
+
+ // Create the status bar
+ GetStatusBar().Create(this);
+ ShowStatusBar(m_bShowStatusBar);
+
+ // Create the view window
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(this);
+
+ // Disable XP themes for the menubar
+ if ( m_bUseThemes || (GetWinVersion() < 2600) ) // themes or WinVersion < Vista
+ GetMenuBar().SetWindowTheme(L" ", L" ");
+
+ // Start timer for Status updates
+ if (m_bShowIndicatorStatus || m_bShowMenuStatus)
+ SetTimer(ID_STATUS_TIMER, 200, NULL);
+
+ // Reposition the child windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::OnDestroy()
+ {
+ SetMenu(NULL);
+ KillTimer(ID_STATUS_TIMER);
+ ::PostQuitMessage(0); // Terminates the application
+ }
+
+ inline LRESULT CFrame::OnDrawItem(WPARAM wParam, LPARAM lParam)
+ // OwnerDraw is used to render the popup menu items
+ {
+ LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam;
+ if (pdis->CtlType != ODT_MENU)
+ return CWnd::WndProcDefault(WM_DRAWITEM, wParam, lParam);
+
+ CRect rc = pdis->rcItem;
+ ItemData* pmd = (ItemData*)pdis->itemData;
+ CDC* pDrawDC = FromHandle(pdis->hDC);
+ MenuTheme tm = GetMenuTheme();
+
+ int Iconx = 16;
+ int Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+ int BarWidth = tm.UseThemes? Iconx + 8 : 0;
+
+ // Draw the side bar
+ if (tm.UseThemes)
+ {
+ CRect rcBar = rc;
+ rcBar.right = BarWidth;
+ pDrawDC->GradientFill(tm.clrPressed1, tm.clrPressed2, rcBar, TRUE);
+ }
+
+ if (pmd->fType & MFT_SEPARATOR)
+ {
+ // draw separator
+ CRect rcSep = rc;
+ rcSep.left = BarWidth;
+ if (tm.UseThemes)
+ pDrawDC->SolidFill(RGB(255,255,255), rcSep);
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_MENU), rcSep);
+ rcSep.top += (rc.bottom - rc.top)/2;
+ rcSep.left = BarWidth + 2;
+ pDrawDC->DrawEdge(rcSep, EDGE_ETCHED, BF_TOP);
+ }
+ else
+ {
+ // draw menu item
+ BOOL bDisabled = pdis->itemState & ODS_GRAYED;
+ BOOL bSelected = pdis->itemState & ODS_SELECTED;
+ BOOL bChecked = pdis->itemState & ODS_CHECKED;
+ CRect rcDraw = rc;
+
+ if ((bSelected) && (!bDisabled))
+ {
+ // draw selected item background
+ if (tm.UseThemes)
+ {
+ pDrawDC->CreateSolidBrush(tm.clrHot1);
+ pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline);
+ pDrawDC->Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom);
+ }
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_HIGHLIGHT), rcDraw);
+ }
+ else
+ {
+ // draw non-selected item background
+ rcDraw.left = BarWidth;
+ if (tm.UseThemes)
+ pDrawDC->SolidFill(RGB(255,255,255), rcDraw);
+ else
+ pDrawDC->SolidFill(GetSysColor(COLOR_MENU), rcDraw);
+ }
+
+ if (bChecked)
+ DrawCheckmark(pdis, *pDrawDC);
+ else
+ DrawMenuIcon(pdis, *pDrawDC, bDisabled);
+
+ // Calculate the text rect size
+ rc.left = rc.bottom - rc.top + 2;
+ if (_tcschr(pmd->GetItemText(), _T('\t')))
+ rc.right -= POST_TEXT_GAP; // Add POST_TEXT_GAP if the text includes a tab
+
+ // Draw the text
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ COLORREF colorText;
+ if (tm.UseThemes)
+ {
+ rc.left += 8;
+ colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : COLOR_MENUTEXT);
+ }
+ else
+ colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);
+
+ DrawMenuText(*pDrawDC, pmd->GetItemText(), rc, colorText);
+ pDrawDC->SetBkMode(iMode);
+ }
+
+ pDrawDC->Detach(); // Optional, deletes GDI objects sooner
+ return TRUE;
+ }
+
+ inline void CFrame::OnExitMenuLoop()
+ {
+ if (m_bUseCustomDraw)
+ {
+ for (UINT nItem = 0; nItem < m_vMenuItemData.size(); ++nItem)
+ {
+ // Undo OwnerDraw and put the text back
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ mii.fMask = MIIM_TYPE | MIIM_DATA;
+ mii.fType = m_vMenuItemData[nItem]->fType;
+ mii.dwTypeData = m_vMenuItemData[nItem]->GetItemText();
+ mii.cch = lstrlen(m_vMenuItemData[nItem]->GetItemText());
+ mii.dwItemData = 0;
+ ::SetMenuItemInfo(m_vMenuItemData[nItem]->hMenu, m_vMenuItemData[nItem]->nPos, TRUE, &mii);
+ }
+
+ m_vMenuItemData.clear();
+ }
+ }
+
+ inline void CFrame::OnHelp()
+ {
+ // Ensure only one dialog displayed even for multiple hits of the F1 button
+ if (!m_AboutDialog.IsWindow())
+ {
+ // Store the window handle that currently has keyboard focus
+ HWND hPrevFocus = ::GetFocus();
+ if (hPrevFocus == GetMenuBar())
+ hPrevFocus = m_hWnd;
+
+ m_AboutDialog.SetDlgParent(this);
+ m_AboutDialog.DoModal();
+
+ ::SetFocus(hPrevFocus);
+ }
+ }
+
+ inline void CFrame::OnInitMenuPopup(WPARAM wParam, LPARAM lParam)
+ {
+ // The system menu shouldn't be owner drawn
+ if (HIWORD(lParam)) return;
+
+ if (m_bUseCustomDraw)
+ {
+ CMenu* pMenu = FromHandle((HMENU)wParam);
+
+ for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i)
+ {
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ TCHAR szMenuItem[MAX_MENU_STRING] = _T("");
+
+ // Use old fashioned MIIM_TYPE instead of MIIM_FTYPE for MS VC6 compatibility
+ mii.fMask = MIIM_TYPE | MIIM_DATA | MIIM_SUBMENU;
+ mii.dwTypeData = szMenuItem;
+ mii.cch = MAX_MENU_STRING -1;
+
+ // Send message for menu updates
+ UINT menuItem = pMenu->GetMenuItemID(i);
+ SendMessage(UWM_UPDATE_COMMAND, (WPARAM)menuItem, 0);
+
+ // Specify owner-draw for the menu item type
+ if (pMenu->GetMenuItemInfo(i, &mii, TRUE))
+ {
+ if (0 == mii.dwItemData)
+ {
+ ItemData* pItem = new ItemData; // deleted in OnExitMenuLoop
+ pItem->hMenu = *pMenu;
+ pItem->nPos = i;
+ pItem->fType = mii.fType;
+ pItem->hSubMenu = mii.hSubMenu;
+ mii.fType |= MFT_OWNERDRAW;
+ lstrcpyn(pItem->GetItemText(), szMenuItem, MAX_MENU_STRING);
+ mii.dwItemData = (DWORD_PTR)pItem;
+
+ m_vMenuItemData.push_back(ItemDataPtr(pItem)); // Store pItem in m_vMenuItemData
+ pMenu->SetMenuItemInfo(i, &mii, TRUE); // Store pItem in mii
+ }
+ }
+ }
+ }
+ }
+
+ inline LRESULT CFrame::OnMeasureItem(WPARAM wParam, LPARAM lParam)
+ // Called before the Popup menu is displayed, so that the MEASUREITEMSTRUCT
+ // values can be assigned with the menu item's dimensions.
+ {
+ LPMEASUREITEMSTRUCT pmis = (LPMEASUREITEMSTRUCT) lParam;
+ if (pmis->CtlType != ODT_MENU)
+ return CWnd::WndProcDefault(WM_MEASUREITEM, wParam, lParam);
+
+ ItemData* pmd = (ItemData *) pmis->itemData;
+ assert(::IsMenu(pmd->hMenu)); // Does itemData contain a valid ItemData struct?
+ MenuTheme tm = GetMenuTheme();
+
+ if (pmd->fType & MFT_SEPARATOR)
+ {
+ pmis->itemHeight = 7;
+ pmis->itemWidth = 0;
+ }
+
+ else
+ {
+ CClientDC DesktopDC(NULL);
+
+ // Get the font used in menu items
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nm), &nm, 0);
+ // Default menu items are bold, so take this into account
+ if ((int)::GetMenuDefaultItem(pmd->hMenu, TRUE, GMDI_USEDISABLED) != -1)
+ nm.lfMenuFont.lfWeight = FW_BOLD;
+
+ TCHAR* pItemText = &(pmd->vItemText[0]);
+ DesktopDC.CreateFontIndirect(&nm.lfMenuFont);
+
+ // Calculate the size of the text
+ CSize size = DesktopDC.GetTextExtentPoint32(pItemText, lstrlen(pItemText));
+
+ // Calculate the size of the icon
+ int Iconx = 16;
+ int Icony = 16;
+ if (m_himlMenu) ImageList_GetIconSize(m_himlMenu, &Iconx, &Icony);
+
+ pmis->itemHeight = 2+ MAX(MAX(size.cy, GetSystemMetrics(SM_CYMENU)-2), Icony+2);
+ pmis->itemWidth = size.cx + MAX(::GetSystemMetrics(SM_CXMENUSIZE), Iconx+2);
+
+ // Allow extra width if the text includes a tab
+ if (_tcschr(pItemText, _T('\t')))
+ pmis->itemWidth += POST_TEXT_GAP;
+
+ // Allow extra width if the menu item has a sub menu
+ if (pmd->hSubMenu)
+ pmis->itemWidth += 10;
+
+ // Allow extra width for themed menu
+ if (tm.UseThemes)
+ pmis->itemWidth += 8;
+ }
+ return TRUE;
+ }
+
+ inline LRESULT CFrame::OnMenuChar(WPARAM wParam, LPARAM lParam)
+ {
+ if ((IsMenuBarUsed()) && (LOWORD(wParam)!= VK_SPACE))
+ {
+ // Activate MenuBar for key pressed with Alt key held down
+ GetMenuBar().OnMenuChar(wParam, lParam);
+ return -1L;
+ }
+ return CWnd::WndProcDefault(WM_MENUCHAR, wParam, lParam);
+ }
+
+ inline void CFrame::OnMenuSelect(WPARAM wParam, LPARAM lParam)
+ {
+ // Set the StatusBar text when we hover over a menu
+ // Only popup submenus have status strings
+ if (m_bShowMenuStatus)
+ {
+ int nID = LOWORD (wParam);
+ CMenu* pMenu = FromHandle((HMENU) lParam);
+
+ if ((pMenu != GetMenu()) && (nID != 0) && !(HIWORD(wParam) & MF_POPUP))
+ m_tsStatusText = LoadString(nID);
+ else
+ m_tsStatusText = _T("Ready");
+
+ SetStatusText();
+ }
+ }
+
+ inline LRESULT CFrame::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case UWM_UNDOCKED:
+ m_hOldFocus = 0;
+ break;
+ case RBN_HEIGHTCHANGE:
+ RecalcLayout();
+ Invalidate();
+ break;
+ // case RBN_LAYOUTCHANGED:
+ // if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ // GetReBar().MoveBandsLeft();
+ // break;
+ case RBN_MINMAX:
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().ShortBands)
+ return 1L; // Supress maximise or minimise rebar band
+ break;
+
+ // Display tooltips for the toolbar
+ case TTN_GETDISPINFO:
+ if (GetToolBar().IsWindow())
+ {
+ CToolBar* pToolBar = 0;
+ if (IsReBarUsed())
+ {
+ // Get the ToolBar's CWnd
+ CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
+ if (pWnd && (lstrcmp(pWnd->GetClassName(), _T("ToolbarWindow32")) == 0))
+ {
+ pToolBar = (CToolBar*)pWnd;
+ }
+ }
+
+ if (pToolBar)
+ {
+ LPNMTTDISPINFO lpDispInfo = (LPNMTTDISPINFO)lParam;
+ int iIndex = pToolBar->HitTest();
+ if (iIndex >= 0)
+ {
+ int nID = pToolBar->GetCommandID(iIndex);
+ if (nID > 0)
+ {
+ m_tsTooltip = LoadString(nID);
+ lpDispInfo->lpszText = (LPTSTR)m_tsTooltip.c_str();
+ }
+ else
+ m_tsTooltip = _T("");
+ }
+ }
+ }
+ break;
+ } // switch LPNMHDR
+
+ return 0L;
+
+ } // CFrame::Onotify(...)
+
+ inline void CFrame::OnSetFocus()
+ {
+ SetStatusText();
+ }
+
+ inline void CFrame::OnSysColorChange()
+ {
+ // Honour theme color changes
+ for (int nBand = 0; nBand <= GetReBar().GetBandCount(); ++nBand)
+ {
+ GetReBar().SetBandColor(nBand, GetSysColor(COLOR_BTNTEXT), GetSysColor(COLOR_BTNFACE));
+ }
+
+ // Update the status bar font and text
+ NONCLIENTMETRICS nm = {0};
+ nm.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0);
+ LOGFONT lf = nm.lfStatusFont;
+ CFont* pFont = FromHandle(CreateFontIndirect(&lf));
+ GetStatusBar().SetFont(pFont, FALSE);
+ SetStatusText();
+
+ if ((m_bUpdateTheme) && (m_bUseThemes)) SetTheme();
+
+ // Reposition and redraw everything
+ RecalcLayout();
+ RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ // Forward the message to the view window
+ m_pView->PostMessage(WM_SYSCOLORCHANGE, 0L, 0L);
+ }
+
+ inline LRESULT CFrame::OnSysCommand(WPARAM wParam, LPARAM lParam)
+ {
+ if ((SC_KEYMENU == wParam) && (VK_SPACE != lParam) && IsMenuBarUsed())
+ {
+ GetMenuBar().OnSysCommand(wParam, lParam);
+ return 0L;
+ }
+
+ if (SC_MINIMIZE == wParam)
+ m_hOldFocus = ::GetFocus();
+
+ return CWnd::WndProcDefault(WM_SYSCOMMAND, wParam, lParam);
+ }
+
+ inline void CFrame::OnTimer(WPARAM wParam)
+ {
+ if (ID_STATUS_TIMER == wParam)
+ {
+ if (m_bShowMenuStatus)
+ {
+ // Get the toolbar the point is over
+ CToolBar* pToolBar = 0;
+ if (IsReBarUsed())
+ {
+ // Get the ToolBar's CWnd
+ CWnd* pWnd = FromHandle(GetReBar().HitTest(GetCursorPos()));
+ if (pWnd && (dynamic_cast(pWnd)) && !(dynamic_cast(pWnd)))
+ pToolBar = (CToolBar*)pWnd;
+ }
+ else
+ {
+ CPoint pt = GetCursorPos();
+ CWnd* pWnd = WindowFromPoint(GetCursorPos());
+ if (pWnd && (dynamic_cast(pWnd)))
+ pToolBar = (CToolBar*)pWnd;
+ }
+
+ if ((pToolBar) && (WindowFromPoint(GetCursorPos()) == pToolBar))
+ {
+ // Which toolbar button is the mouse cursor hovering over?
+ int nButton = pToolBar->HitTest();
+ if (nButton >= 0)
+ {
+ int nID = pToolBar->GetCommandID(nButton);
+ // Only update the statusbar if things have changed
+ if (nID != m_nOldID)
+ {
+ if (nID != 0)
+ m_tsStatusText = LoadString(nID);
+ else
+ m_tsStatusText = _T("Ready");
+
+ if (GetStatusBar().IsWindow())
+ SetStatusText();
+ }
+ m_nOldID = nID;
+ }
+ }
+ else
+ {
+ if (m_nOldID != -1)
+ {
+ m_tsStatusText = _T("Ready");
+ SetStatusText();
+ }
+ m_nOldID = -1;
+ }
+ }
+
+ if (m_bShowIndicatorStatus)
+ SetStatusIndicators();
+ }
+ }
+
+ inline void CFrame::OnViewStatusBar()
+ {
+ m_bShowStatusBar = !m_bShowStatusBar;
+ ShowStatusBar(m_bShowStatusBar);
+ }
+
+ inline void CFrame::OnViewToolBar()
+ {
+ m_bShowToolBar = !m_bShowToolBar;
+ ShowToolBar(m_bShowToolBar);
+ }
+
+ inline void CFrame::PreCreate(CREATESTRUCT& cs)
+ {
+ // Set the frame window styles
+ cs.style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
+
+ // Set the original window position
+ cs.x = m_rcPosition.left;
+ cs.y = m_rcPosition.top;
+ cs.cx = m_rcPosition.Width();
+ cs.cy = m_rcPosition.Height();
+ }
+
+ inline void CFrame::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Win32++ Frame");
+ }
+
+ inline void CFrame::RecalcLayout()
+ {
+ CWnd* pView = GetView();
+ if ((!pView) || (!pView->GetHwnd()))
+ return;
+
+ // Resize the status bar
+ if (GetStatusBar().IsWindow() && m_bShowStatusBar)
+ {
+ GetStatusBar().SetWindowPos(NULL, 0, 0, 0, 0, SWP_SHOWWINDOW);
+ GetStatusBar().Invalidate();
+ SetStatusText();
+ }
+
+ // Resize the rebar or toolbar
+ if (IsReBarUsed())
+ {
+ GetReBar().SendMessage(WM_SIZE, 0L, 0L);
+ GetReBar().Invalidate();
+ }
+ else if (m_bUseToolBar && m_bShowToolBar)
+ GetToolBar().SendMessage(TB_AUTOSIZE, 0L, 0L);
+
+ // Resize the View window
+ CRect rClient = GetViewRect();
+ if ((rClient.bottom - rClient.top) >= 0)
+ {
+ int x = rClient.left;
+ int y = rClient.top;
+ int cx = rClient.Width();
+ int cy = rClient.Height();
+
+ pView->SetWindowPos( NULL, x, y, cx, cy, SWP_SHOWWINDOW|SWP_ASYNCWINDOWPOS );
+ }
+
+ // Adjust rebar bands
+ if (IsReBarUsed())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+
+ if (IsMenuBarUsed())
+ SetMenuBarBandSize();
+ }
+ }
+
+ inline void CFrame::RemoveMRUEntry(LPCTSTR szMRUEntry)
+ {
+ std::vector::iterator it;
+ for (it = m_vMRUEntries.begin(); it != m_vMRUEntries.end(); ++it)
+ {
+ if ((*it) == szMRUEntry)
+ {
+ m_vMRUEntries.erase(it);
+ break;
+ }
+ }
+
+ UpdateMRUMenu();
+ }
+
+ inline BOOL CFrame::SaveRegistrySettings()
+ {
+ // Store the window position in the registry
+ if (!m_tsKeyName.empty())
+ {
+ tString tsKeyName = _T("Software\\") + m_tsKeyName + _T("\\Frame Settings");
+ HKEY hKey = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw CWinException(_T("RegCreateKeyEx failed"));
+
+ WINDOWPLACEMENT Wndpl = {0};
+ Wndpl.length = sizeof(WINDOWPLACEMENT);
+
+ if (GetWindowPlacement(Wndpl))
+ {
+ // Get the Frame's window position
+ CRect rc = Wndpl.rcNormalPosition;
+ DWORD dwTop = MAX(rc.top, 0);
+ DWORD dwLeft = MAX(rc.left, 0);
+ DWORD dwWidth = MAX(rc.Width(), 100);
+ DWORD dwHeight = MAX(rc.Height(), 50);
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Top"), 0, REG_DWORD, (LPBYTE)&dwTop, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Left"), 0, REG_DWORD, (LPBYTE)&dwLeft, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Width"), 0, REG_DWORD, (LPBYTE)&dwWidth, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("Height"), 0, REG_DWORD, (LPBYTE)&dwHeight, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ }
+
+ // Store the ToolBar and statusbar states
+ DWORD dwShowToolBar = m_bShowToolBar;
+ DWORD dwShowStatusBar = m_bShowStatusBar;
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("ToolBar"), 0, REG_DWORD, (LPBYTE)&dwShowToolBar, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, _T("StatusBar"), 0, REG_DWORD, (LPBYTE)&dwShowStatusBar, sizeof(DWORD)))
+ throw CWinException(_T("RegSetValueEx failed"));
+
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to save registry settings\n"));
+
+ if (hKey)
+ {
+ // Roll back the registry changes by deleting this subkey
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+
+ // Store the MRU entries in the registry
+ if (m_nMaxMRU > 0)
+ {
+ tString tsKeyName = _T("Software\\") + m_tsKeyName + _T("\\Recent Files");
+ HKEY hKey = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw CWinException(_T("RegCreateKeyEx failed"));
+
+ for (UINT i = 0; i < m_nMaxMRU; ++i)
+ {
+ TCHAR szSubKey[10];
+ wsprintf(szSubKey, _T("File %d\0"), i+1);
+ tString tsPathName;
+ if (i < m_vMRUEntries.size())
+ tsPathName = m_vMRUEntries[i];
+
+ if (ERROR_SUCCESS != RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (LPBYTE)tsPathName.c_str(), (1 + lstrlen(tsPathName.c_str()))*sizeof(TCHAR)))
+ throw CWinException(_T("RegSetValueEx failed"));
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ catch (const CWinException& e)
+ {
+ TRACE(_T("Failed to save registry MRU settings\n"));
+
+ if (hKey)
+ {
+ // Roll back the registry changes by deleting this subkey
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CFrame::SetFrameMenu(INT ID_MENU)
+ {
+ // Sets the frame's menu from a Resouce ID.
+ // A resource ID of 0 removes the menu from the frame.
+ HMENU hMenu = 0;
+ if (ID_MENU != 0)
+ {
+ // Sets the frame's menu from a resource ID.
+ hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(ID_MENU));
+ assert (hMenu);
+ }
+
+ SetFrameMenu(hMenu);
+ }
+
+ inline void CFrame::SetFrameMenu(HMENU hMenu)
+ {
+ // Sets the frame's menu from a HMENU.
+ m_Menu.Attach(hMenu);
+
+ if (IsMenuBarUsed())
+ {
+ GetMenuBar().SetMenu(GetFrameMenu());
+ BOOL bShow = (hMenu != NULL); // boolean expression
+ ShowMenu(bShow);
+ }
+ else
+ SetMenu(&m_Menu);
+ }
+
+ inline UINT CFrame::SetMenuIcons(const std::vector& MenuData, COLORREF crMask, UINT ToolBarID, UINT ToolBarDisabledID)
+ {
+ // Remove any existing menu icons
+ if (m_himlMenu) ImageList_Destroy(m_himlMenu);
+ if (m_himlMenuDis) ImageList_Destroy(m_himlMenuDis);
+ m_himlMenu = NULL;
+ m_himlMenuDis = NULL;
+ m_vMenuIcons.clear();
+
+ // Exit if no ToolBarID is specified
+ if (ToolBarID == 0) return 0;
+
+ // Add the menu icons from the bitmap IDs
+ return AddMenuIcons(MenuData, crMask, ToolBarID, ToolBarDisabledID);
+ }
+
+ inline void CFrame::SetMenuBarBandSize()
+ {
+ // Sets the minimum width of the MenuBar band to the width of the rebar
+ // This prevents other bands from moving to this MenuBar's row.
+
+ CRect rcClient = GetClientRect();
+ CReBar& RB = GetReBar();
+ int nBand = RB.GetBand(GetMenuBar());
+ CRect rcBorder = RB.GetBandBorders(nBand);
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;
+ RB.GetBandInfo(nBand, rbbi);
+
+ int Width;
+ if ((GetReBar().GetReBarTheme().UseThemes) && (GetReBar().GetReBarTheme().LockMenuBand))
+ Width = rcClient.Width() - rcBorder.Width() - 2;
+ else
+ Width = GetMenuBar().GetMaxSize().cx;
+
+ rbbi.cxMinChild = Width;
+ rbbi.cx = Width;
+
+ RB.SetBandInfo(nBand, rbbi);
+ }
+
+ inline void CFrame::SetMenuTheme(MenuTheme& Theme)
+ {
+ m_ThemeMenu.UseThemes = Theme.UseThemes;
+ m_ThemeMenu.clrHot1 = Theme.clrHot1;
+ m_ThemeMenu.clrHot2 = Theme.clrHot2;
+ m_ThemeMenu.clrPressed1 = Theme.clrPressed1;
+ m_ThemeMenu.clrPressed2 = Theme.clrPressed2;
+ m_ThemeMenu.clrOutline = Theme.clrOutline;
+
+ GetMenuBar().SetMenuBarTheme(Theme); // Sets the theme for MenuBar buttons
+ Invalidate();
+ }
+
+ inline void CFrame::SetStatusIndicators()
+ {
+ if (::IsWindow(GetStatusBar()))
+ {
+ LPCTSTR Status1 = (::GetKeyState(VK_CAPITAL) & 0x0001)? _T("\tCAP") : _T("");
+ LPCTSTR Status2 = (::GetKeyState(VK_NUMLOCK) & 0x0001)? _T("\tNUM") : _T("");
+ LPCTSTR Status3 = (::GetKeyState(VK_SCROLL) & 0x0001)? _T("\tSCRL"): _T("");
+
+ // Only update indictors if the text has changed
+ if (Status1 != m_OldStatus[0]) GetStatusBar().SetPartText(1, (Status1));
+ if (Status2 != m_OldStatus[1]) GetStatusBar().SetPartText(2, (Status2));
+ if (Status3 != m_OldStatus[2]) GetStatusBar().SetPartText(3, (Status3));
+
+ m_OldStatus[0] = Status1;
+ m_OldStatus[1] = Status2;
+ m_OldStatus[2] = Status3;
+ }
+ }
+
+ inline void CFrame::SetStatusText()
+ {
+ if (::IsWindow(GetStatusBar()))
+ {
+ // Calculate the width of the text indicators
+ CClientDC dcStatus(&GetStatusBar());
+ CSize csCAP = dcStatus.GetTextExtentPoint32(_T("\tCAP"), lstrlen(_T("\tCAP")));
+ CSize csNUM = dcStatus.GetTextExtentPoint32(_T("\tNUM"), lstrlen(_T("\tNUM")));
+ CSize csSCRL = dcStatus.GetTextExtentPoint32(_T("\tSCRL "), lstrlen(_T("\tSCRL ")));
+
+ // Get the coordinates of the parent window's client area.
+ CRect rcClient = GetClientRect();
+ int width = MAX(300, rcClient.right);
+
+ if (m_bShowIndicatorStatus)
+ {
+ // Create 4 panes
+ GetStatusBar().SetPartWidth(0, width - (csCAP.cx+csNUM.cx+csSCRL.cx+20));
+ GetStatusBar().SetPartWidth(1, csCAP.cx);
+ GetStatusBar().SetPartWidth(2, csNUM.cx);
+ GetStatusBar().SetPartWidth(3, csSCRL.cx);
+
+ SetStatusIndicators();
+ }
+
+ // Place text in the 1st pane
+ GetStatusBar().SetPartText(0, m_tsStatusText.c_str());
+ }
+ }
+
+ inline void CFrame::SetTheme()
+ {
+ // Note: To modify theme colors, override this function in CMainframe,
+ // and make any modifications there.
+
+ // Avoid themes if using less than 16 bit colors
+ CClientDC DesktopDC(NULL);
+ if (DesktopDC.GetDeviceCaps(BITSPIXEL) < 16)
+ m_bUseThemes = FALSE;
+
+ BOOL T = TRUE;
+ BOOL F = FALSE;
+
+ if (m_bUseThemes)
+ {
+ // Set a flag redo SetTheme when the theme changes
+ m_bUpdateTheme = TRUE;
+
+ // Detect the XP theme name
+ WCHAR Name[30] = L"";
+ HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll"));
+ if(hMod)
+ {
+ typedef HRESULT (__stdcall *PFNGETCURRENTTHEMENAME)(LPWSTR pszThemeFileName, int cchMaxNameChars,
+ LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszSizeBuff, int cchMaxSizeChars);
+
+ PFNGETCURRENTTHEMENAME pfn = (PFNGETCURRENTTHEMENAME)GetProcAddress(hMod, "GetCurrentThemeName");
+
+ (*pfn)(0, 0, Name, 30, 0, 0);
+
+ ::FreeLibrary(hMod);
+ }
+
+ enum Themetype{ Modern, Grey, Blue, Silver, Olive };
+
+ int Theme = Grey;
+ if (GetWinVersion() < 2600) // Not for Vista and above
+ {
+ if (0 == wcscmp(L"NormalColor", Name)) Theme = Blue;
+ if (0 == wcscmp(L"Metallic", Name)) Theme = Silver;
+ if (0 == wcscmp(L"HomeStead", Name)) Theme = Olive;
+ }
+ else
+ Theme = Modern;
+
+ switch (Theme)
+ {
+ case Modern:
+ {
+ ToolBarTheme tt = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(150, 220, 255), RGB(80, 100, 255), RGB(127, 127, 255)};
+ ReBarTheme tr = {T, RGB(220, 225, 250), RGB(240, 242, 250), RGB(240, 240, 250), RGB(180, 200, 230), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(180, 250, 255), RGB(140, 190, 255), RGB(240, 250, 255), RGB(120, 170, 220), RGB(127, 127, 255)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Grey: // A color scheme suitable for 16 bit colors. Suitable for Windows older than XP.
+ {
+ ToolBarTheme tt = {T, RGB(182, 189, 210), RGB(182, 189, 210), RGB(133, 146, 181), RGB(133, 146, 181), RGB(10, 36, 106)};
+ ReBarTheme tr = {T, RGB(212, 208, 200), RGB(212, 208, 200), RGB(230, 226, 222), RGB(220, 218, 208), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(182, 189, 210), RGB( 182, 189, 210), RGB(200, 196, 190), RGB(200, 196, 190), RGB(100, 100, 100)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+ case Blue:
+ {
+ // Used for XP default (blue) color scheme
+ ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(192, 128, 255)};
+ ReBarTheme tr = {T, RGB(150,190,245), RGB(196,215,250), RGB(220,230,250), RGB( 70,130,220), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(220,230,250), RGB(150,190,245), RGB(128, 128, 200)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Silver:
+ {
+ // Used for XP Silver color scheme
+ ToolBarTheme tt = {T, RGB(192, 210, 238), RGB(192, 210, 238), RGB(152, 181, 226), RGB(152, 181, 226), RGB(49, 106, 197)};
+ ReBarTheme tr = {T, RGB(225, 220, 240), RGB(240, 240, 245), RGB(245, 240, 255), RGB(160, 155, 180), F, T, T, T, T, F};
+ MenuTheme tm = {T, RGB(196, 215, 250), RGB( 120, 180, 220), RGB(240, 240, 245), RGB(170, 165, 185), RGB(128, 128, 150)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+
+ case Olive:
+ {
+ // Used for XP Olive color scheme
+ ReBarTheme tr = {T, RGB(215, 216, 182), RGB(242, 242, 230), RGB(249, 255, 227), RGB(178, 191, 145), F, T, T, T, T, F};
+ ToolBarTheme tt = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(255, 140, 40), RGB(255, 180, 80), RGB(200, 128, 128)};
+ MenuTheme tm = {T, RGB(255, 230, 190), RGB(255, 190, 100), RGB(249, 255, 227), RGB(178, 191, 145), RGB(128, 128, 128)};
+
+ GetToolBar().SetToolBarTheme(tt);
+ SetMenuTheme(tm); // Sets the theme for popup menus and MenuBar
+
+ GetReBar().SetReBarTheme(tr);
+ }
+ break;
+ }
+ }
+ else
+ {
+ // Use a classic style by default
+ ReBarTheme tr = {T, 0, 0, 0, 0, F, T, T, F, F, F};
+ GetReBar().SetReBarTheme(tr);
+ }
+
+ RecalcLayout();
+ }
+
+ inline void CFrame::SetToolBarImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID)
+ // Either sets the imagelist or adds/replaces bitmap depending on ComCtl32.dll version
+ // Assumes the width of the button image = bitmap_size / buttons
+ // Assumes buttons have been already been added via AdddToolBarButton
+ // The colour mask is ignored for 32bit bitmaps, but is required for 24bit bitmaps
+ // The colour mask is often grey RGB(192,192,192) or magenta (255,0,255)
+ // The color mask is ignored for 32bit bitmap resources
+ // The Hot and disabled bitmap resources can be 0
+ {
+ GetToolBar().SetImages(crMask, ToolBarID, ToolBarHotID, ToolBarDisabledID);
+ }
+
+ inline void CFrame::SetupToolBar()
+ {
+ // Use this function to set the Resource IDs for the toolbar(s).
+
+/* // Set the Resource IDs for the toolbar buttons
+ AddToolBarButton( IDM_FILE_NEW );
+ AddToolBarButton( IDM_FILE_OPEN );
+ AddToolBarButton( IDM_FILE_SAVE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_EDIT_CUT );
+ AddToolBarButton( IDM_EDIT_COPY );
+ AddToolBarButton( IDM_EDIT_PASTE );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_FILE_PRINT );
+ AddToolBarButton( 0 ); // Separator
+ AddToolBarButton( IDM_HELP_ABOUT );
+*/
+ }
+
+ inline void CFrame::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ if (m_pView != &wndView)
+ {
+ // Destroy the existing view window (if any)
+ if (m_pView) m_pView->Destroy();
+
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ // The frame is already created, so create and position the new view too
+ assert(GetView()); // Use SetView in CMainFrame's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+ }
+ }
+
+ inline void CFrame::ShowMenu(BOOL bShow)
+ {
+ if (bShow)
+ {
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), TRUE);
+ else
+ SetMenu(&m_Menu);
+ }
+ else
+ {
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetMenuBar()), FALSE);
+ else
+ SetMenu(NULL);
+ }
+
+ if (GetReBar().IsWindow())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+
+
+ inline void CFrame::ShowStatusBar(BOOL bShow)
+ {
+ if (bShow)
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_CHECKED);
+ GetStatusBar().ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED);
+ GetStatusBar().ShowWindow(SW_HIDE);
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::ShowToolBar(BOOL bShow)
+ {
+ if (bShow)
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_CHECKED);
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), TRUE);
+ else
+ GetToolBar().ShowWindow(SW_SHOW);
+ }
+ else
+ {
+ m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED);
+ if (IsReBarUsed())
+ GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), FALSE);
+ else
+ GetToolBar().ShowWindow(SW_HIDE);
+ }
+
+ if (GetReBar().IsWindow())
+ {
+ if (GetReBar().GetReBarTheme().UseThemes && GetReBar().GetReBarTheme().BandsLeft)
+ GetReBar().MoveBandsLeft();
+ }
+
+ // Reposition the Windows
+ RecalcLayout();
+ }
+
+ inline void CFrame::UpdateMRUMenu()
+ {
+ if (0 >= m_nMaxMRU) return;
+
+ // Set the text for the MRU Menu
+ tString tsMRUArray[16];
+ UINT MaxMRUArrayIndex = 0;
+ if (m_vMRUEntries.size() > 0)
+ {
+ for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n)
+ {
+ tsMRUArray[n] = m_vMRUEntries[n];
+ if (tsMRUArray[n].length() > MAX_MENU_STRING - 10)
+ {
+ // Truncate the string if its too long
+ tsMRUArray[n].erase(0, tsMRUArray[n].length() - MAX_MENU_STRING +10);
+ tsMRUArray[n] = _T("... ") + tsMRUArray[n];
+ }
+
+ // Prefix the string with its number
+ TCHAR tVal[5];
+ wsprintf(tVal, _T("%d "), n+1);
+ tsMRUArray[n] = tVal + tsMRUArray[n];
+ MaxMRUArrayIndex = n;
+ }
+ }
+ else
+ {
+ tsMRUArray[0] = _T("Recent Files");
+ }
+
+ // Set MRU menu items
+ MENUITEMINFO mii = {0};
+ mii.cbSize = GetSizeofMenuItemInfo();
+
+ int nFileItem = 0; // We place the MRU items under the left most menu item
+ CMenu* pFileMenu = GetFrameMenu().GetSubMenu(nFileItem);
+
+ if (pFileMenu)
+ {
+ // Remove all but the first MRU Menu entry
+ for (UINT u = IDW_FILE_MRU_FILE2; u <= IDW_FILE_MRU_FILE1 +16; ++u)
+ {
+ pFileMenu->DeleteMenu(u, MF_BYCOMMAND);
+ }
+
+ int MaxMRUIndex = (int)MIN(MaxMRUArrayIndex, m_nMaxMRU);
+
+ for (int index = MaxMRUIndex; index >= 0; --index)
+ {
+ mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
+ mii.fState = (0 == m_vMRUEntries.size())? MFS_GRAYED : 0;
+ mii.fType = MFT_STRING;
+ mii.wID = IDW_FILE_MRU_FILE1 + index;
+ mii.dwTypeData = (LPTSTR)tsMRUArray[index].c_str();
+
+ BOOL bResult;
+ if (index == MaxMRUIndex)
+ // Replace the last MRU entry first
+ bResult = pFileMenu->SetMenuItemInfo(IDW_FILE_MRU_FILE1, &mii, FALSE);
+ else
+ // Insert the other MRU entries next
+ bResult = pFileMenu->InsertMenuItem(IDW_FILE_MRU_FILE1 + index + 1, &mii, FALSE);
+
+ if (!bResult)
+ {
+ TRACE(_T("Failed to set MRU menu item\n"));
+ break;
+ }
+ }
+ }
+
+ DrawMenuBar();
+ }
+
+ inline LRESULT CFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ return 0L;
+ case WM_CLOSE:
+ OnClose();
+ break;
+ case WM_DESTROY:
+ OnDestroy();
+ return 0L;
+ case WM_ERASEBKGND:
+ return 0L;
+ case WM_HELP:
+ OnHelp();
+ return 0L;
+ case WM_MENUCHAR:
+ return OnMenuChar(wParam, lParam);
+ case WM_MENUSELECT:
+ OnMenuSelect(wParam, lParam);
+ return 0L;
+ case WM_SETFOCUS:
+ OnSetFocus();
+ break;
+ case WM_SIZE:
+ RecalcLayout();
+ return 0L;
+ case WM_SYSCOLORCHANGE:
+ // Changing themes trigger this
+ OnSysColorChange();
+ return 0L;
+ case WM_SYSCOMMAND:
+ return OnSysCommand(wParam, lParam);
+ case WM_TIMER:
+ OnTimer(wParam);
+ return 0L;
+ case WM_DRAWITEM:
+ // Owner draw menu items
+ return OnDrawItem(wParam, lParam);
+ case WM_INITMENUPOPUP:
+ OnInitMenuPopup(wParam, lParam);
+ break;
+ case WM_MEASUREITEM:
+ return OnMeasureItem(wParam, lParam);
+ case WM_EXITMENULOOP:
+ OnExitMenuLoop();
+ break;
+ case UWM_GETMENUTHEME:
+ {
+ MenuTheme& tm = GetMenuTheme();
+ return (LRESULT)&tm;
+ }
+ case UWM_GETREBARTHEME:
+ {
+ ReBarTheme& rm = GetReBarTheme();
+ return (LRESULT)&rm;
+ }
+ case UWM_GETTOOLBARTHEME:
+ {
+ ToolBarTheme& tt = GetToolBarTheme();
+ return (LRESULT)&tt;
+ }
+ } // switch uMsg
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ } // LRESULT CFrame::WndProcDefault(...)
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_FRAME_H_
diff --git a/external/win32cpp/include/gdi.h b/external/win32cpp/include/gdi.h
new file mode 100644
index 0000000..45141f7
--- /dev/null
+++ b/external/win32cpp/include/gdi.h
@@ -0,0 +1,3944 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// gdi.h
+// Declaration of the CDC class, and CBitmapInfoPtr class
+
+// The CDC class provides a device context, along with the various associated
+// objects such as Bitmaps, Brushes, Bitmaps, Fonts and Pens. This class
+// handles the creation, selection, de-selection and deletion of these objects
+// automatically. It also automatically deletes or releases the device context
+// itself as appropriate. Any failure to create the new GDI object throws an
+// exception.
+//
+// The CDC class is sufficient for most GDI programming needs. Sometimes
+// however we need to have the GDI object seperated from the device context.
+// Wrapper classes for GDI objects are provided for this purpose. The classes
+// are CBitmap, CBrush, CFont, CPalette, CPen and CRgn. These classes
+// automatically delete the GDI resouce assigned to them when their destructor
+// is called. These wrapper class objects can be attached to the CDC as
+// shown below.
+//
+// Coding Exampe without CDC ...
+// void DrawLine()
+// {
+// HDC hdcClient = ::GetDC(m_hWnd);
+// HDC hdcMem = ::CreateCompatibleDC(hdcClient);
+// HBITMAP hBitmap = ::CreateCompatibleBitmap(hdcClient, cx, cy);
+// HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hdcMem, hBitmap);
+// HPEN hPen = ::CreatePen(PS_SOLID, 1, RGB(255,0,0);
+// HPEN hOldPen = (HPEN)::SelectObject(hdcMem, hPen);
+// ::MoveToEx(hdcMem, 0, 0, NULL);
+// ::LineTo(hdcMem, 50, 50);
+// ::BitBlt(hdcClient, 0, 0, cx, cy, hdcMem, 0, 0);
+// ::SelectObject(hdcMem, hOldPen);
+// ::DeleteObject(hPen);
+// ::SelectObject(hdcMem, hOldBitmap);
+// ::DeleteObject(hBitmap);
+// ::DeleteDC(hdcMem);
+// ::ReleaseDC(m_hWnd, hdcClient);
+// }
+//
+// Coding Example with CDC classes ...
+// void DrawLine()
+// {
+// CClientDC dcClient(this)
+// CMemDC dcMem(&dcClient);
+// CBitmap* pOldBitmap = dcMem.CreateCompatibleBitmap(&dcClient, cx, cy);
+// CPen* pOldPen = CMemDC.CreatePen(PS_SOLID, 1, RGB(255,0,0);
+// CMemDC.MoveTo(0, 0);
+// CMemDC.LineTo(50, 50);
+// dcClient.BitBlt(0, 0, cx, cy, &CMemDC, 0, 0);
+// }
+//
+// Coding Example with CDC classes and CPen ...
+// void DrawLine()
+// {
+// CClientDC dcClient(this)
+// CMemDC CMemDC(&dcClient);
+// CBitmap* pOldBitmap = dcMem.CreateCompatibleBitmap(&dcClient, cx, cy);
+// CPen MyPen(PS_SOLID, 1, RGB(255,0,0));
+// CPen* pOldPen = CMemDC.SelectObject(&MyPen);
+// CMemDC.MoveTo(0, 0);
+// CMemDC.LineTo(50, 50);
+// dcClient.BitBlt(0, 0, cx, cy, &CMemDC, 0, 0);
+// }
+
+// Notes:
+// * When the CDC object drops out of scope, it's destructor is called, releasing
+// or deleting the device context as appropriate.
+// * When the destructor for CBitmap, CBrush, CPalette, CPen and CRgn are called,
+// the destructor is called deleting their GDI object.
+// * When the CDC object' destructor is called, any GDI objects created by one of
+// the CDC member functions (CDC::CreatePen for example) will be deleted.
+// * Bitmaps can only be selected into one device context at a time.
+// * Palettes use SelectPalatte to select them into device the context.
+// * Regions use SelectClipRgn to select them into the device context.
+// * The FromHandle function can be used to convert a GDI handle (HDC, HPEN,
+// HBITMAP etc) to a pointer of the appropriate GDI class (CDC, CPen CBitmap etc).
+// The FromHandle function creates a temporary object unless the HANDLE is already
+// assigned to a GDI class. Temporary objects don't delete their GDI object when
+// their destructor is called.
+// * All the GDI classes are reference counted. This allows functions to safely
+// pass these objects by value, as well as by pointer or by reference.
+
+// The CBitmapInfoPtr class is a convienient wrapper for the BITMAPINFO structure.
+// The size of the BITMAPINFO structure is dependant on the type of HBITMAP, and its
+// space needs to be allocated dynamically. CBitmapInfoPtr automatically allocates
+// and deallocates the memory for the structure. A CBitmapInfoPtr object can be
+// used anywhere in place of a LPBITMAPINFO. LPBITMAPINFO is used in functions like
+// GetDIBits and SetDIBits.
+//
+// Coding example ...
+// CDC MemDC = CreateCompatibleDC(NULL);
+// CBitmapInfoPtr pbmi(hBitmap);
+// MemDC.GetDIBits(hBitmap, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+
+#ifndef _WIN32XX_GDI_H_
+#define _WIN32XX_GDI_H_
+
+#include "wincore.h"
+
+// Disable macros from Windowsx.h
+#undef CopyRgn
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////////
+ // Declarations for some global functions in the Win32xx namespace
+ //
+#ifndef _WIN32_WCE
+ void GrayScaleBitmap(CBitmap* pbmSource);
+ void TintBitmap(CBitmap* pbmSource, int cRed, int cGreen, int cBlue);
+ HIMAGELIST CreateDisabledImageList(HIMAGELIST himlNormal);
+#endif
+
+ ///////////////////////////////////////////////
+ // Declarations for the CGDIObject class
+ //
+ class CGDIObject
+ {
+ friend CBitmap* FromHandle(HBITMAP hBitmap);
+ friend CBrush* FromHandle(HBRUSH hBrush);
+ friend CDC* FromHandle(HDC hDC);
+ friend CFont* FromHandle(HFONT hFont);
+ friend CPalette* FromHandle(HPALETTE hPalette);
+ friend CPen* FromHandle(HPEN hPen);
+ friend CRgn* FromHandle(HRGN hRgn);
+
+ public:
+ struct DataMembers // A structure that contains the data members for CGDIObject
+ {
+ HGDIOBJ hGDIObject;
+ long Count;
+ BOOL bRemoveObject;
+ };
+ CGDIObject();
+ CGDIObject(const CGDIObject& rhs);
+ virtual ~CGDIObject();
+ CGDIObject& operator = ( const CGDIObject& rhs );
+ void operator = (HGDIOBJ hObject);
+
+ void Attach(HGDIOBJ hObject);
+ HGDIOBJ Detach();
+ HGDIOBJ GetHandle() const;
+ int GetObject(int nCount, LPVOID pObject) const;
+
+ protected:
+ DataMembers* m_pData;
+
+ private:
+ void AddToMap();
+ BOOL RemoveFromMap();
+ void Release();
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmap class
+ //
+ class CBitmap : public CGDIObject
+ {
+ public:
+ CBitmap();
+ CBitmap(HBITMAP hBitmap);
+ CBitmap(LPCTSTR lpstr);
+ CBitmap(int nID);
+ operator HBITMAP() const;
+ ~CBitmap();
+
+ // Create and load methods
+ BOOL LoadBitmap(LPCTSTR lpszName);
+ BOOL LoadBitmap(int nID);
+ BOOL LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad);
+ BOOL LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad);
+ BOOL LoadOEMBitmap(UINT nIDBitmap);
+ HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, LPCVOID lpBits);
+ HBITMAP CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight);
+ HBITMAP CreateDIBSection(CDC* pDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, LPVOID* ppvBits, HANDLE hSection, DWORD dwOffset);
+
+#ifndef _WIN32_WCE
+ HBITMAP CreateDIBitmap(CDC* pDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, LPCVOID lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse);
+ HBITMAP CreateMappedBitmap(UINT nIDBitmap, UINT nFlags = 0, LPCOLORMAP lpColorMap = NULL, int nMapSize = 0);
+ HBITMAP CreateBitmapIndirect(LPBITMAP lpBitmap);
+ int GetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const;
+ int SetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse);
+ CSize GetBitmapDimensionEx() const;
+ CSize SetBitmapDimensionEx(int nWidth, int nHeight);
+#endif // !_WIN32_WCE
+
+ // Attributes
+ BITMAP GetBitmapData() const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBrush class
+ //
+ class CBrush : public CGDIObject
+ {
+ public:
+ CBrush();
+ CBrush(HBRUSH hBrush);
+ CBrush(COLORREF crColor);
+ operator HBRUSH() const;
+ ~CBrush();
+
+ HBRUSH CreateSolidBrush(COLORREF crColor);
+ HBRUSH CreatePatternBrush(CBitmap* pBitmap);
+ LOGBRUSH GetLogBrush() const;
+
+#ifndef _WIN32_WCE
+ HBRUSH CreateHatchBrush(int nIndex, COLORREF crColor);
+ HBRUSH CreateBrushIndirect(LPLOGBRUSH lpLogBrush);
+ HBRUSH CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec);
+ HBRUSH CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT nUsage);
+#endif // !defined(_WIN32_WCE)
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CFont class
+ //
+ class CFont : public CGDIObject
+ {
+ public:
+ CFont();
+ CFont(HFONT hFont);
+ CFont(const LOGFONT* lpLogFont);
+ operator HFONT() const;
+ ~CFont();
+
+ // Create methods
+ HFONT CreateFontIndirect(const LOGFONT* lpLogFont);
+ HFONT CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL, BOOL bBold = FALSE, BOOL bItalic = FALSE);
+ HFONT CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC = NULL);
+
+#ifndef _WIN32_WCE
+ HFONT CreateFont(int nHeight, int nWidth, int nEscapement,
+ int nOrientation, int nWeight, DWORD dwItalic, DWORD dwUnderline,
+ DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision,
+ DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily,
+ LPCTSTR lpszFacename);
+#endif // #ifndef _WIN32_WCE
+
+ // Attributes
+ LOGFONT GetLogFont() const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPalette class
+ //
+ class CPalette : public CGDIObject
+ {
+ public:
+ CPalette();
+ CPalette(HPALETTE hPalette);
+ operator HPALETTE() const;
+ ~CPalette();
+
+ // Create methods
+ HPALETTE CreatePalette(LPLOGPALETTE lpLogPalette);
+
+#ifndef _WIN32_WCE
+ HPALETTE CreateHalftonePalette(CDC* pDC);
+#endif // !_WIN32_WCE
+
+ // Attributes
+ int GetEntryCount() const;
+ UINT GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const;
+ UINT SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors);
+
+ // Operations
+#ifndef _WIN32_WCE
+ BOOL ResizePalette(UINT nNumEntries);
+ void AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors);
+#endif // !_WIN32_WCE
+
+ UINT GetNearestPaletteIndex (COLORREF crColor) const;
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPen class
+ //
+ class CPen : public CGDIObject
+ {
+ public:
+ CPen();
+ CPen(HPEN hPen);
+ CPen(int nPenStyle, int nWidth, COLORREF crColor);
+#ifndef _WIN32_WCE
+ CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL);
+#endif // !_WIN32_WCE
+ operator HPEN() const;
+ ~CPen();
+
+ HPEN CreatePen(int nPenStyle, int nWidth, COLORREF crColor);
+ HPEN CreatePenIndirect(LPLOGPEN lpLogPen);
+ LOGPEN GetLogPen() const;
+
+#ifndef _WIN32_WCE
+ HPEN ExtCreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount = 0, const DWORD* lpStyle = NULL);
+ EXTLOGPEN GetExtLogPen() const;
+#endif // !_WIN32_WCE
+
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CRgn class
+ //
+ class CRgn : public CGDIObject
+ {
+ public:
+ CRgn();
+ CRgn(HRGN hRgn);
+ operator HRGN() const;
+ ~CRgn ();
+
+ // Create methods
+ HRGN CreateRectRgn(int x1, int y1, int x2, int y2);
+ HRGN CreateRectRgnIndirect(const RECT& rc);
+ HRGN CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData);
+
+#ifndef _WIN32_WCE
+ HRGN CreateEllipticRgn(int x1, int y1, int x2, int y2);
+ HRGN CreateEllipticRgnIndirect(const RECT& rc);
+ HRGN CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode);
+ HRGN CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode);
+ HRGN CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3);
+ HRGN CreateFromPath(HDC hDC);
+#endif // !_WIN32_WCE
+
+ // Operations
+ void SetRectRgn(int x1, int y1, int x2, int y2);
+ void SetRectRgn(const RECT& rc);
+ int CombineRgn(CRgn* pRgnSrc1, CRgn* pRgnSrc2, int nCombineMode);
+ int CombineRgn(CRgn* pRgnSrc, int nCombineMode);
+ int CopyRgn(CRgn* pRgnSrc);
+ BOOL EqualRgn(CRgn* pRgn) const;
+ int OffsetRgn(int x, int y);
+ int OffsetRgn(POINT& pt);
+ int GetRgnBox(RECT& rc) const;
+ BOOL PtInRegion(int x, int y) const;
+ BOOL PtInRegion(POINT& pt) const;
+ BOOL RectInRegion(const RECT& rc) const;
+ int GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const;
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CDC class
+ //
+ class CDC
+ {
+ friend class CWinApp;
+ friend class CWnd;
+ friend CDC* FromHandle(HDC hDC);
+
+ public:
+ struct DataMembers // A structure that contains the data members for CDC
+ {
+ std::vector m_vGDIObjects; // Smart pointers to internally created Bitmaps, Brushes, Fonts, Bitmaps and Regions
+ HDC hDC; // The HDC belonging to this CDC
+ long Count; // Reference count
+ BOOL bRemoveHDC; // Delete/Release the HDC on destruction
+ HWND hWnd; // The HWND of a Window or Client window DC
+ int nSavedDCState; // The save state of the HDC.
+ };
+
+ CDC(); // Constructs a new CDC without assigning a HDC
+ CDC(HDC hDC, HWND hWnd = 0); // Assigns a HDC to a new CDC
+ CDC(const CDC& rhs); // Constructs a new copy of the CDC
+ virtual ~CDC();
+ operator HDC() const { return m_pData->hDC; } // Converts a CDC to a HDC
+ CDC& operator = (const CDC& rhs); // Assigns a CDC to an existing CDC
+
+ void Attach(HDC hDC, HWND hWnd = 0);
+ void Destroy();
+ HDC Detach();
+ HDC GetHDC() const { return m_pData->hDC; }
+ CPalette* SelectPalette(const CPalette* pPalette, BOOL bForceBkgnd);
+ CBitmap* SelectObject(const CBitmap* pBitmap);
+ CBrush* SelectObject(const CBrush* pBrush);
+ CFont* SelectObject(const CFont* pFont);
+ CPalette* SelectObject(const CPalette* pPalette);
+ CPen* SelectObject(const CPen* pPen);
+
+#ifndef _WIN32_WCE
+ void operator = (const HDC hDC);
+#endif
+
+ // Initialization
+ BOOL CreateCompatibleDC(CDC* pDC);
+ BOOL CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData);
+ int GetDeviceCaps(int nIndex) const;
+#ifndef _WIN32_WCE
+ BOOL CreateIC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData);
+#endif
+
+ // Create and Select Bitmaps
+ CBitmap* CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors);
+ CBitmap* CreateCompatibleBitmap(CDC* pDC, int cx, int cy);
+ CBitmap* CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits,
+ HANDLE hSection, DWORD dwOffset);
+ BITMAP GetBitmapData() const;
+ CBitmap* LoadBitmap(UINT nID);
+ CBitmap* LoadBitmap(LPCTSTR lpszName);
+ CBitmap* LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad);
+ CBitmap* LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad);
+ CBitmap* LoadOEMBitmap(UINT nIDBitmap); // for OBM_/OCR_/OIC
+
+#ifndef _WIN32_WCE
+ CBitmap* CreateBitmapIndirect(LPBITMAP pBitmap);
+ CBitmap* CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit,
+ BITMAPINFO& bmi, UINT fuUsage);
+ CBitmap* CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/);
+#endif
+
+ // Create and Select Brushes
+ CBrush* CreatePatternBrush(CBitmap* pBitmap);
+ CBrush* CreateSolidBrush(COLORREF rbg);
+ LOGBRUSH GetLogBrush() const;
+
+#ifndef _WIN32_WCE
+ CBrush* CreateBrushIndirect(LPLOGBRUSH pLogBrush);
+ CBrush* CreateHatchBrush(int fnStyle, COLORREF rgb);
+ CBrush* CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec);
+ CBrush* CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage);
+#endif
+
+ // Create and Select Fonts
+ CFont* CreateFontIndirect(LPLOGFONT plf);
+ LOGFONT GetLogFont() const;
+
+#ifndef _WIN32_WCE
+ CFont* CreateFont(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight,
+ DWORD fdwItalic, DWORD fdwUnderline, DWORD fdwStrikeOut, DWORD fdwCharSet,
+ DWORD fdwOutputPrecision, DWORD fdwClipPrecision, DWORD fdwQuality,
+ DWORD fdwPitchAndFamily, LPCTSTR lpszFace);
+#endif
+
+ // Create and Select Pens
+ CPen* CreatePen(int nStyle, int nWidth, COLORREF rgb);
+ CPen* CreatePenIndirect(LPLOGPEN pLogPen);
+ LOGPEN GetLogPen() const;
+
+ // Create Select Regions
+ int CreateRectRgn(int left, int top, int right, int bottom);
+ int CreateRectRgnIndirect(const RECT& rc);
+ int CreateFromData(const XFORM* Xform, DWORD nCount, const RGNDATA *pRgnData);
+#ifndef _WIN32_WCE
+ int CreateEllipticRgn(int left, int top, int right, int bottom);
+ int CreateEllipticRgnIndirect(const RECT& rc);
+ int CreatePolygonRgn(LPPOINT ppt, int cPoints, int fnPolyFillMode);
+ int CreatePolyPolygonRgn(LPPOINT ppt, LPINT pPolyCounts, int nCount, int fnPolyFillMode);
+#endif
+
+ // Wrappers for WinAPI functions
+
+ // Point and Line Drawing Functions
+ CPoint GetCurrentPosition() const;
+ CPoint MoveTo(int x, int y) const;
+ CPoint MoveTo(POINT pt) const;
+ BOOL LineTo(int x, int y) const;
+ BOOL LineTo(POINT pt) const;
+ COLORREF GetPixel(int x, int y) const;
+ COLORREF GetPixel(POINT pt) const;
+ COLORREF SetPixel(int x, int y, COLORREF crColor) const;
+ COLORREF SetPixel(POINT pt, COLORREF crColor) const;
+#ifndef _WIN32_WCE
+ BOOL Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Arc(RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL ArcTo(RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) const;
+ int GetArcDirection() const;
+ int SetArcDirection(int nArcDirection) const;
+ BOOL PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) const;
+ BOOL Polyline(LPPOINT lpPoints, int nCount) const;
+ BOOL PolyPolyline(const POINT* lpPoints, const DWORD* lpPolyPoints, int nCount) const;
+ BOOL PolylineTo(const POINT* lpPoints, int nCount) const;
+ BOOL PolyBezier(const POINT* lpPoints, int nCount) const;
+ BOOL PolyBezierTo(const POINT* lpPoints, int nCount) const;
+ BOOL SetPixelV(int x, int y, COLORREF crColor) const;
+ BOOL SetPixelV(POINT pt, COLORREF crColor) const;
+#endif
+
+ // Shape Drawing Functions
+ void DrawFocusRect(const RECT& rc) const;
+ BOOL Ellipse(int x1, int y1, int x2, int y2) const;
+ BOOL Ellipse(const RECT& rc) const;
+ BOOL Polygon(LPPOINT lpPoints, int nCount) const;
+ BOOL Rectangle(int x1, int y1, int x2, int y2) const;
+ BOOL Rectangle(const RECT& rc) const;
+ BOOL RoundRect(int x1, int y1, int x2, int y2, int nWidth, int nHeight) const;
+ BOOL RoundRect(const RECT& rc, int nWidth, int nHeight) const;
+
+#ifndef _WIN32_WCE
+ BOOL Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Chord(const RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const;
+ BOOL Pie(const RECT& rc, POINT ptStart, POINT ptEnd) const;
+ BOOL PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) const;
+#endif
+
+ // Fill and Image Drawing functions
+ BOOL FillRect(const RECT& rc, CBrush* pBrushr) const;
+ BOOL InvertRect(const RECT& rc) const;
+ BOOL DrawIconEx(int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, CBrush* pFlickerFreeDraw, UINT diFlags) const;
+ BOOL DrawEdge(const RECT& rc, UINT nEdge, UINT nFlags) const;
+ BOOL DrawFrameControl(const RECT& rc, UINT nType, UINT nState) const;
+ BOOL FillRgn(CRgn* pRgn, CBrush* pBrush) const;
+ void GradientFill(COLORREF Color1, COLORREF Color2, const RECT& rc, BOOL bVertical);
+ void SolidFill(COLORREF Color, const RECT& rc);
+
+#ifndef _WIN32_WCE
+ BOOL DrawIcon(int x, int y, HICON hIcon) const;
+ BOOL DrawIcon(POINT point, HICON hIcon) const;
+ BOOL FrameRect(const RECT& rc, CBrush* pBrush) const;
+ BOOL PaintRgn(CRgn* pRgn) const;
+#endif
+
+ // Bitmap Functions
+ void DrawBitmap(int x, int y, int cx, int cy, CBitmap& Bitmap, COLORREF clrMask);
+ int StretchDIBits(int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth,
+ int nSrcHeight, CONST VOID *lpBits, BITMAPINFO& bi, UINT iUsage, DWORD dwRop) const;
+ BOOL PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) const;
+ BOOL BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) const;
+ BOOL StretchBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) const;
+
+#ifndef _WIN32_WCE
+ int GetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbi, UINT uUsage) const;
+ int SetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, LPBITMAPINFO lpbi, UINT fuColorUse) const;
+ int GetStretchBltMode() const;
+ int SetStretchBltMode(int iStretchMode) const;
+ BOOL FloodFill(int x, int y, COLORREF crColor) const;
+ BOOL ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) const;
+#endif
+
+ // Brush Functions
+#ifdef GetDCBrushColor
+ COLORREF GetDCBrushColor() const;
+ COLORREF SetDCBrushColor(COLORREF crColor) const;
+#endif
+
+ // Clipping Functions
+ int ExcludeClipRect(int Left, int Top, int Right, int BottomRect);
+ int ExcludeClipRect(const RECT& rc);
+ int GetClipBox(RECT& rc);
+ int GetClipRgn(HRGN hrgn);
+ int IntersectClipRect(int Left, int Top, int Right, int Bottom);
+ int IntersectClipRect(const RECT& rc);
+ BOOL RectVisible(const RECT& rc);
+ int SelectClipRgn(CRgn* pRgn);
+
+#ifndef _WIN32_WCE
+ int ExtSelectClipRgn(CRgn* pRgn, int fnMode);
+ int OffsetClipRgn(int nXOffset, int nYOffset);
+ BOOL PtVisible(int X, int Y);
+#endif
+
+ // Co-ordinate Functions
+#ifndef _WIN32_WCE
+ BOOL DPtoLP(LPPOINT lpPoints, int nCount) const;
+ BOOL DPtoLP(RECT& rc) const;
+ BOOL LPtoDP(LPPOINT lpPoints, int nCount) const;
+ BOOL LPtoDP(RECT& rc) const;
+#endif
+
+ // Layout Functions
+ DWORD GetLayout() const;
+ DWORD SetLayout(DWORD dwLayout) const;
+
+ // Mapping functions
+#ifndef _WIN32_WCE
+ int GetMapMode() const;
+ int SetMapMode(int nMapMode) const;
+ BOOL GetViewportOrgEx(LPPOINT lpPoint) const;
+ BOOL SetViewportOrgEx(int x, int y, LPPOINT lpPoint = NULL) const;
+ BOOL SetViewportOrgEx(POINT point, LPPOINT lpPointRet = NULL) const;
+ BOOL OffsetViewportOrgEx(int nWidth, int nHeight, LPPOINT lpPoint = NULL) const;
+ BOOL GetViewportExtEx(LPSIZE lpSize) const;
+ BOOL SetViewportExtEx(int x, int y, LPSIZE lpSize) const;
+ BOOL SetViewportExtEx(SIZE size, LPSIZE lpSizeRet) const;
+ BOOL ScaleViewportExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const;
+ BOOL OffsetWindowOrg(int nWidth, int nHeight, LPPOINT lpPoint) const;
+ BOOL GetWindowExtEx(LPSIZE lpSize) const;
+ BOOL SetWindowExtEx(int x, int y, LPSIZE lpSize) const;
+ BOOL SetWindowExtEx(SIZE size, LPSIZE lpSizeRet) const;
+ BOOL ScaleWindowExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const;
+ BOOL GetWindowOrgEx(LPPOINT lpPoint) const;
+ BOOL SetWindowOrgEx(int x, int y, LPPOINT lpPoint) const;
+ BOOL SetWindowOrgEx(POINT point, LPPOINT lpPointRet) const;
+ BOOL OffsetWindowOrgEx(int nWidth, int nHeight, LPPOINT lpPoint) const;
+#endif
+
+ // Printer Functions
+ int StartDoc(LPDOCINFO lpDocInfo) const;
+ int EndDoc() const;
+ int StartPage() const;
+ int EndPage() const;
+ int AbortDoc() const;
+ int SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) const;
+
+ // Text Functions
+ int DrawText(LPCTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat) const;
+ BOOL ExtTextOut(int x, int y, UINT nOptions, LPCRECT lprc, LPCTSTR lpszString, int nCount = -1, LPINT lpDxWidths = NULL) const;
+ COLORREF GetBkColor() const;
+ int GetBkMode() const;
+ UINT GetTextAlign() const;
+ int GetTextFace(int nCount, LPTSTR lpszFacename) const;
+ COLORREF GetTextColor() const;
+ BOOL GetTextMetrics(TEXTMETRIC& Metrics) const;
+ COLORREF SetBkColor(COLORREF crColor) const;
+ int SetBkMode(int iBkMode) const;
+ UINT SetTextAlign(UINT nFlags) const;
+ COLORREF SetTextColor(COLORREF crColor) const;
+
+#ifndef _WIN32_WCE
+ int DrawTextEx(LPTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat, LPDRAWTEXTPARAMS lpDTParams) const;
+ CSize GetTabbedTextExtent(LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) const;
+ int GetTextCharacterExtra() const;
+ CSize GetTextExtentPoint32(LPCTSTR lpszString, int nCount) const;
+ BOOL GrayString(CBrush* pBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) const;
+ int SetTextCharacterExtra(int nCharExtra) const;
+ int SetTextJustification(int nBreakExtra, int nBreakCount) const;
+ CSize TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) const;
+ BOOL TextOut(int x, int y, LPCTSTR lpszString, int nCount = -1) const;
+#endif
+
+ private:
+ void AddToMap();
+ static CDC* AddTempHDC(HDC hDC, HWND hWnd);
+ void Release();
+ BOOL RemoveFromMap();
+
+ DataMembers* m_pData; // pointer to the class's data members
+ };
+
+ class CClientDC : public CDC
+ {
+ public:
+ CClientDC(const CWnd* pWnd)
+ {
+ if (pWnd) assert(pWnd->IsWindow());
+ HWND hWnd = pWnd? pWnd->GetHwnd() : GetDesktopWindow();
+ Attach(::GetDC(hWnd), hWnd);
+ }
+ virtual ~CClientDC() {}
+ };
+
+ class CMemDC : public CDC
+ {
+ public:
+ CMemDC(const CDC* pDC)
+ {
+ if (pDC) assert(pDC->GetHDC());
+ HDC hDC = pDC? pDC->GetHDC() : NULL;
+ Attach(::CreateCompatibleDC(hDC));
+ }
+ virtual ~CMemDC() {}
+ };
+
+ class CPaintDC : public CDC
+ {
+ public:
+ CPaintDC(const CWnd* pWnd)
+ {
+ assert(pWnd->IsWindow());
+ m_hWnd = pWnd->GetHwnd();
+ Attach(::BeginPaint(pWnd->GetHwnd(), &m_ps), m_hWnd);
+ }
+
+ virtual ~CPaintDC() { ::EndPaint(m_hWnd, &m_ps); }
+
+ private:
+ HWND m_hWnd;
+ PAINTSTRUCT m_ps;
+ };
+
+ class CWindowDC : public CDC
+ {
+ public:
+ CWindowDC(const CWnd* pWnd)
+ {
+ if (pWnd) assert(pWnd->IsWindow());
+ HWND hWnd = pWnd? pWnd->GetHwnd() : GetDesktopWindow();
+ Attach(::GetWindowDC(hWnd), hWnd);
+ }
+ virtual ~CWindowDC() {}
+ };
+
+#ifndef _WIN32_WCE
+ class CMetaFileDC : public CDC
+ {
+ public:
+ CMetaFileDC() : m_hMF(0), m_hEMF(0) {}
+ virtual ~CMetaFileDC()
+ {
+ if (m_hMF)
+ {
+ ::CloseMetaFile(GetHDC());
+ ::DeleteMetaFile(m_hMF);
+ }
+ if (m_hEMF)
+ {
+ ::CloseEnhMetaFile(GetHDC());
+ ::DeleteEnhMetaFile(m_hEMF);
+ }
+ }
+ void Create(LPCTSTR lpszFilename = NULL) { Attach(::CreateMetaFile(lpszFilename)); }
+ void CreateEnhanced(CDC* pDCRef, LPCTSTR lpszFileName, LPCRECT lpBounds, LPCTSTR lpszDescription)
+ {
+ HDC hDC = pDCRef? pDCRef->GetHDC() : NULL;
+ ::CreateEnhMetaFile(hDC, lpszFileName, lpBounds, lpszDescription);
+ assert(GetHDC());
+ }
+ HMETAFILE Close() { return ::CloseMetaFile(GetHDC()); }
+ HENHMETAFILE CloseEnhanced() { return ::CloseEnhMetaFile(GetHDC()); }
+
+ private:
+ HMETAFILE m_hMF;
+ HENHMETAFILE m_hEMF;
+ };
+#endif
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmapInfoPtr class
+ // The CBitmapInfoPtr class is a convienient wrapper for the BITMAPINFO structure.
+ class CBitmapInfoPtr
+ {
+ public:
+ CBitmapInfoPtr(CBitmap* pBitmap)
+ {
+ BITMAP bmSource = pBitmap->GetBitmapData();
+
+ // Convert the color format to a count of bits.
+ WORD cClrBits = (WORD)(bmSource.bmPlanes * bmSource.bmBitsPixel);
+ if (cClrBits == 1) cClrBits = 1;
+ else if (cClrBits <= 4) cClrBits = 4;
+ else if (cClrBits <= 8) cClrBits = 8;
+ else if (cClrBits <= 16) cClrBits = 16;
+ else if (cClrBits <= 24) cClrBits = 24;
+ else cClrBits = 32;
+
+ // Allocate memory for the BITMAPINFO structure.
+ UINT uQuadSize = (cClrBits == 24)? 0 : sizeof(RGBQUAD) * (int)(1 << cClrBits);
+ m_bmi.assign(sizeof(BITMAPINFOHEADER) + uQuadSize, 0);
+ m_pbmiArray = (LPBITMAPINFO) &m_bmi[0];
+
+ m_pbmiArray->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ m_pbmiArray->bmiHeader.biHeight = bmSource.bmHeight;
+ m_pbmiArray->bmiHeader.biWidth = bmSource.bmWidth;
+ m_pbmiArray->bmiHeader.biPlanes = bmSource.bmPlanes;
+ m_pbmiArray->bmiHeader.biBitCount = bmSource.bmBitsPixel;
+ m_pbmiArray->bmiHeader.biCompression = BI_RGB;
+ if (cClrBits < 24)
+ m_pbmiArray->bmiHeader.biClrUsed = (1<() const { return m_pbmiArray; }
+
+ private:
+ CBitmapInfoPtr(const CBitmapInfoPtr&); // Disable copy construction
+ CBitmapInfoPtr& operator = (const CBitmapInfoPtr&); // Disable assignment operator
+ LPBITMAPINFO m_pbmiArray;
+ std::vector m_bmi;
+ };
+
+
+ CBitmap* FromHandle(HBITMAP hBitmap);
+ CBrush* FromHandle(HBRUSH hBrush);
+ CFont* FromHandle(HFONT hFont);
+ CPalette* FromHandle(HPALETTE hPalette);
+ CPen* FromHandle(HPEN hPen);
+ CRgn* FromHandle(HRGN hRgn);
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////////////////
+ // Declarations for the CGDIObject class
+ //
+
+ inline CGDIObject::CGDIObject()
+ // Constructs the CGDIObject
+ {
+ m_pData = new DataMembers;
+ m_pData->hGDIObject = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveObject = TRUE;
+ }
+
+ inline CGDIObject::CGDIObject(const CGDIObject& rhs)
+ // Note: A copy of a CGDIObject is a clone of the original.
+ // Both objects manipulate the one HGDIOBJ.
+ {
+ m_pData = rhs.m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+
+ inline CGDIObject::~CGDIObject()
+ // Deconstructs the CGDIObject
+ {
+ Release();
+ }
+
+ inline CGDIObject& CGDIObject::operator = ( const CGDIObject& rhs )
+ // Note: A copy of a CGDIObject is a clone of the original.
+ // Both objects manipulate the one HGDIOBJ.
+ {
+ if (this != &rhs)
+ {
+ InterlockedIncrement(&rhs.m_pData->Count);
+ Release();
+ m_pData = rhs.m_pData;
+ }
+
+ return *this;
+ }
+
+ inline void CGDIObject::operator = (HGDIOBJ hObject)
+ {
+ assert(m_pData);
+ assert (m_pData->hGDIObject == NULL);
+ m_pData->hGDIObject = hObject;
+ }
+
+ inline void CGDIObject::AddToMap()
+ // Store the HDC and CDC pointer in the HDC map
+ {
+ assert( GetApp() );
+ GetApp()->m_csMapLock.Lock();
+
+ assert(m_pData->hGDIObject);
+ assert(!GetApp()->GetCGDIObjectFromMap(m_pData->hGDIObject));
+
+ GetApp()->m_mapGDI.insert(std::make_pair(m_pData->hGDIObject, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline void CGDIObject::Attach(HGDIOBJ hObject)
+ // Attaches a GDI HANDLE to the CGDIObject.
+ // The HGDIOBJ will be automatically deleted when the destructor is called unless it is detached.
+ {
+ assert(m_pData);
+
+ if (m_pData->hGDIObject != NULL && m_pData->hGDIObject != hObject)
+ {
+ ::DeleteObject(Detach());
+ }
+
+ CGDIObject* pObject = GetApp()->GetCGDIObjectFromMap(hObject);
+ if (pObject)
+ {
+ delete m_pData;
+ m_pData = pObject->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ m_pData->hGDIObject = hObject;
+ AddToMap();
+ }
+ }
+
+ inline HGDIOBJ CGDIObject::Detach()
+ // Detaches the HGDIOBJ from this object.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject);
+
+ GetApp()->m_csMapLock.Lock();
+ RemoveFromMap();
+ HGDIOBJ hObject = m_pData->hGDIObject;
+ m_pData->hGDIObject = 0;
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ delete m_pData;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+
+ // Assign values to our data members
+ m_pData = new DataMembers;
+ m_pData->hGDIObject = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveObject = TRUE;
+
+ return hObject;
+ }
+
+ inline HGDIOBJ CGDIObject::GetHandle() const
+ {
+ assert(m_pData);
+ return m_pData->hGDIObject;
+ }
+
+ inline int CGDIObject::GetObject(int nCount, LPVOID pObject) const
+ {
+ assert(m_pData);
+ return ::GetObject(m_pData->hGDIObject, nCount, pObject);
+ }
+
+ inline void CGDIObject::Release()
+ {
+ assert(m_pData);
+ BOOL bSucceeded = TRUE;
+
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ if (m_pData->hGDIObject != NULL)
+ {
+ if (m_pData->bRemoveObject)
+ bSucceeded = ::DeleteObject(m_pData->hGDIObject);
+ else
+ bSucceeded = TRUE;
+ }
+
+ RemoveFromMap();
+ delete m_pData;
+ m_pData = 0;
+ }
+
+ assert(bSucceeded);
+ }
+
+ inline BOOL CGDIObject::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if( GetApp() )
+ {
+ // Allocate an iterator for our HDC map
+ std::map::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CGDIObject pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ m = pApp->m_mapGDI.find(m_pData->hGDIObject);
+ if (m != pApp->m_mapGDI.end())
+ {
+ pApp->m_mapGDI.erase(m);
+ Success = TRUE;
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+
+ return Success;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CBitmap class
+ //
+ inline CBitmap::CBitmap()
+ {
+ }
+
+ inline CBitmap::CBitmap(HBITMAP hBitmap)
+ {
+ assert(m_pData);
+ Attach(hBitmap);
+ }
+
+ inline CBitmap::CBitmap(LPCTSTR lpszName)
+ {
+ LoadBitmap(lpszName);
+ }
+
+ inline CBitmap::CBitmap(int nID)
+ {
+ LoadBitmap(nID);
+ }
+
+ inline CBitmap::operator HBITMAP() const
+ {
+ assert(m_pData);
+ return (HBITMAP)m_pData->hGDIObject;
+ }
+
+ inline CBitmap::~CBitmap()
+ {
+ }
+
+ inline BOOL CBitmap::LoadBitmap(int nID)
+ // Loads a bitmap from a resource using the resource ID.
+ {
+ return LoadBitmap(MAKEINTRESOURCE(nID));
+ }
+
+ inline BOOL CBitmap::LoadBitmap(LPCTSTR lpszName)
+ // Loads a bitmap from a resource using the resource string.
+ {
+ assert(GetApp());
+ assert(m_pData);
+
+ HBITMAP hBitmap = (HBITMAP)::LoadImage(GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
+ if (hBitmap)
+ {
+ Attach(hBitmap);
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+ inline BOOL CBitmap::LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from a resource using the resource ID.
+ {
+ return LoadImage(MAKEINTRESOURCE(nID), cxDesired, cyDesired, fuLoad);
+ }
+
+ inline BOOL CBitmap::LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from a resource using the resource string.
+ {
+ assert(GetApp());
+ assert(m_pData);
+
+ HBITMAP hBitmap = (HBITMAP)::LoadImage(GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, cxDesired, cyDesired, fuLoad);
+ if (hBitmap)
+ {
+ Attach(hBitmap);
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+ inline BOOL CBitmap::LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
+ // Loads a predefined bitmap
+ // Predefined bitmaps include: OBM_BTNCORNERS, OBM_BTSIZE, OBM_CHECK, OBM_CHECKBOXES, OBM_CLOSE, OBM_COMBO
+ // OBM_DNARROW, OBM_DNARROWD, OBM_DNARROWI, OBM_LFARROW, OBM_LFARROWD, OBM_LFARROWI, OBM_MNARROW,OBM_OLD_CLOSE
+ // OBM_OLD_DNARROW, OBM_OLD_LFARROW, OBM_OLD_REDUCE, OBM_OLD_RESTORE, OBM_OLD_RGARROW, OBM_OLD_UPARROW
+ // OBM_OLD_ZOOM, OBM_REDUCE, OBM_REDUCED, OBM_RESTORE, OBM_RESTORED, OBM_RGARROW, OBM_RGARROWD, OBM_RGARROWI
+ // OBM_SIZE, OBM_UPARROW, OBM_UPARROWD, OBM_UPARROWI, OBM_ZOOM, OBM_ZOOMD
+ {
+ assert(m_pData);
+
+ HBITMAP hBitmap = ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap));
+ if (hBitmap)
+ {
+ Attach( ::LoadBitmap(NULL, MAKEINTRESOURCE(nIDBitmap)) );
+ }
+ return (0 != hBitmap); // boolean expression
+ }
+
+#ifndef _WIN32_WCE
+ inline HBITMAP CBitmap::CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/)
+ // Creates a new bitmap using the bitmap data and colors specified by the bitmap resource and the color mapping information.
+ {
+ assert(GetApp());
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateMappedBitmap(GetApp()->GetResourceHandle(), nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitsPerPixel, LPCVOID lpBits)
+ // Creates a bitmap with the specified width, height, and color format (color planes and bits-per-pixel).
+ {
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateBitmap(nWidth, nHeight, nPlanes, nBitsPerPixel, lpBits);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+#ifndef _WIN32_WCE
+ inline HBITMAP CBitmap::CreateBitmapIndirect(LPBITMAP lpBitmap)
+ // Creates a bitmap with the width, height, and color format specified in the BITMAP structure.
+ {
+ assert(m_pData);
+ HBITMAP hBitmap = ::CreateBitmapIndirect(lpBitmap);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateCompatibleBitmap(CDC* pDC, int nWidth, int nHeight)
+ // Creates a bitmap compatible with the device that is associated with the specified device context.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateCompatibleBitmap(pDC->GetHDC(), nWidth, nHeight);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+ // Attributes
+ inline BITMAP CBitmap::GetBitmapData() const
+ // Retrieves the BITMAP structure
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ BITMAP bmp = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(BITMAP), &bmp);
+ return bmp;
+ }
+
+#ifndef _WIN32_WCE
+ inline CSize CBitmap::GetBitmapDimensionEx() const
+ // Retrieves the dimensions of a compatible bitmap.
+ // The retrieved dimensions must have been set by the SetBitmapDimensionEx function.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ CSize Size;
+ ::GetBitmapDimensionEx((HBITMAP)m_pData->hGDIObject, &Size);
+ return Size;
+ }
+
+ inline CSize CBitmap::SetBitmapDimensionEx(int nWidth, int nHeight)
+ // The SetBitmapDimensionEx function assigns preferred dimensions to a bitmap.
+ // These dimensions can be used by applications; however, they are not used by the system.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ CSize Size;
+ ::SetBitmapDimensionEx((HBITMAP)m_pData->hGDIObject, nWidth, nHeight, Size);
+ return Size;
+ }
+
+ // DIB support
+ inline HBITMAP CBitmap::CreateDIBitmap(CDC* pDC, CONST BITMAPINFOHEADER* lpbmih, DWORD dwInit, CONST VOID* lpbInit, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+ // Creates a compatible bitmap (DDB) from a DIB and, optionally, sets the bitmap bits.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetHDC(), lpbmih, dwInit, lpbInit, lpbmi, uColorUse);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+#endif // !_WIN32_WCE
+
+ inline HBITMAP CBitmap::CreateDIBSection(CDC* pDC, CONST BITMAPINFO* lpbmi, UINT uColorUse, VOID** ppvBits, HANDLE hSection, DWORD dwOffset)
+ // Creates a DIB that applications can write to directly. The function gives you a pointer to the location of the bitmap bit values.
+ // You can supply a handle to a file-mapping object that the function will use to create the bitmap, or you can let the system allocate the memory for the bitmap.
+ {
+ assert(m_pData);
+ assert(pDC);
+ HBITMAP hBitmap = ::CreateDIBSection(pDC->GetHDC(), lpbmi, uColorUse, ppvBits, hSection, dwOffset);
+ Attach(hBitmap);
+ return hBitmap;
+ }
+
+#ifndef _WIN32_WCE
+ inline int CBitmap::GetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT uColorUse) const
+ // Retrieves the bits of the specified compatible bitmap and copies them into a buffer as a DIB using the specified format.
+ {
+ assert(m_pData);
+ assert(pDC);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetDIBits(pDC->GetHDC(), (HBITMAP)m_pData->hGDIObject, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+ }
+
+ inline int CBitmap::SetDIBits(CDC* pDC, UINT uStartScan, UINT cScanLines, CONST VOID* lpvBits, CONST BITMAPINFO* lpbmi, UINT uColorUse)
+ // Sets the pixels in a compatible bitmap (DDB) using the color data found in the specified DIB.
+ {
+ assert(m_pData);
+ assert(pDC);
+ assert(m_pData->hGDIObject != NULL);
+ return ::SetDIBits(pDC->GetHDC(), (HBITMAP)m_pData->hGDIObject, uStartScan, cScanLines, lpvBits, lpbmi, uColorUse);
+ }
+#endif // !_WIN32_WCE
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CBrush class
+ //
+ inline CBrush::CBrush()
+ {
+ }
+
+ inline CBrush::CBrush(HBRUSH hBrush)
+ {
+ assert(m_pData);
+ Attach(hBrush);
+ }
+
+ inline CBrush::CBrush(COLORREF crColor)
+ {
+ Attach( ::CreateSolidBrush(crColor) );
+ assert (m_pData->hGDIObject);
+ }
+
+ inline CBrush::operator HBRUSH() const
+ {
+ assert(m_pData);
+ return (HBRUSH)m_pData->hGDIObject;
+ }
+
+ inline CBrush::~CBrush()
+ {
+ }
+
+ inline HBRUSH CBrush::CreateSolidBrush(COLORREF crColor)
+ // Creates a logical brush that has the specified solid color.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateSolidBrush(crColor);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+#ifndef _WIN32_WCE
+ inline HBRUSH CBrush::CreateHatchBrush(int nIndex, COLORREF crColor)
+ // Creates a logical brush that has the specified hatch pattern and color.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateHatchBrush(nIndex, crColor);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateBrushIndirect(LPLOGBRUSH lpLogBrush)
+ // Creates a logical brush from style, color, and pattern specified in the LOGPRUSH struct.
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateBrushIndirect(lpLogBrush);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec)
+ // Creates a logical brush that has the pattern specified by the specified device-independent bitmap (DIB).
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateDIBPatternBrush(hglbDIBPacked, fuColorSpec);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline HBRUSH CBrush::CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT nUsage)
+ // Creates a logical brush that has the pattern specified by the device-independent bitmap (DIB).
+ {
+ assert(m_pData);
+ HBRUSH hBrush = ::CreateDIBPatternBrushPt(lpPackedDIB, nUsage);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+#endif // !defined(_WIN32_WCE)
+
+ inline HBRUSH CBrush::CreatePatternBrush(CBitmap* pBitmap)
+ // Creates a logical brush with the specified bitmap pattern. The bitmap can be a DIB section bitmap,
+ // which is created by the CreateDIBSection function, or it can be a device-dependent bitmap.
+ {
+ assert(m_pData);
+ assert(pBitmap);
+ HBRUSH hBrush = ::CreatePatternBrush(*pBitmap);
+ Attach(hBrush);
+ return hBrush;
+ }
+
+ inline LOGBRUSH CBrush::GetLogBrush() const
+ // Retrieves the LOGBRUSH structure that defines the style, color, and pattern of a physical brush.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ LOGBRUSH LogBrush = {0};
+ ::GetObject (m_pData->hGDIObject, sizeof(LOGBRUSH), &LogBrush);
+ return LogBrush;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CFont class
+ //
+ inline CFont::CFont()
+ {
+ }
+
+ inline CFont::CFont(HFONT hFont)
+ {
+ assert(m_pData);
+ Attach(hFont);
+ }
+
+ inline CFont::CFont(const LOGFONT* lpLogFont)
+ {
+ assert(m_pData);
+ Attach( ::CreateFontIndirect(lpLogFont) );
+ }
+
+ inline CFont::operator HFONT() const
+ {
+ assert(m_pData);
+ return (HFONT)m_pData->hGDIObject;
+ }
+
+ inline CFont::~CFont()
+ {
+ }
+
+ inline HFONT CFont::CreateFontIndirect(const LOGFONT* lpLogFont)
+ // Creates a logical font that has the specified characteristics.
+ {
+ assert(m_pData);
+ HFONT hFont = ::CreateFontIndirect(lpLogFont);
+ Attach(hFont);
+ return hFont;
+ }
+
+ inline HFONT CFont::CreatePointFont(int nPointSize, LPCTSTR lpszFaceName, CDC* pDC /*= NULL*/, BOOL bBold /*= FALSE*/, BOOL bItalic /*= FALSE*/)
+ // Creates a font of a specified typeface and point size.
+ {
+ LOGFONT logFont = { 0 };
+ logFont.lfCharSet = DEFAULT_CHARSET;
+ logFont.lfHeight = nPointSize;
+
+ lstrcpy(logFont.lfFaceName, lpszFaceName);
+
+ if (bBold)
+ logFont.lfWeight = FW_BOLD;
+ if (bItalic)
+ logFont.lfItalic = (BYTE)TRUE;
+
+ return CreatePointFontIndirect(&logFont, pDC);
+ }
+
+ inline HFONT CFont::CreatePointFontIndirect(const LOGFONT* lpLogFont, CDC* pDC /* = NULL*/)
+ // Creates a font of a specified typeface and point size.
+ // This function automatically converts the height in lfHeight to logical units using the specified device context.
+ {
+ HDC hDC = pDC? pDC->GetHDC() : NULL;
+ HDC hDC1 = (hDC != NULL) ? hDC : ::GetDC(HWND_DESKTOP);
+
+ // convert nPointSize to logical units based on hDC
+ LOGFONT logFont = *lpLogFont;
+
+#ifndef _WIN32_WCE
+ POINT pt = { 0, 0 };
+ pt.y = ::MulDiv(::GetDeviceCaps(hDC1, LOGPIXELSY), logFont.lfHeight, 720); // 72 points/inch, 10 decipoints/point
+ ::DPtoLP(hDC1, &pt, 1);
+
+ POINT ptOrg = { 0, 0 };
+ ::DPtoLP(hDC1, &ptOrg, 1);
+
+ logFont.lfHeight = -abs(pt.y - ptOrg.y);
+#else // CE specific
+ // DP and LP are always the same on CE
+ logFont.lfHeight = -abs(((::GetDeviceCaps(hDC1, LOGPIXELSY)* logFont.lfHeight)/ 720));
+#endif // _WIN32_WCE
+
+ if (hDC == NULL)
+ ::ReleaseDC (NULL, hDC1);
+
+ return CreateFontIndirect (&logFont);
+ }
+
+#ifndef _WIN32_WCE
+
+ inline HFONT CFont::CreateFont(int nHeight, int nWidth, int nEscapement,
+ int nOrientation, int nWeight, DWORD dwItalic, DWORD dwUnderline,
+ DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision,
+ DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily,
+ LPCTSTR lpszFacename)
+ // Creates a logical font with the specified characteristics.
+ {
+ HFONT hFont = ::CreateFont(nHeight, nWidth, nEscapement,
+ nOrientation, nWeight, dwItalic, dwUnderline, dwStrikeOut,
+ dwCharSet, dwOutPrecision, dwClipPrecision, dwQuality,
+ dwPitchAndFamily, lpszFacename);
+
+ Attach(hFont);
+ return hFont;
+ }
+#endif // #ifndef _WIN32_WCE
+
+ inline LOGFONT CFont::GetLogFont() const
+ // Retrieves the Logfont structure that contains font attributes.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ LOGFONT LogFont = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(LOGFONT), &LogFont);
+ return LogFont;
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CPalette class
+ //
+ inline CPalette::CPalette()
+ {
+ }
+
+ inline CPalette::CPalette(HPALETTE hPalette)
+ {
+ Attach(hPalette);
+ }
+
+ inline CPalette::operator HPALETTE() const
+ {
+ assert(m_pData);
+ return (HPALETTE)m_pData->hGDIObject;
+ }
+
+ inline CPalette::~CPalette ()
+ {
+ }
+
+ inline HPALETTE CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)
+ // Creates a logical palette from the information in the specified LOGPALETTE structure.
+ {
+ assert(m_pData);
+ HPALETTE hPalette = ::CreatePalette (lpLogPalette);
+ Attach(hPalette);
+ return hPalette;
+ }
+
+#ifndef _WIN32_WCE
+ inline HPALETTE CPalette::CreateHalftonePalette(CDC* pDC)
+ // Creates a halftone palette for the specified device context (DC).
+ {
+ assert(m_pData);
+ assert(pDC);
+ HPALETTE hPalette = ::CreateHalftonePalette(pDC->GetHDC());
+ Attach(hPalette);
+ return hPalette;
+ }
+#endif // !_WIN32_WCE
+
+ inline int CPalette::GetEntryCount() const
+ // Retrieve the number of entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ WORD nEntries = 0;
+ ::GetObject(m_pData->hGDIObject, sizeof(WORD), &nEntries);
+ return (int)nEntries;
+ }
+
+ inline UINT CPalette::GetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors) const
+ // Retrieves a specified range of palette entries from the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetPaletteEntries((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+ inline UINT CPalette::SetPaletteEntries(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+ // Sets RGB (red, green, blue) color values and flags in a range of entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::SetPaletteEntries((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+#ifndef _WIN32_WCE
+ inline void CPalette::AnimatePalette(UINT nStartIndex, UINT nNumEntries, LPPALETTEENTRY lpPaletteColors)
+ // Replaces entries in the palette.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::AnimatePalette((HPALETTE)m_pData->hGDIObject, nStartIndex, nNumEntries, lpPaletteColors);
+ }
+
+ inline BOOL CPalette::ResizePalette(UINT nNumEntries)
+ // Increases or decreases the size of the palette based on the specified value.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::ResizePalette((HPALETTE)m_pData->hGDIObject, nNumEntries);
+ }
+#endif // !_WIN32_WCE
+
+ inline UINT CPalette::GetNearestPaletteIndex(COLORREF crColor) const
+ // Retrieves the index for the entry in the palette most closely matching a specified color value.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetNearestPaletteIndex((HPALETTE)m_pData->hGDIObject, crColor);
+ }
+
+
+ ///////////////////////////////////////////////
+ // Declarations for the CPen class
+ //
+ inline CPen::CPen()
+ {
+ }
+
+ inline CPen::CPen(HPEN hPen)
+ {
+ Attach(hPen);
+ }
+
+ inline CPen::CPen(int nPenStyle, int nWidth, COLORREF crColor)
+ {
+ assert(m_pData);
+ Attach( ::CreatePen(nPenStyle, nWidth, crColor) );
+ }
+
+#ifndef _WIN32_WCE
+ inline CPen::CPen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount /*= 0*/, const DWORD* lpStyle /*= NULL*/)
+ {
+ assert(m_pData);
+ Attach( ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle) );
+ }
+#endif // !_WIN32_WCE
+
+ inline CPen::operator HPEN () const
+ {
+ assert(m_pData);
+ return (HPEN)m_pData->hGDIObject;
+ }
+
+ inline CPen::~CPen()
+ {
+ }
+
+ inline HPEN CPen::CreatePen(int nPenStyle, int nWidth, COLORREF crColor)
+ // Creates a logical pen that has the specified style, width, and color.
+ {
+ assert(m_pData);
+ HPEN hPen = ::CreatePen(nPenStyle, nWidth, crColor);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline HPEN CPen::CreatePenIndirect(LPLOGPEN lpLogPen)
+ // Creates a logical cosmetic pen that has the style, width, and color specified in a structure.
+ {
+ assert(m_pData);
+ HPEN hPen = ::CreatePenIndirect(lpLogPen);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline LOGPEN CPen::GetLogPen() const
+ {
+ // Retrieves the LOGPEN struct that specifies the pen's style, width, and color.
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+
+ LOGPEN LogPen = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(LOGPEN), &LogPen);
+ return LogPen;
+ }
+
+#ifndef _WIN32_WCE
+ inline HPEN CPen::ExtCreatePen(int nPenStyle, int nWidth, const LOGBRUSH* pLogBrush, int nStyleCount /* = 0*/, const DWORD* lpStyle /*= NULL*/)
+ // Creates a logical cosmetic or geometric pen that has the specified style, width, and brush attributes.
+ {
+ assert(m_pData);
+ HPEN hPen = ::ExtCreatePen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle);
+ Attach(hPen);
+ return hPen;
+ }
+
+ inline EXTLOGPEN CPen::GetExtLogPen() const
+ // Retrieves the EXTLOGPEN struct that specifies the pen's style, width, color and brush attributes.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+
+ EXTLOGPEN ExLogPen = {0};
+ ::GetObject(m_pData->hGDIObject, sizeof(EXTLOGPEN), &ExLogPen);
+ return ExLogPen;
+ }
+#endif // !_WIN32_WCE
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CRgn class
+ //
+ inline CRgn::CRgn()
+ {
+ }
+
+ inline CRgn::CRgn(HRGN hRgn)
+ {
+ assert(m_pData);
+ Attach(hRgn);
+ }
+
+ inline CRgn::operator HRGN() const
+ {
+ assert(m_pData);
+ return (HRGN)m_pData->hGDIObject;
+ }
+
+ inline CRgn::~CRgn()
+ {
+ }
+
+ inline HRGN CRgn::CreateRectRgn(int x1, int y1, int x2, int y2)
+ // Creates a rectangular region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRectRgn(x1, y1, x2, y2);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateRectRgnIndirect(const RECT& rc)
+ // Creates a rectangular region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRectRgnIndirect(&rc);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+#ifndef _WIN32_WCE
+ inline HRGN CRgn::CreateEllipticRgn(int x1, int y1, int x2, int y2)
+ // Creates an elliptical region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateEllipticRgn(x1, y1, x2, y2);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateEllipticRgnIndirect(const RECT& rc)
+ // Creates an elliptical region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateEllipticRgnIndirect(&rc);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode)
+ // Creates a polygonal region.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreatePolygonRgn(lpPoints, nCount, nMode);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreatePolyPolygonRgn(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount, int nPolyFillMode)
+ // Creates a region consisting of a series of polygons. The polygons can overlap.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreatePolyPolygonRgn(lpPoints, lpPolyCounts, nCount, nPolyFillMode);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateRoundRectRgn(int x1, int y1, int x2, int y2, int x3, int y3)
+ // Creates a rectangular region with rounded corners.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::CreateRoundRectRgn(x1, y1, x2, y2, x3, y3);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline HRGN CRgn::CreateFromPath(HDC hDC)
+ // Creates a region from the path that is selected into the specified device context.
+ // The resulting region uses device coordinates.
+ {
+ assert(m_pData);
+ assert(hDC != NULL);
+ HRGN hRgn = ::PathToRegion(hDC);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+#endif // !_WIN32_WCE
+
+ inline HRGN CRgn::CreateFromData(const XFORM* lpXForm, int nCount, const RGNDATA* pRgnData)
+ // Creates a region from the specified region and transformation data.
+ {
+ assert(m_pData);
+ HRGN hRgn = ::ExtCreateRegion(lpXForm, nCount, pRgnData);
+ Attach(hRgn);
+ return hRgn;
+ }
+
+ inline void CRgn::SetRectRgn(int x1, int y1, int x2, int y2)
+ // converts the region into a rectangular region with the specified coordinates.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::SetRectRgn((HRGN)m_pData->hGDIObject, x1, y1, x2, y2);
+ }
+
+ inline void CRgn::SetRectRgn(const RECT& rc)
+ // converts the region into a rectangular region with the specified coordinates.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ ::SetRectRgn((HRGN)m_pData->hGDIObject, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline int CRgn::CombineRgn(CRgn* pRgnSrc1, CRgn* pRgnSrc2, int nCombineMode)
+ // Combines two sepcified regions and stores the result.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgnSrc1);
+ assert(pRgnSrc2);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, *pRgnSrc1, *pRgnSrc2, nCombineMode);
+ }
+
+ inline int CRgn::CombineRgn(CRgn* pRgnSrc, int nCombineMode)
+ // Combines the sepcified region with the current region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgnSrc);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, (HRGN)m_pData->hGDIObject, *pRgnSrc, nCombineMode);
+ }
+
+ inline int CRgn::CopyRgn(CRgn* pRgnSrc)
+ // Assigns the specified region to the current region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject == NULL);
+ assert(pRgnSrc);
+ return ::CombineRgn((HRGN)m_pData->hGDIObject, *pRgnSrc, NULL, RGN_COPY);
+ }
+
+ inline BOOL CRgn::EqualRgn(CRgn* pRgn) const
+ // Checks the two specified regions to determine whether they are identical.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ assert(pRgn);
+ return ::EqualRgn((HRGN)m_pData->hGDIObject, *pRgn);
+ }
+
+ inline int CRgn::OffsetRgn(int x, int y)
+ // Moves a region by the specified offsets.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::OffsetRgn((HRGN)m_pData->hGDIObject, x, y);
+ }
+
+ inline int CRgn::OffsetRgn(POINT& pt)
+ // Moves a region by the specified offsets.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::OffsetRgn((HRGN)m_pData->hGDIObject, pt.x, pt.y);
+ }
+
+ inline int CRgn::GetRgnBox(RECT& rc) const
+ // Retrieves the bounding rectangle of the region, and stores it in the specified RECT.
+ // The return value indicates the region's complexity: NULLREGION;SIMPLEREGION; or COMPLEXREGION.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::GetRgnBox((HRGN)m_pData->hGDIObject, &rc);
+ }
+
+ inline int CRgn::GetRegionData(LPRGNDATA lpRgnData, int nDataSize) const
+ // Fills the specified buffer with data describing a region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return (int)::GetRegionData((HRGN)m_pData->hGDIObject, nDataSize, lpRgnData);
+ }
+
+ inline BOOL CRgn::PtInRegion(int x, int y) const
+ // Determines whether the specified point is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::PtInRegion((HRGN)m_pData->hGDIObject, x, y);
+ }
+
+ inline BOOL CRgn::PtInRegion(POINT& pt) const
+ // Determines whether the specified point is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::PtInRegion((HRGN)m_pData->hGDIObject, pt.x, pt.y);
+ }
+
+ inline BOOL CRgn::RectInRegion(const RECT& rc) const
+ // Determines whether the specified rect is inside the specified region.
+ {
+ assert(m_pData);
+ assert(m_pData->hGDIObject != NULL);
+ return ::RectInRegion((HRGN)m_pData->hGDIObject, &rc);
+ }
+
+
+ ///////////////////////////////////////////////
+ // Definitions of the CDC class
+ //
+ inline CDC::CDC()
+ {
+ // Allocate memory for our data members
+ m_pData = new DataMembers;
+
+ // Assign values to our data members
+ m_pData->hDC = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->hWnd = 0;
+ }
+
+ inline CDC::CDC(HDC hDC, HWND hWnd /*= 0*/)
+ // This constructor assigns an existing HDC to the CDC
+ // The HDC WILL be released or deleted when the CDC object is destroyed
+ // The hWnd paramter is only used in WindowsCE. It specifies the HWND of a Window or
+ // Window Client DC
+
+ // Note: this constructor permits a call like this:
+ // CDC MyCDC = SomeHDC;
+ // or
+ // CDC MyCDC = ::CreateCompatibleDC(SomeHDC);
+ // or
+ // CDC MyCDC = ::GetDC(SomeHWND);
+ {
+ UNREFERENCED_PARAMETER(hWnd);
+ assert(hDC);
+
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (pDC)
+ {
+ m_pData = pDC->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ // Allocate memory for our data members
+ m_pData = new DataMembers;
+
+ // Assign values to our data members
+ m_pData->hDC = hDC;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->nSavedDCState = ::SaveDC(hDC);
+#ifndef _WIN32_WCE
+ m_pData->hWnd = ::WindowFromDC(hDC);
+#else
+ m_pData->hWnd = hWnd;
+#endif
+ if (m_pData->hWnd)
+ AddToMap();
+ }
+ }
+
+#ifndef _WIN32_WCE
+ inline void CDC::operator = (const HDC hDC)
+ // Note: this assignment operater permits a call like this:
+ // CDC MyCDC;
+ // MyCDC = SomeHDC;
+ {
+ Attach(hDC);
+ }
+#endif
+
+ inline CDC::CDC(const CDC& rhs) // Copy constructor
+ // The copy constructor is called when a temporary copy of the CDC needs to be created.
+ // This can happen when a CDC is passed by value in a function call. Each CDC copy manages
+ // the same Device Context and GDI objects.
+ {
+ m_pData = rhs.m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+
+ inline CDC& CDC::operator = (const CDC& rhs)
+ // Note: A copy of a CDC is a clone of the original.
+ // Both objects manipulate the one HDC
+ {
+ if (this != &rhs)
+ {
+ InterlockedIncrement(&rhs.m_pData->Count);
+ Release();
+ m_pData = rhs.m_pData;
+ }
+
+ return *this;
+ }
+
+ inline CDC::~CDC ()
+ {
+ Release();
+ }
+
+ inline void CDC::AddToMap()
+ // Store the HDC and CDC pointer in the HDC map
+ {
+ assert( GetApp() );
+ assert(m_pData->hDC);
+ GetApp()->m_csMapLock.Lock();
+
+ assert(m_pData->hDC);
+ assert(!GetApp()->GetCDCFromMap(m_pData->hDC));
+
+ GetApp()->m_mapHDC.insert(std::make_pair(m_pData->hDC, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline void CDC::Attach(HDC hDC, HWND hWnd /* = 0*/)
+ // Attaches a HDC to the CDC object.
+ // The HDC will be automatically deleted or released when the destructor is called.
+ // The hWnd parameter is only used on WindowsCE. It specifies the HWND of a Window or
+ // Window Client DC
+ {
+ UNREFERENCED_PARAMETER(hWnd);
+ assert(m_pData);
+ assert(0 == m_pData->hDC);
+ assert(hDC);
+
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (pDC)
+ {
+ delete m_pData;
+ m_pData = pDC->m_pData;
+ InterlockedIncrement(&m_pData->Count);
+ }
+ else
+ {
+ m_pData->hDC = hDC;
+
+#ifndef _WIN32_WCE
+ m_pData->hWnd = ::WindowFromDC(hDC);
+#else
+ m_pData->hWnd = hWnd;
+#endif
+
+ if (m_pData->hWnd == 0)
+ AddToMap();
+ m_pData->nSavedDCState = ::SaveDC(hDC);
+ }
+ }
+
+ inline HDC CDC::Detach()
+ // Detaches the HDC from this object.
+ {
+ assert(m_pData);
+ assert(m_pData->hDC);
+
+ GetApp()->m_csMapLock.Lock();
+ RemoveFromMap();
+ HDC hDC = m_pData->hDC;
+ m_pData->hDC = 0;
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ delete m_pData;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+
+ // Assign values to our data members
+ m_pData = new DataMembers;
+ m_pData->hDC = 0;
+ m_pData->Count = 1L;
+ m_pData->bRemoveHDC = TRUE;
+ m_pData->hWnd = 0;
+
+ return hDC;
+ }
+
+ // Initialization
+ inline BOOL CDC::CreateCompatibleDC(CDC* pDC)
+ // Returns a memory device context (DC) compatible with the specified device.
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hdcSource = (pDC == NULL)? NULL : pDC->GetHDC();
+ HDC hDC = ::CreateCompatibleDC(hdcSource);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+
+ inline BOOL CDC::CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData)
+ // Returns a device context (DC) for a device using the specified name.
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hDC = ::CreateDC(lpszDriver, lpszDevice, lpszOutput, pInitData);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::CreateIC(LPCTSTR lpszDriver, LPCTSTR lpszDevice, LPCTSTR lpszOutput, const DEVMODE* pInitData)
+ {
+ assert(m_pData->hDC == NULL);
+ HDC hDC = ::CreateIC(lpszDriver, lpszDevice, lpszOutput, pInitData);
+ if (hDC)
+ {
+ m_pData->hDC = hDC;
+ AddToMap();
+ }
+ return (hDC != NULL); // boolean expression
+ }
+#endif
+
+ inline void CDC::DrawBitmap(int x, int y, int cx, int cy, CBitmap& Bitmap, COLORREF clrMask)
+ // Draws the specified bitmap to the specified DC using the mask colour provided as the transparent colour
+ // Suitable for use with a Window DC or a memory DC
+ {
+ // Create the Image memory DC
+ CMemDC dcImage(this);
+ dcImage.SetBkColor(clrMask);
+ dcImage.SelectObject(&Bitmap);
+
+ // Create the Mask memory DC
+ CMemDC dcMask(this);
+ dcMask.CreateBitmap(cx, cy, 1, 1, NULL);
+ dcMask.BitBlt(0, 0, cx, cy, &dcImage, 0, 0, SRCCOPY);
+
+ // Mask the image to 'this' DC
+ BitBlt(x, y, cx, cy, &dcImage, 0, 0, SRCINVERT);
+ BitBlt(x, y, cx, cy, &dcMask, 0, 0, SRCAND);
+ BitBlt(x, y, cx, cy, &dcImage, 0, 0, SRCINVERT);
+ }
+
+ inline CDC* CDC::AddTempHDC(HDC hDC, HWND hWnd)
+ // Returns the CDC object associated with the device context handle
+ // The HDC is removed when the CDC is destroyed
+ {
+ assert( GetApp() );
+ CDC* pDC = new CDC;
+ pDC->m_pData->hDC = hDC;
+ GetApp()->AddTmpDC(pDC);
+ pDC->m_pData->bRemoveHDC = TRUE;
+ pDC->m_pData->hWnd = hWnd;
+ return pDC;
+ }
+
+ inline void CDC::GradientFill(COLORREF Color1, COLORREF Color2, const RECT& rc, BOOL bVertical)
+ // An efficient color gradient filler compatible with all Windows operating systems
+ {
+ int Width = rc.right - rc.left;
+ int Height = rc.bottom - rc.top;
+
+ int r1 = GetRValue(Color1);
+ int g1 = GetGValue(Color1);
+ int b1 = GetBValue(Color1);
+
+ int r2 = GetRValue(Color2);
+ int g2 = GetGValue(Color2);
+ int b2 = GetBValue(Color2);
+
+ COLORREF OldBkColor = GetBkColor();
+
+ if (bVertical)
+ {
+ for(int i=0; i < Width; ++i)
+ {
+ int r = r1 + (i * (r2-r1) / Width);
+ int g = g1 + (i * (g2-g1) / Width);
+ int b = b1 + (i * (b2-b1) / Width);
+ SetBkColor(RGB(r, g, b));
+ CRect line( i + rc.left, rc.top, i + 1 + rc.left, rc.top+Height);
+ ExtTextOut(0, 0, ETO_OPAQUE, line, NULL, 0, 0);
+ }
+ }
+ else
+ {
+ for(int i=0; i < Height; ++i)
+ {
+ int r = r1 + (i * (r2-r1) / Height);
+ int g = g1 + (i * (g2-g1) / Height);
+ int b = b1 + (i * (b2-b1) / Height);
+ SetBkColor(RGB(r, g, b));
+ CRect line(rc.left, i + rc.top, rc.left+Width, i + 1 + rc.top);
+ ExtTextOut(0, 0, ETO_OPAQUE, line, NULL, 0, 0);
+ }
+ }
+
+ SetBkColor(OldBkColor);
+ }
+
+ inline void CDC::Release()
+ {
+ GetApp()->m_csMapLock.Lock();
+
+ if (m_pData->Count)
+ {
+ if (InterlockedDecrement(&m_pData->Count) == 0)
+ {
+ Destroy();
+ delete m_pData;
+ m_pData = 0;
+ }
+ }
+
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline BOOL CDC::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if( GetApp() )
+ {
+ // Allocate an iterator for our HDC map
+ std::map::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CDC pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ m = pApp->m_mapHDC.find(m_pData->hDC);
+ if (m != pApp->m_mapHDC.end())
+ {
+ pApp->m_mapHDC.erase(m);
+ Success = TRUE;
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+ return Success;
+ }
+
+ inline void CDC::SolidFill(COLORREF Color, const RECT& rc)
+ // Fills a rectangle with a solid color
+ {
+ COLORREF OldColor = SetBkColor(Color);
+ ExtTextOut(0, 0, ETO_OPAQUE, &rc, NULL, 0, 0);
+ SetBkColor(OldColor);
+ }
+
+ // Bitmap functions
+ inline CBitmap* CDC::CreateCompatibleBitmap(CDC* pDC, int cx, int cy)
+ // Creates a compatible bitmap and selects it into the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateCompatibleBitmap(pDC, cx, cy);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline CBitmap* CDC::CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateBitmap(cx, cy, Planes, BitsPerPixel, pvColors);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+#ifndef _WIN32_WCE
+ inline CBitmap* CDC::CreateBitmapIndirect (LPBITMAP lpBitmap)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateBitmapIndirect(lpBitmap);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline CBitmap* CDC::CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit,
+ BITMAPINFO& bmi, UINT fuUsage)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateDIBitmap(pDC, &bmih, fdwInit, lpbInit, &bmi, fuUsage);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+#endif
+
+ inline CBitmap* CDC::CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits,
+ HANDLE hSection, DWORD dwOffset)
+ // Creates a bitmap and selects it into the device context.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+ assert(pDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateDIBSection(pDC, &bmi, iUsage, ppvBits, hSection, dwOffset);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+
+ inline void CDC::Destroy()
+ // Deletes or releases the device context and returns the CDC object to its
+ // default state, ready for reuse.
+ {
+ if (m_pData->hDC)
+ {
+ RemoveFromMap();
+ if (m_pData->bRemoveHDC)
+ {
+ // Return the DC back to its initial state
+ ::RestoreDC(m_pData->hDC, m_pData->nSavedDCState);
+
+ // We need to release a Window DC, and delete a memory DC
+ if (m_pData->hWnd)
+ ::ReleaseDC(m_pData->hWnd, m_pData->hDC);
+ else
+ if (!::DeleteDC(m_pData->hDC))
+ ::ReleaseDC(NULL, m_pData->hDC);
+
+ m_pData->hDC = 0;
+ m_pData->hWnd = 0;
+ m_pData->bRemoveHDC = TRUE;
+ }
+ }
+
+ // RemoveFromMap();
+ }
+
+ inline BITMAP CDC::GetBitmapData() const
+ // Retrieves the BITMAP information for the current HBITMAP.
+ {
+ assert(m_pData->hDC);
+
+ HBITMAP hbm = (HBITMAP)::GetCurrentObject(m_pData->hDC, OBJ_BITMAP);
+ BITMAP bm = {0};
+ ::GetObject(hbm, sizeof(bm), &bm);
+ return bm;
+ }
+
+ inline CBitmap* CDC::LoadBitmap(UINT nID)
+ // Loads a bitmap from the resource and selects it into the device context
+ {
+ return LoadBitmap(MAKEINTRESOURCE(nID));
+ }
+
+ inline CBitmap* CDC::LoadBitmap(LPCTSTR lpszName)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadBitmap(lpszName);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+ inline CBitmap* CDC::LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ return LoadImage(nID, cxDesired, cyDesired, fuLoad);
+ }
+
+ inline CBitmap* CDC::LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad)
+ // Loads a bitmap from the resource and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadImage(lpszName, cxDesired, cyDesired, fuLoad);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+ inline CBitmap* CDC::LoadOEMBitmap(UINT nIDBitmap) // for OBM_/OCR_/OIC_
+ // Loads a predefined system bitmap and selects it into the device context
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ BOOL bResult = pBitmap->LoadOEMBitmap(nIDBitmap);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return bResult? SelectObject(pBitmap) : NULL;
+ }
+
+#ifndef _WIN32_WCE
+ inline CBitmap* CDC::CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/)
+ // creates and selects a new bitmap using the bitmap data and colors specified by the bitmap resource and the color mapping information.
+ // Returns a pointer to the old bitmap selected out of the device context
+ {
+ assert(m_pData->hDC);
+
+ CBitmap* pBitmap = new CBitmap;
+ pBitmap->CreateMappedBitmap(nIDBitmap, (WORD)nFlags, lpColorMap, nMapSize);
+ m_pData->m_vGDIObjects.push_back(pBitmap);
+ return SelectObject(pBitmap);
+ }
+#endif // !_WIN32_WCE
+
+
+ // Brush functions
+#ifndef _WIN32_WCE
+ inline CBrush* CDC::CreateBrushIndirect(LPLOGBRUSH pLogBrush)
+ // Creates the brush and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateBrushIndirect(pLogBrush);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateHatchBrush(int fnStyle, COLORREF rgb)
+ // Creates a brush with the specified hatch pattern and color, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateHatchBrush(fnStyle, rgb);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec)
+ // Creates a logical from the specified device-independent bitmap (DIB), and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateDIBPatternBrush(hglbDIBPacked, fuColorSpec);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage)
+ // Creates a logical from the specified device-independent bitmap (DIB), and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateDIBPatternBrushPt(lpPackedDIB, iUsage);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+#endif
+
+ inline CBrush* CDC::CreatePatternBrush(CBitmap* pBitmap)
+ // Creates the brush with the specified pattern, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreatePatternBrush(pBitmap);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline CBrush* CDC::CreateSolidBrush(COLORREF rgb)
+ // Creates the brush with the specified color, and selects it into the device context.
+ // Returns a pointer to the old brush selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CBrush* pBrush = new CBrush;
+ pBrush->CreateSolidBrush(rgb);
+ m_pData->m_vGDIObjects.push_back(pBrush);
+ return SelectObject(pBrush);
+ }
+
+ inline LOGBRUSH CDC::GetLogBrush() const
+ // Retrieves the current brush information
+ {
+ assert(m_pData->hDC);
+
+ HBRUSH hBrush = (HBRUSH)::GetCurrentObject(m_pData->hDC, OBJ_BRUSH);
+ LOGBRUSH lBrush = {0};
+ ::GetObject(hBrush, sizeof(lBrush), &lBrush);
+ return lBrush;
+ }
+
+
+ // Font functions
+#ifndef _WIN32_WCE
+ inline CFont* CDC::CreateFont (
+ int nHeight, // height of font
+ int nWidth, // average character width
+ int nEscapement, // angle of escapement
+ int nOrientation, // base-line orientation angle
+ int fnWeight, // font weight
+ DWORD fdwItalic, // italic attribute option
+ DWORD fdwUnderline, // underline attribute option
+ DWORD fdwStrikeOut, // strikeout attribute option
+ DWORD fdwCharSet, // character set identifier
+ DWORD fdwOutputPrecision, // output precision
+ DWORD fdwClipPrecision, // clipping precision
+ DWORD fdwQuality, // output quality
+ DWORD fdwPitchAndFamily, // pitch and family
+ LPCTSTR lpszFace // typeface name
+ )
+
+ // Creates a logical font with the specified characteristics.
+ // Returns a pointer to the old font selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CFont* pFont = new CFont;
+ pFont->CreateFont (nHeight, nWidth, nEscapement, nOrientation, fnWeight,
+ fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
+ fdwOutputPrecision, fdwClipPrecision, fdwQuality,
+ fdwPitchAndFamily, lpszFace);
+ m_pData->m_vGDIObjects.push_back(pFont);
+ return SelectObject(pFont);
+ }
+#endif
+
+ inline CFont* CDC::CreateFontIndirect(LPLOGFONT plf)
+ // Creates a logical font and selects it into the device context.
+ // Returns a pointer to the old font selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CFont* pFont = new CFont;
+ pFont->CreateFontIndirect(plf);
+ m_pData->m_vGDIObjects.push_back(pFont);
+ return SelectObject(pFont);
+ }
+
+ inline LOGFONT CDC::GetLogFont() const
+ // Retrieves the current font information.
+ {
+ assert(m_pData->hDC);
+
+ HFONT hFont = (HFONT)::GetCurrentObject(m_pData->hDC, OBJ_FONT);
+ LOGFONT lFont = {0};
+ ::GetObject(hFont, sizeof(lFont), &lFont);
+ return lFont;
+ }
+
+ // Pen functions
+ inline CPen* CDC::CreatePen (int nStyle, int nWidth, COLORREF rgb)
+ // Creates the pen and selects it into the device context.
+ // Returns a pointer to the old pen selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CPen* pPen = new CPen;
+ pPen->CreatePen(nStyle, nWidth, rgb);
+ m_pData->m_vGDIObjects.push_back(pPen);
+ return SelectObject(pPen);
+ }
+
+ inline CPen* CDC::CreatePenIndirect (LPLOGPEN pLogPen)
+ // Creates the pen and selects it into the device context.
+ // Returns a pointer to the old pen selected out of the device context.
+ {
+ assert(m_pData->hDC);
+
+ CPen* pPen = new CPen;
+ pPen->CreatePenIndirect(pLogPen);
+ m_pData->m_vGDIObjects.push_back(pPen);
+ return SelectObject(pPen);
+ }
+
+ inline LOGPEN CDC::GetLogPen() const
+ // Retrieves the current pen information as a LOGPEN
+ {
+ assert(m_pData->hDC);
+
+ HPEN hPen = (HPEN)::GetCurrentObject(m_pData->hDC, OBJ_PEN);
+ LOGPEN lPen = {0};
+ ::GetObject(hPen, sizeof(lPen), &lPen);
+ return lPen;
+ }
+
+ // Region functions
+ inline int CDC::CreateRectRgn(int left, int top, int right, int bottom)
+ // Creates a rectangular region from the rectangle co-ordinates.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateRectRgn(left, top, right, bottom);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateRectRgnIndirect(const RECT& rc)
+ // Creates a rectangular region from the rectangle co-ordinates.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateRectRgnIndirect(rc);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateFromData(const XFORM* Xform, DWORD nCount, const RGNDATA *pRgnData)
+ // Creates a region from the specified region data and tranformation data.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ // Notes: GetRegionData can be used to get a region's data
+ // If the XFROM pointer is NULL, the identity transformation is used.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateFromData(Xform, nCount, pRgnData);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+
+#ifndef _WIN32_WCE
+ inline int CDC::CreateEllipticRgn(int left, int top, int right, int bottom)
+ // Creates the ellyiptical region from the bounding rectangle co-ordinates
+ // and selects it into the device context.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateEllipticRgn(left, top, right, bottom);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreateEllipticRgnIndirect(const RECT& rc)
+ // Creates the ellyiptical region from the bounding rectangle co-ordinates
+ // and selects it into the device context.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreateEllipticRgnIndirect(rc);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreatePolygonRgn(LPPOINT ppt, int cPoints, int fnPolyFillMode)
+ // Creates the polygon region from the array of points and selects it into
+ // the device context. The polygon is presumed closed.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreatePolygonRgn(ppt, cPoints, fnPolyFillMode);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+
+ inline int CDC::CreatePolyPolygonRgn(LPPOINT ppt, LPINT pPolyCounts, int nCount, int fnPolyFillMode)
+ // Creates the polygon region from a series of polygons.The polygons can overlap.
+ // The return value specifies the region's complexity: NULLREGION;SIMPLEREGION;COMPLEXREGION;ERROR.
+ {
+ assert(m_pData->hDC);
+
+ CRgn* pRgn = new CRgn;
+ pRgn->CreatePolyPolygonRgn(ppt, pPolyCounts, nCount, fnPolyFillMode);
+ m_pData->m_vGDIObjects.push_back(pRgn);
+ return SelectClipRgn(pRgn);
+ }
+#endif
+
+
+ // Wrappers for WinAPI functions
+
+ inline int CDC::GetDeviceCaps (int nIndex) const
+ // Retrieves device-specific information for the specified device.
+ {
+ assert(m_pData->hDC);
+ return ::GetDeviceCaps(m_pData->hDC, nIndex);
+ }
+
+ // Brush Functions
+#ifdef GetDCBrushColor
+ inline COLORREF CDC::GetDCBrushColor() const
+ {
+ assert(m_pData->hDC);
+ return ::GetDCBrushColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetDCBrushColor(COLORREF crColor) const
+ {
+ assert(m_pData->hDC);
+ return ::SetDCBrushColor(m_pData->hDC, crColor);
+ }
+#endif
+
+ // Clipping functions
+ inline int CDC::ExcludeClipRect(int Left, int Top, int Right, int BottomRect)
+ // Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::ExcludeClipRect(m_pData->hDC, Left, Top, Right, BottomRect);
+ }
+
+ inline int CDC::ExcludeClipRect(const RECT& rc)
+ // Creates a new clipping region that consists of the existing clipping region minus the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::ExcludeClipRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline int CDC::GetClipBox (RECT& rc)
+ // Retrieves the dimensions of the tightest bounding rectangle that can be drawn around the current visible area on the device.
+ {
+ assert(m_pData->hDC);
+ return ::GetClipBox(m_pData->hDC, &rc);
+ }
+
+ inline int CDC::GetClipRgn(HRGN hrgn)
+ // Retrieves a handle identifying the current application-defined clipping region for the specified device context.
+ // hrgn: A handle to an existing region before the function is called.
+ // After the function returns, this parameter is a handle to a copy of the current clipping region.
+ {
+ assert(m_pData->hDC);
+ return ::GetClipRgn(m_pData->hDC, hrgn);
+ }
+
+ inline int CDC::IntersectClipRect(int Left, int Top, int Right, int Bottom)
+ // Creates a new clipping region from the intersection of the current clipping region and the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::IntersectClipRect(m_pData->hDC, Left, Top, Right, Bottom);
+ }
+
+ inline int CDC::IntersectClipRect(const RECT& rc)
+ // Creates a new clipping region from the intersection of the current clipping region and the specified rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::IntersectClipRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::RectVisible(const RECT& rc)
+ // Determines whether any part of the specified rectangle lies within the clipping region of a device context.
+ {
+ assert(m_pData->hDC);
+ return ::RectVisible (m_pData->hDC, &rc);
+ }
+
+ inline int CDC::SelectClipRgn(CRgn* pRgn)
+ // Selects a region as the current clipping region for the specified device context.
+ // Note: Only a copy of the selected region is used.
+ // To remove a device-context's clipping region, specify a NULL region handle.
+ {
+ assert(m_pData->hDC);
+ return ::SelectClipRgn(m_pData->hDC, pRgn? (HRGN)pRgn->GetHandle() : 0);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::ExtSelectClipRgn(CRgn* pRgn, int fnMode)
+ // Combines the specified region with the current clipping region using the specified mode.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ return ::ExtSelectClipRgn(m_pData->hDC, *pRgn, fnMode);
+ }
+#endif
+
+ inline CBitmap* CDC::SelectObject(const CBitmap* pBitmap)
+ // Use this to attach an existing bitmap.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+
+ return FromHandle( (HBITMAP)::SelectObject(m_pData->hDC, *pBitmap) );
+ }
+
+ inline CBrush* CDC::SelectObject(const CBrush* pBrush)
+ // Use this to attach an existing brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+
+ return FromHandle( (HBRUSH)::SelectObject(m_pData->hDC, *pBrush) );
+ }
+
+ inline CFont* CDC::SelectObject(const CFont* pFont)
+ // Use this to attach an existing font.
+ {
+ assert(m_pData->hDC);
+ assert(pFont);
+
+ return FromHandle( (HFONT)::SelectObject(m_pData->hDC, *pFont) );
+ }
+
+ inline CPalette* CDC::SelectObject(const CPalette* pPalette)
+ // Use this to attach an existing Palette.
+ {
+ assert(m_pData->hDC);
+ assert(pPalette);
+
+ return FromHandle( (HPALETTE)::SelectObject(m_pData->hDC, *pPalette) );
+ }
+
+ inline CPen* CDC::SelectObject(const CPen* pPen)
+ // Use this to attach an existing pen.
+ {
+ assert(m_pData->hDC);
+ assert(pPen);
+
+ return FromHandle( (HPEN)::SelectObject(m_pData->hDC, *pPen) );
+ }
+
+ inline CPalette* CDC::SelectPalette(const CPalette* pPalette, BOOL bForceBkgnd)
+ // Use this to attach an existing palette.
+ {
+ assert(m_pData->hDC);
+ assert(pPalette);
+
+ return FromHandle( (HPALETTE)::SelectPalette(m_pData->hDC, *pPalette, bForceBkgnd) );
+ }
+#ifndef _WIN32_WCE
+ inline BOOL CDC::PtVisible(int X, int Y)
+ // Determines whether the specified point is within the clipping region of a device context.
+ {
+ assert(m_pData->hDC);
+ return ::PtVisible (m_pData->hDC, X, Y);
+ }
+
+ inline int CDC::OffsetClipRgn(int nXOffset, int nYOffset)
+ // Moves the clipping region of a device context by the specified offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetClipRgn (m_pData->hDC, nXOffset, nYOffset);
+ }
+#endif
+
+ // Point and Line Drawing Functions
+ inline CPoint CDC::GetCurrentPosition() const
+ // Returns the current "MoveToEx" position.
+ {
+ assert(m_pData->hDC);
+ CPoint pt;
+ ::MoveToEx(m_pData->hDC, 0, 0, &pt);
+ ::MoveToEx(m_pData->hDC, pt.x, pt.y, NULL);
+ return pt;
+ }
+
+ inline CPoint CDC::MoveTo(int x, int y) const
+ // Updates the current position to the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::MoveToEx(m_pData->hDC, x, y, NULL);
+ }
+
+ inline CPoint CDC::MoveTo(POINT pt) const
+ // Updates the current position to the specified point
+ {
+ assert(m_pData->hDC);
+ return ::MoveToEx(m_pData->hDC, pt.x, pt.y, NULL);
+ }
+
+ inline BOOL CDC::LineTo(int x, int y) const
+ // Draws a line from the current position up to, but not including, the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::LineTo(m_pData->hDC, x, y);
+ }
+
+ inline BOOL CDC::LineTo(POINT pt) const
+ // Draws a line from the current position up to, but not including, the specified point.
+ {
+ assert(m_pData->hDC);
+ return ::LineTo(m_pData->hDC, pt.x, pt.y);
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::Arc(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::Arc(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Arc(RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::Arc(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::ArcTo(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::ArcTo(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::ArcTo(RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws an elliptical arc.
+ {
+ assert(m_pData->hDC);
+ return ::ArcTo (m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::AngleArc(int x, int y, int nRadius, float fStartAngle, float fSweepAngle) const
+ // Draws a line segment and an arc.
+ {
+ assert(m_pData->hDC);
+ return ::AngleArc(m_pData->hDC, x, y, nRadius, fStartAngle, fSweepAngle);
+ }
+
+ inline int CDC::GetArcDirection() const
+ // Retrieves the current arc direction ( AD_COUNTERCLOCKWISE or AD_CLOCKWISE ).
+ {
+ assert(m_pData->hDC);
+ return ::GetArcDirection(m_pData->hDC);
+ }
+
+ inline int CDC::SetArcDirection(int nArcDirection) const
+ // Sets the current arc direction ( AD_COUNTERCLOCKWISE or AD_CLOCKWISE ).
+ {
+ assert(m_pData->hDC);
+ return ::SetArcDirection(m_pData->hDC, nArcDirection);
+ }
+
+ inline BOOL CDC::PolyDraw(const POINT* lpPoints, const BYTE* lpTypes, int nCount) const
+ // Draws a set of line segments and Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyDraw(m_pData->hDC, lpPoints, lpTypes, nCount);
+ }
+
+ inline BOOL CDC::Polyline(LPPOINT lpPoints, int nCount) const
+ // Draws a series of line segments by connecting the points in the specified array.
+ {
+ assert(m_pData->hDC);
+ return ::Polyline(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::PolyPolyline(const POINT* lpPoints, const DWORD* lpPolyPoints, int nCount) const
+ // Draws multiple series of connected line segments.
+ {
+ assert(m_pData->hDC);
+ return ::PolyPolyline(m_pData->hDC, lpPoints, lpPolyPoints, nCount);
+ }
+
+ inline BOOL CDC::PolylineTo(const POINT* lpPoints, int nCount) const
+ // Draws one or more straight lines.
+ {
+ assert(m_pData->hDC);
+ return ::PolylineTo(m_pData->hDC, lpPoints, nCount);
+ }
+ inline BOOL CDC::PolyBezier(const POINT* lpPoints, int nCount) const
+ // Draws one or more Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyBezier(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::PolyBezierTo(const POINT* lpPoints, int nCount) const
+ // Draws one or more Bzier curves.
+ {
+ assert(m_pData->hDC);
+ return ::PolyBezierTo(m_pData->hDC, lpPoints, nCount );
+ }
+
+ inline COLORREF CDC::GetPixel(int x, int y) const
+ // Retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::GetPixel(m_pData->hDC, x, y);
+ }
+
+ inline COLORREF CDC::GetPixel(POINT pt) const
+ // Retrieves the red, green, blue (RGB) color value of the pixel at the specified coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::GetPixel(m_pData->hDC, pt.x, pt.y);
+ }
+
+ inline COLORREF CDC::SetPixel (int x, int y, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixel(m_pData->hDC, x, y, crColor);
+ }
+
+ inline COLORREF CDC::SetPixel(POINT pt, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixel(m_pData->hDC, pt.x, pt.y, crColor);
+ }
+
+ inline BOOL CDC::SetPixelV(int x, int y, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the closest approximation of the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixelV(m_pData->hDC, x, y, crColor);
+ }
+
+ inline BOOL CDC::SetPixelV(POINT pt, COLORREF crColor) const
+ // Sets the pixel at the specified coordinates to the closest approximation of the specified color.
+ {
+ assert(m_pData->hDC);
+ return ::SetPixelV(m_pData->hDC, pt.x, pt.y, crColor);
+ }
+#endif
+
+ // Shape Drawing Functions
+ inline void CDC::DrawFocusRect(const RECT& rc) const
+ // Draws a rectangle in the style used to indicate that the rectangle has the focus.
+ {
+ assert(m_pData->hDC);
+ ::DrawFocusRect(m_pData->hDC, &rc);
+ }
+
+ inline BOOL CDC::Ellipse(int x1, int y1, int x2, int y2) const
+ // Draws an ellipse. The center of the ellipse is the center of the specified bounding rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::Ellipse(m_pData->hDC, x1, y1, x2, y2);
+ }
+
+ inline BOOL CDC::Ellipse(const RECT& rc) const
+ // Draws an ellipse. The center of the ellipse is the center of the specified bounding rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::Ellipse(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::Polygon(LPPOINT lpPoints, int nCount) const
+ // Draws a polygon consisting of two or more vertices connected by straight lines.
+ {
+ assert(m_pData->hDC);
+ return ::Polygon(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::Rectangle(int x1, int y1, int x2, int y2) const
+ // Draws a rectangle. The rectangle is outlined by using the current pen and filled by using the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::Rectangle(m_pData->hDC, x1, y1, x2, y2);
+ }
+
+ inline BOOL CDC::Rectangle(const RECT& rc) const
+ // Draws a rectangle. The rectangle is outlined by using the current pen and filled by using the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::Rectangle(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom);
+ }
+
+ inline BOOL CDC::RoundRect(int x1, int y1, int x2, int y2, int nWidth, int nHeight) const
+ // Draws a rectangle with rounded corners.
+ {
+ assert(m_pData->hDC);
+ return ::RoundRect(m_pData->hDC, x1, y1, x2, y2, nWidth, nHeight);
+ }
+ inline BOOL CDC::RoundRect(const RECT& rc, int nWidth, int nHeight) const
+ // Draws a rectangle with rounded corners.
+ {
+ assert(m_pData->hDC);
+ return ::RoundRect(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom, nWidth, nHeight );
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::Chord(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws a chord (a region bounded by the intersection of an ellipse and a line segment, called a secant).
+ {
+ assert(m_pData->hDC);
+ return ::Chord(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Chord(const RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws a chord (a region bounded by the intersection of an ellipse and a line segment, called a secant).
+ {
+ assert(m_pData->hDC);
+ return ::Chord(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::Pie(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4) const
+ // Draws a pie-shaped wedge bounded by the intersection of an ellipse and two radials.
+ {
+ assert(m_pData->hDC);
+ return ::Pie(m_pData->hDC, x1, y1, x2, y2, x3, y3, x4, y4);
+ }
+
+ inline BOOL CDC::Pie(const RECT& rc, POINT ptStart, POINT ptEnd) const
+ // Draws a pie-shaped wedge bounded by the intersection of an ellipse and two radials.
+ {
+ assert(m_pData->hDC);
+ return ::Pie(m_pData->hDC, rc.left, rc.top, rc.right, rc.bottom,
+ ptStart.x, ptStart.y, ptEnd.x, ptEnd.y);
+ }
+
+ inline BOOL CDC::PolyPolygon(LPPOINT lpPoints, LPINT lpPolyCounts, int nCount) const
+ // Draws a series of closed polygons.
+ {
+ assert(m_pData->hDC);
+ return ::PolyPolygon(m_pData->hDC, lpPoints, lpPolyCounts, nCount);
+ }
+#endif
+
+ // Fill and 3D Drawing functions
+ inline BOOL CDC::FillRect(const RECT& rc, CBrush* pBrush) const
+ // Fills a rectangle by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return (BOOL)::FillRect(m_pData->hDC, &rc, *pBrush);
+ }
+
+ inline BOOL CDC::InvertRect(const RECT& rc) const
+ // Inverts a rectangle in a window by performing a logical NOT operation on the color values for each pixel in the rectangle's interior.
+ {
+ assert(m_pData->hDC);
+ return ::InvertRect( m_pData->hDC, &rc);
+ }
+
+ inline BOOL CDC::DrawIconEx(int xLeft, int yTop, HICON hIcon, int cxWidth, int cyWidth, UINT istepIfAniCur, CBrush* pFlickerFreeDraw, UINT diFlags) const
+ // draws an icon or cursor, performing the specified raster operations, and stretching or compressing the icon or cursor as specified.
+ {
+ assert(m_pData->hDC);
+ HBRUSH hFlickerFreeDraw = pFlickerFreeDraw? (HBRUSH)pFlickerFreeDraw->GetHandle() : NULL;
+ return ::DrawIconEx(m_pData->hDC, xLeft, yTop, hIcon, cxWidth, cyWidth, istepIfAniCur, hFlickerFreeDraw, diFlags);
+ }
+
+ inline BOOL CDC::DrawEdge(const RECT& rc, UINT nEdge, UINT nFlags) const
+ // Draws one or more edges of rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::DrawEdge(m_pData->hDC, (LPRECT)&rc, nEdge, nFlags);
+ }
+
+ inline BOOL CDC::DrawFrameControl(const RECT& rc, UINT nType, UINT nState) const
+ // Draws a frame control of the specified type and style.
+ {
+ assert(m_pData->hDC);
+ return ::DrawFrameControl(m_pData->hDC, (LPRECT)&rc, nType, nState);
+ }
+
+ inline BOOL CDC::FillRgn(CRgn* pRgn, CBrush* pBrush) const
+ // Fills a region by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ assert(pBrush);
+ return ::FillRgn(m_pData->hDC, *pRgn, *pBrush);
+ }
+
+#ifndef _WIN32_WCE
+ inline BOOL CDC::DrawIcon(int x, int y, HICON hIcon) const
+ // Draws an icon or cursor.
+ {
+ assert(m_pData->hDC);
+ return ::DrawIcon(m_pData->hDC, x, y, hIcon);
+ }
+
+ inline BOOL CDC::DrawIcon(POINT pt, HICON hIcon) const
+ // Draws an icon or cursor.
+ {
+ assert(m_pData->hDC);
+ return ::DrawIcon(m_pData->hDC, pt.x, pt.y, hIcon);
+ }
+
+ inline BOOL CDC::FrameRect(const RECT& rc, CBrush* pBrush) const
+ // Draws a border around the specified rectangle by using the specified brush.
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return (BOOL)::FrameRect(m_pData->hDC, &rc, *pBrush);
+ }
+
+ inline BOOL CDC::PaintRgn(CRgn* pRgn) const
+ // Paints the specified region by using the brush currently selected into the device context.
+ {
+ assert(m_pData->hDC);
+ assert(pRgn);
+ return ::PaintRgn(m_pData->hDC, *pRgn);
+ }
+#endif
+
+ // Bitmap Functions
+ inline int CDC::StretchDIBits(int XDest, int YDest, int nDestWidth, int nDestHeight, int XSrc, int YSrc, int nSrcWidth,
+ int nSrcHeight, CONST VOID *lpBits, BITMAPINFO& bi, UINT iUsage, DWORD dwRop) const
+ // Copies the color data for a rectangle of pixels in a DIB to the specified destination rectangle.
+ {
+ assert(m_pData->hDC);
+ return ::StretchDIBits(m_pData->hDC, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, nSrcWidth, nSrcHeight, lpBits, &bi, iUsage, dwRop);
+ }
+
+ inline BOOL CDC::PatBlt(int x, int y, int nWidth, int nHeight, DWORD dwRop) const
+ // Paints the specified rectangle using the brush that is currently selected into the device context.
+ {
+ assert(m_pData->hDC);
+ return ::PatBlt(m_pData->hDC, x, y, nWidth, nHeight, dwRop);
+ }
+
+ inline BOOL CDC::BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop) const
+ // Performs a bit-block transfer of the color data corresponding to a rectangle of pixels from the specified source device context into a destination device context.
+ {
+ assert(m_pData->hDC);
+ assert(pSrcDC);
+ return ::BitBlt(m_pData->hDC, x, y, nWidth, nHeight, pSrcDC->GetHDC(), xSrc, ySrc, dwRop);
+ }
+
+ inline BOOL CDC::StretchBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop) const
+ // Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary.
+ {
+ assert(m_pData->hDC);
+ assert(pSrcDC);
+ return ::StretchBlt(m_pData->hDC, x, y, nWidth, nHeight, pSrcDC->GetHDC(), xSrc, ySrc, nSrcWidth, nSrcHeight, dwRop);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::GetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, LPVOID lpvBits, LPBITMAPINFO lpbi, UINT uUsage) const
+ // Retrieves the bits of the specified compatible bitmap and copies them into a buffer as a DIB using the specified format.
+ {
+ assert(m_pData->hDC);
+ assert(pBitmap);
+ return ::GetDIBits(m_pData->hDC, *pBitmap, uStartScan, cScanLines, lpvBits, lpbi, uUsage);
+ }
+
+ inline int CDC::SetDIBits(CBitmap* pBitmap, UINT uStartScan, UINT cScanLines, CONST VOID *lpvBits, LPBITMAPINFO lpbi, UINT fuColorUse) const
+ // Sets the pixels in a compatible bitmap (DDB) using the color data found in the specified DIB.
+ {
+ assert(m_pData->hDC);
+ return ::SetDIBits(m_pData->hDC, *pBitmap, uStartScan, cScanLines, lpvBits, lpbi, fuColorUse);
+ }
+
+ inline int CDC::GetStretchBltMode() const
+ // Retrieves the current stretching mode.
+ // Possible modes: BLACKONWHITE, COLORONCOLOR, HALFTONE, STRETCH_ANDSCANS, STRETCH_DELETESCANS, STRETCH_HALFTONE, STRETCH_ORSCANS, WHITEONBLACK
+ {
+ assert(m_pData->hDC);
+ return ::GetStretchBltMode(m_pData->hDC);
+ }
+
+ inline int CDC::SetStretchBltMode(int iStretchMode) const
+ // Sets the stretching mode.
+ // Possible modes: BLACKONWHITE, COLORONCOLOR, HALFTONE, STRETCH_ANDSCANS, STRETCH_DELETESCANS, STRETCH_HALFTONE, STRETCH_ORSCANS, WHITEONBLACK
+ {
+ assert(m_pData->hDC);
+ return ::SetStretchBltMode(m_pData->hDC, iStretchMode);
+ }
+
+ inline BOOL CDC::FloodFill(int x, int y, COLORREF crColor) const
+ // Fills an area of the display surface with the current brush.
+ {
+ assert(m_pData->hDC);
+ return ::FloodFill(m_pData->hDC, x, y, crColor);
+ }
+
+ inline BOOL CDC::ExtFloodFill(int x, int y, COLORREF crColor, UINT nFillType) const
+ // Fills an area of the display surface with the current brush.
+ // Fill type: FLOODFILLBORDER or FLOODFILLSURFACE
+ {
+ assert(m_pData->hDC);
+ return ::ExtFloodFill(m_pData->hDC, x, y, crColor, nFillType );
+ }
+
+ // co-ordinate functions
+ inline BOOL CDC::DPtoLP(LPPOINT lpPoints, int nCount) const
+ // Converts device coordinates into logical coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::DPtoLP(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::DPtoLP(RECT& rc) const
+ // Converts device coordinates into logical coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::DPtoLP(m_pData->hDC, (LPPOINT)&rc, 2);
+ }
+
+ inline BOOL CDC::LPtoDP(LPPOINT lpPoints, int nCount) const
+ // Converts logical coordinates into device coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::LPtoDP(m_pData->hDC, lpPoints, nCount);
+ }
+
+ inline BOOL CDC::LPtoDP(RECT& rc) const
+ // Converts logical coordinates into device coordinates.
+ {
+ assert(m_pData->hDC);
+ return ::LPtoDP(m_pData->hDC, (LPPOINT)&rc, 2);
+ }
+
+#endif
+
+ // Layout Functions
+ inline DWORD CDC::GetLayout() const
+ // Returns the layout of a device context (LAYOUT_RTL and LAYOUT_BITMAPORIENTATIONPRESERVED).
+ {
+#if defined(WINVER) && defined(GetLayout) && (WINVER >= 0x0500)
+ return ::GetLayout(m_pData->hDC);
+#else
+ return 0;
+#endif
+ }
+
+ inline DWORD CDC::SetLayout(DWORD dwLayout) const
+ // changes the layout of a device context (DC).
+ // dwLayout values: LAYOUT_RTL or LAYOUT_BITMAPORIENTATIONPRESERVED
+ {
+#if defined(WINVER) && defined (SetLayout) && (WINVER >= 0x0500)
+ // Sets the layout of a device context
+ return ::SetLayout(m_pData->hDC, dwLayout);
+#else
+ UNREFERENCED_PARAMETER(dwLayout); // no-op
+ return 0;
+#endif
+ }
+
+ // Mapping Functions
+#ifndef _WIN32_WCE
+ inline int CDC::GetMapMode() const
+ // Rretrieves the current mapping mode.
+ // Possible modes: MM_ANISOTROPIC, MM_HIENGLISH, MM_HIMETRIC, MM_ISOTROPIC, MM_LOENGLISH, MM_LOMETRIC, MM_TEXT, and MM_TWIPS.
+ {
+ assert(m_pData->hDC);
+ return ::GetMapMode(m_pData->hDC);
+ }
+
+ inline BOOL CDC::GetViewportOrgEx(LPPOINT lpPoint) const
+ // Retrieves the x-coordinates and y-coordinates of the viewport origin for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetViewportOrgEx(m_pData->hDC, lpPoint);
+ }
+
+ inline int CDC::SetMapMode(int nMapMode) const
+ // Sets the mapping mode of the specified device context.
+ {
+ assert(m_pData->hDC);
+ return ::SetMapMode(m_pData->hDC, nMapMode);
+ }
+
+ inline BOOL CDC::SetViewportOrgEx(int x, int y, LPPOINT lpPoint /* = NULL */) const
+ // Specifies which device point maps to the window origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return ::SetViewportOrgEx(m_pData->hDC, x, y, lpPoint);
+ }
+
+ inline BOOL CDC::SetViewportOrgEx(POINT point, LPPOINT lpPointRet /* = NULL */) const
+ // Specifies which device point maps to the window origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return SetViewportOrgEx(point.x, point.y, lpPointRet);
+ }
+
+ inline BOOL CDC::OffsetViewportOrgEx(int nWidth, int nHeight, LPPOINT lpPoint /* = NULL */) const
+ // Modifies the viewport origin for the device context using the specified horizontal and vertical offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetViewportOrgEx(m_pData->hDC, nWidth, nHeight, lpPoint);
+ }
+
+ inline BOOL CDC::GetViewportExtEx(LPSIZE lpSize) const
+ // Retrieves the x-extent and y-extent of the current viewport for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetViewportExtEx(m_pData->hDC, lpSize);
+ }
+
+ inline BOOL CDC::SetViewportExtEx(int x, int y, LPSIZE lpSize ) const
+ // Sets the horizontal and vertical extents of the viewport for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return ::SetViewportExtEx(m_pData->hDC, x, y, lpSize);
+ }
+
+ inline BOOL CDC::SetViewportExtEx(SIZE size, LPSIZE lpSizeRet ) const
+ // Sets the horizontal and vertical extents of the viewport for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return SetViewportExtEx(size.cx, size.cy, lpSizeRet);
+ }
+
+ inline BOOL CDC::ScaleViewportExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize ) const
+ // Modifies the viewport for the device context using the ratios formed by the specified multiplicands and divisors.
+ {
+ assert(m_pData->hDC);
+ return ::ScaleViewportExtEx(m_pData->hDC, xNum, xDenom, yNum, yDenom, lpSize);
+ }
+
+ inline BOOL CDC::GetWindowOrgEx(LPPOINT lpPoint) const
+ // Retrieves the x-coordinates and y-coordinates of the window origin for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetWindowOrgEx(m_pData->hDC, lpPoint);
+ }
+
+ inline BOOL CDC::SetWindowOrgEx(int x, int y, LPPOINT lpPoint ) const
+ // Specifies which window point maps to the viewport origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return ::SetWindowOrgEx(m_pData->hDC, x, y, lpPoint);
+ }
+
+ inline BOOL CDC::SetWindowOrgEx(POINT point, LPPOINT lpPointRet ) const
+ // Specifies which window point maps to the viewport origin (0,0).
+ {
+ assert(m_pData->hDC);
+ return SetWindowOrgEx(point.x, point.y, lpPointRet);
+ }
+
+ inline BOOL CDC::OffsetWindowOrgEx(int nWidth, int nHeight, LPPOINT lpPoint ) const
+ // Modifies the window origin for the device context using the specified horizontal and vertical offsets.
+ {
+ assert(m_pData->hDC);
+ return ::OffsetWindowOrgEx(m_pData->hDC, nWidth, nHeight, lpPoint);
+ }
+
+ inline BOOL CDC::GetWindowExtEx(LPSIZE lpSize) const
+ // Retrieves the x-extent and y-extent of the window for the device context.
+ {
+ assert(m_pData->hDC);
+ return ::GetWindowExtEx(m_pData->hDC, lpSize);
+ }
+
+ inline BOOL CDC::SetWindowExtEx(int x, int y, LPSIZE lpSize ) const
+ // Sets the horizontal and vertical extents of the window for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return ::SetWindowExtEx(m_pData->hDC, x, y, lpSize);
+ }
+
+ inline BOOL CDC::SetWindowExtEx(SIZE size, LPSIZE lpSizeRet) const
+ // Sets the horizontal and vertical extents of the window for the device context by using the specified values.
+ {
+ assert(m_pData->hDC);
+ return SetWindowExtEx(size.cx, size.cy, lpSizeRet);
+ }
+
+ inline BOOL CDC::ScaleWindowExtEx(int xNum, int xDenom, int yNum, int yDenom, LPSIZE lpSize) const
+ // Modifies the window for the device context using the ratios formed by the specified multiplicands and divisors.
+ {
+ assert(m_pData->hDC);
+ return ::ScaleWindowExtEx(m_pData->hDC, xNum, xDenom, yNum, yDenom, lpSize);
+ }
+#endif
+
+ // Printer Functions
+ inline int CDC::StartDoc(LPDOCINFO lpDocInfo) const
+ // Starts a print job.
+ {
+ assert(m_pData->hDC);
+ return ::StartDoc(m_pData->hDC, lpDocInfo);
+ }
+
+ inline int CDC::EndDoc() const
+ // Ends a print job.
+ {
+ assert(m_pData->hDC);
+ return ::EndDoc(m_pData->hDC);
+ }
+
+ inline int CDC::StartPage() const
+ // Prepares the printer driver to accept data.
+ {
+ assert(m_pData->hDC);
+ return ::StartPage(m_pData->hDC);
+ }
+
+ inline int CDC::EndPage() const
+ // Notifies the device that the application has finished writing to a page.
+ {
+ assert(m_pData->hDC);
+ return ::EndPage(m_pData->hDC);
+ }
+
+ inline int CDC::AbortDoc() const
+ // Stops the current print job and erases everything drawn since the last call to the StartDoc function.
+ {
+ assert(m_pData->hDC);
+ return ::AbortDoc(m_pData->hDC);
+ }
+
+ inline int CDC::SetAbortProc(BOOL (CALLBACK* lpfn)(HDC, int)) const
+ // Sets the application-defined abort function that allows a print job to be canceled during spooling.
+ {
+ assert(m_pData->hDC);
+ return ::SetAbortProc(m_pData->hDC, lpfn);
+ }
+
+ // Text Functions
+ inline BOOL CDC::ExtTextOut(int x, int y, UINT nOptions, LPCRECT lprc, LPCTSTR lpszString, int nCount /*= -1*/, LPINT lpDxWidths /*=NULL*/) const
+ // Draws text using the currently selected font, background color, and text color
+ {
+ assert(m_pData->hDC);
+
+ if (nCount == -1)
+ nCount = lstrlen (lpszString);
+
+ return ::ExtTextOut(m_pData->hDC, x, y, nOptions, lprc, lpszString, nCount, lpDxWidths );
+ }
+
+ inline int CDC::DrawText(LPCTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat) const
+ // Draws formatted text in the specified rectangle
+ {
+ assert(m_pData->hDC);
+ return ::DrawText(m_pData->hDC, lpszString, nCount, lprc, nFormat );
+ }
+
+ inline UINT CDC::GetTextAlign() const
+ // Retrieves the text-alignment setting
+ // Values: TA_BASELINE, TA_BOTTOM, TA_TOP, TA_CENTER, TA_LEFT, TA_RIGHT, TA_RTLREADING, TA_NOUPDATECP, TA_UPDATECP
+ {
+ assert(m_pData->hDC);
+ return ::GetTextAlign(m_pData->hDC);
+ }
+
+ inline UINT CDC::SetTextAlign(UINT nFlags) const
+ // Sets the text-alignment setting
+ // Values: TA_BASELINE, TA_BOTTOM, TA_TOP, TA_CENTER, TA_LEFT, TA_RIGHT, TA_RTLREADING, TA_NOUPDATECP, TA_UPDATECP
+ {
+ assert(m_pData->hDC);
+ return ::SetTextAlign(m_pData->hDC, nFlags);
+ }
+
+ inline int CDC::GetTextFace(int nCount, LPTSTR lpszFacename) const
+ // Retrieves the typeface name of the font that is selected into the device context
+ {
+ assert(m_pData->hDC);
+ return ::GetTextFace(m_pData->hDC, nCount, lpszFacename);
+ }
+
+ inline BOOL CDC::GetTextMetrics(TEXTMETRIC& Metrics) const
+ // Fills the specified buffer with the metrics for the currently selected font
+ {
+ assert(m_pData->hDC);
+ return ::GetTextMetrics(m_pData->hDC, &Metrics);
+ }
+
+ inline COLORREF CDC::GetBkColor() const
+ // Returns the current background color
+ {
+ assert(m_pData->hDC);
+ return ::GetBkColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetBkColor(COLORREF crColor) const
+ // Sets the current background color to the specified color value
+ {
+ assert(m_pData->hDC);
+ return ::SetBkColor(m_pData->hDC, crColor);
+ }
+
+ inline COLORREF CDC::GetTextColor() const
+ // Retrieves the current text color
+ {
+ assert(m_pData->hDC);
+ return ::GetTextColor(m_pData->hDC);
+ }
+
+ inline COLORREF CDC::SetTextColor(COLORREF crColor) const
+ // Sets the current text color
+ {
+ assert(m_pData->hDC);
+ return ::SetTextColor(m_pData->hDC, crColor);
+ }
+
+ inline int CDC::GetBkMode() const
+ // returns the current background mix mode (OPAQUE or TRANSPARENT)
+ {
+ assert(m_pData->hDC);
+ return ::GetBkMode(m_pData->hDC);
+ }
+
+ inline int CDC::SetBkMode(int iBkMode) const
+ // Sets the current background mix mode (OPAQUE or TRANSPARENT)
+ {
+ assert(m_pData->hDC);
+ return ::SetBkMode(m_pData->hDC, iBkMode);
+ }
+
+#ifndef _WIN32_WCE
+ inline int CDC::DrawTextEx(LPTSTR lpszString, int nCount, LPRECT lprc, UINT nFormat, LPDRAWTEXTPARAMS lpDTParams) const
+ // Draws formatted text in the specified rectangle with more formatting options
+ {
+ assert(m_pData->hDC);
+ return ::DrawTextEx(m_pData->hDC, lpszString, nCount, lprc, nFormat, lpDTParams);
+ }
+
+ inline CSize CDC::GetTextExtentPoint32(LPCTSTR lpszString, int nCount) const
+ // Computes the width and height of the specified string of text
+ {
+ assert(m_pData->hDC);
+ CSize sz;
+ ::GetTextExtentPoint32(m_pData->hDC, lpszString, nCount, &sz);
+ return sz;
+ }
+
+ inline CSize CDC::GetTabbedTextExtent(LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions) const
+ // Computes the width and height of a character string
+ {
+ assert(m_pData->hDC);
+ DWORD dwSize = ::GetTabbedTextExtent(m_pData->hDC, lpszString, nCount, nTabPositions, lpnTabStopPositions );
+ CSize sz(dwSize);
+ return sz;
+ }
+
+ inline BOOL CDC::GrayString(CBrush* pBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData, int nCount, int x, int y, int nWidth, int nHeight) const
+ // Draws gray text at the specified location
+ {
+ assert(m_pData->hDC);
+ assert(pBrush);
+ return ::GrayString(m_pData->hDC, *pBrush, lpOutputFunc, lpData, nCount, x, y, nWidth, nHeight);
+ }
+
+ inline int CDC::SetTextJustification(int nBreakExtra, int nBreakCount) const
+ // Specifies the amount of space the system should add to the break characters in a string of text
+ {
+ assert(m_pData->hDC);
+ return ::SetTextJustification(m_pData->hDC, nBreakExtra, nBreakCount);
+ }
+
+ inline int CDC::GetTextCharacterExtra() const
+ // Retrieves the current intercharacter spacing for the device context
+ {
+ assert(m_pData->hDC);
+ return ::GetTextCharacterExtra(m_pData->hDC);
+ }
+
+ inline int CDC::SetTextCharacterExtra(int nCharExtra) const
+ // Sets the intercharacter spacing
+ {
+ assert(m_pData->hDC);
+ return ::SetTextCharacterExtra(m_pData->hDC, nCharExtra);
+ }
+
+ inline CSize CDC::TabbedTextOut(int x, int y, LPCTSTR lpszString, int nCount, int nTabPositions, LPINT lpnTabStopPositions, int nTabOrigin) const
+ // Writes a character string at a specified location, expanding tabs to the values specified in an array of tab-stop positions
+ {
+ assert(m_pData->hDC);
+ DWORD dwSize = ::TabbedTextOut(m_pData->hDC, x, y, lpszString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin );
+ CSize sz(dwSize);
+ return sz;
+ }
+
+ inline BOOL CDC::TextOut(int x, int y, LPCTSTR lpszString, int nCount/* = -1*/) const
+ // Writes a character string at the specified location
+ {
+ assert(m_pData->hDC);
+ if (nCount == -1)
+ nCount = lstrlen (lpszString);
+
+ return ::TextOut(m_pData->hDC, x, y, lpszString, nCount);
+ }
+
+#endif
+
+
+
+ /////////////////////////////////////////////////////////////////
+ // Definitions for some global functions in the Win32xx namespace
+ //
+
+#ifndef _WIN32_WCE
+ inline void TintBitmap (CBitmap* pbmSource, int cRed, int cGreen, int cBlue)
+ // Modifies the colour of the supplied Device Dependant Bitmap, by the colour
+ // correction values specified. The correction values can range from -255 to +255.
+ // This function gains its speed by accessing the bitmap colour information
+ // directly, rather than using GetPixel/SetPixel.
+ {
+ // Create our LPBITMAPINFO object
+ CBitmapInfoPtr pbmi(pbmSource);
+ pbmi->bmiHeader.biBitCount = 24;
+
+ // Create the reference DC for GetDIBits to use
+ CMemDC MemDC(NULL);
+
+ // Use GetDIBits to create a DIB from our DDB, and extract the colour data
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+ std::vector vBits(pbmi->bmiHeader.biSizeImage, 0);
+ byte* pByteArray = &vBits[0];
+
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ UINT nWidthBytes = pbmi->bmiHeader.biSizeImage/pbmi->bmiHeader.biHeight;
+
+ // Ensure sane colour correction values
+ cBlue = MIN(cBlue, 255);
+ cBlue = MAX(cBlue, -255);
+ cRed = MIN(cRed, 255);
+ cRed = MAX(cRed, -255);
+ cGreen = MIN(cGreen, 255);
+ cGreen = MAX(cGreen, -255);
+
+ // Pre-calculate the RGB modification values
+ int b1 = 256 - cBlue;
+ int g1 = 256 - cGreen;
+ int r1 = 256 - cRed;
+
+ int b2 = 256 + cBlue;
+ int g2 = 256 + cGreen;
+ int r2 = 256 + cRed;
+
+ // Modify the colour
+ int yOffset = 0;
+ int xOffset;
+ int Index;
+ for (int Row=0; Row < pbmi->bmiHeader.biHeight; Row++)
+ {
+ xOffset = 0;
+
+ for (int Column=0; Column < pbmi->bmiHeader.biWidth; Column++)
+ {
+ // Calculate Index
+ Index = yOffset + xOffset;
+
+ // Adjust the colour values
+ if (cBlue > 0)
+ pByteArray[Index] = (BYTE)(cBlue + (((pByteArray[Index] *b1)) >>8));
+ else if (cBlue < 0)
+ pByteArray[Index] = (BYTE)((pByteArray[Index] *b2) >>8);
+
+ if (cGreen > 0)
+ pByteArray[Index+1] = (BYTE)(cGreen + (((pByteArray[Index+1] *g1)) >>8));
+ else if (cGreen < 0)
+ pByteArray[Index+1] = (BYTE)((pByteArray[Index+1] *g2) >>8);
+
+ if (cRed > 0)
+ pByteArray[Index+2] = (BYTE)(cRed + (((pByteArray[Index+2] *r1)) >>8));
+ else if (cRed < 0)
+ pByteArray[Index+2] = (BYTE)((pByteArray[Index+2] *r2) >>8);
+
+ // Increment the horizontal offset
+ xOffset += pbmi->bmiHeader.biBitCount >> 3;
+ }
+
+ // Increment vertical offset
+ yOffset += nWidthBytes;
+ }
+
+ // Save the modified colour back into our source DDB
+ MemDC.SetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ }
+
+ inline void GrayScaleBitmap(CBitmap* pbmSource)
+ {
+ // Create our LPBITMAPINFO object
+ CBitmapInfoPtr pbmi(pbmSource);
+
+ // Create the reference DC for GetDIBits to use
+ CMemDC MemDC(NULL);
+
+ // Use GetDIBits to create a DIB from our DDB, and extract the colour data
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, NULL, pbmi, DIB_RGB_COLORS);
+ std::vector vBits(pbmi->bmiHeader.biSizeImage, 0);
+ byte* pByteArray = &vBits[0];
+
+ MemDC.GetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ UINT nWidthBytes = pbmi->bmiHeader.biSizeImage/pbmi->bmiHeader.biHeight;
+
+ int yOffset = 0;
+ int xOffset;
+ int Index;
+
+ for (int Row=0; Row < pbmi->bmiHeader.biHeight; Row++)
+ {
+ xOffset = 0;
+
+ for (int Column=0; Column < pbmi->bmiHeader.biWidth; Column++)
+ {
+ // Calculate Index
+ Index = yOffset + xOffset;
+
+ BYTE byGray = (BYTE) ((pByteArray[Index] + pByteArray[Index+1]*6 + pByteArray[Index+2] *3)/10);
+ pByteArray[Index] = byGray;
+ pByteArray[Index+1] = byGray;
+ pByteArray[Index+2] = byGray;
+
+ // Increment the horizontal offset
+ xOffset += pbmi->bmiHeader.biBitCount >> 3;
+ }
+
+ // Increment vertical offset
+ yOffset += nWidthBytes;
+ }
+
+ // Save the modified colour back into our source DDB
+ MemDC.SetDIBits(pbmSource, 0, pbmi->bmiHeader.biHeight, pByteArray, pbmi, DIB_RGB_COLORS);
+ }
+
+ inline HIMAGELIST CreateDisabledImageList(HIMAGELIST himlNormal)
+ // Returns a greyed image list, created from hImageList
+ {
+ int cx, cy;
+ int nCount = ImageList_GetImageCount(himlNormal);
+ if (0 == nCount)
+ return NULL;
+
+ ImageList_GetIconSize(himlNormal, &cx, &cy);
+
+ // Create the disabled ImageList
+ HIMAGELIST himlDisabled = ImageList_Create(cx, cy, ILC_COLOR24 | ILC_MASK, nCount, 0);
+
+ // Process each image in the ImageList
+ for (int i = 0 ; i < nCount; ++i)
+ {
+ CClientDC DesktopDC(NULL);
+ CMemDC MemDC(NULL);
+ CBitmap* pOldBitmap = MemDC.CreateCompatibleBitmap(&DesktopDC, cx, cx);
+ CRect rc;
+ rc.SetRect(0, 0, cx, cx);
+
+ // Set the mask color to grey for the new ImageList
+ COLORREF crMask = RGB(200, 199, 200);
+ if ( GetDeviceCaps(DesktopDC, BITSPIXEL) < 24)
+ {
+ HPALETTE hPal = (HPALETTE)GetCurrentObject(DesktopDC, OBJ_PAL);
+ UINT Index = GetNearestPaletteIndex(hPal, crMask);
+ if (Index != CLR_INVALID) crMask = PALETTEINDEX(Index);
+ }
+
+ MemDC.SolidFill(crMask, rc);
+
+ // Draw the image on the memory DC
+ ImageList_SetBkColor(himlNormal, crMask);
+ ImageList_Draw(himlNormal, i, MemDC, 0, 0, ILD_NORMAL);
+
+ // Convert colored pixels to gray
+ for (int x = 0 ; x < cx; ++x)
+ {
+ for (int y = 0; y < cy; ++y)
+ {
+ COLORREF clr = ::GetPixel(MemDC, x, y);
+
+ if (clr != crMask)
+ {
+ BYTE byGray = (BYTE) (95 + (GetRValue(clr) *3 + GetGValue(clr)*6 + GetBValue(clr))/20);
+ MemDC.SetPixel(x, y, RGB(byGray, byGray, byGray));
+ }
+
+ }
+ }
+
+ // Detach the bitmap so we can use it.
+ CBitmap* pBitmap = MemDC.SelectObject(pOldBitmap);
+ ImageList_AddMasked(himlDisabled, *pBitmap, crMask);
+ }
+
+ return himlDisabled;
+ }
+#endif
+
+ ////////////////////////////////////////////
+ // Global Function Definitions
+ //
+
+ inline CDC* FromHandle(HDC hDC)
+ // Returns the CDC object associated with the device context handle
+ // If a CDC object doesn't already exist, a temporary CDC object is created.
+ // The HDC belonging to a temporary CDC is not released or destroyed when the
+ // temporary CDC is deconstructed.
+ {
+ assert( GetApp() );
+ CDC* pDC = GetApp()->GetCDCFromMap(hDC);
+ if (hDC != 0 && pDC == 0)
+ {
+ pDC = new CDC;
+ GetApp()->AddTmpDC(pDC);
+ pDC->m_pData->hDC = hDC;
+ pDC->m_pData->bRemoveHDC = FALSE;
+ }
+ return pDC;
+ }
+
+ inline CBitmap* FromHandle(HBITMAP hBitmap)
+ // Returns the CBitmap associated with the Bitmap handle
+ // If a CBitmap object doesn't already exist, a temporary CBitmap object is created.
+ // The HBITMAP belonging to a temporary CBitmap is not released or destroyed
+ // when the temporary CBitmap is deconstructed.
+ {
+ assert( GetApp() );
+ CBitmap* pBitmap = (CBitmap*)GetApp()->GetCGDIObjectFromMap(hBitmap);
+ if (hBitmap != 0 && pBitmap == 0)
+ {
+ pBitmap = new CBitmap;
+ GetApp()->AddTmpGDI(pBitmap);
+ pBitmap->m_pData->hGDIObject = hBitmap;
+ pBitmap->m_pData->bRemoveObject = FALSE;
+ }
+ return pBitmap;
+ }
+
+ inline CBrush* FromHandle(HBRUSH hBrush)
+ // Returns the CBrush associated with the Brush handle
+ // If a CBrush object doesn't already exist, a temporary CBrush object is created.
+ // The HBRUSH belonging to a temporary CBrush is not released or destroyed
+ // when the temporary CBrush is deconstructed.
+ {
+ assert( GetApp() );
+ CBrush* pBrush = (CBrush*)GetApp()->GetCGDIObjectFromMap(hBrush);
+ if (hBrush != 0 && pBrush == 0)
+ {
+ pBrush = new CBrush;
+ GetApp()->AddTmpGDI(pBrush);
+ pBrush->m_pData->hGDIObject = hBrush;
+ pBrush->m_pData->bRemoveObject = FALSE;
+ }
+ return pBrush;
+ }
+
+ inline CFont* FromHandle(HFONT hFont)
+ // Returns the CFont associated with the Font handle
+ // If a CFont object doesn't already exist, a temporary CFont object is created.
+ // The HFONT belonging to a temporary CFont is not released or destroyed
+ // when the temporary CFont is deconstructed.
+ {
+ assert( GetApp() );
+ CFont* pFont = (CFont*)GetApp()->GetCGDIObjectFromMap(hFont);
+ if (hFont != 0 && pFont == 0)
+ {
+ pFont = new CFont;
+ GetApp()->AddTmpGDI(pFont);
+ pFont->m_pData->hGDIObject = hFont;
+ pFont->m_pData->bRemoveObject = FALSE;
+ }
+ return pFont;
+ }
+
+ inline CPalette* FromHandle(HPALETTE hPalette)
+ // Returns the CPalette associated with the palette handle
+ // If a CPalette object doesn't already exist, a temporary CPalette object is created.
+ // The HPALETTE belonging to a temporary CPalette is not released or destroyed
+ // when the temporary CPalette is deconstructed.
+ {
+ assert( GetApp() );
+ CPalette* pPalette = (CPalette*)GetApp()->GetCGDIObjectFromMap(hPalette);
+ if (hPalette != 0 && pPalette == 0)
+ {
+ pPalette = new CPalette;
+ GetApp()->AddTmpGDI(pPalette);
+ pPalette->m_pData->hGDIObject = hPalette;
+ pPalette->m_pData->bRemoveObject = FALSE;
+ }
+ return pPalette;
+ }
+
+ inline CPen* FromHandle(HPEN hPen)
+ // Returns the CPen associated with the HPEN.
+ // If a CPen object doesn't already exist, a temporary CPen object is created.
+ // The HPEN belonging to a temporary CPen is not released or destroyed
+ // when the temporary CPen is deconstructed.
+ {
+ assert( GetApp() );
+ CPen* pPen = (CPen*)GetApp()->GetCGDIObjectFromMap(hPen);
+ if (hPen != 0 && pPen == 0)
+ {
+ pPen = new CPen;
+ GetApp()->AddTmpGDI(pPen);
+ pPen->m_pData->hGDIObject = hPen;
+ pPen->m_pData->bRemoveObject = FALSE;
+ }
+ return pPen;
+ }
+
+ inline CRgn* FromHandle(HRGN hRgn)
+ // Returns the CRgn associated with the HRGN.
+ // If a CRgn object doesn't already exist, a temporary CRgn object is created.
+ // The HRGN belonging to a temporary CRgn is not released or destroyed
+ // when the temporary CRgn is deconstructed.
+ {
+ assert( GetApp() );
+ CRgn* pRgn = (CRgn*)GetApp()->GetCGDIObjectFromMap(hRgn);
+ if (hRgn != 0 && pRgn == 0)
+ {
+ pRgn = new CRgn;
+ GetApp()->AddTmpGDI(pRgn);
+ pRgn->m_pData->hGDIObject = hRgn;
+ pRgn->m_pData->bRemoveObject = FALSE;
+ }
+ return pRgn;
+ }
+
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_GDI_H_
+
diff --git a/external/win32cpp/include/info.txt b/external/win32cpp/include/info.txt
new file mode 100644
index 0000000..a4dbda8
--- /dev/null
+++ b/external/win32cpp/include/info.txt
@@ -0,0 +1,205 @@
+Generic Information about Win32++ Projects
+==========================================
+The various directories may contain the following types of files:
+
+Extension | Description
+----------+------------
+cbp | A project file used by CodeBlocks
+dsp | A project file used by Visual Studio 6
+dsw | A project file used by Visual Studio 6
+sln | A project file used by Visual Studio 2003, VS2005 or VS2008
+vcproj | A project file used by Visual Studio 2003, VS2005 or VS2008
+vcxproj | A project file used by Visual Studio 2010
+filters | A supplementary project file used by Visual Studio 2010
+bdsproj | A project file used by Borland Developer Studio 2006
+bpf | A project file used by Borland Developer Studio 2006
+vcp | A project file used by eMbedded Visual C++
+vcw | A project file used by eMbedded Visual C++
+dev | A project file used by Dev-C++
+cpp | A C++ source file
+h | A C++ header file
+rc | A C++ resouce script file
+jpg | A jpeg resource file
+ico | An icon resource file
+bmp | A bitmap resource file
+cur | A cursor resource file
+manifest | A manifest resource file
+txt | A text file
+xml | An Extensible Markup Language file (defines the ribbon UI)
+
+Supported Compilers and Integrated Development Environments (IDEs)
+==================================================================
+Win32++ supports the following:
+* Borland Compiler Version 5.5
+* Borland Developer Studio 2006
+* Borland Turbo C++ 2006
+* CodeBlocks
+* Dev-C++
+* MinGW GCC Compiler
+* Visual Studio 6
+* Visual Studio.net 2003
+* Visual C++ Toolkit 2003
+* Visual Studio.net 2005
+* Visual Studio.net 2005 Express
+* Visual Studio.net 2008
+* Visual Studio.net 2008 Express
+* Visual Studio.net 2010
+
+CodeBlocks is an IDE. The project files are configured for the following
+compilers:
+* Borland Compiler Version 5.5
+* MinGW GNU compiler
+* Visual C++ Toolkit 2003
+
+Dev-C++ is an IDE which supports the MinGW GNU compiler
+
+Supported Operating Systems
+===========================
+The programs compiled with Win32++ can run on the following operating systems:
+* Win95 (all versions, with or without Internet Explorer 4 installed)
+* Win98 (both versions)
+* WinME
+* Windows NT 4
+* Windows 2000
+* Windows XP
+* Windows XP x64
+* Windows Vista
+* Windows Vista x64
+* Windows 7
+* Windows 7 x64
+* Windows Server 2003
+* Windows Server 2003 x64
+* Windows Server 2008
+* Windows Server 2008 x64
+* Windows CE
+
+Note: Programs compiled with Visual Studio.net 2008 and Visual Studio.net 2008
+Express will not run on Win32 operating systems earlier than Windows 2000.
+
+Win32++ automatically detects if the operating system is capable of using
+rebars. If rebars are not supported by the OS, Win32++ produces a frame without
+rebars.
+
+Win32++ is Unicode compliant and can therefore be used to develop Unicode
+applications. Users are advised that older operating systems (namely Win95,
+Win98 and WinME) don't support Unicode applications.
+
+Win32++ supports 64bit compilers, and can be used to develop 64bit code.
+
+Directory Structure
+===================
+When extracting the files from the zip archive, be sure to preserve the
+directory structure. The directory structure will typically look like this:
+
+.\include
+.\new projects
+.\output
+.\samples
+.\tools
+.\tutorials
+.\WCE samples
+
+The files which form the Win32++ library are contained in the include
+subdirectory.
+
+Components of Win32++
+=====================
+
+ Files | Classes | Operating Systems | Description
+==================+==================+===================+=====================
+controls.h | CAnimation | Win32, Win64 | Adds support for the
+ | CComboBox | and WinCE | following controls:
+ | CComboBoxEx | | Animation, ComboBox,
+ | CProgressBar | | ComboBoxEx, Progress
+ | CScrollBar | | bar, Scroll bar,
+ | CSlider | | Slider, Spin button.
+ | CSpinButton | |
+------------------+------------------+-------------------+---------------------
+dialog.h | CDialog | Win32, Win64 | Adds dialog support.
+ | CResizer | WinCE for CDialog |
+------------------+------------------+-------------------+---------------------
+docking.h | CDocker | Win32, Win64 | Adds support for
+ | CDockContainer | | docking windows and
+ | | | splitter windows.
+------------------+------------------+-------------------+---------------------
+frame.h | CMenubar | Win32, Win64 | Adds support for
+ | CFrame | | frames. Frames use a
+ | | | toolbar and menubar
+ | | | inside a rebar, and
+ | | | a statusbar.
+------------------+------------------+-------------------+---------------------
+gdi.h | CDC | Win32, Win64 | A helper class for
+ | CBitmap | and WinCE | GDI graphics.
+ | CBrush | |
+ | CFont | |
+ | CPalette | |
+ | CPen | |
+ | CRgn | |
+------------------+------------------+-------------------+---------------------
+listView.h | CListView | Win32, Win64 | Adds support for a
+ | | and WinCE | ListView control.
+------------------+------------------+-------------------+---------------------
+mdi.h | CMDIFrame | Win32, Win64 | Adds support for MDI
+ | CMDIChild | | frames.
+------------------+------------------+-------------------+---------------------
+propertysheet.h | CPropertySheet | Win32, Win64 | Adds property sheet
+ | CPropertyPage | and WinCE | support.
+------------------+------------------+-------------------+---------------------
+rebar.h | CRebar | Win32, Win64 | Adds support for a
+ | | and WinCE | Rebar control.
+------------------+------------------+-------------------+---------------------
+ribbon.h | CRibbon | Win32, Win64 | Adds support for the
+ | CRibbonFrame | | Windows 7 ribbon.
+------------------+------------------+-------------------+---------------------
+shared_ptr.h | Shared_Ptr | Win32, Win64, | Add a smart pointer
+ | | and WinCE | for use in vectors.
+------------------+------------------+-------------------+---------------------
+socket.h | CSocket | Win32, Win64 | Adds network
+ | | and WinCE | support.
+------------------+------------------+-------------------+---------------------
+splitter.h | CSplitter | Win32, Win64 | Adds splitter support
+ | | | (depreciated)
+------------------+------------------+-------------------+----------------------
+statusbar.h | CStatusbar | Win32, Win64 | Adds support for a
+ | | and WinCE | Status bar control.
+------------------+------------------+-------------------+---------------------
+stdcontrols.h | CButton | Win32, Win64 | Adds support for
+ | CEdit | and WinCE | Button, Edit,
+ | CListBox | | ListBox and Static
+ | CStatic | | controls.
+------------------+------------------+-------------------+---------------------
+tab.h | CTab | Win32, Win64 | Adds support for tab
+ | CMDITab | | controls, and MDI
+ | | | tab windows.
+------------------+------------------+-------------------+---------------------
+taskdialog.h | CTaskDialog | Win32, Win64 | Adds support for tab
+ | | | task dialogs.
+------------------+------------------+-------------------+---------------------
+thread.h | CThread | Win32, Win64 | Adds support for
+ | | and WinCE | threads.
+------------------+------------------+-------------------+---------------------
+toolbar.h | CToolbar | Win32, Win64 | Adds support for a
+ | | and WinCE | Toolbar control.
+------------------+------------------+-------------------+---------------------
+treeview.h | CTreeView | Win32, Win64 | Adds support for a
+ | | and WinCE | TreeView control.
+------------------+------------------+-------------------+---------------------
+wceframe.h | CWceFrame | WinCE only | Adds support for
+ | CCmdbar | | frames in WinCE.
+------------------+------------------+-------------------+---------------------
+webbrowser.h | CAXWindow | Win32, Win64 | Adds support for a
+ | CWebBrowser | and WinCE | ActiveX container and
+ | | | a WebBrowser window.
+------------------+------------------+-------------------+---------------------
+wincore.h | CCriticalSection | Win32, Win64, | The core set of
+ | CWinApp | and WinCE | classes required for
+ | CWinException | | all Win32++
+ | CWnd | | applications.
+------------------+------------------+-------------------+---------------------
+winutils.h | CPoint | Win32, Win64, | Additional utility
+ | CRect | and WinCE | classes.
+ | CSize | |
+------------------+------------------+-------------------+---------------------
+
+Refer to the help documentation that ships with Win32++ for more information on
+using Win32++.
\ No newline at end of file
diff --git a/external/win32cpp/include/listview.h b/external/win32cpp/include/listview.h
new file mode 100644
index 0000000..810e762
--- /dev/null
+++ b/external/win32cpp/include/listview.h
@@ -0,0 +1,867 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+
+#ifndef _WIN32XX_LISTVIEW_H_
+#define _WIN32XX_LISTVIEW_H_
+
+#include "wincore.h"
+#include "commctrl.h"
+
+namespace Win32xx
+{
+
+ class CListView : public CWnd
+ {
+ public:
+ CListView() {}
+ virtual ~CListView() {}
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ // Attributes
+ CSize ApproximateViewRect(CSize sz = CSize(-1, -1), int iCount = -1) const;
+ COLORREF GetBkColor( ) const;
+ BOOL GetBkImage( LVBKIMAGE& lvbkImage ) const;
+ UINT GetCallbackMask( ) const;
+ BOOL GetCheckState( UINT nItem ) const;
+ BOOL GetColumn( int iCol, LVCOLUMN& Column ) const;
+ BOOL GetColumnOrderArray( LPINT piArray, int iCount = -1 );
+ int GetColumnWidth( int iCol ) const;
+ int GetCountPerPage( ) const;
+ HWND GetEditControl( ) const;
+ DWORD GetExtendedStyle( ) const;
+ HWND GetHeader( ) const;
+ HCURSOR GetHotCursor( );
+ int GetHotItem( ) const;
+ DWORD GetHoverTime( ) const;
+ HIMAGELIST GetImageList( int nImageType ) const;
+ BOOL GetItem( LVITEM& lvItem ) const;
+ int GetItemCount( ) const;
+ DWORD_PTR GetItemData( int iItem ) const;
+ BOOL GetItemPosition( int iItem, CPoint& pt ) const;
+ BOOL GetItemRect( int iItem, CRect& rc, UINT nCode ) const;
+ UINT GetItemState( int iItem, UINT nMask ) const;
+ tString GetItemText( int iItem, int iSubItem, UINT nTextMax = 260 ) const;
+ int GetNextItem( int iItem, int iFlags ) const;
+ UINT GetNumberOfWorkAreas( ) const;
+ BOOL GetOrigin( CPoint& pt ) const;
+ UINT GetSelectedCount( ) const;
+ int GetSelectionMark( ) const;
+ int GetStringWidth( LPCTSTR pszString ) const;
+ BOOL GetSubItemRect( int iItem, int iSubItem, int iCode, CRect& rc ) const;
+ COLORREF GetTextBkColor( ) const;
+ COLORREF GetTextColor( ) const;
+ HWND GetToolTips( ) const;
+ int GetTopIndex( ) const;
+ BOOL GetViewRect( CRect& rc ) const;
+ void GetWorkAreas( int iWorkAreas, LPRECT pRectArray ) const;
+ BOOL SetBkColor( COLORREF clrBk ) const;
+ BOOL SetBkImage( LVBKIMAGE& plvbkImage ) const;
+ BOOL SetCallbackMask( UINT nMask ) const;
+ void SetCheckState( int iItem, BOOL fCheck = TRUE ) const;
+ BOOL SetColumn( int iCol, const LVCOLUMN& pColumn ) const;
+ BOOL SetColumnOrderArray( int iCount, LPINT piArray ) const;
+ BOOL SetColumnWidth( int iCol, int cx ) const;
+ DWORD SetExtendedStyle( DWORD dwNewStyle ) const;
+ HCURSOR SetHotCursor( HCURSOR hCursor ) const;
+ int SetHotItem( int nIndex ) const;
+ DWORD SetHoverTime( DWORD dwHoverTime = (DWORD)-1 ) const;
+ CSize SetIconSpacing( int cx, int cy ) const;
+ CSize SetIconSpacing( CSize sz ) const;
+ HIMAGELIST SetImageList( HIMAGELIST himl, int iImageListType ) const;
+ BOOL SetItem( LVITEM& pItem ) const;
+ BOOL SetItem( int iItem, int iSubItem, UINT nMask, LPCTSTR pszText, int iImage,
+ UINT nState, UINT nStateMask, LPARAM lParam, int iIndent ) const;
+ void SetItemCount( int iCount ) const;
+ void SetItemCountEx( int iCount, DWORD dwFlags = LVSICF_NOINVALIDATEALL ) const;
+ BOOL SetItemData( int iItem, DWORD_PTR dwData ) const;
+ BOOL SetItemPosition( int iItem, CPoint& pt ) const;
+ BOOL SetItemState( int iItem, LVITEM& Item ) const;
+ void SetItemState( int iItem, UINT nState, UINT nMask ) const;
+ void SetItemText( int iItem, int iSubItem, LPCTSTR pszText ) const;
+ int SetSelectionMark( int iIndex ) const;
+ BOOL SetTextBkColor( COLORREF clrBkText ) const;
+ BOOL SetTextColor( COLORREF clrText ) const;
+ HWND SetToolTips( HWND hWndToolTip ) const;
+ void SetWorkAreas( int nWorkAreas, CRect& pRectArray ) const;
+ int SubItemHitTest( LVHITTESTINFO& htInfo ) const;
+
+ // Operations
+ BOOL Arrange( UINT nCode ) const;
+ HIMAGELIST CreateDragImage( int iItem, CPoint& pt ) const;
+ BOOL DeleteAllItems( ) const;
+ BOOL DeleteColumn( int iCol ) const;
+ BOOL DeleteItem( int iItem ) const;
+ HWND EditLabel( int iItem ) const;
+ BOOL EnsureVisible( int iItem, BOOL fPartialOK ) const;
+ int FindItem( LVFINDINFO& FindInfo, int iStart = -1 ) const;
+ int HitTest( LVHITTESTINFO& HitTestInfo ) const;
+ int HitTest( CPoint pt, UINT* pFlags = NULL ) const;
+ int InsertColumn( int iCol, const LVCOLUMN& pColumn ) const;
+ int InsertColumn( int iCol, LPCTSTR pszColumnHeading, int iFormat = LVCFMT_LEFT,
+ int iWidth = -1, int iSubItem = -1 ) const;
+ int InsertItem( const LVITEM& pItem ) const;
+ int InsertItem( int iItem, LPCTSTR pszText ) const;
+ int InsertItem( int iItem, LPCTSTR pszText, int iImage ) const;
+ BOOL RedrawItems( int iFirst, int iLast ) const;
+ BOOL Scroll( CSize sz ) const;
+ BOOL SortItems( PFNLVCOMPARE pfnCompare, DWORD_PTR dwData ) const;
+ BOOL Update( int iItem ) const;
+
+ private:
+ CListView(const CListView&); // Disable copy construction
+ CListView& operator = (const CListView&); // Disable assignment operator
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline void CListView::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = WC_LISTVIEW;
+ }
+
+ inline CSize CListView::ApproximateViewRect(CSize sz /*= CSize(-1, -1)*/, int iCount /* = -1*/) const
+ // Calculates the approximate width and height required to display a given number of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_ApproximateViewRect( m_hWnd, sz.cx, sz.cy, iCount ) );
+ }
+
+ inline COLORREF CListView::GetBkColor( ) const
+ // Retrieves the background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetBkColor( m_hWnd );
+ }
+
+ inline BOOL CListView::GetBkImage( LVBKIMAGE& lvbkImage ) const
+ // Retrieves the background image in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetBkImage( m_hWnd, &lvbkImage );
+ }
+
+ inline UINT CListView::GetCallbackMask( ) const
+ // Retrieves the callback mask for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCallbackMask( m_hWnd );
+ }
+
+ inline BOOL CListView::GetCheckState( UINT nItem ) const
+ // Determines if an item in a list-view control is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCheckState( m_hWnd, nItem );
+ }
+
+ inline BOOL CListView::GetColumn( int iCol, LVCOLUMN& Column ) const
+ // Retrieves the attributes of a list-view control's column.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline BOOL CListView::GetColumnOrderArray( LPINT piArray, int iCount /*= -1*/ )
+ // Retrieves the current left-to-right order of columns in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumnOrderArray( m_hWnd, iCount, piArray );
+ }
+
+ inline int CListView::GetColumnWidth( int iCol ) const
+ // Retrieves the width of a column in report or list view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetColumnWidth( m_hWnd, iCol );
+ }
+
+ inline int CListView::GetCountPerPage( ) const
+ // Calculates the number of items that can fit vertically in the visible area of a
+ // list-view control when in list or report view. Only fully visible items are counted.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetCountPerPage( m_hWnd );
+ }
+
+ inline HWND CListView::GetEditControl( ) const
+ // Retrieves the handle to the edit control being used to edit a list-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetEditControl( m_hWnd );
+ }
+
+ inline DWORD CListView::GetExtendedStyle( ) const
+ // Retrieves the extended styles that are currently in use for a given list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetExtendedListViewStyle( m_hWnd );
+ }
+
+ inline HWND CListView::GetHeader( ) const
+ // Retrieves the handle to the header control used by a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHeader( m_hWnd );
+ }
+
+ inline HCURSOR CListView::GetHotCursor( )
+ // Retrieves the HCURSOR used when the pointer is over an item while hot tracking is enabled.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHotCursor( m_hWnd );
+ }
+
+ inline int CListView::GetHotItem( ) const
+ // Retrieves the index of the hot item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHotItem( m_hWnd );
+ }
+
+ inline DWORD CListView::GetHoverTime( ) const
+ // Retrieves the amount of time that the mouse cursor must hover over an item before it is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetHoverTime( m_hWnd );
+ }
+
+ inline HIMAGELIST CListView::GetImageList( int nImageType ) const
+ // Retrieves the handle to an image list used for drawing list-view items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetImageList( m_hWnd, nImageType );
+ }
+
+ inline BOOL CListView::GetItem( LVITEM& Item ) const
+ // Retrieves some or all of a list-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItem( m_hWnd, &Item );
+ }
+
+ inline int CListView::GetItemCount( ) const
+ // Retrieves the number of items in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemCount( m_hWnd );
+ }
+
+ inline DWORD_PTR CListView::GetItemData( int iItem ) const
+ // Retrieves the value(lParam) specific to the item.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.mask = LVIF_PARAM;
+ ListView_GetItem(m_hWnd, &lvi);
+ return lvi.lParam;
+ }
+
+ inline BOOL CListView::GetItemPosition( int iItem, CPoint& pt ) const
+ // Retrieves the position of a list-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemPosition( m_hWnd, iItem, &pt );
+ }
+
+ inline BOOL CListView::GetItemRect( int iItem, CRect& rc, UINT nCode ) const
+ // Retrieves the bounding rectangle for all or part of an item in the current view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemRect( m_hWnd, iItem, &rc, nCode );
+ }
+
+ inline UINT CListView::GetItemState( int iItem, UINT nMask ) const
+ // Retrieves the state of a list-view item.
+
+ // Possible values of nMask:
+ // LVIS_CUT The item is marked for a cut-and-paste operation.
+ // LVIS_DROPHILITED The item is highlighted as a drag-and-drop target.
+ // LVIS_FOCUSED The item has the focus, so it is surrounded by a standard focus rectangle.
+ // LVIS_SELECTED The item is selected.
+ // LVIS_OVERLAYMASK Use this mask to retrieve the item's overlay image index.
+ // LVIS_STATEIMAGEMASK Use this mask to retrieve the item's state image index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetItemState( m_hWnd, iItem, nMask );
+ }
+
+ inline tString CListView::GetItemText( int iItem, int iSubItem, UINT nTextMax /* = 260 */ ) const
+ // Retrieves the text of a list-view item.
+ // Note: Although the list-view control allows any length string to be stored
+ // as item text, only the first 260 characters are displayed.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ tString t;
+ if (nTextMax > 0)
+ {
+ std::vector vTChar(nTextMax +1, _T('\0'));
+ TCHAR* pszText = &vTChar.front();
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.mask = LVIF_TEXT;
+ lvi.cchTextMax = nTextMax;
+ lvi.pszText = pszText;
+ ListView_GetItem( m_hWnd, &lvi );
+ t = lvi.pszText;
+ }
+ return t;
+ }
+
+ inline int CListView::GetNextItem( int iItem, int iFlags ) const
+ // Searches for a list-view item that has the specified properties and
+ // bears the specified relationship to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetNextItem( m_hWnd, iItem, iFlags );
+ }
+
+ inline UINT CListView::GetNumberOfWorkAreas( ) const
+ // Retrieves the working areas from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ UINT nWorkAreas = 0;
+ ListView_GetWorkAreas( m_hWnd, nWorkAreas, NULL );
+ return nWorkAreas;
+ }
+
+ inline BOOL CListView::GetOrigin( CPoint& pt ) const
+ // Retrieves the current view origin for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetOrigin( m_hWnd, &pt );
+ }
+
+ inline UINT CListView::GetSelectedCount( ) const
+ // Determines the number of selected items in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)::SendMessage( m_hWnd, LVM_GETSELECTEDCOUNT, 0L, 0L );
+ }
+
+ inline int CListView::GetSelectionMark( ) const
+ // Retrieves the selection mark from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage( m_hWnd, LVM_GETSELECTIONMARK, 0L, 0L );
+ }
+
+ inline int CListView::GetStringWidth( LPCTSTR pszString ) const
+ // Determines the width of a specified string using the specified list-view control's current font.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage( m_hWnd, LVM_GETSTRINGWIDTH, 0L, (LPARAM)pszString );
+ }
+
+ inline BOOL CListView::GetSubItemRect( int iItem, int iSubItem, int iCode, CRect& rc ) const
+ // Retrieves information about the rectangle that surrounds a subitem in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetSubItemRect( m_hWnd, iItem, iSubItem, iCode, &rc );
+ }
+
+ inline COLORREF CListView::GetTextBkColor( ) const
+ // Retrieves the text background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTextBkColor( m_hWnd );
+ }
+
+ inline COLORREF CListView::GetTextColor( ) const
+ // Retrieves the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTextColor( m_hWnd );
+ }
+
+ inline HWND CListView::GetToolTips( ) const
+ // Retrieves the ToolTip control that the list-view control uses to display ToolTips.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetToolTips( m_hWnd );
+ }
+
+ inline int CListView::GetTopIndex( ) const
+ // Retrieves the index of the topmost visible item when in list or report view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetTopIndex( m_hWnd );
+ }
+
+ inline BOOL CListView::GetViewRect( CRect& rc ) const
+ // Retrieves the bounding rectangle of all items in the list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_GetViewRect( m_hWnd, &rc );
+ }
+
+ inline void CListView::GetWorkAreas( int iWorkAreas, LPRECT pRectArray ) const
+ // Retrieves the working areas from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_GetWorkAreas( m_hWnd, iWorkAreas, pRectArray );
+ }
+
+ inline BOOL CListView::SetBkColor( COLORREF clrBk ) const
+ // Sets the background color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetBkColor( m_hWnd, clrBk );
+ }
+
+ inline BOOL CListView::SetBkImage( LVBKIMAGE& lvbkImage ) const
+ // Sets the background image in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetBkImage( m_hWnd, &lvbkImage );
+ }
+
+ inline BOOL CListView::SetCallbackMask( UINT nMask ) const
+ // Changes the callback mask for a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetCallbackMask( m_hWnd, nMask );
+ }
+
+ inline void CListView::SetCheckState( int iItem, BOOL fCheck /*= TRUE*/ ) const
+ // Used to select or deselect an item in a list-view control.
+ // This macro should only be used for list-view controls with the LVS_EX_CHECKBOXES style.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemState(m_hWnd, iItem, INDEXTOSTATEIMAGEMASK((fCheck==TRUE)?2:1),LVIS_STATEIMAGEMASK);
+ }
+
+ inline BOOL CListView::SetColumn( int iCol, const LVCOLUMN& Column ) const
+ // Sets the attributes of a list-view column.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline BOOL CListView::SetColumnOrderArray( int iCount, LPINT piArray ) const
+ // Sets the left-to-right order of columns in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumnOrderArray( m_hWnd, iCount, piArray );
+ }
+
+ inline BOOL CListView::SetColumnWidth( int iCol, int cx ) const
+ // Used to change the width of a column in report view or the width of all columns in list-view mode.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetColumnWidth( m_hWnd, iCol, cx );
+ }
+
+ inline DWORD CListView::SetExtendedStyle( DWORD dwNewStyle ) const
+ // Sets extended styles for list-view controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetExtendedListViewStyle( m_hWnd, dwNewStyle );
+ }
+
+ inline HCURSOR CListView::SetHotCursor( HCURSOR hCursor ) const
+ // Sets the HCURSOR that the list-view control uses when the pointer is
+ // over an item while hot tracking is enabled.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHotCursor( m_hWnd, hCursor );
+ }
+
+ inline int CListView::SetHotItem( int nIndex ) const
+ // Sets the hot item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHotItem( m_hWnd, nIndex );
+ }
+
+ inline DWORD CListView::SetHoverTime( DWORD dwHoverTime /*= (DWORD)-1*/ ) const
+ // Sets the amount of time that the mouse cursor must hover over an item before it is selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetHoverTime( m_hWnd, dwHoverTime );
+ }
+
+ inline CSize CListView::SetIconSpacing( int cx, int cy ) const
+ // Sets the spacing between icons in list-view controls set to the LVS_ICON style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_SetIconSpacing( m_hWnd, cx, cy ) );
+ }
+
+ inline CSize CListView::SetIconSpacing( CSize sz ) const
+ // Sets the spacing between icons in list-view controls set to the LVS_ICON style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CSize( ListView_SetIconSpacing( m_hWnd, sz.cx, sz.cy ) );
+ }
+
+ inline HIMAGELIST CListView::SetImageList( HIMAGELIST himl, int iImageListType ) const
+ // Assigns an image list to a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetImageList( m_hWnd, himl, iImageListType );
+ }
+
+ inline BOOL CListView::SetItem( LVITEM& Item ) const
+ // Sets some or all of a list-view item's attributes.
+
+ // The declaration for TVITEM:
+ // typedef struct _LVITEM {
+ // UINT mask;
+ // int iItem;
+ // int iSubItem;
+ // UINT state;
+ // UINT stateMask;
+ // LPTSTR pszText;
+ // int cchTextMax;
+ // int iImage;
+ // LPARAM lParam;
+ // } LVITEM, *LVITEM&;
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetItem( m_hWnd, &Item );
+ }
+
+ inline BOOL CListView::SetItem( int iItem, int iSubItem, UINT nMask, LPCTSTR pszText, int iImage,
+ UINT nState, UINT nStateMask, LPARAM lParam, int iIndent ) const
+ // Sets some or all of a list-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.iSubItem = iSubItem;
+ lvi.mask = nMask;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.iImage = iImage;
+ lvi.state = nState;
+ lvi.stateMask = nStateMask;
+ lvi.lParam = lParam;
+ lvi.iIndent = iIndent;
+
+ return ListView_SetItem( m_hWnd, &lvi);
+ }
+
+ inline void CListView::SetItemCount( int iCount ) const
+ // Causes the list-view control to allocate memory for the specified number of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemCount( m_hWnd, iCount );
+ }
+
+ inline void CListView::SetItemCountEx( int iCount, DWORD dwFlags /*= LVSICF_NOINVALIDATEALL*/ ) const
+ // Sets the virtual number of items in a virtual list view.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemCountEx( m_hWnd, iCount, dwFlags );
+ }
+
+ inline BOOL CListView::SetItemData( int iItem, DWORD_PTR dwData ) const
+ // Sets the value(lParam) specific to the item.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.lParam = dwData;
+ lvi.mask = LVIF_PARAM;
+ return ListView_SetItem(m_hWnd, &lvi);
+ }
+
+ inline BOOL CListView::SetItemPosition( int iItem, CPoint& pt ) const
+ // Moves an item to a specified position in a list-view control (in icon or small icon view).
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetItemPosition( m_hWnd, iItem, pt.x, pt.y );
+ }
+
+ inline BOOL CListView::SetItemState( int iItem, LVITEM& Item ) const
+ // Changes the state of an item in a list-view control.
+
+ // Possible values of nMask:
+ // LVIS_CUT The item is marked for a cut-and-paste operation.
+ // LVIS_DROPHILITED The item is highlighted as a drag-and-drop target.
+ // LVIS_FOCUSED The item has the focus, so it is surrounded by a standard focus rectangle.
+ // LVIS_SELECTED The item is selected.
+ // LVIS_OVERLAYMASK Use this mask to retrieve the item's overlay image index.
+ // LVIS_STATEIMAGEMASK Use this mask to retrieve the item's state image index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::SendMessage(m_hWnd, LVM_SETITEMSTATE, (WPARAM)iItem, (LPARAM)&Item);
+ }
+
+ inline void CListView::SetItemState( int iItem, UINT nState, UINT nMask ) const
+ // Changes the state of an item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemState(m_hWnd, iItem, nState, nMask);
+ }
+
+ inline void CListView::SetItemText( int iItem, int iSubItem, LPCTSTR pszText ) const
+ // Sets the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetItemText(m_hWnd, iItem, iSubItem, (LPTSTR)pszText );
+ }
+
+ inline int CListView::SetSelectionMark( int iIndex ) const
+ // Sets the selection mark in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetSelectionMark( m_hWnd, iIndex );
+ }
+
+ inline BOOL CListView::SetTextBkColor( COLORREF clrBkText ) const
+ // Sets the background color of text in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetTextBkColor( m_hWnd, clrBkText );
+ }
+
+ inline BOOL CListView::SetTextColor( COLORREF clrText ) const
+ // Sets the text color of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SetTextColor( m_hWnd, clrText );
+ }
+
+ inline HWND CListView::SetToolTips( HWND hWndToolTip ) const
+ // Sets the ToolTip control that the list-view control will use to display ToolTips.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hWndToolTip, 0L);
+ }
+
+ inline void CListView::SetWorkAreas( int nWorkAreas, CRect& pRectArray ) const
+ // Sets the working area within a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ ListView_SetWorkAreas( m_hWnd, nWorkAreas, pRectArray );
+ }
+
+ inline int CListView::SubItemHitTest( LVHITTESTINFO& htInfo ) const
+ // Determines which list-view item or subitem is located at a given position.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SubItemHitTest( m_hWnd, &htInfo );
+ }
+
+ // Operations
+
+ inline BOOL CListView::Arrange( UINT nCode ) const
+ // Arranges items in icon view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Arrange( m_hWnd, nCode );
+ }
+
+ inline HIMAGELIST CListView::CreateDragImage( int iItem, CPoint& pt ) const
+ // Creates a drag image list for the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_CreateDragImage( m_hWnd, iItem, &pt );
+ }
+
+ inline BOOL CListView::DeleteAllItems( ) const
+ // ListView_DeleteAllItems
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteAllItems( m_hWnd );
+ }
+
+ inline BOOL CListView::DeleteColumn( int iCol ) const
+ // Removes a column from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteColumn( m_hWnd, iCol );
+ }
+
+ inline BOOL CListView::DeleteItem( int iItem ) const
+ // Removes an item from a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_DeleteItem( m_hWnd, iItem );
+ }
+
+ inline HWND CListView::EditLabel( int iItem ) const
+ // Begins in-place editing of the specified list-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_EditLabel( m_hWnd, iItem );
+ }
+
+ inline BOOL CListView::EnsureVisible( int iItem, BOOL fPartialOK ) const
+ // Ensures that a list-view item is either entirely or partially visible,
+ // scrolling the list-view control if necessary.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LVM_ENSUREVISIBLE, (WPARAM)iItem, (LPARAM)fPartialOK );
+ }
+
+ inline int CListView::FindItem( LVFINDINFO& FindInfo, int iStart /*= -1*/ ) const
+ // Searches for a list-view item with the specified characteristics.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_FindItem( m_hWnd, iStart, &FindInfo );
+ }
+
+ inline int CListView::HitTest( LVHITTESTINFO& HitTestInfo ) const
+ // Determines which list-view item, if any, is at a specified position.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_HitTest( m_hWnd, &HitTestInfo );
+ }
+
+ inline int CListView::HitTest( CPoint pt, UINT* pFlags /*= NULL*/ ) const
+ // Determines which list-view item, if any, is at a specified position.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVHITTESTINFO hti = {0};
+ hti.flags = *pFlags;
+ hti.pt = pt;
+ return ListView_HitTest( m_hWnd, &hti );
+ }
+
+ inline int CListView::InsertColumn( int iCol, const LVCOLUMN& Column ) const
+ // Inserts a new column in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_InsertColumn( m_hWnd, iCol, &Column );
+ }
+
+ inline int CListView::InsertColumn( int iCol, LPCTSTR pszColumnHeading, int iFormat /*= LVCFMT_LEFT*/,
+ int iWidth /*= -1*/, int iSubItem /*= -1*/ ) const
+ // Inserts a new column in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVCOLUMN lvc = {0};
+ lvc.mask = LVCF_TEXT|LVCF_ORDER|LVCF_FMT;
+ if (-1 != iWidth)
+ {
+ lvc.mask |= LVCF_WIDTH;
+ lvc.cx = iWidth;
+ }
+ if (-1 != iSubItem)
+ {
+ lvc.mask |= LVCF_SUBITEM;
+ lvc.iSubItem = iSubItem;
+ }
+
+ lvc.iOrder = iCol;
+ lvc.pszText = (LPTSTR)pszColumnHeading;
+ lvc.fmt = iFormat;
+ lvc.iSubItem = iSubItem;
+ return ListView_InsertColumn( m_hWnd, iCol, &lvc );
+ }
+
+ inline int CListView::InsertItem( const LVITEM& Item ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_InsertItem( m_hWnd, &Item );
+ }
+
+ inline int CListView::InsertItem( int iItem, LPCTSTR pszText ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.mask = LVIF_TEXT;
+ return ListView_InsertItem( m_hWnd, &lvi );
+ }
+
+ inline int CListView::InsertItem( int iItem, LPCTSTR pszText, int iImage ) const
+ // Inserts a new item in a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ LVITEM lvi = {0};
+ lvi.iItem = iItem;
+ lvi.pszText = (LPTSTR)pszText;
+ lvi.iImage = iImage;
+ lvi.mask = LVIF_TEXT | LVIF_IMAGE;
+ return ListView_InsertItem( m_hWnd, &lvi );
+ }
+
+ inline BOOL CListView::RedrawItems( int iFirst, int iLast ) const
+ // Forces a list-view control to redraw a range of items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_RedrawItems( m_hWnd, iFirst, iLast );
+ }
+
+ inline BOOL CListView::Scroll( CSize sz ) const
+ // Scrolls the content of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Scroll( m_hWnd, sz.cx, sz.cy );
+ }
+
+ inline BOOL CListView::SortItems( PFNLVCOMPARE pfnCompare, DWORD_PTR dwData ) const
+ // Uses an application-defined comparison function to sort the items of a list-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_SortItems( m_hWnd, pfnCompare, dwData );
+ }
+
+ inline BOOL CListView::Update( int iItem ) const
+ // Updates a list-view item. If the list-view control has the LVS_AUTOARRANGE style,
+ // the list-view control is rearranged.
+ {
+ assert(::IsWindow(m_hWnd));
+ return ListView_Update( m_hWnd, iItem );
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_LISTVIEW_H_
+
diff --git a/external/win32cpp/include/mdi.h b/external/win32cpp/include/mdi.h
new file mode 100644
index 0000000..474bd32
--- /dev/null
+++ b/external/win32cpp/include/mdi.h
@@ -0,0 +1,784 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// mdi.h
+// Declaration of the CMDIChild and CMDIFrame classes
+
+// The classes defined here add MDI frames support to Win32++. MDI
+// (Multiple Document Interface) frames host one or more child windows. The
+// child windows hosted by a MDI frame can be different types. For example,
+// some MDI child windows could be used to edit text, while others could be
+// used to display a bitmap. Four classes are defined here to support MDI
+// frames:
+
+
+// 1) CMDIFrame. This class inherits from CFrame, and adds the functionality
+// required by MDI frames. It keeps track of the MDI children created and
+// destroyed, and adjusts the menu when a MDI child is activated. Use the
+// AddMDIChild function to add MDI child windows to the MDI frame. Inherit
+// from CMDIFrame to create your own MDI frame.
+//
+// 2) CMDIChild: All MDI child windows (ie. CWnd classes) should inherit from
+// this class. Each MDI child type can have a different frame menu.
+
+// Use the MDIFrame generic application as the starting point for your own MDI
+// frame applications.
+// Refer to the MDIDemo sample for an example on how to use these classes to
+// create a MDI frame application with different types of MDI child windows.
+
+
+#ifndef _WIN32XX_MDI_H_
+#define _WIN32XX_MDI_H_
+
+#include "frame.h"
+#include
+
+
+
+namespace Win32xx
+{
+ class CMDIChild;
+ class CMDIFrame;
+ typedef Shared_Ptr MDIChildPtr;
+
+ /////////////////////////////////////
+ // Declaration of the CMDIChild class
+ //
+ class CMDIChild : public CWnd
+ {
+ friend class CMDIFrame;
+ public:
+ CMDIChild();
+ virtual ~CMDIChild();
+
+ // These are the functions you might wish to override
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual void RecalcLayout();
+
+ // These functions aren't virtual, and shouldn't be overridden
+ void SetHandles(HMENU MenuName, HACCEL AccelName);
+ CMDIFrame* GetMDIFrame() const;
+ CWnd* GetView() const {return m_pView;}
+ void SetView(CWnd& pwndView);
+ void MDIActivate() const;
+ void MDIDestroy() const;
+ void MDIMaximize() const;
+ void MDIRestore() const;
+
+ protected:
+ // Its unlikely you would need to override these functions
+ virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMDIChild(const CMDIChild&); // Disable copy construction
+ CMDIChild& operator = (const CMDIChild&); // Disable assignment operator
+
+ CWnd* m_pView; // pointer to the View CWnd object
+ HMENU m_hChildMenu;
+ HACCEL m_hChildAccel;
+ };
+
+
+ /////////////////////////////////////
+ // Declaration of the CMDIFrame class
+ //
+ class CMDIFrame : public CFrame
+ {
+ friend class CMDIChild; // CMDIChild uses m_hOrigMenu
+ typedef Shared_Ptr MDIChildPtr;
+
+ public:
+ class CMDIClient : public CWnd // a nested class within CMDIFrame
+ {
+ public:
+ CMDIClient() {}
+ virtual ~CMDIClient() {}
+ virtual HWND Create(CWnd* pParent = NULL);
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ CMDIFrame* GetMDIFrame() const { return (CMDIFrame*)GetParent(); }
+
+ private:
+ CMDIClient(const CMDIClient&); // Disable copy construction
+ CMDIClient& operator = (const CMDIClient&); // Disable assignment operator
+ };
+
+
+ CMDIFrame();
+ virtual ~CMDIFrame() {}
+
+ virtual CMDIChild* AddMDIChild(MDIChildPtr pMDIChild);
+ virtual CMDIClient& GetMDIClient() const { return (CMDIClient&)m_MDIClient; }
+ virtual BOOL IsMDIFrame() const { return TRUE; }
+ virtual void RemoveMDIChild(HWND hWnd);
+ virtual BOOL RemoveAllMDIChildren();
+ virtual void UpdateCheckMarks();
+
+ // These functions aren't virtual, so don't override them
+ std::vector & GetAllMDIChildren() {return m_vMDIChild;}
+ CMDIChild* GetActiveMDIChild() const;
+ BOOL IsMDIChildMaxed() const;
+ void MDICascade(int nType = 0) const;
+ void MDIIconArrange() const;
+ void MDIMaximize() const;
+ void MDINext() const;
+ void MDIPrev() const;
+ void MDIRestore() const;
+ void MDITile(int nType = 0) const;
+ void SetActiveMDIChild(CMDIChild* pChild);
+
+ protected:
+ // These are the functions you might wish to override
+ virtual void OnClose();
+ virtual void OnViewStatusBar();
+ virtual void OnViewToolBar();
+ virtual void OnWindowPosChanged();
+ virtual void RecalcLayout();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CMDIFrame(const CMDIFrame&); // Disable copy construction
+ CMDIFrame& operator = (const CMDIFrame&); // Disable assignment operator
+ void AppendMDIMenu(HMENU hMenuWindow);
+ LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ void UpdateFrameMenu(HMENU hMenu);
+
+ CMDIClient m_MDIClient;
+ std::vector m_vMDIChild;
+ HWND m_hActiveMDIChild;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////
+ // Definitions for the CMDIFrame class
+ //
+ inline CMDIFrame::CMDIFrame() : m_hActiveMDIChild(NULL)
+ {
+ SetView(GetMDIClient());
+ }
+
+ inline CMDIChild* CMDIFrame::AddMDIChild(MDIChildPtr pMDIChild)
+ {
+ assert(NULL != pMDIChild.get()); // Cannot add Null MDI Child
+
+ m_vMDIChild.push_back(pMDIChild);
+ pMDIChild->Create(GetView());
+
+ return pMDIChild.get();
+ }
+
+ inline void CMDIFrame::AppendMDIMenu(HMENU hMenuWindow)
+ {
+ // Adds the additional menu items the the "Window" submenu when
+ // MDI child windows are created
+
+ if (!IsMenu(hMenuWindow))
+ return;
+
+ // Delete previously appended items
+ int nItems = ::GetMenuItemCount(hMenuWindow);
+ UINT uLastID = ::GetMenuItemID(hMenuWindow, --nItems);
+ if ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))
+ {
+ while ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))
+ {
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);
+ uLastID = ::GetMenuItemID(hMenuWindow, --nItems);
+ }
+ //delete the separator too
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);
+ }
+
+ int nWindow = 0;
+
+ // Allocate an iterator for our MDIChild vector
+ std::vector ::iterator v;
+
+ for (v = GetAllMDIChildren().begin(); v < GetAllMDIChildren().end(); ++v)
+ {
+ if ((*v)->GetWindowLongPtr(GWL_STYLE) & WS_VISIBLE) // IsWindowVisible is unreliable here
+ {
+ // Add Separator
+ if (0 == nWindow)
+ ::AppendMenu(hMenuWindow, MF_SEPARATOR, 0, NULL);
+
+ // Add a menu entry for each MDI child (up to 9)
+ if (nWindow < 9)
+ {
+ tString tsMenuItem ( (*v)->GetWindowText() );
+
+ if (tsMenuItem.length() > MAX_MENU_STRING -10)
+ {
+ // Truncate the string if its too long
+ tsMenuItem.erase(tsMenuItem.length() - MAX_MENU_STRING +10);
+ tsMenuItem += _T(" ...");
+ }
+
+ TCHAR szMenuString[MAX_MENU_STRING+1];
+ wsprintf(szMenuString, _T("&%d %s"), nWindow+1, tsMenuItem.c_str());
+
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, szMenuString);
+
+ if (GetActiveMDIChild() == (*v).get())
+ ::CheckMenuItem(hMenuWindow, IDW_FIRSTCHILD+nWindow, MF_CHECKED);
+
+ ++nWindow;
+ }
+ else if (9 == nWindow)
+ // For the 10th MDI child, add this menu item and return
+ {
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, _T("&Windows..."));
+ return;
+ }
+ }
+ }
+ }
+
+ inline LRESULT CMDIFrame::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ return ::DefFrameProc(m_hWnd, GetMDIClient(), uMsg, wParam, lParam);
+ }
+
+ inline CMDIChild* CMDIFrame::GetActiveMDIChild() const
+ {
+ return (CMDIChild*)FromHandle(m_hActiveMDIChild);
+ }
+
+ inline BOOL CMDIFrame::IsMDIChildMaxed() const
+ {
+ BOOL bMaxed = FALSE;
+ GetMDIClient().SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);
+ return bMaxed;
+ }
+
+ inline void CMDIFrame::MDICascade(int nType /* = 0*/) const
+ {
+ // Possible values for nType are:
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being cascaded.
+
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDICASCADE, (WPARAM)nType, 0L);
+ }
+
+ inline void CMDIFrame::MDIIconArrange() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIICONARRANGE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDIMaximize() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIMAXIMIZE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDINext() const
+ {
+ assert(::IsWindow(m_hWnd));
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, FALSE);
+ }
+
+ inline void CMDIFrame::MDIPrev() const
+ {
+ assert(::IsWindow(m_hWnd));
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, TRUE);
+ }
+
+ inline void CMDIFrame::MDIRestore() const
+ {
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDIRESTORE, 0L, 0L);
+ }
+
+ inline void CMDIFrame::MDITile(int nType /* = 0*/) const
+ {
+ // Possible values for nType are:
+ // MDITILE_HORIZONTAL Tiles MDI child windows so that one window appears above another.
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being tiled.
+ // MDITILE_VERTICAL Tiles MDI child windows so that one window appears beside another.
+
+ assert(::IsWindow(m_hWnd));
+ GetView()->SendMessage(WM_MDITILE, (WPARAM)nType, 0L);
+ }
+
+ inline void CMDIFrame::OnClose()
+ {
+ if (RemoveAllMDIChildren())
+ {
+ CFrame::OnClose();
+ Destroy();
+ }
+ }
+
+ inline void CMDIFrame::OnViewStatusBar()
+ {
+ CFrame::OnViewStatusBar();
+ UpdateCheckMarks();
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
+ }
+
+ inline void CMDIFrame::OnViewToolBar()
+ {
+ CFrame::OnViewToolBar();
+ UpdateCheckMarks();
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
+ }
+
+ inline void CMDIFrame::OnWindowPosChanged()
+ {
+ if (IsMenuBarUsed())
+ {
+ // Refresh MenuBar Window
+ HMENU hMenu= GetMenuBar().GetMenu();
+ GetMenuBar().SetMenu(hMenu);
+ UpdateCheckMarks();
+ }
+ }
+
+ inline BOOL CMDIFrame::PreTranslateMessage(MSG* pMsg)
+ {
+ if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
+ {
+ if (TranslateMDISysAccel(GetView()->GetHwnd(), pMsg))
+ return TRUE;
+ }
+
+ return CFrame::PreTranslateMessage(pMsg);
+ }
+
+ inline void CMDIFrame::RecalcLayout()
+ {
+ CFrame::RecalcLayout();
+
+ if (GetView()->IsWindow())
+ MDIIconArrange();
+ }
+
+ inline BOOL CMDIFrame::RemoveAllMDIChildren()
+ {
+ BOOL bResult = TRUE;
+ int Children = (int)m_vMDIChild.size();
+
+ // Remove the children in reverse order
+ for (int i = Children-1; i >= 0; --i)
+ {
+ if (IDNO == m_vMDIChild[i]->SendMessage(WM_CLOSE, 0L, 0L)) // Also removes the MDI child
+ bResult = FALSE;
+ }
+
+ return bResult;
+ }
+
+ inline void CMDIFrame::RemoveMDIChild(HWND hWnd)
+ {
+ // Allocate an iterator for our HWND map
+ std::vector ::iterator v;
+
+ for (v = m_vMDIChild.begin(); v!= m_vMDIChild.end(); ++v)
+ {
+ if ((*v)->GetHwnd() == hWnd)
+ {
+ m_vMDIChild.erase(v);
+ break;
+ }
+ }
+
+ if (GetActiveMDIChild())
+ {
+ if (GetActiveMDIChild()->m_hChildMenu)
+ UpdateFrameMenu(GetActiveMDIChild()->m_hChildMenu);
+ if (GetActiveMDIChild()->m_hChildAccel)
+ GetApp()->SetAccelerators(GetActiveMDIChild()->m_hChildAccel, this);
+ }
+ else
+ {
+ if (IsMenuBarUsed())
+ GetMenuBar().SetMenu(GetFrameMenu());
+ else
+ SetMenu(FromHandle(GetFrameMenu()));
+
+ GetApp()->SetAccelerators(GetFrameAccel(), this);
+ }
+ }
+
+ inline void CMDIFrame::SetActiveMDIChild(CMDIChild* pChild)
+ {
+ assert ( pChild->IsWindow() );
+
+ GetMDIClient().SendMessage(WM_MDIACTIVATE, (WPARAM)pChild->GetHwnd(), 0L);
+
+ // Verify
+ assert ( m_hActiveMDIChild == pChild->GetHwnd() );
+ }
+
+ inline void CMDIFrame::UpdateCheckMarks()
+ {
+ if ((GetActiveMDIChild()) && GetActiveMDIChild()->m_hChildMenu)
+ {
+ HMENU hMenu = GetActiveMDIChild()->m_hChildMenu;
+
+ UINT uCheck = GetToolBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;
+ ::CheckMenuItem(hMenu, IDW_VIEW_TOOLBAR, uCheck);
+
+ uCheck = GetStatusBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;
+ ::CheckMenuItem (hMenu, IDW_VIEW_STATUSBAR, uCheck);
+ }
+ }
+
+ inline void CMDIFrame::UpdateFrameMenu(HMENU hMenu)
+ {
+ int nMenuItems = GetMenuItemCount(hMenu);
+ if (nMenuItems > 0)
+ {
+ // The Window menu is typically second from the right
+ int nWindowItem = MAX (nMenuItems -2, 0);
+ HMENU hMenuWindow = ::GetSubMenu (hMenu, nWindowItem);
+
+ if (hMenuWindow)
+ {
+ if (IsMenuBarUsed())
+ {
+ AppendMDIMenu(hMenuWindow);
+ GetMenuBar().SetMenu(hMenu);
+ }
+ else
+ {
+ GetView()->SendMessage (WM_MDISETMENU, (WPARAM) hMenu, (LPARAM)hMenuWindow);
+ DrawMenuBar();
+ }
+ }
+ }
+ UpdateCheckMarks();
+ }
+
+ inline LRESULT CMDIFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_CLOSE:
+ OnClose();
+ return 0;
+
+ case WM_WINDOWPOSCHANGED:
+ // MDI Child or MDI frame has been resized
+ OnWindowPosChanged();
+ break; // Continue with default processing
+
+ } // switch uMsg
+ return CFrame::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline HWND CMDIFrame::CMDIClient::Create(CWnd* pParent)
+ {
+ assert(pParent != 0);
+
+ CLIENTCREATESTRUCT clientcreate ;
+ clientcreate.hWindowMenu = m_hWnd;
+ clientcreate.idFirstChild = IDW_FIRSTCHILD ;
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
+
+ // Create the view window
+ CreateEx(WS_EX_CLIENTEDGE, _T("MDICLient"), TEXT(""), dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate);
+
+ return m_hWnd;
+ }
+
+ inline LRESULT CMDIFrame::CMDIClient::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MDIDESTROY:
+ {
+ // Do default processing first
+ CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);
+
+ // Now remove MDI child
+ GetMDIFrame()->RemoveMDIChild((HWND) wParam);
+ }
+ return 0; // Discard message
+
+ case WM_MDISETMENU:
+ {
+ if (GetMDIFrame()->IsMenuBarUsed())
+ {
+ return 0L;
+ }
+ }
+ break;
+
+ case WM_MDIACTIVATE:
+ {
+ // Suppress redraw to avoid flicker when activating maximised MDI children
+ SendMessage(WM_SETREDRAW, FALSE, 0L);
+ LRESULT lr = CallWindowProc(GetPrevWindowProc(), WM_MDIACTIVATE, wParam, lParam);
+ SendMessage(WM_SETREDRAW, TRUE, 0L);
+ RedrawWindow(0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ return lr;
+ }
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+ /////////////////////////////////////
+ //Definitions for the CMDIChild class
+ //
+ inline CMDIChild::CMDIChild() : m_pView(NULL), m_hChildMenu(NULL)
+ {
+ // Set the MDI Child's menu and accelerator in the constructor, like this ...
+ // HMENU hChildMenu = LoadMenu(GetApp()->GetResourceHandle(), _T("MdiMenuView"));
+ // HACCEL hChildAccel = LoadAccelerators(GetApp()->GetResourceHandle(), _T("MDIAccelView"));
+ // SetHandles(hChildMenu, hChildAccel);
+ }
+
+ inline CMDIChild::~CMDIChild()
+ {
+ if (IsWindow())
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);
+
+ if (m_hChildMenu)
+ ::DestroyMenu(m_hChildMenu);
+ }
+
+ inline HWND CMDIChild::Create(CWnd* pParent /*= NULL*/)
+ // We create the MDI child window and then maximize if required.
+ // This technique avoids unnecessary flicker when creating maximized MDI children.
+ {
+ //Call PreCreate in case its overloaded
+ PreCreate(*m_pcs);
+
+ //Determine if the window should be created maximized
+ BOOL bMax = FALSE;
+ pParent->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMax);
+ bMax = bMax | (m_pcs->style & WS_MAXIMIZE);
+
+ // Set the Window Class Name
+ TCHAR szClassName[MAX_STRING_SIZE + 1] = _T("Win32++ MDI Child");
+ if (m_pcs->lpszClass)
+ lstrcpyn(szClassName, m_pcs->lpszClass, MAX_STRING_SIZE);
+
+ // Set the window style
+ DWORD dwStyle;
+ dwStyle = m_pcs->style & ~WS_MAXIMIZE;
+ dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW ;
+
+ // Set window size and position
+ int x = CW_USEDEFAULT;
+ int y = CW_USEDEFAULT;
+ int cx = CW_USEDEFAULT;
+ int cy = CW_USEDEFAULT;
+ if(m_pcs->cx && m_pcs->cy)
+ {
+ x = m_pcs->x;
+ y = m_pcs->y;
+ cx = m_pcs->cx;
+ cy = m_pcs->cy;
+ }
+
+ // Set the extended style
+ DWORD dwExStyle = m_pcs->dwExStyle | WS_EX_MDICHILD;
+
+ // Turn off redraw while creating the window
+ pParent->SendMessage(WM_SETREDRAW, FALSE, 0L);
+
+ // Create the window
+ if (!CreateEx(dwExStyle, szClassName, m_pcs->lpszName, dwStyle, x, y,
+ cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams))
+ throw CWinException(_T("CMDIChild::Create ... CreateEx failed"));
+
+ if (bMax)
+ ShowWindow(SW_MAXIMIZE);
+
+ // Turn redraw back on
+ pParent->SendMessage(WM_SETREDRAW, TRUE, 0L);
+ pParent->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
+
+ // Ensure bits revealed by round corners (XP themes) are redrawn
+ SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);
+
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, this);
+
+ return m_hWnd;
+ }
+
+ inline CMDIFrame* CMDIChild::GetMDIFrame() const
+ {
+ CMDIFrame* pMDIFrame = (CMDIFrame*)GetParent()->GetParent();
+ assert(dynamic_cast(pMDIFrame));
+ return pMDIFrame;
+ }
+
+ inline LRESULT CMDIChild::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ return ::DefMDIChildProc(m_hWnd, uMsg, wParam, lParam);
+ }
+
+ inline void CMDIChild::MDIActivate() const
+ {
+ GetParent()->SendMessage(WM_MDIACTIVATE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIDestroy() const
+ {
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIMaximize() const
+ {
+ GetParent()->SendMessage(WM_MDIMAXIMIZE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::MDIRestore() const
+ {
+ GetParent()->SendMessage(WM_MDIRESTORE, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CMDIChild::OnCreate()
+ {
+ // Create the view window
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+
+ inline void CMDIChild::RecalcLayout()
+ {
+ // Resize the View window
+ CRect rc = GetClientRect();
+ m_pView->SetWindowPos( NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW );
+ }
+
+ inline void CMDIChild::SetHandles(HMENU hMenu, HACCEL hAccel)
+ {
+ m_hChildMenu = hMenu;
+ m_hChildAccel = hAccel;
+
+ // Note: It is valid to call SetChildMenu before the window is created
+ if (IsWindow())
+ {
+ CWnd* pWnd = GetMDIFrame()->GetActiveMDIChild();
+ if (pWnd == this)
+ {
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, GetMDIFrame());
+ }
+ }
+ }
+
+ inline void CMDIChild::SetView(CWnd& wndView)
+ // Sets or changes the View window displayed within the frame
+ {
+ if (m_pView != &wndView)
+ {
+ // Destroy the existing view window (if any)
+ if (m_pView) m_pView->Destroy();
+
+ // Assign the view window
+ m_pView = &wndView;
+
+ if (m_hWnd)
+ {
+ // The frame is already created, so create and position the new view too
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window
+ GetView()->Create(this);
+ RecalcLayout();
+ }
+ }
+ }
+
+ inline LRESULT CMDIChild::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MDIACTIVATE:
+ {
+ // This child is being activated
+ if (lParam == (LPARAM) m_hWnd)
+ {
+ GetMDIFrame()->m_hActiveMDIChild = m_hWnd;
+ // Set the menu to child default menu
+ if (m_hChildMenu)
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);
+ if (m_hChildAccel)
+ GetApp()->SetAccelerators(m_hChildAccel, this);
+ }
+
+ // No child is being activated
+ if (0 == lParam)
+ {
+ GetMDIFrame()->m_hActiveMDIChild = NULL;
+ // Set the menu to frame's original menu
+ GetMDIFrame()->UpdateFrameMenu(GetMDIFrame()->GetFrameMenu());
+ GetApp()->SetAccelerators(GetMDIFrame()->GetFrameAccel(), this);
+ }
+ }
+ return 0L ;
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ RecalcLayout();
+ break;
+ }
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_MDI_H_
+
diff --git a/external/win32cpp/include/menu.h b/external/win32cpp/include/menu.h
new file mode 100644
index 0000000..136bafa
--- /dev/null
+++ b/external/win32cpp/include/menu.h
@@ -0,0 +1,600 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// menu.h
+// Declaration of the CMenu class
+
+// Notes
+// 1) Owner-drawn menus send the WM_MEASUREITEM and WM_DRAWITEM messages
+// to the window that owns the menu. To manage owner drawing for menus,
+// handle these two messages in the CWnd's WndProc function.
+//
+// 2) The CMenu pointer returned by FromHandle might be a temporary pointer. It
+// should be used immediately, not saved for later use.
+//
+// 3) The CMenu pointers returned by FromHandle or GetSubMenu do not need
+// to be deleted. They are automatically deleted by the Win32++.
+//
+// 4) CMenu pointers returned by GetSubMenu are deleted when the parent CMenu is
+// detached, destroyed or deconstructed.
+//
+// 5) The HMENU that is attached to a CMenu object (using the attach function) is
+// automatically deleted when the CMenu object goes out of scope. Detach the
+// HMENU to stop it being deleted when CMenu's destructor is called.
+//
+// 6) Pass CMenu objects by reference or by pointer when passing them as function
+// arguments.
+//
+// 7) In those functions that use a MENUITEMINFO structure, its cbSize member is
+// automatically set to the correct value.
+
+// Program sample
+// --------------
+// void CView::CreatePopup()
+// {
+// CPoint pt = GetCursorPos();
+//
+// // Create the menu
+// CMenu Popup;
+// Popup.CreatePopupMenu();
+//
+// // Add some menu items
+// Popup.AppendMenu(MF_STRING, 101, _T("Menu Item &1"));
+// Popup.AppendMenu(MF_STRING, 102, _T("Menu Item &2"));
+// Popup.AppendMenu(MF_STRING, 103, _T("Menu Item &3"));
+// Popup.AppendMenu(MF_SEPARATOR);
+// Popup.AppendMenu(MF_STRING, 104, _T("Menu Item &4"));
+//
+// // Set menu item states
+// Popup.CheckMenuRadioItem(101, 101, 101, MF_BYCOMMAND);
+// Popup.CheckMenuItem(102, MF_BYCOMMAND | MF_CHECKED);
+// Popup.EnableMenuItem(103, MF_BYCOMMAND | MF_GRAYED);
+// Popup.SetDefaultItem(104);
+//
+// // Display the popup menu
+// Popup.TrackPopupMenu(0, pt.x, pt.y, this);
+// }
+
+
+
+#if !defined(_WIN32XX_MENU_H_) && !defined(_WIN32_WCE)
+#define _WIN32XX_MENU_H_
+
+
+#include "wincore.h"
+#include "gdi.h"
+
+
+namespace Win32xx
+{
+
+ // Forward declarations
+ class CBitmap;
+
+ class CMenu
+ {
+ friend class CWinApp;
+
+ public:
+ //Construction
+ CMenu() : m_hMenu(0), m_IsTmpMenu(FALSE) {}
+ CMenu(UINT nID) : m_IsTmpMenu(FALSE)
+ {
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(nID));
+ }
+ ~CMenu();
+
+ //Initialization
+ void Attach(HMENU hMenu);
+ void CreateMenu();
+ void CreatePopupMenu();
+ void DestroyMenu();
+ HMENU Detach();
+ HMENU GetHandle() const;
+ BOOL LoadMenu(LPCTSTR lpszResourceName);
+ BOOL LoadMenu(UINT uIDResource);
+ BOOL LoadMenuIndirect(const void* lpMenuTemplate);
+
+ //Menu Operations
+ BOOL TrackPopupMenu(UINT uFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = 0);
+ BOOL TrackPopupMenuEx(UINT uFlags, int x, int y, CWnd* pWnd, LPTPMPARAMS lptpm);
+
+ //Menu Item Operations
+ BOOL AppendMenu(UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL AppendMenu(UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ UINT CheckMenuItem(UINT uIDCheckItem, UINT uCheck);
+ BOOL CheckMenuRadioItem(UINT uIDFirst, UINT uIDLast, UINT uIDItem, UINT uFlags);
+ BOOL DeleteMenu(UINT uPosition, UINT uFlags);
+ UINT EnableMenuItem(UINT uIDEnableItem, UINT uEnable);
+ UINT GetDefaultItem(UINT gmdiFlags, BOOL fByPos = FALSE);
+ DWORD GetMenuContextHelpId() const;
+
+#if(WINVER >= 0x0500) // Minimum OS required is Win2000
+ BOOL GetMenuInfo(LPMENUINFO lpcmi) const;
+ BOOL SetMenuInfo(LPCMENUINFO lpcmi);
+#endif
+
+ UINT GetMenuItemCount() const;
+ UINT GetMenuItemID(int nPos) const;
+ BOOL GetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+ UINT GetMenuState(UINT uID, UINT uFlags) const;
+ int GetMenuString(UINT uIDItem, LPTSTR lpString, int nMaxCount, UINT uFlags) const;
+ int GetMenuString(UINT uIDItem, CString& rString, UINT uFlags) const;
+ CMenu* GetSubMenu(int nPos);
+ BOOL InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ BOOL InsertMenuItem(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+ BOOL ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem = 0, LPCTSTR lpszNewItem = NULL);
+ BOOL ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp);
+ BOOL RemoveMenu(UINT uPosition, UINT uFlags);
+ BOOL SetDefaultItem(UINT uItem, BOOL fByPos = FALSE);
+ BOOL SetMenuContextHelpId(DWORD dwContextHelpId);
+ BOOL SetMenuItemBitmaps(UINT uPosition, UINT uFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked);
+ BOOL SetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos = FALSE);
+
+ //Operators
+ BOOL operator != (const CMenu& menu) const;
+ BOOL operator == (const CMenu& menu) const;
+ operator HMENU () const;
+
+ private:
+ CMenu(const CMenu&); // Disable copy construction
+ CMenu& operator = (const CMenu&); // Disable assignment operator
+ void AddToMap();
+ BOOL RemoveFromMap();
+ std::vector m_vSubMenus; // A vector of smart pointers to CMenu
+ HMENU m_hMenu;
+ BOOL m_IsTmpMenu;
+ };
+
+ inline CMenu::~CMenu()
+ {
+ if (m_hMenu)
+ {
+ if (!m_IsTmpMenu)
+ {
+ ::DestroyMenu(m_hMenu);
+ }
+
+ RemoveFromMap();
+ }
+
+ m_vSubMenus.clear();
+ }
+
+ inline void CMenu::AddToMap()
+ // Store the HMENU and CMenu pointer in the HMENU map
+ {
+ assert( GetApp() );
+ assert(m_hMenu);
+
+ GetApp()->m_csMapLock.Lock();
+ GetApp()->m_mapHMENU.insert(std::make_pair(m_hMenu, this));
+ GetApp()->m_csMapLock.Release();
+ }
+
+ inline BOOL CMenu::RemoveFromMap()
+ {
+ BOOL Success = FALSE;
+
+ if (GetApp())
+ {
+ // Allocate an iterator for our HDC map
+ std::map::iterator m;
+
+ CWinApp* pApp = GetApp();
+ if (pApp)
+ {
+ // Erase the CDC pointer entry from the map
+ pApp->m_csMapLock.Lock();
+ for (m = pApp->m_mapHMENU.begin(); m != pApp->m_mapHMENU.end(); ++m)
+ {
+ if (this == m->second)
+ {
+ pApp->m_mapHMENU.erase(m);
+ Success = TRUE;
+ break;
+ }
+ }
+
+ pApp->m_csMapLock.Release();
+ }
+ }
+
+ return Success;
+ }
+
+
+ inline BOOL CMenu::AppendMenu(UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Appends a new item to the end of the specified menu bar, drop-down menu, submenu, or shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::AppendMenu(m_hMenu, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::AppendMenu(UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Appends a new item to the end of the specified menu bar, drop-down menu, submenu, or shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(pBmp);
+ return ::AppendMenu(m_hMenu, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline void CMenu::Attach(HMENU hMenu)
+ // Attaches an existing menu to this CMenu
+ {
+ if (m_hMenu != NULL && m_hMenu != hMenu)
+ {
+ ::DestroyMenu(Detach());
+ }
+
+ if (hMenu)
+ {
+ m_hMenu = hMenu;
+ AddToMap();
+ }
+ }
+
+ inline UINT CMenu::CheckMenuItem(UINT uIDCheckItem, UINT uCheck)
+ // Sets the state of the specified menu item's check-mark attribute to either selected or clear.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::CheckMenuItem(m_hMenu, uIDCheckItem, uCheck);
+ }
+
+ inline BOOL CMenu::CheckMenuRadioItem(UINT uIDFirst, UINT uIDLast, UINT uIDItem, UINT uFlags)
+ // Checks a specified menu item and makes it a radio item. At the same time, the function clears
+ // all other menu items in the associated group and clears the radio-item type flag for those items.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::CheckMenuRadioItem(m_hMenu, uIDFirst, uIDLast, uIDItem, uFlags);
+ }
+
+ inline void CMenu::CreateMenu()
+ // Creates an empty menu.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::CreateMenu();
+ AddToMap();
+ }
+
+ inline void CMenu::CreatePopupMenu()
+ // Creates a drop-down menu, submenu, or shortcut menu. The menu is initially empty.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::CreatePopupMenu();
+ AddToMap();
+ }
+
+ inline BOOL CMenu::DeleteMenu(UINT uPosition, UINT uFlags)
+ // Deletes an item from the specified menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::DeleteMenu(m_hMenu, uPosition, uFlags);
+ }
+
+ inline void CMenu::DestroyMenu()
+ // Destroys the menu and frees any memory that the menu occupies.
+ {
+ if (::IsMenu(m_hMenu))
+ ::DestroyMenu(m_hMenu);
+
+ m_hMenu = 0;
+ RemoveFromMap();
+ m_vSubMenus.clear();
+ }
+
+ inline HMENU CMenu::Detach()
+ // Detaches the HMENU from this CMenu. If the HMENU is not detached it will be
+ // destroyed when this CMenu is deconstructed.
+ {
+ assert(IsMenu(m_hMenu));
+ HMENU hMenu = m_hMenu;
+ m_hMenu = 0;
+ RemoveFromMap();
+ m_vSubMenus.clear();
+ return hMenu;
+ }
+
+ inline HMENU CMenu::GetHandle() const
+ // Returns the HMENU assigned to this CMenu
+ {
+ return m_hMenu;
+ }
+
+ inline UINT CMenu::EnableMenuItem(UINT uIDEnableItem, UINT uEnable)
+ // Enables, disables, or grays the specified menu item.
+ // The uEnable parameter must be a combination of either MF_BYCOMMAND or MF_BYPOSITION
+ // and MF_ENABLED, MF_DISABLED, or MF_GRAYED.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::EnableMenuItem(m_hMenu, uIDEnableItem, uEnable);
+ }
+
+ inline UINT CMenu::GetDefaultItem(UINT gmdiFlags, BOOL fByPos /*= FALSE*/)
+ // Determines the default menu item.
+ // The gmdiFlags parameter specifies how the function searches for menu items.
+ // This parameter can be zero or more of the following values: GMDI_GOINTOPOPUPS; GMDI_USEDISABLED.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuDefaultItem(m_hMenu, fByPos, gmdiFlags);
+ }
+
+ inline DWORD CMenu::GetMenuContextHelpId() const
+ // Retrieves the Help context identifier associated with the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuContextHelpId(m_hMenu);
+ }
+
+#if(WINVER >= 0x0500)
+// minimum OS required : Win2000
+
+ inline BOOL CMenu::GetMenuInfo(LPMENUINFO lpcmi) const
+ // Retrieves the menu information.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuInfo(m_hMenu, lpcmi);
+ }
+
+ inline BOOL CMenu::SetMenuInfo(LPCMENUINFO lpcmi)
+ // Sets the menu information from the specified MENUINFO structure.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuInfo(m_hMenu, lpcmi);
+ }
+
+#endif
+
+ inline UINT CMenu::GetMenuItemCount() const
+ // Retrieves the number of menu items.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuItemCount(m_hMenu);
+ }
+
+ inline UINT CMenu::GetMenuItemID(int nPos) const
+ // Retrieves the menu item identifier of a menu item located at the specified position
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuItemID(m_hMenu, nPos);
+ }
+
+ inline BOOL CMenu::GetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // retrieves information about the specified menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::GetMenuItemInfo(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline UINT CMenu::GetMenuState(UINT uID, UINT uFlags) const
+ // Retrieves the menu flags associated with the specified menu item.
+ // Possible values for uFlags are: MF_BYCOMMAND (default) or MF_BYPOSITION.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuState(m_hMenu, uID, uFlags);
+ }
+
+ inline int CMenu::GetMenuString(UINT uIDItem, LPTSTR lpString, int nMaxCount, UINT uFlags) const
+ // Copies the text string of the specified menu item into the specified buffer.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpString);
+ return ::GetMenuString(m_hMenu, uIDItem, lpString, nMaxCount, uFlags);
+ }
+
+ inline int CMenu::GetMenuString(UINT uIDItem, CString& rString, UINT uFlags) const
+ // Copies the text string of the specified menu item into the specified buffer.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::GetMenuString(m_hMenu, uIDItem, (LPTSTR)rString.c_str(), rString.GetLength(), uFlags);
+ }
+
+ inline CMenu* CMenu::GetSubMenu(int nPos)
+ // Retrieves the CMenu object of a pop-up menu.
+ {
+ assert(IsMenu(m_hMenu));
+ CMenu* pMenu = new CMenu;
+ pMenu->m_hMenu = ::GetSubMenu(m_hMenu, nPos);
+ pMenu->m_IsTmpMenu = TRUE;
+ m_vSubMenus.push_back(pMenu);
+ return pMenu;
+ }
+
+ inline BOOL CMenu::InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Inserts a new menu item into a menu, moving other items down the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::InsertMenu(m_hMenu, uPosition, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::InsertMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Inserts a new menu item into a menu, moving other items down the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::InsertMenu(m_hMenu, uPosition, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline BOOL CMenu::InsertMenuItem(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // Inserts a new menu item at the specified position in a menu.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::InsertMenuItem(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline BOOL CMenu::LoadMenu(LPCTSTR lpszResourceName)
+ // Loads the menu from the specified windows resource.
+ {
+ assert(NULL == m_hMenu);
+ assert(lpszResourceName);
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), lpszResourceName);
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::LoadMenu(UINT uIDResource)
+ // Loads the menu from the specified windows resource.
+ {
+ assert(NULL == m_hMenu);
+ m_hMenu = ::LoadMenu(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(uIDResource));
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::LoadMenuIndirect(const void* lpMenuTemplate)
+ // Loads the specified menu template and assigns it to this CMenu.
+ {
+ assert(NULL == m_hMenu);
+ assert(lpMenuTemplate);
+ m_hMenu = ::LoadMenuIndirect(lpMenuTemplate);
+ if (m_hMenu) AddToMap();
+ return NULL != m_hMenu;
+ }
+
+ inline BOOL CMenu::ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem /*= 0*/, LPCTSTR lpszNewItem /*= NULL*/)
+ // Changes an existing menu item. This function is used to specify the content, appearance, and behavior of the menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::ModifyMenu(m_hMenu, uPosition, uFlags, uIDNewItem, lpszNewItem);
+ }
+
+ inline BOOL CMenu::ModifyMenu(UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, const CBitmap* pBmp)
+ // Changes an existing menu item. This function is used to specify the content, appearance, and behavior of the menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(pBmp);
+ return ::ModifyMenu(m_hMenu, uPosition, uFlags, uIDNewItem, (LPCTSTR)pBmp->GetHandle());
+ }
+
+ inline BOOL CMenu::RemoveMenu(UINT uPosition, UINT uFlags)
+ // Deletes a menu item or detaches a submenu from the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::RemoveMenu(m_hMenu, uPosition, uFlags);
+ }
+
+ inline BOOL CMenu::SetDefaultItem(UINT uItem, BOOL fByPos /*= FALSE*/)
+ // sets the default menu item for the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuDefaultItem(m_hMenu, uItem, fByPos);
+ }
+
+ inline BOOL CMenu::SetMenuContextHelpId(DWORD dwContextHelpId)
+ // Associates a Help context identifier with the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuContextHelpId(m_hMenu, dwContextHelpId);
+ }
+
+ inline BOOL CMenu::SetMenuItemBitmaps(UINT uPosition, UINT uFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked)
+ // Associates the specified bitmap with a menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ return ::SetMenuItemBitmaps(m_hMenu, uPosition, uFlags, *pBmpUnchecked, *pBmpChecked);
+ }
+
+ inline BOOL CMenu::SetMenuItemInfo(UINT uItem, LPMENUITEMINFO lpMenuItemInfo, BOOL fByPos /*= FALSE*/)
+ // Changes information about a menu item.
+ {
+ assert(IsMenu(m_hMenu));
+ assert(lpMenuItemInfo);
+ lpMenuItemInfo->cbSize = GetSizeofMenuItemInfo();
+ return ::SetMenuItemInfo(m_hMenu, uItem, fByPos, lpMenuItemInfo);
+ }
+
+ inline BOOL CMenu::TrackPopupMenu(UINT uFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect /*= 0*/)
+ // Displays a shortcut menu at the specified location and tracks the selection of items on the menu.
+ {
+ assert(IsMenu(m_hMenu));
+ HWND hWnd = pWnd? pWnd->GetHwnd() : 0;
+ return ::TrackPopupMenu(m_hMenu, uFlags, x, y, 0, hWnd, lpRect);
+ }
+
+ inline BOOL CMenu::TrackPopupMenuEx(UINT uFlags, int x, int y, CWnd* pWnd, LPTPMPARAMS lptpm)
+ // Displays a shortcut menu at the specified location and tracks the selection of items on the shortcut menu.
+ {
+ assert(IsMenu(m_hMenu));
+ HWND hWnd = pWnd? pWnd->GetHwnd() : 0;
+ return ::TrackPopupMenuEx(m_hMenu, uFlags, x, y, hWnd, lptpm);
+ }
+
+ inline BOOL CMenu::operator != (const CMenu& menu) const
+ // Returns TRUE if the two menu objects are not equal.
+ {
+ return menu.m_hMenu != m_hMenu;
+ }
+
+ inline BOOL CMenu::operator == (const CMenu& menu) const
+ // Returns TRUE of the two menu object are equal
+ {
+ return menu.m_hMenu == m_hMenu;
+ }
+
+ inline CMenu::operator HMENU () const
+ // Retrieves the menu's handle.
+ {
+ return m_hMenu;
+ }
+
+
+ ///////////////////////////////////////
+ // Global functions
+ //
+
+ inline CMenu* FromHandle(HMENU hMenu)
+ // Returns the CMenu object associated with the menu handle (HMENU).
+ {
+ assert( GetApp() );
+ CMenu* pMenu = GetApp()->GetCMenuFromMap(hMenu);
+ if (::IsMenu(hMenu) && pMenu == 0)
+ {
+ GetApp()->AddTmpMenu(hMenu);
+ pMenu = GetApp()->GetCMenuFromMap(hMenu);
+ }
+ return pMenu;
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_MENU_H_
+
diff --git a/external/win32cpp/include/propertysheet.h b/external/win32cpp/include/propertysheet.h
new file mode 100644
index 0000000..4048942
--- /dev/null
+++ b/external/win32cpp/include/propertysheet.h
@@ -0,0 +1,960 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// propertysheet.h
+// Declaration of the following classes:
+// CPropertyPage and CPropertySheet
+
+// These classes add support for property sheets to Win32++. A property sheet
+// will have one or more property pages. These pages are much like dialogs
+// which are presented within a tabbed dialog or within a wizard. The data
+// on a property page can be validated before the next page is presented.
+// Property sheets have three modes of use: Modal, Modeless, and Wizard.
+//
+// Refer to the PropertySheet demo program for an example of how propert sheets
+// can be used.
+
+
+#ifndef _WIN32XX_PROPERTYSHEET_H_
+#define _WIN32XX_PROPERTYSHEET_H_
+
+#include "dialog.h"
+
+#define ID_APPLY_NOW 0x3021
+#define ID_WIZBACK 0x3023
+#define ID_WIZNEXT 0x3024
+#define ID_WIZFINISH 0x3025
+#define ID_HELP 0xE146
+
+#ifndef PROPSHEETHEADER_V1_SIZE
+ #define PROPSHEETHEADER_V1_SIZE 40
+#endif
+
+namespace Win32xx
+{
+ class CPropertyPage;
+ typedef Shared_Ptr PropertyPagePtr;
+
+ class CPropertyPage : public CWnd
+ {
+ public:
+ CPropertyPage (UINT nIDTemplate, LPCTSTR szTitle = NULL);
+ virtual ~CPropertyPage() {}
+
+ virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual int OnApply();
+ virtual void OnCancel();
+ virtual void OnHelp();
+ virtual BOOL OnInitDialog();
+ virtual BOOL OnKillActive();
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual int OnOK();
+ virtual BOOL OnQueryCancel();
+ virtual BOOL OnQuerySiblings(WPARAM wParam, LPARAM lParam);
+ virtual int OnSetActive();
+ virtual int OnWizardBack();
+ virtual INT_PTR OnWizardFinish();
+ virtual int OnWizardNext();
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+
+ static UINT CALLBACK StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
+ static INT_PTR CALLBACK StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ void CancelToClose() const;
+ PROPSHEETPAGE GetPSP() const {return m_PSP;}
+ BOOL IsButtonEnabled(int iButton) const;
+ LRESULT QuerySiblings(WPARAM wParam, LPARAM lParam) const;
+ void SetModified(BOOL bChanged) const;
+ void SetTitle(LPCTSTR szTitle);
+ void SetWizardButtons(DWORD dwFlags) const;
+
+ protected:
+ PROPSHEETPAGE m_PSP;
+
+ private:
+ CPropertyPage(const CPropertyPage&); // Disable copy construction
+ CPropertyPage& operator = (const CPropertyPage&); // Disable assignment operator
+
+ tString m_Title;
+ };
+
+ class CPropertySheet : public CWnd
+ {
+ public:
+ CPropertySheet(UINT nIDCaption, CWnd* pParent = NULL);
+ CPropertySheet(LPCTSTR pszCaption = NULL, CWnd* pParent = NULL);
+ virtual ~CPropertySheet() {}
+
+ // Operations
+ virtual CPropertyPage* AddPage(CPropertyPage* pPage);
+ virtual HWND Create(CWnd* pParent = 0);
+ virtual INT_PTR CreatePropertySheet(LPCPROPSHEETHEADER ppsph);
+ virtual void DestroyButton(int iButton);
+ virtual void Destroy();
+ virtual int DoModal();
+ virtual void RemovePage(CPropertyPage* pPage);
+
+ // State functions
+ BOOL IsModeless() const;
+ BOOL IsWizard() const;
+
+ //Attributes
+ CPropertyPage* GetActivePage() const;
+ int GetPageCount() const;
+ int GetPageIndex(CPropertyPage* pPage) const;
+ HWND GetTabControl() const;
+ virtual BOOL SetActivePage(int nPage);
+ virtual BOOL SetActivePage(CPropertyPage* pPage);
+ virtual void SetIcon(UINT idIcon);
+ virtual void SetTitle(LPCTSTR szTitle);
+ virtual void SetWizardMode(BOOL bWizard);
+
+ protected:
+ virtual BOOL PreTranslateMessage(MSG* pMsg);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CPropertySheet(const CPropertySheet&); // Disable copy construction
+ CPropertySheet& operator = (const CPropertySheet&); // Disable assignment operator
+ void BuildPageArray();
+ static void CALLBACK Callback(HWND hwnd, UINT uMsg, LPARAM lParam);
+
+ tString m_Title;
+ std::vector m_vPages; // vector of CPropertyPage
+ std::vector m_vPSP; // vector of PROPSHEETPAGE
+ BOOL m_bInitialUpdate;
+ PROPSHEETHEADER m_PSH;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////////
+ // Definitions for the CPropertyPage class
+ //
+ inline CPropertyPage::CPropertyPage(UINT nIDTemplate, LPCTSTR szTitle /* = NULL*/)
+ {
+ ZeroMemory(&m_PSP, sizeof(PROPSHEETPAGE));
+ SetTitle(szTitle);
+
+ m_PSP.dwSize = sizeof(PROPSHEETPAGE);
+ m_PSP.dwFlags |= PSP_USECALLBACK;
+ m_PSP.hInstance = GetApp()->GetResourceHandle();
+ m_PSP.pszTemplate = MAKEINTRESOURCE(nIDTemplate);
+ m_PSP.pszTitle = m_Title.c_str();
+ m_PSP.pfnDlgProc = (DLGPROC)CPropertyPage::StaticDialogProc;
+ m_PSP.lParam = (LPARAM)this;
+ m_PSP.pfnCallback = CPropertyPage::StaticPropSheetPageProc;
+ }
+
+ inline void CPropertyPage::CancelToClose() const
+ // Disables the Cancel button and changes the text of the OK button to "Close."
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(PSM_CANCELTOCLOSE, 0L, 0L);
+ }
+
+
+ inline INT_PTR CPropertyPage::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CPropertyPage if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Win32 API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Win32 API documentation
+ // }
+
+ // Always pass unhandled messages on to DialogProcDefault
+ return DialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline INT_PTR CPropertyPage::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // All DialogProc functions should pass unhandled messages to this function
+ {
+ LRESULT lr = 0L;
+
+ switch (uMsg)
+ {
+ case UWM_CLEANUPTEMPS:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pTLSData->vTmpWnds.clear();
+ }
+ break;
+
+ case WM_INITDIALOG:
+ return OnInitDialog();
+
+ case PSM_QUERYSIBLINGS:
+ return (BOOL)OnQuerySiblings(wParam, lParam);
+
+ case WM_COMMAND:
+ {
+ // Refelect this message if it's from a control
+ CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
+ if (pWnd != NULL)
+ lr = pWnd->OnCommand(wParam, lParam);
+
+ // Handle user commands
+ if (!lr)
+ lr = OnCommand(wParam, lParam);
+
+ if (lr) return 0L;
+ }
+ break;
+
+ case WM_NOTIFY:
+ {
+ // Do Notification reflection if it came from a CWnd object
+ HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
+ CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
+
+ if (pWndFrom != NULL)
+ lr = pWndFrom->OnNotifyReflect(wParam, lParam);
+ else
+ {
+ // Some controls (eg ListView) have child windows.
+ // Reflect those notifications too.
+ CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
+ if (pWndFromParent != NULL)
+ lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
+ }
+
+ // Handle user notifications
+ if (!lr) lr = OnNotify(wParam, lParam);
+
+ // Set the return code for notifications
+ if (IsWindow())
+ SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
+
+ return (BOOL)lr;
+ }
+
+ case WM_PAINT:
+ {
+ if (::GetUpdateRect(m_hWnd, NULL, FALSE))
+ {
+ CPaintDC dc(this);
+ OnDraw(&dc);
+ }
+ else
+ // RedrawWindow can require repainting without an update rect
+ {
+ CClientDC dc(this);
+ OnDraw(&dc);
+ }
+
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ CDC dc((HDC)wParam);
+ BOOL bResult = OnEraseBkgnd(&dc);
+ dc.Detach();
+ if (bResult) return TRUE;
+ }
+ break;
+
+ // A set of messages to be reflected back to the control that generated them
+ case WM_CTLCOLORBTN:
+ case WM_CTLCOLOREDIT:
+ case WM_CTLCOLORDLG:
+ case WM_CTLCOLORLISTBOX:
+ case WM_CTLCOLORSCROLLBAR:
+ case WM_CTLCOLORSTATIC:
+ case WM_DRAWITEM:
+ case WM_MEASUREITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_CHARTOITEM:
+ case WM_VKEYTOITEM:
+ case WM_HSCROLL:
+ case WM_VSCROLL:
+ case WM_PARENTNOTIFY:
+ return MessageReflect(m_hWnd, uMsg, wParam, lParam);
+
+ } // switch(uMsg)
+ return FALSE;
+
+ } // INT_PTR CALLBACK CPropertyPage::DialogProc(...)
+
+ inline BOOL CPropertyPage::IsButtonEnabled(int iButton) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->GetDlgItem(iButton)->IsWindowEnabled();
+ }
+
+ inline int CPropertyPage::OnApply()
+ {
+ // This function is called for each page when the Apply button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline void CPropertyPage::OnCancel()
+ {
+ // This function is called for each page when the Cancel button is pressed
+ // Override this function in your derived class if required.
+ }
+
+ inline void CPropertyPage::OnHelp()
+ {
+ // This function is called in response to the PSN_HELP notification.
+ SendMessage(m_hWnd, WM_COMMAND, ID_HELP, 0L);
+ }
+
+ inline BOOL CPropertyPage::OnQueryCancel()
+ {
+ // Called when the cancel button is pressed, and before the cancel has taken place
+ // Returns TRUE to prevent the cancel operation, or FALSE to allow it.
+
+ return FALSE; // Allow cancel to proceed
+ }
+
+ inline BOOL CPropertyPage::OnQuerySiblings(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+ UNREFERENCED_PARAMETER(lParam);
+
+ // Responds to a query request from the Property Sheet.
+ // The values for wParam and lParam are the ones set by
+ // the CPropertySheet::QuerySiblings call
+
+ // return FALSE to allow other siblings to be queried, or
+ // return TRUE to stop query at this page.
+
+ return FALSE;
+ }
+
+ inline BOOL CPropertyPage::OnInitDialog()
+ {
+ // Called when the property page is created
+ // Override this function in your derived class if required.
+
+ return TRUE; // Pass Keyboard control to handle in WPARAM
+ }
+
+ inline BOOL CPropertyPage::OnKillActive()
+ {
+ // This is called in response to a PSN_KILLACTIVE notification, which
+ // is sent whenever the OK or Apply button is pressed.
+ // It provides an opportunity to validate the page contents before it's closed.
+ // Return TRUE to prevent the page from losing the activation, or FALSE to allow it.
+
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnOK()
+ {
+ // Called for each page when the OK button is pressed
+ // Override this function in your derived class if required.
+
+ // The possible return values are:
+ // PSNRET_NOERROR. The changes made to this page are valid and have been applied
+ // PSNRET_INVALID. The property sheet will not be destroyed, and focus will be returned to this page.
+ // PSNRET_INVALID_NOCHANGEPAGE. The property sheet will not be destroyed, and focus will be returned;
+
+ return PSNRET_NOERROR;
+ }
+
+ inline LRESULT CPropertyPage::OnNotify(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ LPPSHNOTIFY pNotify = (LPPSHNOTIFY)lParam;
+ switch(pNotify->hdr.code)
+ {
+ case PSN_SETACTIVE:
+ return OnSetActive();
+ case PSN_KILLACTIVE:
+ return OnKillActive();
+ case PSN_APPLY:
+ if (pNotify->lParam)
+ return OnOK();
+ else
+ return OnApply();
+ case PSN_RESET:
+ OnCancel();
+ return FALSE;
+ case PSN_QUERYCANCEL:
+ return OnQueryCancel();
+ case PSN_WIZNEXT:
+ return OnWizardNext();
+ case PSN_WIZBACK:
+ return OnWizardBack();
+ case PSN_WIZFINISH:
+ return OnWizardFinish();
+ case PSN_HELP:
+ OnHelp();
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ inline int CPropertyPage::OnSetActive()
+ {
+ // Called when a page becomes active
+ // Override this function in your derived class if required.
+
+ // Returns zero to accept the activation, or -1 to activate the next or the previous page (depending
+ // on whether the user clicked the Next or Back button). To set the activation to a particular page,
+ // return the resource identifier of the page.
+
+ return 0;
+ }
+
+ inline int CPropertyPage::OnWizardBack()
+ {
+ // This function is called when the Back button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Returns 0 to allow the wizard to go to the previous page. Returns -1 to prevent the wizard
+ // from changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline INT_PTR CPropertyPage::OnWizardFinish()
+ {
+ // This function is called when the Finish button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return Value:
+ // Return non-zero to prevent the wizard from finishing.
+ // Version 5.80. and later. Return a window handle to prevent the wizard from finishing. The wizard will set the focus to that window. The window must be owned by the wizard page.
+ // Return 0 to allow the wizard to finish.
+
+ return 0; // Allow wizard to finish
+ }
+
+ inline int CPropertyPage::OnWizardNext()
+ {
+ // This function is called when the Next button is pressed on a wizard page
+ // Override this function in your derived class if required.
+
+ // Return 0 to allow the wizard to go to the next page. Return -1 to prevent the wizard from
+ // changing pages. To display a particular page, return its dialog resource identifier.
+
+ return 0;
+ }
+
+ inline BOOL CPropertyPage::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow the tab control to translate keyboard input
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ CWnd* pWndParent = GetParent();
+ if (pWndParent->SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ if (IsDialogMessage(pMsg))
+ return TRUE;
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline LRESULT CPropertyPage::QuerySiblings(WPARAM wParam, LPARAM lParam) const
+ {
+ // Sent to a property sheet, which then forwards the message to each of its pages.
+ // Set wParam and lParam to values you want passed to the property pages.
+ // Returns the nonzero value from a page in the property sheet, or zero if no page returns a nonzero value.
+
+ assert(::IsWindow(m_hWnd));
+ return GetParent()->SendMessage(PSM_QUERYSIBLINGS, wParam, lParam);
+ }
+
+ inline void CPropertyPage::SetModified(BOOL bChanged) const
+ {
+ // The property sheet will enable the Apply button if bChanged is TRUE.
+
+ assert(::IsWindow(m_hWnd));
+
+ if (bChanged)
+ GetParent()->SendMessage(PSM_CHANGED, (WPARAM)m_hWnd, 0L);
+ else
+ GetParent()->SendMessage(PSM_UNCHANGED, (WPARAM)m_hWnd, 0L);
+ }
+
+ inline void CPropertyPage::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ {
+ m_Title = szTitle;
+ m_PSP.dwFlags |= PSP_USETITLE;
+ }
+ else
+ {
+ m_Title.erase();
+ m_PSP.dwFlags &= ~PSP_USETITLE;
+ }
+
+ m_PSP.pszTitle = m_Title.c_str();
+ }
+
+ inline void CPropertyPage::SetWizardButtons(DWORD dwFlags) const
+ {
+ // dwFlags: A value that specifies which wizard buttons are enabled. You can combine one or more of the following flags.
+ // PSWIZB_BACK Enable the Back button. If this flag is not set, the Back button is displayed as disabled.
+ // PSWIZB_DISABLEDFINISH Display a disabled Finish button.
+ // PSWIZB_FINISH Display an enabled Finish button.
+ // PSWIZB_NEXT Enable the Next button. If this flag is not set, the Next button is displayed as disabled.
+
+ assert (::IsWindow(m_hWnd));
+ PropSheet_SetWizButtons(::GetParent(m_hWnd), dwFlags);
+ }
+
+ inline UINT CALLBACK CPropertyPage::StaticPropSheetPageProc(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp)
+ {
+ assert( GetApp() );
+ UNREFERENCED_PARAMETER(hwnd);
+
+ // Note: the hwnd is always NULL
+
+ switch (uMsg)
+ {
+ case PSPCB_CREATE:
+ {
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ // Store the CPropertyPage pointer in Thread Local Storage
+ pTLSData->pCWnd = (CWnd*)ppsp->lParam;
+ }
+ break;
+ }
+
+ return TRUE;
+ }
+
+ inline INT_PTR CALLBACK CPropertyPage::StaticDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ // Find matching CWnd pointer for this HWND
+ CPropertyPage* pPage = (CPropertyPage*)GetApp()->GetCWndFromMap(hwndDlg);
+ if (0 == pPage)
+ {
+ // matching CWnd pointer not found, so add it to HWNDMap now
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ pPage = (CPropertyPage*)pTLSData->pCWnd;
+
+ // Set the hWnd members and call DialogProc for this message
+ pPage->m_hWnd = hwndDlg;
+ pPage->AddToMap();
+ }
+
+ return pPage->DialogProc(uMsg, wParam, lParam);
+ }
+
+
+ ///////////////////////////////////////////
+ // Definitions for the CPropertySheet class
+ //
+ inline CPropertySheet::CPropertySheet(UINT nIDCaption, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(LoadString(nIDCaption));
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertySheet::CPropertySheet(LPCTSTR pszCaption /*= NULL*/, CWnd* pParent /* = NULL*/)
+ {
+ ZeroMemory(&m_PSH, sizeof (PROPSHEETHEADER));
+ SetTitle(pszCaption);
+ m_bInitialUpdate = FALSE;
+
+#ifdef _WIN32_WCE
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#else
+ if (GetComCtlVersion() >= 471)
+ m_PSH.dwSize = sizeof(PROPSHEETHEADER);
+ else
+ m_PSH.dwSize = PROPSHEETHEADER_V1_SIZE;
+#endif
+
+ m_PSH.dwFlags = PSH_PROPSHEETPAGE | PSH_USECALLBACK;
+ m_PSH.hwndParent = pParent? pParent->GetHwnd() : 0;;
+ m_PSH.hInstance = GetApp()->GetInstanceHandle();
+ m_PSH.pfnCallback = (PFNPROPSHEETCALLBACK)CPropertySheet::Callback;
+ }
+
+ inline CPropertyPage* CPropertySheet::AddPage(CPropertyPage* pPage)
+ // Adds a Property Page to the Property Sheet
+ {
+ assert(NULL != pPage);
+
+ m_vPages.push_back(PropertyPagePtr(pPage));
+
+ if (m_hWnd)
+ {
+ // property sheet already exists, so add page to it
+ PROPSHEETPAGE psp = pPage->GetPSP();
+ HPROPSHEETPAGE hpsp = ::CreatePropertySheetPage(&psp);
+ PropSheet_AddPage(m_hWnd, hpsp);
+ }
+
+ m_PSH.nPages = (int)m_vPages.size();
+
+ return pPage;
+ }
+
+ inline void CPropertySheet::BuildPageArray()
+ // Builds the PROPSHEETPAGE array
+ {
+ m_vPSP.clear();
+ std::vector::iterator iter;
+ for (iter = m_vPages.begin(); iter < m_vPages.end(); ++iter)
+ m_vPSP.push_back((*iter)->GetPSP());
+
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front(); // Array of PROPSHEETPAGE
+ m_PSH.ppsp = pPSPArray;
+ }
+
+ inline void CALLBACK CPropertySheet::Callback(HWND hwnd, UINT uMsg, LPARAM lParam)
+ {
+ assert( GetApp() );
+
+ switch(uMsg)
+ {
+ //called before the dialog is created, hwnd = NULL, lParam points to dialog resource
+ case PSCB_PRECREATE:
+ {
+ LPDLGTEMPLATE lpTemplate = (LPDLGTEMPLATE)lParam;
+
+ if(!(lpTemplate->style & WS_SYSMENU))
+ {
+ lpTemplate->style |= WS_SYSMENU;
+ }
+ }
+ break;
+
+ //called after the dialog is created
+ case PSCB_INITIALIZED:
+ {
+ // Retrieve pointer to CWnd object from Thread Local Storage
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ assert(pTLSData);
+
+ CPropertySheet* w = (CPropertySheet*)pTLSData->pCWnd;
+ assert(w);
+
+ w->Attach(hwnd);
+ w->OnCreate();
+ }
+ break;
+ }
+ }
+
+
+ inline HWND CPropertySheet::Create(CWnd* pParent /*= 0*/)
+ // Creates a modeless Property Sheet
+ {
+ assert( GetApp() );
+
+ if (pParent)
+ {
+ m_PSH.hwndParent = pParent->GetHwnd();
+ }
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create a modeless Property Sheet
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ m_PSH.dwFlags |= PSH_MODELESS;
+ HWND hWnd = (HWND)CreatePropertySheet(&m_PSH);
+
+ return hWnd;
+ }
+
+ inline INT_PTR CPropertySheet::CreatePropertySheet(LPCPROPSHEETHEADER ppsph)
+ {
+ assert( GetApp() );
+
+ INT_PTR ipResult = 0;
+
+ // Only one window per CWnd instance allowed
+ assert(!::IsWindow(m_hWnd));
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the 'this' pointer in Thread Local Storage
+ pTLSData->pCWnd = this;
+
+ // Create the property sheet
+ ipResult = PropertySheet(ppsph);
+
+ return ipResult;
+ }
+
+ inline void CPropertySheet::DestroyButton(int IDButton)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ HWND hwndButton = ::GetDlgItem(m_hWnd, IDButton);
+ if (hwndButton != NULL)
+ {
+ // Hide and disable the button
+ ::ShowWindow(hwndButton, SW_HIDE);
+ ::EnableWindow(hwndButton, FALSE);
+ }
+ }
+
+ inline void CPropertySheet::Destroy()
+ {
+ CWnd::Destroy();
+ m_vPages.clear();
+ }
+
+ inline int CPropertySheet::DoModal()
+ {
+ assert( GetApp() );
+
+ BuildPageArray();
+ PROPSHEETPAGE* pPSPArray = &m_vPSP.front();
+ m_PSH.ppsp = pPSPArray;
+
+ // Create the Property Sheet
+ int nResult = (int)CreatePropertySheet(&m_PSH);
+
+ m_vPages.clear();
+
+ return nResult;
+ }
+
+ inline CPropertyPage* CPropertySheet::GetActivePage() const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CPropertyPage* pPage = NULL;
+ if (m_hWnd != NULL)
+ {
+ HWND hPage = (HWND)SendMessage(PSM_GETCURRENTPAGEHWND, 0L, 0L);
+ pPage = (CPropertyPage*)FromHandle(hPage);
+ }
+
+ return pPage;
+ }
+
+ inline int CPropertySheet::GetPageCount() const
+ // Returns the number of Property Pages in this Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)m_vPages.size();
+ }
+
+ inline int CPropertySheet::GetPageIndex(CPropertyPage* pPage) const
+ {
+ assert(::IsWindow(m_hWnd));
+
+ for (int i = 0; i < GetPageCount(); i++)
+ {
+ if (m_vPages[i].get() == pPage)
+ return i;
+ }
+ return -1;
+ }
+
+ inline HWND CPropertySheet::GetTabControl() const
+ // Returns the handle to the Property Sheet's tab control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(PSM_GETTABCONTROL, 0L, 0L);
+ }
+
+ inline BOOL CPropertySheet::IsModeless() const
+ {
+ return (m_PSH.dwFlags & PSH_MODELESS);
+ }
+
+ inline BOOL CPropertySheet::IsWizard() const
+ {
+ return (m_PSH.dwFlags & PSH_WIZARD);
+ }
+
+ inline void CPropertySheet::RemovePage(CPropertyPage* pPage)
+ // Removes a Property Page from the Property Sheet
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nPage = GetPageIndex(pPage);
+ if (m_hWnd != NULL)
+ SendMessage(m_hWnd, PSM_REMOVEPAGE, nPage, 0L);
+
+ m_vPages.erase(m_vPages.begin() + nPage, m_vPages.begin() + nPage+1);
+ m_PSH.nPages = (int)m_vPages.size();
+ }
+
+ inline BOOL CPropertySheet::PreTranslateMessage(MSG* pMsg)
+ {
+ // allow sheet to translate Ctrl+Tab, Shift+Ctrl+Tab, Ctrl+PageUp, and Ctrl+PageDown
+ if (pMsg->message == WM_KEYDOWN && GetAsyncKeyState(VK_CONTROL) < 0 &&
+ (pMsg->wParam == VK_TAB || pMsg->wParam == VK_PRIOR || pMsg->wParam == VK_NEXT))
+ {
+ if (SendMessage(PSM_ISDIALOGMESSAGE, 0L, (LPARAM)pMsg))
+ return TRUE;
+ }
+
+ // allow the dialog to translate keyboard input
+ if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
+ {
+ return GetActivePage()->PreTranslateMessage(pMsg);
+ }
+
+ return CWnd::PreTranslateMessage(pMsg);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(int nPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(m_hWnd, PSM_SETCURSEL, nPage, 0L);
+ }
+
+ inline BOOL CPropertySheet::SetActivePage(CPropertyPage* pPage)
+ {
+ assert(::IsWindow(m_hWnd));
+ int nPage = GetPageIndex(pPage);
+ if ((nPage >= 0))
+ return SetActivePage(nPage);
+
+ return FALSE;
+ }
+
+ inline void CPropertySheet::SetIcon(UINT idIcon)
+ {
+ m_PSH.pszIcon = MAKEINTRESOURCE(idIcon);
+ m_PSH.dwFlags |= PSH_USEICONID;
+ }
+
+ inline void CPropertySheet::SetTitle(LPCTSTR szTitle)
+ {
+ if (szTitle)
+ m_Title = szTitle;
+ else
+ m_Title.erase();
+
+ m_PSH.pszCaption = m_Title.c_str();
+ }
+
+ inline void CPropertySheet::SetWizardMode(BOOL bWizard)
+ {
+ if (bWizard)
+ m_PSH.dwFlags |= PSH_WIZARD;
+ else
+ m_PSH.dwFlags &= ~PSH_WIZARD;
+ }
+
+ inline LRESULT CPropertySheet::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS lpWinPos = (LPWINDOWPOS)lParam;
+ if (lpWinPos->flags & SWP_SHOWWINDOW)
+ {
+ if (!m_bInitialUpdate)
+ // The first window positioning with the window visible
+ OnInitialUpdate();
+ m_bInitialUpdate = TRUE;
+ }
+ }
+ break;
+
+ case WM_DESTROY:
+ m_bInitialUpdate = FALSE;
+ break;
+
+ case WM_SYSCOMMAND:
+ if ((SC_CLOSE == wParam) && (m_PSH.dwFlags & PSH_MODELESS))
+ {
+ Destroy();
+ return 0L;
+ }
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+}
+
+#endif // _WIN32XX_PROPERTYSHEET_H_
diff --git a/external/win32cpp/include/rebar.h b/external/win32cpp/include/rebar.h
new file mode 100644
index 0000000..1a339dc
--- /dev/null
+++ b/external/win32cpp/include/rebar.h
@@ -0,0 +1,709 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_REBAR_H_
+#define _WIN32XX_REBAR_H_
+
+#include "wincore.h"
+#include "gdi.h"
+
+
+namespace Win32xx
+{
+
+ struct ReBarTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrBkgnd1; // Colour 1 for rebar background
+ COLORREF clrBkgnd2; // Colour 2 for rebar background
+ COLORREF clrBand1; // Colour 1 for rebar band background. Use NULL if not required
+ COLORREF clrBand2; // Colour 2 for rebar band background. Use NULL if not required
+ BOOL FlatStyle; // Bands are rendered with flat rather than raised style
+ BOOL BandsLeft; // Position bands left on rearrange
+ BOOL LockMenuBand; // Lock MenuBar's band in dedicated top row, without gripper
+ BOOL RoundBorders; // Use rounded band borders
+ BOOL ShortBands; // Allows bands to be shorter than maximum available width
+ BOOL UseLines; // Displays horizontal lines between bands
+ };
+
+ ////////////////////////////////////
+ // Declaration of the CReBar class
+ //
+ class CReBar : public CWnd
+ {
+ public:
+ CReBar();
+ virtual ~CReBar();
+
+ // Operations
+ BOOL DeleteBand(const int nBand) const;
+ int HitTest(RBHITTESTINFO& rbht);
+ HWND HitTest(POINT pt);
+ int IDToIndex(UINT uBandID) const;
+ BOOL InsertBand(const int nBand, REBARBANDINFO& rbbi) const;
+ BOOL IsBandVisible(int nBand) const;
+ void MaximizeBand(UINT uBand, BOOL fIdeal = FALSE);
+ void MinimizeBand(UINT uBand);
+ BOOL MoveBand(UINT uFrom, UINT uTo);
+ void MoveBandsLeft();
+ BOOL ResizeBand(const int nBand, const CSize& sz) const;
+ BOOL ShowGripper(int nBand, BOOL fShow) const;
+ BOOL ShowBand(int nBand, BOOL fShow) const;
+ BOOL SizeToRect(CRect& rect) const;
+
+ // Attributes
+ int GetBand(const HWND hWnd) const;
+ CRect GetBandBorders(int nBand) const;
+ int GetBandCount() const;
+ BOOL GetBandInfo(const int nBand, REBARBANDINFO& rbbi) const;
+ CRect GetBandRect(int i) const;
+ UINT GetBarHeight() const;
+ BOOL GetBarInfo(REBARINFO& rbi) const;
+ HWND GetMenuBar() {return m_hMenuBar;}
+ ReBarTheme& GetReBarTheme() {return m_Theme;}
+ UINT GetRowCount() const;
+ int GetRowHeight(int nRow) const;
+ UINT GetSizeofRBBI() const;
+ HWND GetToolTips() const;
+ BOOL SetBandBitmap(const int nBand, const CBitmap* pBackground) const;
+ BOOL SetBandColor(const int nBand, const COLORREF clrFore, const COLORREF clrBack) const;
+ BOOL SetBandInfo(const int nBand, REBARBANDINFO& rbbi) const;
+ BOOL SetBarInfo(REBARINFO& rbi) const;
+ void SetMenuBar(HWND hMenuBar) {m_hMenuBar = hMenuBar;}
+ void SetReBarTheme(ReBarTheme& Theme);
+
+ protected:
+ //Overridables
+ virtual BOOL OnEraseBkgnd(CDC* pDC);
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CReBar(const CReBar&); // Disable copy construction
+ CReBar& operator = (const CReBar&); // Disable assignment operator
+
+ ReBarTheme m_Theme;
+ BOOL m_bIsDragging;
+ HWND m_hMenuBar;
+ LPARAM m_Orig_lParam;
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////
+ // Definitions for the CReBar class
+ //
+ inline CReBar::CReBar() : m_bIsDragging(FALSE), m_hMenuBar(0), m_Orig_lParam(0L)
+ {
+ ZeroMemory(&m_Theme, sizeof(ReBarTheme));
+ }
+
+ inline CReBar::~CReBar()
+ {
+ }
+
+ inline BOOL CReBar::DeleteBand(int nBand) const
+ // Deletes a band from a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_DELETEBAND, nBand, 0L);
+ }
+
+ inline int CReBar::GetBand(HWND hWnd) const
+ // Returns the zero based band number for this window handle
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int nResult = -1;
+ if (NULL == hWnd) return nResult;
+
+ for (int nBand = 0; nBand < GetBandCount(); ++nBand)
+ {
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD;
+ GetBandInfo(nBand, rbbi);
+ if (rbbi.hwndChild == hWnd)
+ nResult = nBand;
+ }
+
+ return nResult;
+ }
+
+ inline CRect CReBar::GetBandBorders(int nBand) const
+ // Retrieves the borders of a band.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CRect rc;
+ SendMessage(RB_GETBANDBORDERS, nBand, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CReBar::GetBandCount() const
+ // Retrieves the count of bands currently in the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_GETBANDCOUNT, 0L, 0L);
+ }
+
+ inline BOOL CReBar::GetBandInfo(int nBand, REBARBANDINFO& rbbi) const
+ // Retrieves information about a specified band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(nBand >= 0);
+
+ // REBARBANDINFO describes individual BAND characteristics
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_GETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline CRect CReBar::GetBandRect(int i) const
+ // Retrieves the bounding rectangle for a given band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ SendMessage(RB_GETRECT, i, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline UINT CReBar::GetBarHeight() const
+ // Retrieves the height of the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(RB_GETBARHEIGHT, 0L, 0L);
+ }
+
+ inline BOOL CReBar::GetBarInfo(REBARINFO& rbi) const
+ // Retrieves information about the rebar control and the image list it uses.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // REBARINFO describes overall rebar control characteristics
+ rbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_GETBARINFO, 0L, (LPARAM)&rbi);
+ }
+
+ inline UINT CReBar::GetRowCount() const
+ // Retrieves the number of rows of bands in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(RB_GETROWCOUNT, 0L, 0L);
+ }
+
+ inline int CReBar::GetRowHeight(int nRow) const
+ // Retrieves the height of a specified row in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_GETROWHEIGHT, nRow, 0L);
+ }
+
+ inline UINT CReBar::GetSizeofRBBI() const
+ // The size of the REBARBANDINFO struct changes according to _WIN32_WINNT
+ // sizeof(REBARBANDINFO) can report an incorrect size for older Window versions,
+ // or newer Window version without XP themes enabled.
+ // Use this function to get a safe size for REBARBANDINFO.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ UINT uSizeof = sizeof(REBARBANDINFO);
+
+ #if defined REBARBANDINFO_V6_SIZE // only defined for VS2008 or higher
+ #if !defined (_WIN32_WINNT) || _WIN32_WINNT >= 0x0600
+ if ((GetWinVersion() < 2600) || (GetComCtlVersion() < 610)) // Vista and Vista themes?
+ uSizeof = REBARBANDINFO_V6_SIZE;
+ #endif
+ #endif
+
+ return uSizeof;
+ }
+
+ inline HWND CReBar::GetToolTips() const
+ // Retrieves the handle to any ToolTip control associated with the rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(RB_GETTOOLTIPS, 0L, 0L);
+ }
+
+ inline int CReBar::HitTest(RBHITTESTINFO& rbht)
+ // Determines which portion of a rebar band is at a given point on the screen,
+ // if a rebar band exists at that point.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_HITTEST, 0L, (LPARAM)&rbht);
+ }
+
+ inline HWND CReBar::HitTest(POINT pt)
+ // Return the child HWND at the given point
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // Convert the point to client co-ordinates
+ ScreenToClient(pt);
+
+ // Get the rebar band with the point
+ RBHITTESTINFO rbhti = {0};
+ rbhti.pt = pt;
+ int iBand = HitTest(rbhti);
+
+ if (iBand >= 0)
+ {
+ // Get the rebar band's hWnd
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD;
+ GetBandInfo(iBand, rbbi);
+
+ return rbbi.hwndChild;
+ }
+ else
+ return NULL;
+ }
+
+ inline int CReBar::IDToIndex(UINT uBandID) const
+ // Converts a band identifier to a band index in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(RB_IDTOINDEX, (WPARAM)uBandID, 0L);
+ }
+
+ inline BOOL CReBar::InsertBand(int nBand, REBARBANDINFO& rbbi) const
+ // Inserts a new band in a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_INSERTBAND, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::IsBandVisible(int nBand) const
+ // Returns true if the band is visible
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+
+ return !(rbbi.fStyle & RBBS_HIDDEN);
+ }
+
+ inline BOOL CReBar::OnEraseBkgnd(CDC* pDC)
+ {
+ BOOL Erase = TRUE;
+ if (!m_Theme.UseThemes)
+ Erase = FALSE;
+
+ if (!m_Theme.clrBkgnd1 && !m_Theme.clrBkgnd2 && !m_Theme.clrBand1 && !m_Theme.clrBand2)
+ Erase = FALSE;
+
+ if (Erase)
+ {
+ CRect rcReBar = GetClientRect();
+ int BarWidth = rcReBar.Width();
+ int BarHeight = rcReBar.Height();
+
+ // Create and set up our memory DC
+ CMemDC MemDC(pDC);
+ MemDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+
+ // Draw to ReBar background to the memory DC
+ rcReBar.right = 600;
+ MemDC.GradientFill(m_Theme.clrBkgnd1, m_Theme.clrBkgnd2, rcReBar, TRUE);
+ if (BarWidth >= 600)
+ {
+ rcReBar.left = 600;
+ rcReBar.right = BarWidth;
+ MemDC.SolidFill(m_Theme.clrBkgnd2, rcReBar);
+ }
+
+ if (m_Theme.clrBand1 || m_Theme.clrBand2)
+ {
+ // Draw the individual band backgrounds
+ for (int nBand = 0 ; nBand < GetBandCount(); ++nBand)
+ {
+ if (IsBandVisible(nBand))
+ {
+ if (nBand != GetBand(m_hMenuBar))
+ {
+ // Determine the size of this band
+ CRect rcBand = GetBandRect(nBand);
+
+ // Determine the size of the child window
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILD ;
+ GetBandInfo(nBand, rbbi);
+ CRect rcChild;
+ ::GetWindowRect(rbbi.hwndChild, &rcChild);
+ int ChildWidth = rcChild.right - rcChild.left;
+
+ // Determine our drawing rectangle
+ CRect rcDraw = rcBand;
+ rcDraw.bottom = rcDraw.top + (rcBand.bottom - rcBand.top)/2;
+ int xPad = IsXPThemed()? 2: 0;
+ rcDraw.left -= xPad;
+
+ // Fill the Source CDC with the band's background
+ CMemDC SourceDC(pDC);
+ SourceDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+ CRect rcBorder = GetBandBorders(nBand);
+ rcDraw.right = rcBand.left + ChildWidth + rcBorder.left;
+ SourceDC.SolidFill(m_Theme.clrBand1, rcDraw);
+ rcDraw.top = rcDraw.bottom;
+ rcDraw.bottom = rcBand.bottom;
+ SourceDC.GradientFill(m_Theme.clrBand1, m_Theme.clrBand2, rcDraw, FALSE);
+
+ // Set Curve amount for rounded edges
+ int Curve = m_Theme.RoundBorders? 12 : 0;
+
+ // Create our mask for rounded edges using RoundRect
+ CMemDC MaskDC(pDC);
+ MaskDC.CreateCompatibleBitmap(pDC, BarWidth, BarHeight);
+
+ rcDraw.top = rcBand.top;
+ if (!m_Theme.FlatStyle)
+ ::InflateRect(&rcDraw, 1, 1);
+
+ int left = rcDraw.left;
+ int right = rcDraw.right;
+ int top = rcDraw.top;
+ int bottom = rcDraw.bottom;
+ int cx = rcDraw.right - rcBand.left + xPad;
+ int cy = rcDraw.bottom - rcBand.top;
+
+ if (m_Theme.FlatStyle)
+ {
+ MaskDC.SolidFill(RGB(0,0,0), rcDraw);
+ MaskDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, PATINVERT);
+ MaskDC.RoundRect(left, top, right, bottom, Curve, Curve);
+ }
+ else
+ {
+ MaskDC.SolidFill(RGB(0,0,0), rcDraw);
+ MaskDC.RoundRect(left, top, right, bottom, Curve, Curve);
+ MaskDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, PATINVERT);
+ }
+
+ // Copy Source DC to Memory DC using the RoundRect mask
+ MemDC.BitBlt(left, top, cx, cy, &SourceDC, left, top, SRCINVERT);
+ MemDC.BitBlt(left, top, cx, cy, &MaskDC, left, top, SRCAND);
+ MemDC.BitBlt(left, top, cx, cy, &SourceDC, left, top, SRCINVERT);
+
+ // Extra drawing to prevent jagged edge while moving bands
+ if (m_bIsDragging)
+ {
+ CClientDC ReBarDC(this);
+ ReBarDC.BitBlt(rcDraw.right - ChildWidth, rcDraw.top, ChildWidth, cy, &MemDC, rcDraw.right - ChildWidth, rcDraw.top, SRCCOPY);
+ }
+ }
+ }
+ }
+ }
+
+ if (m_Theme.UseLines)
+ {
+ // Draw lines between bands
+ for (int j = 0; j < GetBandCount()-1; ++j)
+ {
+ rcReBar = GetBandRect(j);
+ rcReBar.left = MAX(0, rcReBar.left - 4);
+ rcReBar.bottom +=2;
+ MemDC.DrawEdge(rcReBar, EDGE_ETCHED, BF_BOTTOM | BF_ADJUST);
+ }
+ }
+
+ // Copy the Memory DC to the window's DC
+ pDC->BitBlt(0, 0, BarWidth, BarHeight, &MemDC, 0, 0, SRCCOPY);
+ }
+
+ return Erase;
+ }
+
+ inline void CReBar::PreCreate(CREATESTRUCT &cs)
+ // Sets the CREATESTRUCT paramaters prior to window creation
+ {
+ cs.style = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
+ CCS_NODIVIDER | RBS_VARHEIGHT | RBS_BANDBORDERS ;
+
+ cs.cy = 100;
+ }
+
+ inline void CReBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = REBARCLASSNAME;
+ }
+
+ inline void CReBar::MaximizeBand(UINT uBand, BOOL fIdeal /*= FALSE*/)
+ // Resizes a band in a rebar control to either its ideal or largest size.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(RB_MAXIMIZEBAND, (WPARAM)uBand, (LPARAM)fIdeal);
+ }
+
+ inline void CReBar::MinimizeBand(UINT uBand)
+ // Resizes a band in a rebar control to its smallest size.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(RB_MINIMIZEBAND, (WPARAM)uBand, 0L);
+ }
+
+ inline BOOL CReBar::MoveBand(UINT uFrom, UINT uTo)
+ // Moves a band from one index to another.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_MOVEBAND, (WPARAM)uFrom, (LPARAM)uTo);
+ }
+
+ inline void CReBar::MoveBandsLeft()
+ // Repositions the bands so they are left justified
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int OldrcTop = -1;
+ for (int nBand = GetBandCount() -1; nBand >= 0; --nBand)
+ {
+ CRect rc = GetBandRect(nBand);
+ if (rc.top != OldrcTop)
+ {
+ // Maximize the last band on each row
+ if (IsBandVisible(nBand))
+ {
+ ::SendMessage(GetHwnd(), RB_MAXIMIZEBAND, nBand, 0L);
+ OldrcTop = rc.top;
+ }
+ }
+ }
+ }
+
+ inline BOOL CReBar::ResizeBand(int nBand, const CSize& sz) const
+ // Sets a band's size
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_CHILDSIZE | RBBIM_SIZE;
+
+ GetBandInfo(nBand, rbbi);
+ rbbi.cx = sz.cx + 2;
+ rbbi.cxMinChild = sz.cx + 2;
+ rbbi.cyMinChild = sz.cy;
+ rbbi.cyMaxChild = sz.cy;
+
+ return SetBandInfo(nBand, rbbi );
+ }
+
+ inline BOOL CReBar::SetBandBitmap(int nBand, const CBitmap* pBackground) const
+ // Sets the band's bitmaps
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(pBackground);
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+ rbbi.fMask |= RBBIM_BACKGROUND;
+ rbbi.hbmBack = *pBackground;
+
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBandColor(int nBand, COLORREF clrFore, COLORREF clrBack) const
+ // Sets the band's color
+ // Note: No effect with XP themes enabled
+ // No effect if a bitmap has been set
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_COLORS;
+ rbbi.clrFore = clrFore;
+ rbbi.clrBack = clrBack;
+
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBandInfo(int nBand, REBARBANDINFO& rbbi) const
+ // Sets the characteristics of a rebar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(nBand >= 0);
+
+ // REBARBANDINFO describes individual BAND characteristics0
+ rbbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_SETBANDINFO, nBand, (LPARAM)&rbbi);
+ }
+
+ inline BOOL CReBar::SetBarInfo(REBARINFO& rbi) const
+ // REBARINFO associates an image list with the rebar
+ // A band will also need to set RBBIM_IMAGE
+ {
+ assert(::IsWindow(m_hWnd));
+
+ rbi.cbSize = GetSizeofRBBI();
+ return (BOOL)SendMessage(RB_SETBARINFO, 0L, (LPARAM)&rbi);
+ }
+
+ inline void CReBar::SetReBarTheme(ReBarTheme& Theme)
+ {
+ m_Theme.UseThemes = Theme.UseThemes;
+ m_Theme.clrBkgnd1 = Theme.clrBkgnd1;
+ m_Theme.clrBkgnd2 = Theme.clrBkgnd2;
+ m_Theme.clrBand1 = Theme.clrBand1;
+ m_Theme.clrBand2 = Theme.clrBand2;
+ m_Theme.BandsLeft = Theme.BandsLeft;
+ m_Theme.LockMenuBand = Theme.LockMenuBand;
+ m_Theme.ShortBands = Theme.ShortBands;
+ m_Theme.UseLines = Theme.UseLines;
+ m_Theme.FlatStyle = Theme.FlatStyle;
+ m_Theme.RoundBorders = Theme.RoundBorders;
+
+ if (IsWindow())
+ {
+ if (m_Theme.LockMenuBand)
+ ShowGripper(GetBand(m_hMenuBar), FALSE);
+ else
+ ShowGripper(GetBand(m_hMenuBar), TRUE);
+
+ Invalidate();
+ }
+ }
+
+ inline BOOL CReBar::ShowBand(int nBand, BOOL fShow) const
+ // Show or hide a band
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_SHOWBAND, (WPARAM)nBand, (LPARAM)fShow);
+ }
+
+ inline BOOL CReBar::ShowGripper(int nBand, BOOL fShow) const
+ // Show or hide the band's gripper
+ {
+ assert(::IsWindow(m_hWnd));
+
+ REBARBANDINFO rbbi = {0};
+ rbbi.cbSize = GetSizeofRBBI();
+ rbbi.fMask = RBBIM_STYLE;
+ GetBandInfo(nBand, rbbi);
+ if (fShow)
+ {
+ rbbi.fStyle |= RBBS_GRIPPERALWAYS;
+ rbbi.fStyle &= ~RBBS_NOGRIPPER;
+ }
+ else
+ {
+ rbbi.fStyle &= ~RBBS_GRIPPERALWAYS;
+ rbbi.fStyle |= RBBS_NOGRIPPER;
+ }
+
+ return SetBandInfo(nBand, rbbi);
+ }
+
+ inline BOOL CReBar::SizeToRect(CRect& rect) const
+ // Attempts to find the best layout of the bands for the given rectangle.
+ // The rebar bands will be arranged and wrapped as necessary to fit the rectangle.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(RB_SIZETORECT, 0, (LPARAM) (LPRECT)rect);
+ }
+
+ inline LRESULT CReBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_MOUSEMOVE:
+ if (m_Theme.UseThemes && m_Theme.LockMenuBand)
+ {
+ // We want to lock the first row in place, but allow other bands to move!
+ // Use move messages to limit the resizing of bands
+ int y = GET_Y_LPARAM(lParam);
+
+ if (y <= GetRowHeight(0))
+ return 0L; // throw this message away
+ }
+ break;
+ case WM_LBUTTONDOWN:
+ m_Orig_lParam = lParam; // Store the x,y position
+ m_bIsDragging = TRUE;
+ break;
+ case WM_LBUTTONUP:
+ if (m_Theme.UseThemes && m_Theme.LockMenuBand)
+ {
+ // Use move messages to limit the resizing of bands
+ int y = GET_Y_LPARAM(lParam);
+
+ if (y <= GetRowHeight(0))
+ {
+ // Use x,y from WM_LBUTTONDOWN for WM_LBUTTONUP position
+ lParam = m_Orig_lParam;
+ }
+ }
+ m_bIsDragging = FALSE;
+ break;
+ case UWM_GETREBARTHEME:
+ {
+ ReBarTheme& rm = GetReBarTheme();
+ return (LRESULT)&rm;
+ }
+ case UWM_TOOLBAR_RESIZE:
+ {
+ HWND hToolBar = (HWND)wParam;
+ LPSIZE pToolBarSize = (LPSIZE)lParam;
+ ResizeBand(GetBand(hToolBar), *pToolBarSize);
+ }
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_REBAR_H_
diff --git a/external/win32cpp/include/release notes.txt b/external/win32cpp/include/release notes.txt
new file mode 100644
index 0000000..bc3114d
--- /dev/null
+++ b/external/win32cpp/include/release notes.txt
@@ -0,0 +1,116 @@
+About Win32++
+-------------
+Win32++ is simple and easy to understand framework for developing Win32
+applications using C++. It brings an object oriented approach to programming
+directly with the Win32 API. Each window created is a C++ class object capable
+of having its own window procedure for routing messages.
+
+Win32++ supports the following compilers and development environments:
+* Borland C++ Compiler 5.5
+* Borland Developer Studio 2006
+* Dev-C++
+* Microsoft Visual C++ Toolkit 2003
+* Microsoft Visual C++ 2005 Express Edition
+* Microsoft Visual C++ 2008 Express Edition
+* Microsoft Visual C++ 2010 Express Edition
+* Microsoft Visual Studio 6.0
+* Microsoft Visual Studio.net 2003
+* Microsoft Visual Studio.net 2005
+* Microsoft Visual Studio.net 2008
+* Microsoft Visual Studio.net 2010
+* MinGW compiler
+
+Win32++ supports the following operating systems
+* Windows 95
+* Windows 98
+* Windows ME
+* Windows NT 4
+* Windows 2000
+* Windows XP (32bit and 64bit)
+* Windows 2003 Server (32bit and 64bit)
+* Windows Vista (32bit and 64bit)
+* Windows 2008 Server (32bit and 64bit)
+* Windows 7 (32 bit and 64 bit)
+* Windows CE from WCE400 (Windows mobile 2003) to WCE600 (Windows mobile 6)
+
+
+Features
+--------
+Win32++ code has the following features
+ * Object Orientated
+ * Subclassing support
+ * Notification reflection and message reflection
+ * Unicode compliant, with multilingual support
+ * Multi-threaded support.
+ * Tracing
+ * 64 bit support
+ * Windows 7 ribbon support
+ * Themes support
+ * Network support (including IP version 6)
+ * Docking windows
+ * Tabbed MDIs
+
+Frames produced by Win32++ include the following:
+ * Rebar
+ * Menubar
+ * Toolbar
+ * Status bar
+ * Tool tips
+
+About the file downloads
+------------------------
+The file download from Sourceforge includes the following:
+ * The Win32++ library itself
+ * Help for the library
+ * A set of tutorials
+ * A collection of sample applications
+
+The sample applications include:
+ * Browser - An Internet browser application with an event sink.
+ * Dialog - An example of a simple dialog application.
+ * DialogDemo - An interative dialog application demonstrating slider controls and progress bars.
+ * DialogResizing - An example of a resizable dialog.
+ * DialogTab - A dialog application with a tab control.
+ * DirectX - A simple DirectX application.
+ * DLL - Shows how to run Win32++ from within a DLL
+ * Dock - An example of a simple docking application.
+ * DockContainer - An example of a docking application which incorporates containers.
+ * DockTabbedMDI - An example of a docking application with containers and a tabbed MDI.
+ * Explorer - A Windows Explorer-like application.
+ * FastGDI - An application which demonstrates direct manipulation of a bitmap's colour.
+ * FormDemo - An example of a modeless dialog within a frame.
+ * Frame - A simple frame application.
+ * GDIPlus - Demonstrates how to use GDI+ with Win32++.
+ * MDIFrame - A simple MDI frame application.
+ * MDIFrameDemo - Demonstrates some additional features of MDI frames.
+ * MDIFrameSplitter - Demonstrates how to implement splitter windows in MDI Child windows.
+ * Networking - Demonstrates the use of networking.
+ * Notepad - A simple text editor with printing.
+ * Performance - Measures Win32++'s message handling speed.
+ * Picture - A simple picture rendering application.
+ * PropertySheets - A demonstration of property sheets.
+ * RibbonFrame - Demonstrates how to use the Windows 7 ribbon with a frame.
+ * RibbonSimple - Demonstrates how to use the Windwos 7 ribbon with a simple window.
+ * Scribble - A simple drawing application.
+ * Simple - Creates a simple window.
+ * Splitter - Demonstrates how to use dockers to create splitter windows.
+ * TabDemo - Demonstrates the use of a CTab control in a frame.
+ * TaskDialog - Demonstrates the use of task dialogs (available on Vista and above).
+ * Themes - Demonstrates how to customise the colours for rebar and toolbar controls.
+ * Threads - Demonstrates multi-threaded Windows.
+ * Tray - Demonstrates how to "minimise" an application to the system tray.
+ * WinCE samples - A small collection of samples for Windows CE
+
+Getting Started
+---------------
+Each file download includes the project files for Dev-C++, CodeBlocks and the
+various compilers from Microsoft. CodeBlocks is an IDE (Integrated Development
+Environment) that supports GNU GCC, Borland Developer Studio 2006 and Microsoft
+C++ Toolkit 2003.
+
+You can start with one of the sample programs, and add your code. Alternatively
+you can start with the projects and sample code provided in the "new projects"
+folder.
+
+For additional information on getting started, refer to the help included
+in the documentation.
\ No newline at end of file
diff --git a/external/win32cpp/include/ribbon.h b/external/win32cpp/include/ribbon.h
new file mode 100644
index 0000000..9f6dac5
--- /dev/null
+++ b/external/win32cpp/include/ribbon.h
@@ -0,0 +1,527 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// ribbon.h
+// Declaration of the following classes:
+// CRibbon and CRibbonFrame
+//
+
+#ifndef _WIN32XX_RIBBON_H_
+#define _WIN32XX_RIBBON_H_
+
+
+// Notes: 1) The Windows 7 SDK must be installed and its directories added to the IDE
+// 2) The ribbon only works on OS Windows 7 and above
+
+//#include
+#include // Contained within the Windows 7 SDK
+#include
+
+namespace Win32xx
+{
+ // Defines the callback entry-point methods for the Ribbon framework.
+ class CRibbon : public IUICommandHandler, public IUIApplication
+ {
+ public:
+ CRibbon() : m_cRef(1), m_pRibbonFramework(NULL) {}
+ ~CRibbon();
+
+ // IUnknown methods.
+ STDMETHOD_(ULONG, AddRef());
+ STDMETHOD_(ULONG, Release());
+ STDMETHOD(QueryInterface(REFIID iid, void** ppv));
+
+ // IUIApplication methods
+ STDMETHOD(OnCreateUICommand)(UINT nCmdID, __in UI_COMMANDTYPE typeID,
+ __deref_out IUICommandHandler** ppCommandHandler);
+
+ STDMETHOD(OnDestroyUICommand)(UINT32 commandId, __in UI_COMMANDTYPE typeID,
+ __in_opt IUICommandHandler* commandHandler);
+
+ STDMETHOD(OnViewChanged)(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
+ UI_VIEWVERB verb, INT uReasonCode);
+
+ // IUICommandHandle methods
+ STDMETHODIMP Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
+ __in_opt IUISimplePropertySet* pCommandExecutionProperties);
+
+ STDMETHODIMP UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
+ __out PROPVARIANT* ppropvarNewValue);
+
+ bool virtual CreateRibbon(CWnd* pWnd);
+ void virtual DestroyRibbon();
+ IUIFramework* GetRibbonFramework() { return m_pRibbonFramework; }
+
+ private:
+ IUIFramework* m_pRibbonFramework;
+ LONG m_cRef; // Reference count.
+
+ };
+
+
+ class CRibbonFrame : public CFrame, public CRibbon
+ {
+ public:
+ // A nested class for the MRU item properties
+ class CRecentFiles : public IUISimplePropertySet
+ {
+ public:
+ CRecentFiles(PWSTR wszFullPath);
+ ~CRecentFiles() {}
+
+ // IUnknown methods.
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+ STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
+
+ // IUISimplePropertySet methods
+ STDMETHODIMP GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *value);
+
+ private:
+ LONG m_cRef; // Reference count.
+ WCHAR m_wszDisplayName[MAX_PATH];
+ WCHAR m_wszFullPath[MAX_PATH];
+ };
+
+ typedef Shared_Ptr RecentFilesPtr;
+
+ CRibbonFrame() : m_uRibbonHeight(0) {}
+ virtual ~CRibbonFrame() {}
+ virtual CRect GetViewRect() const;
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual STDMETHODIMP OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode);
+ virtual HRESULT PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue);
+ virtual void UpdateMRUMenu();
+
+ UINT GetRibbonHeight() const { return m_uRibbonHeight; }
+
+ private:
+ std::vector m_vRecentFiles;
+ void SetRibbonHeight(UINT uRibbonHeight) { m_uRibbonHeight = uRibbonHeight; }
+ UINT m_uRibbonHeight;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+ //////////////////////////////////////////////
+ // Definitions for the CRibbon class
+ //
+
+ inline CRibbon::~CRibbon()
+ {
+ // Reference count must be 1 or we have a leak!
+ assert(m_cRef == 1);
+ }
+
+ // IUnknown method implementations.
+ inline STDMETHODIMP_(ULONG) CRibbon::AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbon::Release()
+ {
+ LONG cRef = InterlockedDecrement(&m_cRef);
+ return cRef;
+ }
+
+ inline STDMETHODIMP CRibbon::Execute(UINT nCmdID, UI_EXECUTIONVERB verb, __in_opt const PROPERTYKEY* key, __in_opt const PROPVARIANT* ppropvarValue,
+ __in_opt IUISimplePropertySet* pCommandExecutionProperties)
+ {
+ UNREFERENCED_PARAMETER (nCmdID);
+ UNREFERENCED_PARAMETER (verb);
+ UNREFERENCED_PARAMETER (key);
+ UNREFERENCED_PARAMETER (ppropvarValue);
+ UNREFERENCED_PARAMETER (pCommandExecutionProperties);
+
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CRibbon::QueryInterface(REFIID iid, void** ppv)
+ {
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppv = static_cast(static_cast(this));
+ }
+ else if (iid == __uuidof(IUICommandHandler))
+ {
+ *ppv = static_cast(this);
+ }
+ else if (iid == __uuidof(IUIApplication))
+ {
+ *ppv = static_cast(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ // Called by the Ribbon framework for each command specified in markup, to bind the Command to an IUICommandHandler.
+ inline STDMETHODIMP CRibbon::OnCreateUICommand(UINT nCmdID, __in UI_COMMANDTYPE typeID,
+ __deref_out IUICommandHandler** ppCommandHandler)
+ {
+ UNREFERENCED_PARAMETER(typeID);
+ UNREFERENCED_PARAMETER(nCmdID);
+
+ // By default we use the single command handler provided as part of CRibbon.
+ // Override this function to account for multiple command handlers.
+
+ return QueryInterface(IID_PPV_ARGS(ppCommandHandler));
+ }
+
+ // Called when the state of the Ribbon changes, for example, created, destroyed, or resized.
+ inline STDMETHODIMP CRibbon::OnViewChanged(UINT viewId, __in UI_VIEWTYPE typeId, __in IUnknown* pView,
+ UI_VIEWVERB verb, INT uReasonCode)
+ {
+ UNREFERENCED_PARAMETER(viewId);
+ UNREFERENCED_PARAMETER(typeId);
+ UNREFERENCED_PARAMETER(pView);
+ UNREFERENCED_PARAMETER(verb);
+ UNREFERENCED_PARAMETER(uReasonCode);
+
+
+ return E_NOTIMPL;
+ }
+
+ // Called by the Ribbon framework for each command at the time of ribbon destruction.
+ inline STDMETHODIMP CRibbon::OnDestroyUICommand(UINT32 nCmdID, __in UI_COMMANDTYPE typeID,
+ __in_opt IUICommandHandler* commandHandler)
+ {
+ UNREFERENCED_PARAMETER(commandHandler);
+ UNREFERENCED_PARAMETER(typeID);
+ UNREFERENCED_PARAMETER(nCmdID);
+
+ return E_NOTIMPL;
+ }
+
+ // Called by the Ribbon framework when a command property (PKEY) needs to be updated.
+ inline STDMETHODIMP CRibbon::UpdateProperty(UINT nCmdID, __in REFPROPERTYKEY key, __in_opt const PROPVARIANT* ppropvarCurrentValue,
+ __out PROPVARIANT* ppropvarNewValue)
+ {
+ UNREFERENCED_PARAMETER(nCmdID);
+ UNREFERENCED_PARAMETER(key);
+ UNREFERENCED_PARAMETER(ppropvarCurrentValue);
+ UNREFERENCED_PARAMETER(ppropvarNewValue);
+
+ return E_NOTIMPL;
+ }
+
+ inline bool CRibbon::CreateRibbon(CWnd* pWnd)
+ {
+ ::CoInitialize(NULL);
+
+ // Instantiate the Ribbon framework object.
+ ::CoCreateInstance(CLSID_UIRibbonFramework, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pRibbonFramework));
+
+ // Connect the host application to the Ribbon framework.
+ HRESULT hr = m_pRibbonFramework->Initialize(pWnd->GetHwnd(), this);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ // Load the binary markup. APPLICATION_RIBBON is the default name generated by uicc.
+ hr = m_pRibbonFramework->LoadUI(GetModuleHandle(NULL), L"APPLICATION_RIBBON");
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ inline void CRibbon::DestroyRibbon()
+ {
+ if (m_pRibbonFramework)
+ {
+ m_pRibbonFramework->Destroy();
+ m_pRibbonFramework->Release();
+ m_pRibbonFramework = NULL;
+ }
+ }
+
+
+ //////////////////////////////////////////////
+ // Definitions for the CRibbonFrame class
+ //
+
+ inline CRect CRibbonFrame::GetViewRect() const
+ {
+ // Get the frame's client area
+ CRect rcFrame = GetClientRect();
+
+ // Get the statusbar's window area
+ CRect rcStatus;
+ if (GetStatusBar().IsWindowVisible() || !IsWindowVisible())
+ rcStatus = GetStatusBar().GetWindowRect();
+
+ // Get the top rebar or toolbar's window area
+ CRect rcTop;
+ if (IsReBarSupported() && m_bUseReBar)
+ rcTop = GetReBar().GetWindowRect();
+ else
+ if (m_bUseToolBar && GetToolBar().IsWindowVisible())
+ rcTop = GetToolBar().GetWindowRect();
+
+ // Return client size less the rebar and status windows
+ int top = rcFrame.top + rcTop.Height() + m_uRibbonHeight;
+ int left = rcFrame.left;
+ int right = rcFrame.right;
+ int bottom = rcFrame.Height() - (rcStatus.Height());
+ if ((bottom <= top) ||( right <= left))
+ top = left = right = bottom = 0;
+
+ CRect rcView(left, top, right, bottom);
+ return rcView;
+ }
+
+ inline void CRibbonFrame::OnCreate()
+ {
+ // OnCreate is called automatically during window creation when a
+ // WM_CREATE message received.
+
+ // Tasks such as setting the icon, creating child windows, or anything
+ // associated with creating windows are normally performed here.
+
+ if (GetWinVersion() >= 2601) // WinVersion >= Windows 7
+ {
+ m_bUseReBar = FALSE; // Don't use rebars
+ m_bUseToolBar = FALSE; // Don't use a toolbar
+
+ CFrame::OnCreate();
+
+ if (CreateRibbon(this))
+ TRACE(_T("Ribbon Created Succesfully\n"));
+ else
+ throw CWinException(_T("Failed to create ribbon"));
+ }
+ else
+ {
+ CFrame::OnCreate();
+ }
+ }
+
+ inline void CRibbonFrame::OnDestroy()
+ {
+ DestroyRibbon();
+ CFrame::OnDestroy();
+ }
+
+ inline STDMETHODIMP CRibbonFrame::OnViewChanged(UINT32 viewId, UI_VIEWTYPE typeId, IUnknown* pView, UI_VIEWVERB verb, INT32 uReasonCode)
+ {
+ UNREFERENCED_PARAMETER(viewId);
+ UNREFERENCED_PARAMETER(uReasonCode);
+
+ HRESULT hr = E_NOTIMPL;
+
+ // Checks to see if the view that was changed was a Ribbon view.
+ if (UI_VIEWTYPE_RIBBON == typeId)
+ {
+ switch (verb)
+ {
+ // The view was newly created.
+ case UI_VIEWVERB_CREATE:
+ hr = S_OK;
+ break;
+
+ // The view has been resized. For the Ribbon view, the application should
+ // call GetHeight to determine the height of the ribbon.
+ case UI_VIEWVERB_SIZE:
+ {
+ IUIRibbon* pRibbon = NULL;
+ UINT uRibbonHeight;
+
+ hr = pView->QueryInterface(IID_PPV_ARGS(&pRibbon));
+ if (SUCCEEDED(hr))
+ {
+ // Call to the framework to determine the desired height of the Ribbon.
+ hr = pRibbon->GetHeight(&uRibbonHeight);
+ SetRibbonHeight(uRibbonHeight);
+ pRibbon->Release();
+
+ RecalcLayout();
+ // Use the ribbon height to position controls in the client area of the window.
+ }
+ }
+ break;
+ // The view was destroyed.
+ case UI_VIEWVERB_DESTROY:
+ hr = S_OK;
+ break;
+ }
+ }
+
+ return hr;
+ }
+
+ inline HRESULT CRibbonFrame::PopulateRibbonRecentItems(__deref_out PROPVARIANT* pvarValue)
+ {
+ LONG iCurrentFile = 0;
+ std::vector FileNames = GetMRUEntries();
+ std::vector::iterator iter;
+ int iFileCount = FileNames.size();
+ HRESULT hr = E_FAIL;
+ SAFEARRAY* psa = SafeArrayCreateVector(VT_UNKNOWN, 0, iFileCount);
+ m_vRecentFiles.clear();
+
+ if (psa != NULL)
+ {
+ for (iter = FileNames.begin(); iter < FileNames.end(); ++iter)
+ {
+ tString strCurrentFile = (*iter);
+ WCHAR wszCurrentFile[MAX_PATH] = {0L};
+ lstrcpynW(wszCurrentFile, T2W(strCurrentFile.c_str()), MAX_PATH);
+
+ CRecentFiles* pRecentFiles = new CRecentFiles(wszCurrentFile);
+ m_vRecentFiles.push_back(RecentFilesPtr(pRecentFiles));
+ hr = SafeArrayPutElement(psa, &iCurrentFile, static_cast(pRecentFiles));
+ ++iCurrentFile;
+ }
+
+ SAFEARRAYBOUND sab = {iCurrentFile,0};
+ SafeArrayRedim(psa, &sab);
+ hr = UIInitPropertyFromIUnknownArray(UI_PKEY_RecentItems, psa, pvarValue);
+
+ SafeArrayDestroy(psa); // Calls release for each element in the array
+ }
+
+ return hr;
+ }
+
+ inline void CRibbonFrame::UpdateMRUMenu()
+ {
+ // Suppress UpdateMRUMenu when ribbon is used
+ if (0 != GetRibbonFramework()) return;
+
+ CFrame::UpdateMRUMenu();
+ }
+
+
+ ////////////////////////////////////////////////////////
+ // Declaration of the nested CRecentFiles class
+ //
+ inline CRibbonFrame::CRecentFiles::CRecentFiles(PWSTR wszFullPath) : m_cRef(1)
+ {
+ SHFILEINFOW sfi;
+ DWORD_PTR dwPtr = NULL;
+ m_wszFullPath[0] = L'\0';
+ m_wszDisplayName[0] = L'\0';
+
+ if (NULL != lstrcpynW(m_wszFullPath, wszFullPath, MAX_PATH))
+ {
+ dwPtr = ::SHGetFileInfoW(wszFullPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_USEFILEATTRIBUTES);
+
+ if (dwPtr != NULL)
+ {
+ lstrcpynW(m_wszDisplayName, sfi.szDisplayName, MAX_PATH);
+ }
+ else // Provide a reasonable fallback.
+ {
+ lstrcpynW(m_wszDisplayName, m_wszFullPath, MAX_PATH);
+ }
+ }
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::AddRef()
+ {
+ return InterlockedIncrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP_(ULONG) CRibbonFrame::CRecentFiles::Release()
+ {
+ return InterlockedDecrement(&m_cRef);
+ }
+
+ inline STDMETHODIMP CRibbonFrame::CRecentFiles::QueryInterface(REFIID iid, void** ppv)
+ {
+ if (!ppv)
+ {
+ return E_POINTER;
+ }
+
+ if (iid == __uuidof(IUnknown))
+ {
+ *ppv = static_cast(this);
+ }
+ else if (iid == __uuidof(IUISimplePropertySet))
+ {
+ *ppv = static_cast(this);
+ }
+ else
+ {
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ // IUISimplePropertySet methods.
+ inline STDMETHODIMP CRibbonFrame::CRecentFiles::GetValue(__in REFPROPERTYKEY key, __out PROPVARIANT *ppropvar)
+ {
+ HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+
+ if (key == UI_PKEY_Label)
+ {
+ hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
+ }
+ else if (key == UI_PKEY_LabelDescription)
+ {
+ hr = UIInitPropertyFromString(key, m_wszDisplayName, ppropvar);
+ }
+
+ return hr;
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_RIBBON_H_
+
diff --git a/external/win32cpp/include/shared_ptr.h b/external/win32cpp/include/shared_ptr.h
new file mode 100644
index 0000000..0d2f8b0
--- /dev/null
+++ b/external/win32cpp/include/shared_ptr.h
@@ -0,0 +1,199 @@
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// This software was developed from code available in the public domain
+// and has no copyright.
+
+
+// About Shared_Ptr:
+// Shared_Ptr wraps a reference-counted smart pointer around a dynamically
+// allocated object. Unlike auto_ptr, the Shared_Ptr can be used as a smart
+// pointer for objects stored in containers like std::vector. Do not use
+// Shared_Ptr (or shared_ptr or auto_ptr) for dynamically allocated arrays.
+// See below for advice on how to wrap dynamically allocated arrays in a
+// vector.
+//
+// The next standard of C++ will also contain a shared_ptr. Some modern
+// compilers already have a shared_ptr available as std::tr1::shared_ptr. If
+// your compiler already provides a shared_ptr, or if you have Boost, you
+// should use that smart pointer instead. This class has been provided for
+// those users who don't have easy access to an "official" shared_ptr.
+// Note that this class is "Shared_Ptr", a slightly different name to the
+// future "shared_ptr" to avoid naming conflicts.
+
+// Advantages of Shared_Ptr (or shared_ptr where available):
+// - Shared_Ptr can be safely copied. This makes then suitable for containers.
+// - Shared_Ptr automatically calls delete for the wrapped pointer when
+// its last copy goes out of scope.
+// - Shared_Ptr simplifies exception safety.
+//
+// Without smart pointers, it can be quite challenging to ensure that every
+// dynamically allocated pointer (i.e. use of new) is deleted in the event of
+// all possible exceptions. In addition to the exceptions we throw ourselves,
+// "new" itself will throw an exception it it fails, as does the STL (Standard
+// Template Library which includes vector and string). Without smart pointers
+// we often need to resort to additional try/catch blocks simply to avoid
+// memory leaks when exceptions occur.
+
+// Examples:
+// Shared_Ptr w1(new CWnd);
+// or
+// Shared_Ptr w1 = new CWnd;
+// or
+// typedef Shared_Ptr CWndPtr;
+// CWndPtr w1 = new CWnd;
+// or
+// typedef Shared_Ptr CWndPtr;
+// CWndPtr w1(new CWnd);
+//
+// And with a vector
+// typedef Shared_Ptr CWndPtr;
+// std::vector MyVector;
+// MyVector.push_back(new CWnd);
+// or
+// typedef Shared_Ptr CWndPtr;
+// CWnd* pWnd = new CWnd;
+// std::vector MyVector;
+// MyVector.push_back(pWnd);
+//
+
+// How to handle dynamically allocated arrays:
+// While we could create a smart pointer for arrays, we don't need to because
+// std::vector already handles this for us. Consider the following example:
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// pTChar = new TCHAR[nLength+1];
+// memset(pTChar, 0, (nLength+1)*sizeof(TCHAR));
+// ::GetWindowText(m_hWnd, m_pTChar, nLength+1);
+// ....
+// delete[] pTChar;
+//
+// This can be improved by using a vector instead of an array
+// int nLength = ::GetWindowTextLength(m_hWnd);
+// std::vector vTChar( nLength+1, _T('\0') );
+// TCHAR* pTCharArray = &vTChar.front();
+// ::GetWindowText(m_hWnd, pTCharArray, nLength+1);
+//
+// This works because the memory in a vector is always contiguous. Note that
+// this is NOT always true of std::string.
+
+
+// Summing up:
+// In my opinion, "naked" pointers for dynamically created objects should be
+// avoided in modern C++ code. That's to say that calls to "new" should be
+// wrapped in some sort of smart pointer wherever possible. This eliminates
+// the possibility of memory leaks (particularly in the event of exceptions).
+// It also elminiates the need for delete in user's code.
+
+#ifndef _WIN32XX_SHARED_PTR_
+#define _WIN32XX_SHARED_PTR_
+
+namespace Win32xx
+{
+
+ template
+ class Shared_Ptr
+ {
+ public:
+ Shared_Ptr() : m_ptr(NULL), m_count(NULL) { }
+ Shared_Ptr(T1 * p) : m_ptr(p), m_count(NULL)
+ {
+ try
+ {
+ if (m_ptr) m_count = new long(0);
+ inc_ref();
+ }
+ // catch the unlikely event of 'new long(0)' throwing an exception
+ catch (const std::bad_alloc&)
+ {
+ delete m_ptr;
+ throw;
+ }
+ }
+ Shared_Ptr(const Shared_Ptr& rhs) : m_ptr(rhs.m_ptr), m_count(rhs.m_count) { inc_ref(); }
+ ~Shared_Ptr()
+ {
+ if(m_count && 0 == dec_ref())
+ {
+ // Note: This code doesn't handle a pointer to an array.
+ // We would need delete[] m_ptr to handle that.
+ delete m_ptr;
+ delete m_count;
+ }
+ }
+
+ T1* get() const { return m_ptr; }
+ long use_count() const { return m_count? *m_count : 0; }
+ bool unique() const { return (m_count && (*m_count == 1)); }
+
+ void swap(Shared_Ptr& rhs)
+ {
+ std::swap(m_ptr, rhs.m_ptr);
+ std::swap(m_count, rhs.m_count);
+ }
+
+ Shared_Ptr& operator=(const Shared_Ptr& rhs)
+ {
+ Shared_Ptr tmp(rhs);
+ this->swap(tmp);
+ return *this;
+ }
+
+ T1* operator->() const
+ {
+ assert(m_ptr);
+ return m_ptr;
+ }
+
+ T1& operator*() const
+ {
+ assert (m_ptr);
+ return *m_ptr;
+ }
+
+ bool operator== (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr == *rhs.m_ptr);
+ }
+
+ bool operator!= (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr != *rhs.m_ptr);
+ }
+
+ bool operator< (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr < *rhs.m_ptr );
+ }
+
+ bool operator> (const Shared_Ptr& rhs) const
+ {
+ return ( *m_ptr > *rhs.m_ptr );
+ }
+
+ private:
+ void inc_ref()
+ {
+ if(m_count)
+ InterlockedIncrement(m_count);
+ }
+
+ int dec_ref()
+ {
+ assert (m_count);
+ return InterlockedDecrement(m_count);
+ }
+
+ T1* m_ptr;
+ long* m_count;
+ };
+
+}
+
+#endif // _WIN32XX_SHARED_PTR_
diff --git a/external/win32cpp/include/socket.h b/external/win32cpp/include/socket.h
new file mode 100644
index 0000000..63a7770
--- /dev/null
+++ b/external/win32cpp/include/socket.h
@@ -0,0 +1,778 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// socket.h
+// Declaration of the CSocket class
+//
+// The CSocket class represents a network socket. It encapsualtes many of
+// the Windows Socket SPI fuctions, providing an object-oriented approach
+// to network programming. After StartEvents is called, CSocket monitors
+// the socket and responds automatically to network events. This event
+// monitoring, for example, automatically calls OnReceive when there is
+// data on the socket to be read, and OnAccept when a server should accept
+// a connection from a client.
+
+// Users of this class should be aware that functions like OnReceive,
+// OnAccept, etc. are called on a different thread from the one CSocket is
+// instanciated on. The thread for these functions needs to respond quickly
+// to other network events, so it shouldn't be delayed. It also doesn't run
+// a message loop, so it can't be used to create windows. For these reasons
+// it might be best to use PostMessage in response to these functions in a
+// windows environment.
+
+// Refer to the network samples for an example of how to use this class to
+// create a TCP client & server, and a UDP client and server.
+
+// To compile programs with CSocket, link with ws3_32.lib for Win32,
+// and ws2.lib for Windows CE. Windows 95 systems will need to install the
+// "Windows Sockets 2.0 for Windows 95". It's available from:
+// http://support.microsoft.com/kb/182108/EN-US/
+
+// For a TCP server, inherit a class from CSocket and override OnAccept, OnDisconnect
+// and OnRecieve. Create one instance of this class and use it as a listening socket.
+// The purpose of the listening socket is to detect connections from clients and accept them.
+// For the listening socket, we do the following:
+// 1) Create the socket.
+// 2) Bind an IP address to the socket.
+// 3) Listen on the socket for incoming connection requests.
+// 4) Use StartNotifyRevents to receive notification of network events.
+// 5) Override OnAccept to accept requests on a newly created data CSocket object.
+// 6) Create a new data socket for each client connection accepted.
+// 7) The server socket uses the 'accept' function to accept an incoming connection
+// from this new data socket.
+
+// The purpose of the data socket is to send data to, and recieve data from the client.
+// There will be one data socket for each client accepted by the server.
+// To use it we do the following:
+// * To recieve data from the client, override OnReceive and use Receive.
+// * To send data to use Send.
+// * OnDisconnect can be used to detect when the client is disconnected.
+
+// For a TCP client, inherit from CSocket and override OnReceive and OnDisconnect.
+// Create an instance of this inherited class, and perform the following steps:
+// 1) Create the socket.
+// 2) Connect to the server.
+// 3) Use StartNotifyRevents to receive notification of network events.
+// We are now ready to send and recieve data from the server.
+// * Use Send to send data to the server.
+// * Override OnReceive and use Recieve to receive data from the server
+// * OnDisconnect can be used to detect when the client is disconnected from the server.
+
+// Notes regarding IPv6 support
+// * IPv6 is supported on Windows Vista and above. Windows XP with SP2 provides
+// "experimental" support, which can be enabled by entering "ipv6 install"
+// at a command prompt.
+// * IPv6 is not supported by all compilters and devlopment environments. In
+// particular, it is not supported by Dev-C++ or Borland 5.5. A modern
+// Platform SDK needs to be added to Visual Studio 6 for it to support IPv6.
+// * IsIPV6Supported returns false if either the operating system or the
+// development environment fails to support IPv6.
+//
+
+#ifndef _WIN32XX_SOCKET_H_
+#define _WIN32XX_SOCKET_H_
+
+
+#include "wincore.h"
+#include
+#include
+#include
+
+
+#define THREAD_TIMEOUT 100
+
+
+namespace Win32xx
+{
+
+ typedef int WINAPI GETADDRINFO(LPCSTR, LPCSTR, const struct addrinfo*, struct addrinfo**);
+ typedef void WINAPI FREEADDRINFO(struct addrinfo*);
+
+ class CSocket
+ {
+ public:
+ CSocket();
+ virtual ~CSocket();
+
+ // Operations
+ virtual void Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen);
+ virtual int Bind(LPCTSTR addr, LPCTSTR port);
+ virtual int Bind(const struct sockaddr* name, int namelen);
+ virtual int Connect(LPCTSTR addr, LPCTSTR port);
+ virtual int Connect(const struct sockaddr* name, int namelen);
+ virtual BOOL Create( int family, int type, int protocol = IPPROTO_IP);
+ virtual void Disconnect();
+ virtual void FreeAddrInfo( struct addrinfo* ai );
+ virtual int GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res);
+ virtual LPCTSTR GetLastError();
+ virtual int ioCtlSocket(long cmd, u_long* argp);
+ virtual BOOL IsIPV6Supported();
+ virtual int Listen(int backlog = SOMAXCONN);
+ virtual int Receive(TCHAR* buf, int len, int flags);
+ virtual int ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen);
+ virtual int Send(LPCTSTR buf, int len, int flags);
+ virtual int SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port);
+ virtual int SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen);
+
+ virtual void StartEvents();
+ virtual void StopEvents();
+
+ // Attributes
+ virtual int GetPeerName(struct sockaddr* name, int* namelen);
+ virtual int GetSockName(struct sockaddr* name, int* namelen);
+ SOCKET& GetSocket() { return m_Socket; }
+ virtual int GetSockOpt(int level, int optname, char* optval, int* optlen);
+ virtual int SetSockOpt(int level, int optname, const char* optval, int optlen);
+
+ // Override these functions to monitor events
+ virtual void OnAccept() {}
+ virtual void OnAddresListChange() {}
+ virtual void OnDisconnect() {}
+ virtual void OnConnect() {}
+ virtual void OnOutOfBand() {}
+ virtual void OnQualityOfService() {}
+ virtual void OnReceive() {}
+ virtual void OnRoutingChange() {}
+ virtual void OnSend() {}
+
+
+
+ // Allow CSocket to be used as a SOCKET
+ operator SOCKET() const {return m_Socket;}
+
+ private:
+ CSocket(const CSocket&); // Disable copy construction
+ CSocket& operator = (const CSocket&); // Disable assignment operator
+ static UINT WINAPI EventThread(LPVOID thread_data);
+
+ tString m_tsErrorMessage;
+ SOCKET m_Socket;
+ HMODULE m_hWS2_32;
+ HANDLE m_hEventThread; // Handle to the thread
+ HANDLE m_StopRequest; // An event to signal the event thread should stop
+ HANDLE m_Stopped; // An event to signal the event thread is stopped
+
+ GETADDRINFO* m_pfnGetAddrInfo; // pointer for the GetAddrInfo function
+ FREEADDRINFO* m_pfnFreeAddrInfo; // pointer for the FreeAddrInfo function
+ };
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline CSocket::CSocket() : m_Socket(INVALID_SOCKET), m_hEventThread(0)
+ {
+ // Initialise the Windows Socket services
+ WSADATA wsaData;
+
+ if (0 != ::WSAStartup(MAKEWORD(2,2), &wsaData))
+ throw CWinException(_T("WSAStartup failed"));
+
+ m_hWS2_32 = ::LoadLibrary(_T("WS2_32.dll"));
+ if (0 == m_hWS2_32)
+ throw CWinException(_T("Failed to load WS2_2.dll"));
+
+ m_pfnGetAddrInfo = (GETADDRINFO*) GetProcAddress(m_hWS2_32, "getaddrinfo");
+ m_pfnFreeAddrInfo = (FREEADDRINFO*) GetProcAddress(m_hWS2_32, "freeaddrinfo");
+
+ m_StopRequest = ::CreateEvent(0, TRUE, FALSE, 0);
+ m_Stopped = ::CreateEvent(0, TRUE, FALSE, 0);
+ }
+
+ inline CSocket::~CSocket()
+ {
+ Disconnect();
+
+ // Close handles
+ ::CloseHandle(m_StopRequest);
+ ::CloseHandle(m_Stopped);
+
+ // Terminate the Windows Socket services
+ ::WSACleanup();
+
+ ::FreeLibrary(m_hWS2_32);
+ }
+
+ inline void CSocket::Accept(CSocket& rClientSock, struct sockaddr* addr, int* addrlen)
+ {
+ // The accept function permits an incoming connection attempt on the socket.
+
+ rClientSock.m_Socket = ::accept(m_Socket, addr, addrlen);
+ if (INVALID_SOCKET == rClientSock.GetSocket())
+ TRACE(_T("Accept failed\n"));
+ }
+
+ inline int CSocket::Bind(LPCTSTR addr, LPCTSTR port)
+ // The bind function associates a local address with the socket.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("GetAddrInfo failed\n"));
+ return RetVal;
+ }
+
+ // Bind the IP address to the listening socket
+ RetVal = ::bind( m_Socket, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("Bind failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocated by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port) );
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::bind( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( 0 != RetVal )
+ TRACE(_T("Bind failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::Bind(const struct sockaddr* name, int namelen)
+ {
+ // The bind function associates a local address with the socket.
+
+ int Result = ::bind (m_Socket, name, namelen);
+ if ( 0 != Result )
+ TRACE(_T("Bind failed\n"));
+ return Result;
+ }
+
+ inline int CSocket::Connect(LPCTSTR addr, LPCTSTR port)
+ // The Connect function establishes a connection to the socket.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("getaddrinfo failed\n"));
+ return SOCKET_ERROR;
+ }
+
+ // Bind the IP address to the listening socket
+ RetVal = Connect( AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("Connect failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocatied by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port) );
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::connect( m_Socket, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( 0 != RetVal )
+ TRACE(_T("Connect failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::Connect(const struct sockaddr* name, int namelen)
+ {
+ // The Connect function establishes a connection to the socket.
+
+ int Result = ::connect( m_Socket, name, namelen );
+ if ( 0 != Result )
+ TRACE(_T("Connect failed\n"));
+
+ return Result;
+ }
+
+ inline BOOL CSocket::Create( int family, int type, int protocol /*= IPPROTO_IP*/)
+ {
+ // Creates the socket
+
+ // Valid values:
+ // family: AF_INET or AF_INET6
+ // type: SOCK_DGRAM, SOCK_SEQPACKET, SOCK_STREAM, SOCK_RAW
+ // protocol: IPPROTO_IP, IPPROTO_TCP, IPPROTO_UDP, IPPROTO_RAW, IPPROTO_ICMP, IPPROTO_ICMPV6
+
+ m_Socket = socket(family, type, protocol);
+ if(m_Socket == INVALID_SOCKET)
+ {
+ TRACE(_T("Failed to create socket\n"));
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ inline void CSocket::Disconnect()
+ {
+ ::shutdown(m_Socket, SD_BOTH);
+ StopEvents();
+ ::closesocket(m_Socket);
+ m_Socket = INVALID_SOCKET;
+ }
+
+ inline UINT WINAPI CSocket::EventThread(LPVOID thread_data)
+ {
+ // These are the possible network event notifications:
+ // FD_READ Notification of readiness for reading.
+ // FD_WRITE Motification of readiness for writing.
+ // FD_OOB Notification of the arrival of Out Of Band data.
+ // FD_ACCEPT Notification of incoming connections.
+ // FD_CONNECT Notification of completed connection or multipoint join operation.
+ // FD_CLOSE Notification of socket closure.
+ // FD_QOS Notification of socket Quality Of Service changes
+ // FD_ROUTING_INTERFACE_CHANGE Notification of routing interface changes for the specified destination.
+ // FD_ADDRESS_LIST_CHANGE Notification of local address list changes for the address family of the socket.
+
+ WSANETWORKEVENTS NetworkEvents;
+ CSocket* pSocket = (CSocket*)thread_data;
+ SOCKET sClient = pSocket->m_Socket;
+
+ WSAEVENT AllEvents[2];
+ AllEvents[0] = ::WSACreateEvent();
+ AllEvents[1] = (WSAEVENT)pSocket->m_StopRequest;
+ long Events = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE |
+ FD_QOS | FD_ROUTING_INTERFACE_CHANGE | FD_ADDRESS_LIST_CHANGE;
+
+ // Associate the network event object (hNetworkEvents) with the
+ // specified network events (Events) on socket sClient.
+ if( SOCKET_ERROR == WSAEventSelect(sClient, AllEvents[0], Events))
+ {
+ TRACE(_T("Error in Event Select\n"));
+ ::SetEvent(pSocket->m_Stopped);
+ ::WSACloseEvent(AllEvents[0]);
+ return 0;
+ }
+
+ // loop until the stop event is set
+ for (;;) // infinite loop
+ {
+ // Wait 100 ms for a network event
+ DWORD dwResult = ::WSAWaitForMultipleEvents(2, AllEvents, FALSE, THREAD_TIMEOUT, FALSE);
+
+ // Check event for stop thread
+ if(::WaitForSingleObject(pSocket->m_StopRequest, 0) == WAIT_OBJECT_0)
+ {
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ if (WSA_WAIT_FAILED == dwResult)
+ {
+ TRACE(_T("WSAWaitForMultipleEvents failed\n"));
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ // Proceed if a network event occurred
+ if (WSA_WAIT_TIMEOUT != dwResult)
+ {
+
+ if ( SOCKET_ERROR == ::WSAEnumNetworkEvents(sClient, AllEvents[0], &NetworkEvents) )
+ {
+ TRACE(_T("WSAEnumNetworkEvents failed\n"));
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+
+ if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
+ pSocket->OnAccept();
+
+ if (NetworkEvents.lNetworkEvents & FD_READ)
+ pSocket->OnReceive();
+
+ if (NetworkEvents.lNetworkEvents & FD_WRITE)
+ pSocket->OnSend();
+
+ if (NetworkEvents.lNetworkEvents & FD_OOB)
+ pSocket->OnOutOfBand();
+
+ if (NetworkEvents.lNetworkEvents & FD_QOS)
+ pSocket->OnQualityOfService();
+
+ if (NetworkEvents.lNetworkEvents & FD_CONNECT)
+ pSocket->OnConnect();
+
+ if (NetworkEvents.lNetworkEvents & FD_ROUTING_INTERFACE_CHANGE)
+ pSocket->OnRoutingChange();
+
+ if (NetworkEvents.lNetworkEvents & FD_ADDRESS_LIST_CHANGE)
+ pSocket->OnAddresListChange();
+
+ if (NetworkEvents.lNetworkEvents & FD_CLOSE)
+ {
+ ::shutdown(sClient, SD_BOTH);
+ ::closesocket(sClient);
+ pSocket->OnDisconnect();
+ ::WSACloseEvent(AllEvents[0]);
+ ::SetEvent(pSocket->m_Stopped);
+ return 0;
+ }
+ }
+ }
+ }
+
+ inline int CSocket::GetAddrInfo( LPCTSTR nodename, LPCTSTR servname, const struct addrinfo* hints, struct addrinfo** res)
+ {
+
+#ifdef GetAddrInfo
+
+ std::string sNodeName = T2A(nodename);
+ std::string sServName = T2A(servname);
+ return (*m_pfnGetAddrInfo)(sNodeName.c_str(), sServName.c_str(), hints, res);
+
+#else
+
+ UNREFERENCED_PARAMETER(nodename);
+ UNREFERENCED_PARAMETER(servname);
+ UNREFERENCED_PARAMETER(hints);
+ UNREFERENCED_PARAMETER(res);
+
+ throw CWinException(_T("getaddrinfo is not supported"));
+
+#endif
+
+ }
+
+ inline LPCTSTR CSocket::GetLastError()
+ {
+ // Retrieves the most recent network error.
+
+ int ErrorCode = WSAGetLastError();
+ LPTSTR Message = NULL;
+ m_tsErrorMessage = _T("");
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR)&Message, 1024, NULL);
+
+ if (Message)
+ {
+ m_tsErrorMessage = Message;
+ ::LocalFree(Message);
+ }
+
+ return m_tsErrorMessage.c_str();
+ }
+
+ inline int CSocket::GetPeerName(struct sockaddr* name, int* namelen)
+ {
+ int Result = ::getpeername(m_Socket, name, namelen);
+ if (0 != Result)
+ TRACE(_T("GetPeerName failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::GetSockName(struct sockaddr* name, int* namelen)
+ {
+ int Result = ::getsockname(m_Socket, name, namelen);
+ if (0 != Result)
+ TRACE(_T("GetSockName Failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::GetSockOpt(int level, int optname, char* optval, int* optlen)
+ {
+ int Result = ::getsockopt(m_Socket, level, optname, optval, optlen);
+ if (0 != Result)
+ TRACE(_T("GetSockOpt Failed\n"));
+
+ return Result;
+ }
+
+ inline void CSocket::FreeAddrInfo( struct addrinfo* ai )
+ {
+
+#ifdef GetAddrInfo
+
+ (*m_pfnFreeAddrInfo)(ai);
+
+#else
+
+ UNREFERENCED_PARAMETER(ai);
+
+ throw CWinException(_T("getaddrinfo is not supported"));
+
+#endif
+
+ }
+
+ inline int CSocket::ioCtlSocket(long cmd, u_long* argp)
+ {
+ int Result = ::ioctlsocket(m_Socket, cmd, argp);
+ if (0 != Result)
+ TRACE(_T("ioCtlSocket Failed\n"));
+
+ return Result;
+ }
+
+ inline BOOL CSocket::IsIPV6Supported()
+ {
+ BOOL IsIPV6Supported = FALSE;
+
+#ifdef GetAddrInfo
+
+ if (m_pfnGetAddrInfo != 0 && m_pfnFreeAddrInfo != 0)
+ IsIPV6Supported = TRUE;
+
+#endif
+
+ return IsIPV6Supported;
+ }
+
+ inline int CSocket::Listen(int backlog /*= SOMAXCONN*/)
+ {
+ int Result = ::listen(m_Socket, backlog);
+ if (0 != Result)
+ TRACE(_T("Listen Failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::Receive(TCHAR* buf, int len, int flags)
+ {
+ std::vector vChar(len+1, '\0');
+ char* pCharArray = &vChar.front();
+ int Result = ::recv(m_Socket, pCharArray, len, flags);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("Receive failed\n"));
+
+ lstrcpyn(buf, A2T(pCharArray), len);
+
+ return Result;
+ }
+
+ inline int CSocket::ReceiveFrom(TCHAR* buf, int len, int flags, struct sockaddr* from, int* fromlen)
+ //The ReceiveFrom function receives a datagram and stores the source address.
+ {
+ std::vector vChar(len+1, '\0');
+ char* pCharArray = &vChar.front();
+ int Result = ::recvfrom(m_Socket, pCharArray, len, flags, from, fromlen);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("ReceiveFrom failed\n"));
+
+ lstrcpyn(buf, A2T(pCharArray), len);
+
+ return Result;
+ }
+
+ inline int CSocket::Send(LPCTSTR buf, int len, int flags)
+ {
+ int Result = ::send(m_Socket, T2A(buf), len, flags);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("Send failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::SendTo(LPCTSTR send, int len, int flags, LPCTSTR addr, LPCTSTR port)
+ // The sendto function sends data to a specific destination.
+ {
+ int RetVal = 0;
+
+ if (IsIPV6Supported())
+ {
+
+#ifdef GetAddrInfo // Skip the following code block for older development environments
+
+ ADDRINFO Hints= {0};
+ Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
+ ADDRINFO *AddrInfo;
+
+ RetVal = GetAddrInfo(addr, port, &Hints, &AddrInfo);
+ if (RetVal != 0)
+ {
+ TRACE( _T("GetAddrInfo failed\n"));
+ return SOCKET_ERROR;
+ }
+
+ RetVal = ::sendto(m_Socket, T2A(send), len, flags, AddrInfo->ai_addr, (int)AddrInfo->ai_addrlen );
+ if ( RetVal == SOCKET_ERROR )
+ {
+ TRACE(_T("SendTo failed\n"));
+ return RetVal;
+ }
+
+ // Free the address information allocatied by GetAddrInfo
+ FreeAddrInfo(AddrInfo);
+
+#endif
+
+ }
+ else
+ {
+ sockaddr_in clientService;
+ clientService.sin_family = AF_INET;
+ clientService.sin_addr.s_addr = inet_addr( T2A(addr) );
+ int nPort = -1;
+ nPort = atoi( T2A(port));
+ if (-1 == nPort)
+ {
+ TRACE(_T("Invalid port number\n"));
+ return SOCKET_ERROR;
+ }
+ clientService.sin_port = htons( (u_short)nPort );
+
+ RetVal = ::sendto( m_Socket, T2A(send), len, flags, (SOCKADDR*) &clientService, sizeof(clientService) );
+ if ( SOCKET_ERROR != RetVal )
+ TRACE(_T("SendTo failed\n"));
+ }
+
+ return RetVal;
+ }
+
+ inline int CSocket::SendTo(LPCTSTR buf, int len, int flags, const struct sockaddr* to, int tolen)
+ // The sendto function sends data to a specific destination.
+ {
+ int Result = ::sendto(m_Socket, T2A(buf), len, flags, to, tolen);
+ if (SOCKET_ERROR == Result)
+ TRACE(_T("SendTo failed\n"));
+
+ return Result;
+ }
+
+ inline int CSocket::SetSockOpt(int level, int optname, const char* optval, int optlen)
+ {
+ int Result = ::setsockopt(m_Socket, level, optname, optval, optlen);
+ if (0 != Result)
+ TRACE(_T("SetSockOpt failed\n"));
+
+ return Result;
+ }
+
+ inline void CSocket::StartEvents()
+ {
+ // This function starts the thread which monitors the socket for events.
+ StopEvents(); // Ensure the thread isn't already running
+ UINT ThreadID; // a return variable required for Win95, Win98, WinME
+ m_hEventThread = (HANDLE)::_beginthreadex(NULL, 0, CSocket::EventThread, (LPVOID) this, 0, &ThreadID);
+ }
+
+ inline void CSocket::StopEvents()
+ {
+ // Terminates the event thread gracefully (if possible)
+ if (m_hEventThread)
+ {
+ ::SetThreadPriority(m_hEventThread, THREAD_PRIORITY_HIGHEST);
+ ::SetEvent(m_StopRequest);
+
+ for (;;) // infinite loop
+ {
+ // wait for the Thread stopping event to be set
+ if ( WAIT_TIMEOUT == ::WaitForSingleObject(m_Stopped, THREAD_TIMEOUT * 10) )
+ {
+ // Note: An excessive delay in processing any of the notification functions
+ // can cause us to get here. (Yes one second is an excessive delay. Its a bug!)
+ TRACE(_T("*** Error: Event Thread won't die ***\n") );
+ }
+ else break;
+ }
+
+ ::CloseHandle(m_hEventThread);
+ m_hEventThread = 0;
+ }
+
+ ::ResetEvent(m_StopRequest);
+ ::ResetEvent(m_Stopped);
+ }
+}
+
+
+#endif // #ifndef _WIN32XX_SOCKET_H_
+
diff --git a/external/win32cpp/include/statusbar.h b/external/win32cpp/include/statusbar.h
new file mode 100644
index 0000000..ad9a007
--- /dev/null
+++ b/external/win32cpp/include/statusbar.h
@@ -0,0 +1,226 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_STATUSBAR_H_
+#define _WIN32XX_STATUSBAR_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Declaration of the CStatusBar class
+ //
+ class CStatusBar : public CWnd
+ {
+ public:
+ CStatusBar();
+ virtual ~CStatusBar() {}
+
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ // Attributes
+ int GetParts();
+ HICON GetPartIcon(int iPart);
+ CRect GetPartRect(int iPart);
+ tString GetPartText(int iPart) const;
+ BOOL IsSimple();
+ BOOL SetPartIcon(int iPart, HICON hIcon);
+ BOOL SetPartText(int iPart, LPCTSTR szText, UINT Style = 0) const;
+ BOOL SetPartWidth(int iPart, int iWidth) const;
+
+ // Operations
+ CStatusBar(const CStatusBar&); // Disable copy construction
+ CStatusBar& operator = (const CStatusBar&); // Disable assignment operator
+
+ BOOL CreateParts(int iParts, const int iPaneWidths[]) const;
+ void SetSimple(BOOL fSimple = TRUE);
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Definitions for the CStatusBar class
+ //
+ inline CStatusBar::CStatusBar()
+ {
+ }
+
+ inline BOOL CStatusBar::CreateParts(int iParts, const int iPaneWidths[]) const
+ // Sets the number of parts in a status window and the coordinate of the right edge of each part.
+ // If an element of iPaneWidths is -1, the right edge of the corresponding part extends
+ // to the border of the window
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(iParts <= 256);
+
+ return (BOOL)SendMessage(SB_SETPARTS, iParts, (LPARAM)iPaneWidths);
+ }
+
+ inline int CStatusBar::GetParts()
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(SB_GETPARTS, 0L, 0L);
+ }
+
+ inline HICON CStatusBar::GetPartIcon(int iPart)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(SB_GETICON, (WPARAM)iPart, 0L);
+ }
+
+ inline CRect CStatusBar::GetPartRect(int iPart)
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CRect rc;
+ SendMessage(SB_GETRECT, (WPARAM)iPart, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline tString CStatusBar::GetPartText(int iPart) const
+ {
+ assert(::IsWindow(m_hWnd));
+ tString PaneText;
+
+ // Get size of Text array
+ int iChars = LOWORD (SendMessage(SB_GETTEXTLENGTH, iPart, 0L));
+
+ std::vector Text( iChars +1, _T('\0') );
+ TCHAR* pTextArray = &Text[0];
+
+ SendMessage(SB_GETTEXT, iPart, (LPARAM)pTextArray);
+ PaneText = pTextArray;
+ return PaneText;
+ }
+
+ inline BOOL CStatusBar::IsSimple()
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(SB_ISSIMPLE, 0L, 0L);
+ }
+
+ inline void CStatusBar::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CCS_BOTTOM | SBARS_SIZEGRIP;
+ }
+
+ inline void CStatusBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = STATUSCLASSNAME;
+ }
+
+ inline BOOL CStatusBar::SetPartText(int iPart, LPCTSTR szText, UINT Style) const
+ // Available Styles: Combinations of ...
+ //0 The text is drawn with a border to appear lower than the plane of the window.
+ //SBT_NOBORDERS The text is drawn without borders.
+ //SBT_OWNERDRAW The text is drawn by the parent window.
+ //SBT_POPOUT The text is drawn with a border to appear higher than the plane of the window.
+ //SBT_RTLREADING The text will be displayed in the opposite direction to the text in the parent window.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ BOOL bResult = FALSE;
+ if (SendMessage(SB_GETPARTS, 0L, 0L) >= iPart)
+ bResult = (BOOL)SendMessage(SB_SETTEXT, iPart | Style, (LPARAM)szText);
+
+ return bResult;
+ }
+
+ inline BOOL CStatusBar::SetPartIcon(int iPart, HICON hIcon)
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(SB_SETICON, (WPARAM)iPart, (LPARAM) hIcon);
+ }
+
+ inline BOOL CStatusBar::SetPartWidth(int iPart, int iWidth) const
+ {
+ // This changes the width of an existing pane, or creates a new pane
+ // with the specified width.
+ // A width of -1 for the last part sets the width to the border of the window.
+
+ assert(::IsWindow(m_hWnd));
+ assert(iPart >= 0 && iPart <= 255);
+
+ // Fill the PartWidths vector with the current width of the statusbar parts
+ int PartsCount = (int)SendMessage(SB_GETPARTS, 0L, 0L);
+ std::vector PartWidths(PartsCount, 0);
+ int* pPartWidthArray = &PartWidths[0];
+ SendMessage(SB_GETPARTS, PartsCount, (LPARAM)pPartWidthArray);
+
+ // Fill the NewPartWidths vector with the new width of the statusbar parts
+ int NewPartsCount = MAX(iPart+1, PartsCount);
+ std::vector NewPartWidths(NewPartsCount, 0);;
+ NewPartWidths = PartWidths;
+ int* pNewPartWidthArray = &NewPartWidths[0];
+
+ if (0 == iPart)
+ pNewPartWidthArray[iPart] = iWidth;
+ else
+ {
+ if (iWidth >= 0)
+ pNewPartWidthArray[iPart] = pNewPartWidthArray[iPart -1] + iWidth;
+ else
+ pNewPartWidthArray[iPart] = -1;
+ }
+
+ // Set the statusbar parts with our new parts count and part widths
+ BOOL bResult = (BOOL)SendMessage(SB_SETPARTS, NewPartsCount, (LPARAM)pNewPartWidthArray);
+
+ return bResult;
+ }
+
+ inline void CStatusBar::SetSimple(BOOL fSimple /* = TRUE*/)
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(SB_SIMPLE, (WPARAM)fSimple, 0L);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_STATUSBAR_H_
diff --git a/external/win32cpp/include/stdcontrols.h b/external/win32cpp/include/stdcontrols.h
new file mode 100644
index 0000000..b362f07
--- /dev/null
+++ b/external/win32cpp/include/stdcontrols.h
@@ -0,0 +1,1000 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// stdcontrols.h
+// Declaration of the CButton, CEdit, CListBox and CStatic classes
+
+// The Button, Edit, ListBox and Static controls are often referred to
+// as "standard controls". These set of older controls were originally
+// developed for Win16 operating systems (Windows 3.1 and 3.11). They use an
+// older form of notification, and send their notifications via a WM_COMMAND
+// message. Newer controls send their notifications via a WM_NOTIFY message.
+
+
+#ifndef _WIN32XX_STDCONTROLS_H_
+#define _WIN32XX_STDCONTROLS_H_
+
+#include "wincore.h"
+
+
+namespace Win32xx
+{
+ class CButton : public CWnd
+ {
+ public:
+ CButton() {}
+ virtual ~CButton() {}
+
+ // Attributes
+ HBITMAP GetBitmap() const;
+ UINT GetButtonStyle() const;
+ int GetCheck() const;
+ HCURSOR GetCursor() const;
+ HICON GetIcon() const;
+ UINT GetState() const;
+ HBITMAP SetBitmap(HBITMAP hBitmap) const;
+ void SetButtonStyle(DWORD dwStyle, BOOL bRedraw) const;
+ void SetCheck(int nCheckState) const;
+ HCURSOR SetCursor(HCURSOR hCursor) const;
+ HICON SetIcon(HICON hIcon) const;
+ void SetState(BOOL bHighlight) const;
+
+ protected:
+ // Overridables
+ virtual void PreCreate(CREATESTRUCT& cs);
+ };
+
+ class CEdit : public CWnd
+ {
+ public:
+ // Construction
+ CEdit() {}
+ virtual ~CEdit() {}
+
+ // Attributes
+ BOOL CanUndo() const;
+ int CharFromPos(CPoint pt) const;
+ int GetFirstVisibleLine() const;
+ HLOCAL GetHandle() const;
+ UINT GetLimitText() const;
+ int GetLine(int nIndex, LPTSTR lpszBuffer) const;
+ int GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const;
+ int GetLineCount() const;
+ DWORD GetMargins() const;
+ BOOL GetModify() const;
+ TCHAR GetPasswordChar() const;
+ void GetRect(LPRECT lpRect) const;
+ void GetSel(int& nStartChar, int& nEndChar) const;
+ DWORD GetSel() const;
+ CPoint PosFromChar(UINT nChar) const;
+ void SetHandle(HLOCAL hBuffer) const;
+ void SetLimitText(UINT nMax) const;
+ void SetMargins(UINT nLeft, UINT nRight) const;
+ void SetModify(BOOL bModified = TRUE) const;
+
+ // Operations
+ void EmptyUndoBuffer() const;
+ BOOL FmtLines(BOOL bAddEOL) const;
+ void LimitText(int nChars = 0) const;
+ int LineFromChar(int nIndex = -1) const;
+ int LineIndex(int nLine = -1) const;
+ int LineLength(int nLine = -1) const;
+ void LineScroll(int nLines, int nChars = 0) const;
+ void ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo) const;
+ void SetPasswordChar(TCHAR ch) const;
+ BOOL SetReadOnly(BOOL bReadOnly = TRUE) const;
+ void SetRect(LPCRECT lpRect) const;
+ void SetRectNP(LPCRECT lpRect) const;
+ void SetSel(DWORD dwSelection, BOOL bNoScroll) const;
+ void SetSel(int nStartChar, int nEndChar, BOOL bNoScroll) const;
+ BOOL SetTabStops(int nTabStops, LPINT rgTabStops) const;
+ BOOL SetTabStops() const;
+ BOOL SetTabStops(const int& cxEachStop) const;
+
+ //Clipboard Operations
+ void Clear() const;
+ void Copy() const;
+ void Cut() const;
+ void Paste() const;
+ void Undo() const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+ class CListBox : public CWnd
+ {
+ public:
+ CListBox() {}
+ virtual ~CListBox() {}
+
+ // General Operations
+ int GetCount() const;
+ int GetHorizontalExtent() const;
+ DWORD GetItemData(int nIndex) const;
+ void* GetItemDataPtr(int nIndex) const;
+ int GetItemHeight(int nIndex) const;
+ int GetItemRect(int nIndex, LPRECT lpRect) const;
+ LCID GetLocale() const;
+ int GetSel(int nIndex) const;
+ int GetText(int nIndex, LPTSTR lpszBuffer) const;
+ int GetTextLen(int nIndex) const;
+ int GetTopIndex() const;
+ UINT ItemFromPoint(CPoint pt, BOOL& bOutside ) const;
+ void SetColumnWidth(int cxWidth) const;
+ void SetHorizontalExtent(int cxExtent) const;
+ int SetItemData(int nIndex, DWORD dwItemData) const;
+ int SetItemDataPtr(int nIndex, void* pData) const;
+ int SetItemHeight(int nIndex, UINT cyItemHeight) const;
+ LCID SetLocale(LCID nNewLocale) const;
+ BOOL SetTabStops(int nTabStops, LPINT rgTabStops) const;
+ void SetTabStops() const;
+ BOOL SetTabStops(const int& cxEachStop) const;
+ int SetTopIndex(int nIndex) const;
+
+ // Single-Selection Operations
+ int GetCurSel() const;
+ int SetCurSel(int nSelect) const;
+
+ // Multiple-Selection Operations
+ int GetAnchorIndex() const;
+ int GetCaretIndex() const;
+ int GetSelCount() const;
+ int GetSelItems(int nMaxItems, LPINT rgIndex) const;
+ int SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) const;
+ void SetAnchorIndex(int nIndex) const;
+ int SetCaretIndex(int nIndex, BOOL bScroll) const;
+ int SetSel(int nIndex, BOOL bSelect) const;
+
+ // String Operations
+ int AddString(LPCTSTR lpszItem) const;
+ int DeleteString(UINT nIndex) const;
+ int Dir(UINT attr, LPCTSTR lpszWildCard) const;
+ int FindString(int nStartAfter, LPCTSTR lpszItem) const;
+ int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const;
+ int InsertString(int nIndex, LPCTSTR lpszItem) const;
+ void ResetContent() const;
+ int SelectString(int nStartAfter, LPCTSTR lpszItem) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ };
+
+ class CStatic : public CWnd
+ {
+ public:
+ CStatic() {}
+ virtual ~CStatic() {}
+
+ // Operations
+ HBITMAP GetBitmap() const;
+ HCURSOR GetCursor() const;
+ HENHMETAFILE GetEnhMetaFile() const;
+ HICON GetIcon() const;
+ HBITMAP SetBitmap(HBITMAP hBitmap) const;
+ HCURSOR SetCursor(HCURSOR hCursor) const;
+ HENHMETAFILE SetEnhMetaFile(HENHMETAFILE hMetaFile) const;
+ HICON SetIcon(HICON hIcon) const;
+
+ protected:
+ // Overridables
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////////
+ // Definitions for the CButton class
+ //
+ inline HBITMAP CButton::GetBitmap() const
+ // returns the handle to the bitmap associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(BM_GETIMAGE, IMAGE_BITMAP, 0);
+ }
+
+ inline UINT CButton::GetButtonStyle() const
+ // returns the style of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)GetWindowLongPtr(GWL_STYLE) & 0xff;
+ }
+
+ inline int CButton::GetCheck() const
+ // returns the check state of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(BM_GETCHECK, 0, 0);
+ }
+
+ inline HCURSOR CButton::GetCursor() const
+ // returns the handle to the cursor associated withe the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)::SendMessage(m_hWnd, BM_GETIMAGE, IMAGE_CURSOR, 0L);
+ }
+
+ inline HICON CButton::GetIcon() const
+ // returns the handle to the icon associated withe the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(BM_GETIMAGE, IMAGE_ICON, 0);
+ }
+
+ inline UINT CButton::GetState() const
+ // returns the state of the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(BM_GETSTATE, 0, 0);
+ }
+
+ inline HBITMAP CButton::SetBitmap(HBITMAP hBitmap) const
+ // sets the bitmap associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
+ }
+
+ inline void CButton::SetButtonStyle(DWORD dwStyle, BOOL bRedraw) const
+ // sets the button style
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETSTYLE, dwStyle, bRedraw);
+ }
+
+ inline void CButton::SetCheck(int nCheckState) const
+ // sets the button check state
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETCHECK, nCheckState, 0);
+ }
+
+ inline HCURSOR CButton::SetCursor(HCURSOR hCursor) const
+ // sets the cursor associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
+ }
+
+ inline HICON CButton::SetIcon(HICON hIcon) const
+ // sets the icon associated with the button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage( BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ }
+
+ inline void CButton::SetState(BOOL bHighlight) const
+ // sets the button state
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(BM_SETSTATE, bHighlight, 0);
+ }
+
+ inline void CButton::PreCreate(CREATESTRUCT& cs)
+ {
+ cs.lpszClass = _T("Button");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CEdit class
+ //
+ inline BOOL CEdit::CanUndo() const
+ // Returns TRUE if the edit control operation can be undone.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_CANUNDO, 0, 0);
+ }
+
+ inline int CEdit::CharFromPos(CPoint pt) const
+ // Returns the character index and line index of the character nearest the specified point.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_CHARFROMPOS, 0, MAKELPARAM(pt.x, pt.y));
+ }
+
+ inline int CEdit::GetFirstVisibleLine() const
+ // Returns the zero-based index of the first visible character in a single-line edit control
+ // or the zero-based index of the uppermost visible line in a multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_GETFIRSTVISIBLELINE, 0, 0);
+ }
+
+ inline HLOCAL CEdit::GetHandle() const
+ // Returns a handle identifying the buffer containing the multiline edit control's text.
+ // It is not processed by single-line edit controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HLOCAL)SendMessage(EM_GETHANDLE, 0, 0);
+ }
+
+ inline UINT CEdit::GetLimitText() const
+ // Returns the current text limit, in characters.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(EM_GETLIMITTEXT, 0, 0);
+ }
+
+ inline int CEdit::GetLine(int nIndex, LPTSTR lpszBuffer) const
+ // Copies characters to a buffer and returns the number of characters copied.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CEdit::GetLine(int nIndex, LPTSTR lpszBuffer, int nMaxLength) const
+ // Copies characters to a buffer and returns the number of characters copied.
+ {
+ assert(::IsWindow(m_hWnd));
+ *(LPWORD)lpszBuffer = (WORD)nMaxLength;
+ return (int)SendMessage(EM_GETLINE, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CEdit::GetLineCount() const
+ // Returns the number of lines in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_GETLINECOUNT, 0, 0);
+ }
+
+ inline DWORD CEdit::GetMargins() const
+ // Returns the widths of the left and right margins.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(EM_GETMARGINS, 0, 0);
+ }
+
+ inline BOOL CEdit::GetModify() const
+ // Returns a flag indicating whether the content of an edit control has been modified.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_GETMODIFY, 0, 0);
+ }
+
+ inline TCHAR CEdit::GetPasswordChar() const
+ // Returns the character that edit controls use in conjunction with the ES_PASSWORD style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (TCHAR)SendMessage(EM_GETPASSWORDCHAR, 0, 0);
+ }
+
+ inline void CEdit::GetRect(LPRECT lpRect) const
+ // Returns the coordinates of the formatting rectangle in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_GETRECT, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::GetSel(int& nStartChar, int& nEndChar) const
+ // Returns the starting and ending character positions of the current selection in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_GETSEL, (WPARAM)&nStartChar,(LPARAM)&nEndChar);
+ }
+
+ inline DWORD CEdit::GetSel() const
+ // Returns the starting and ending character positions of the current selection in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(EM_GETSEL, 0, 0);
+ }
+
+ inline CPoint CEdit::PosFromChar(UINT nChar) const
+ // Returns the client coordinates of the specified character.
+ {
+ assert(::IsWindow(m_hWnd));
+ return CPoint( (DWORD)SendMessage(EM_POSFROMCHAR, nChar, 0));
+ }
+
+ inline void CEdit::SetHandle(HLOCAL hBuffer) const
+ // Sets a handle to the memory used as a text buffer, empties the undo buffer,
+ // resets the scroll positions to zero, and redraws the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETHANDLE, (WPARAM)hBuffer, 0);
+ }
+
+ inline void CEdit::SetLimitText(UINT nMax) const
+ // Sets the maximum number of characters the user may enter in the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETLIMITTEXT, (WPARAM)nMax, 0);
+ }
+
+ inline void CEdit::SetMargins(UINT nLeft, UINT nRight) const
+ // Sets the widths of the left and right margins, and redraws the edit control to reflect the new margins.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG(nLeft, nRight));
+ }
+
+ inline void CEdit::SetModify(BOOL bModified) const
+ // Sets or clears the modification flag to indicate whether the edit control has been modified.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETMODIFY, bModified, 0);
+ }
+
+ inline void CEdit::EmptyUndoBuffer() const
+ // Empties the undo buffer and sets the undo flag retrieved by the EM_CANUNDO message to FALSE.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_EMPTYUNDOBUFFER, 0, 0);
+ }
+
+ inline BOOL CEdit::FmtLines(BOOL bAddEOL) const
+ // Adds or removes soft line-break characters (two carriage returns and a line feed) to the ends of wrapped lines
+ // in a multiline edit control. It is not processed by single-line edit controls.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_FMTLINES, bAddEOL, 0);
+ }
+
+ inline void CEdit::LimitText(int nChars) const
+ // Sets the text limit of an edit control. The text limit is the maximum amount of text, in TCHARs,
+ // that the user can type into the edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_LIMITTEXT, nChars, 0);
+ }
+
+ inline int CEdit::LineFromChar(int nIndex) const
+ // Returns the zero-based number of the line in a multiline edit control that contains a specified character index.
+ // This message is the reverse of the EM_LINEINDEX message.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINEFROMCHAR, (WPARAM)nIndex, 0);
+ }
+
+ inline int CEdit::LineIndex(int nLine) const
+ // Returns the character of a line in a multiline edit control.
+ // This message is the reverse of the EM_LINEFROMCHAR message
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINEINDEX, (WPARAM)nLine, 0);
+ }
+
+ inline int CEdit::LineLength(int nLine) const
+ // Returns the length, in characters, of a single-line edit control. In a multiline edit control,
+ // returns the length, in characters, of a specified line.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(EM_LINELENGTH, (WPARAM)nLine, 0);
+ }
+
+ inline void CEdit::LineScroll(int nLines, int nChars) const
+ // Scrolls the text vertically in a single-line edit control or horizontally in a multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_LINESCROLL, (WPARAM)nChars, (LPARAM)nLines);
+ }
+
+ inline void CEdit::ReplaceSel(LPCTSTR lpszNewText, BOOL bCanUndo) const
+ // Replaces the current selection with the text in an application-supplied buffer, sends the parent window
+ // EN_UPDATE and EN_CHANGE messages, and updates the undo buffer.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_REPLACESEL, (WPARAM) bCanUndo, (LPARAM)lpszNewText);
+ }
+
+ inline void CEdit::SetPasswordChar(TCHAR ch) const
+ // Defines the character that edit controls use in conjunction with the ES_PASSWORD style.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETPASSWORDCHAR, ch, 0);
+ }
+
+ inline BOOL CEdit::SetReadOnly(BOOL bReadOnly) const
+ // Sets or removes the read-only style (ES_READONLY) in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_SETREADONLY, bReadOnly, 0);
+ }
+
+ inline void CEdit::SetRect(LPCRECT lpRect) const
+ // Sets the formatting rectangle for the multiline edit control and redraws the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETRECT, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::SetRectNP(LPCRECT lpRect) const
+ // Sets the formatting rectangle for the multiline edit control but does not redraw the window.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETRECTNP, 0, (LPARAM)lpRect);
+ }
+
+ inline void CEdit::SetSel(DWORD dwSelection, BOOL bNoScroll) const
+ // Selects a range of characters in the edit control by setting the starting and ending positions to be selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_SETSEL, LOWORD(dwSelection), HIWORD(dwSelection));
+ if (!bNoScroll)
+ SendMessage(EM_SCROLLCARET, 0, 0);
+ }
+
+ inline void CEdit::SetSel(int nStartChar, int nEndChar, BOOL bNoScroll) const
+ // Selects a range of characters in the edit control by setting the starting and ending positions to be selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(m_hWnd, EM_SETSEL, nStartChar, nEndChar);
+ if (!bNoScroll)
+ SendMessage(EM_SCROLLCARET, 0, 0);
+ }
+
+ inline BOOL CEdit::SetTabStops(int nTabStops, LPINT rgTabStops) const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)::SendMessage(m_hWnd, EM_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+ }
+
+ inline BOOL CEdit::SetTabStops() const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage( EM_SETTABSTOPS, 0, 0);
+ }
+
+ inline BOOL CEdit::SetTabStops(const int& cxEachStop) const
+ // Sets tab-stop positions in the multiline edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(EM_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+ }
+
+ inline void CEdit::Clear() const
+ // Clears the current selection, if any, in an edit control.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_CLEAR, 0, 0);
+ }
+
+ inline void CEdit::Copy() const
+ // Copies text to the clipboard unless the style is ES_PASSWORD, in which case the message returns zero.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_COPY, 0, 0);
+ }
+
+ inline void CEdit::Cut() const
+ // Cuts the selection to the clipboard, or deletes the character to the left of the cursor if there is no selection.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_CUT, 0, 0);
+ }
+
+ inline void CEdit::Paste() const
+ // Pastes text from the clipboard into the edit control window at the caret position.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(WM_PASTE, 0, 0);
+ }
+
+ inline void CEdit::Undo() const
+ // Removes any text that was just inserted or inserts any deleted characters and sets the selection to the inserted text.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(EM_UNDO, 0, 0);
+ }
+
+ inline void CEdit::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Edit");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CListbox class
+ //
+ inline int CListBox::GetCount() const
+ // Returns the number of items in the list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCOUNT, 0, 0);
+ }
+
+ inline int CListBox::GetHorizontalExtent() const
+ // Returns the scrollable width, in pixels, of a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETHORIZONTALEXTENT, 0, 0);
+ }
+
+ inline DWORD CListBox::GetItemData(int nIndex) const
+ // Returns the value associated with the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(LB_GETITEMDATA, nIndex, 0);
+ }
+
+ inline void* CListBox::GetItemDataPtr(int nIndex) const
+ // Returns the value associated with the specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LPVOID)SendMessage(LB_GETITEMDATA, nIndex, 0);
+ }
+
+ inline int CListBox::GetItemHeight(int nIndex) const
+ // Returns the height, in pixels, of an item in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETITEMHEIGHT, nIndex, 0L);
+ }
+
+ inline int CListBox::GetItemRect(int nIndex, LPRECT lpRect) const
+ // Retrieves the client coordinates of the specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETITEMRECT, nIndex, (LPARAM)lpRect);
+ }
+
+ inline LCID CListBox::GetLocale() const
+ // Retrieves the locale of the list box. The high-order word contains the country/region code
+ // and the low-order word contains the language identifier.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LCID)::SendMessage(m_hWnd, LB_GETLOCALE, 0, 0);
+ }
+
+ inline int CListBox::GetSel(int nIndex) const
+ // Returns the selection state of a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSEL, nIndex, 0);
+ }
+
+ inline int CListBox::GetText(int nIndex, LPTSTR lpszBuffer) const
+ // Retrieves the string associated with a specified item and the length of the string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, LB_GETTEXT, nIndex, (LPARAM)lpszBuffer);
+ }
+
+ inline int CListBox::GetTextLen(int nIndex) const
+ // Returns the length, in characters, of the string associated with a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage( LB_GETTEXTLEN, nIndex, 0);
+ }
+
+ inline int CListBox::GetTopIndex() const
+ // Returns the index of the first visible item in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETTOPINDEX, 0, 0);
+ }
+
+ inline UINT CListBox::ItemFromPoint(CPoint pt, BOOL& bOutside) const
+ // Retrieves the zero-based index of the item nearest the specified point in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ DWORD dw = (DWORD)::SendMessage(m_hWnd, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+ bOutside = !!HIWORD(dw);
+ return LOWORD(dw);
+ }
+
+ inline void CListBox::SetColumnWidth(int cxWidth) const
+ // Sets the width, in pixels, of all columns in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETCOLUMNWIDTH, cxWidth, 0);
+ }
+
+ inline void CListBox::SetHorizontalExtent(int cxExtent) const
+ // Sets the scrollable width, in pixels, of a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETHORIZONTALEXTENT, cxExtent, 0);
+ }
+
+ inline int CListBox::SetItemData(int nIndex, DWORD dwItemData) const
+ // Associates a value with a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETITEMDATA, nIndex, (LPARAM)dwItemData);
+ }
+
+ inline int CListBox::SetItemDataPtr(int nIndex, void* pData) const
+ // Associates a value with a list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return SetItemData(nIndex, (DWORD)(DWORD_PTR)pData);
+ }
+
+ inline int CListBox::SetItemHeight(int nIndex, UINT cyItemHeight) const
+ // Sets the height, in pixels, of an item or items in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETITEMHEIGHT, nIndex, MAKELONG(cyItemHeight, 0));
+ }
+
+ inline LCID CListBox::SetLocale(LCID nNewLocale) const
+ // Sets the locale of a list box and returns the previous locale identifier.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (LCID)::SendMessage(m_hWnd, LB_SETLOCALE, (WPARAM)nNewLocale, 0);
+ }
+
+ inline BOOL CListBox::SetTabStops(int nTabStops, LPINT rgTabStops) const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LB_SETTABSTOPS, nTabStops, (LPARAM)rgTabStops);
+ }
+
+ inline void CListBox::SetTabStops() const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETTABSTOPS, 0, 0);
+ }
+
+ inline BOOL CListBox::SetTabStops(const int& cxEachStop) const
+ // Sets the tab stops to those specified in a specified array.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&cxEachStop);
+ }
+
+ inline int CListBox::SetTopIndex(int nIndex) const
+ // Scrolls the list box so the specified item is at the top of the visible range.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETTOPINDEX, nIndex, 0);
+ }
+
+ inline int CListBox::GetCurSel() const
+ // Returns the index of the currently selected item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCURSEL, 0, 0);
+ }
+
+ inline int CListBox::SetCurSel(int nSelect) const
+ // Selects a specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETCURSEL, nSelect, 0);
+ }
+
+ inline int CListBox::GetAnchorIndex() const
+ // Returns the index of the item that the mouse last selected.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETANCHORINDEX, 0, 0);
+ }
+
+ inline int CListBox::GetCaretIndex() const
+ // Returns the index of the item that has the focus rectangle.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETCARETINDEX, 0, 0L);
+ }
+
+ inline int CListBox::GetSelCount() const
+ // Returns the number of selected items in a multiple-selection list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSELCOUNT, 0, 0);
+ }
+
+ inline int CListBox::GetSelItems(int nMaxItems, LPINT rgIndex) const
+ // Creates an array of the indexes of all selected items in a multiple-selection list box
+ // and returns the total number of selected items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_GETSELITEMS, nMaxItems, (LPARAM)rgIndex);
+ }
+
+ inline int CListBox::SelItemRange(BOOL bSelect, int nFirstItem, int nLastItem) const
+ // Selects a specified range of items in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ if (bSelect)
+ return (int)SendMessage(LB_SELITEMRANGEEX, nFirstItem, nLastItem);
+ else
+ return (int)SendMessage(LB_SELITEMRANGEEX, nLastItem, nFirstItem);
+ }
+
+ inline void CListBox::SetAnchorIndex(int nIndex) const
+ // Sets the item that the mouse last selected to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_SETANCHORINDEX, nIndex, 0);
+ }
+
+ inline int CListBox::SetCaretIndex(int nIndex, BOOL bScroll) const
+ // Sets the focus rectangle to a specified list box item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETCARETINDEX, nIndex, MAKELONG(bScroll, 0));
+ }
+
+ inline int CListBox::SetSel(int nIndex, BOOL bSelect) const
+ // Selects an item in a multiple-selection list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_SETSEL, bSelect, nIndex);
+ }
+
+ inline int CListBox::AddString(LPCTSTR lpszItem) const
+ // Adds a string to a list box and returns its index.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_ADDSTRING, 0, (LPARAM)lpszItem);
+ }
+
+ inline int CListBox::DeleteString(UINT nIndex) const
+ // Removes a string from a list box and returns the number of strings remaining in the list.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_DELETESTRING, nIndex, 0);
+ }
+
+ inline int CListBox::Dir(UINT attr, LPCTSTR lpszWildCard) const
+ // Adds a list of filenames to a list box and returns the index of the last filename added.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_DIR, attr, (LPARAM)lpszWildCard);
+ }
+
+ inline int CListBox::FindString(int nStartAfter, LPCTSTR lpszItem) const
+ // Returns the index of the first string in the list box that begins with a specified string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_FINDSTRING, nStartAfter, (LPARAM)lpszItem);
+ }
+
+ inline int CListBox::FindStringExact(int nIndexStart, LPCTSTR lpszFind) const
+ // Returns the index of the string in the list box that is equal to a specified string.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_FINDSTRINGEXACT, nIndexStart, (LPARAM)lpszFind);
+ }
+
+ inline int CListBox::InsertString(int nIndex, LPCTSTR lpszItem) const
+ // Inserts a string at a specified index in a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(LB_INSERTSTRING, nIndex, (LPARAM)lpszItem);
+ }
+
+ inline void CListBox::ResetContent() const
+ // Removes all items from a list box.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(LB_RESETCONTENT, 0, 0);
+ }
+
+ inline int CListBox::SelectString(int nStartAfter, LPCTSTR lpszItem) const
+ // Selects the first string it finds that matches a specified prefix.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)::SendMessage(m_hWnd, LB_SELECTSTRING, nStartAfter, (LPARAM)lpszItem);
+ }
+
+ inline void CListBox::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("ListBox");
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CStatic class
+ //
+ inline HBITMAP CStatic::GetBitmap() const
+ // Returns the handle to the bitmap for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(STM_GETIMAGE, IMAGE_BITMAP, 0);
+ }
+
+ inline HCURSOR CStatic::GetCursor() const
+ // Returns the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_GETIMAGE, IMAGE_CURSOR, 0);
+ }
+
+ inline HENHMETAFILE CStatic::GetEnhMetaFile() const
+ // Returns the handle to the enhanced metafile for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HENHMETAFILE)SendMessage(STM_GETIMAGE, IMAGE_ENHMETAFILE, 0);
+ }
+
+ inline HICON CStatic::GetIcon() const
+ // Returns the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(STM_GETIMAGE, IMAGE_ICON, 0);
+ }
+
+ inline HBITMAP CStatic::SetBitmap(HBITMAP hBitmap) const
+ // Sets the handle to the bitmap for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HBITMAP)SendMessage(STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
+ }
+
+ inline HCURSOR CStatic::SetCursor(HCURSOR hCursor) const
+ // Sets the handle to the cursor for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HCURSOR)SendMessage(STM_SETIMAGE, IMAGE_CURSOR, (LPARAM)hCursor);
+ }
+
+ inline HENHMETAFILE CStatic::SetEnhMetaFile(HENHMETAFILE hMetaFile) const
+ // Sets the handle to the enhanced metafile for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HENHMETAFILE)SendMessage(STM_SETIMAGE, IMAGE_ENHMETAFILE, (LPARAM)hMetaFile);
+ }
+
+ inline HICON CStatic::SetIcon(HICON hIcon) const
+ // Sets the handle to the icon for the static control
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HICON)SendMessage(STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
+ }
+
+ inline void CStatic::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = _T("Static");
+ }
+
+}
+
+#endif // _WIN32XX_STDCONTROLS_H_
+
diff --git a/external/win32cpp/include/tab.h b/external/win32cpp/include/tab.h
new file mode 100644
index 0000000..1569914
--- /dev/null
+++ b/external/win32cpp/include/tab.h
@@ -0,0 +1,1658 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// tab.h
+// Declaration of the CTab and CMDITab classes
+
+#ifndef _WIN32XX_TAB_H_
+#define _WIN32XX_TAB_H_
+
+#include "wincore.h"
+#include "dialog.h"
+#include "gdi.h"
+#include "default_resource.h"
+
+namespace Win32xx
+{
+
+ struct TabPageInfo
+ {
+ TCHAR szTabText[MAX_MENU_STRING];
+ int iImage; // index of this tab's image
+ int idTab; // identifier for this tab (optional)
+ CWnd* pView; // pointer to the view window
+ };
+
+ class CTab : public CWnd
+ {
+ protected:
+ // Declaration of the CSelectDialog class, a nested class of CTab
+ // It creates the dialog to choose which tab to activate
+ class CSelectDialog : public CDialog
+ {
+ public:
+ CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);
+ virtual ~CSelectDialog() {}
+ virtual void AddItem(LPCTSTR szString);
+ virtual BOOL IsTab() const { return FALSE; }
+
+ protected:
+ virtual BOOL OnInitDialog();
+ virtual void OnOK();
+ virtual void OnCancel() { EndDialog(-2); }
+
+ private:
+ CSelectDialog(const CSelectDialog&); // Disable copy construction
+ CSelectDialog& operator = (const CSelectDialog&); // Disable assignment operator
+
+ std::vector m_vItems;
+ int IDC_LIST;
+
+ };
+ public:
+ CTab();
+ virtual ~CTab();
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab);
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText, int nID_Icon, UINT idTab = 0);
+ virtual int AddTabPage(WndPtr pView, LPCTSTR szTabText);
+ virtual CRect GetCloseRect() const;
+ virtual CRect GetListRect() const;
+ virtual HMENU GetListMenu();
+ virtual BOOL GetTabsAtTop() const;
+ virtual int GetTabIndex(CWnd* pWnd) const;
+ virtual TabPageInfo GetTabPageInfo(UINT nTab) const;
+ virtual int GetTextHeight() const;
+ virtual void RecalcLayout();
+ virtual void RemoveTabPage(int nPage);
+ virtual void SelectPage(int nPage);
+ virtual void SetFixedWidth(BOOL bEnabled);
+ virtual void SetOwnerDraw(BOOL bEnabled);
+ virtual void SetShowButtons(BOOL bShow);
+ virtual void SetTabIcon(int i, HICON hIcon);
+ virtual void SetTabsAtTop(BOOL bTop);
+ virtual void SetTabText(UINT nTab, LPCTSTR szText);
+ virtual void SwapTabs(UINT nTab1, UINT nTab2);
+
+ // Attributes
+ std::vector & GetAllTabs() const { return (std::vector &) m_vTabPageInfo; }
+ HIMAGELIST GetImageList() const { return m_himlTab; }
+ BOOL GetShowButtons() const { return m_bShowButtons; }
+ int GetTabHeight() const { return m_nTabHeight; }
+ CWnd* GetActiveView() const { return m_pActiveView; }
+ void SetTabHeight(int nTabHeight) { m_nTabHeight = nTabHeight; NotifyChanged();}
+
+ // Wrappers for Win32 Macros
+ void AdjustRect(BOOL fLarger, RECT *prc) const;
+ int GetCurFocus() const;
+ int GetCurSel() const;
+ BOOL GetItem(int iItem, LPTCITEM pitem) const;
+ int GetItemCount() const;
+ int HitTest(TCHITTESTINFO& info) const;
+ void SetCurFocus(int iItem) const;
+ int SetCurSel(int iItem) const;
+ DWORD SetItemSize(int cx, int cy) const;
+ int SetMinTabWidth(int cx) const;
+ void SetPadding(int cx, int cy) const;
+
+ protected:
+ virtual void DrawCloseButton(CDC& DrawDC);
+ virtual void DrawListButton(CDC& DrawDC);
+ virtual void DrawTabs(CDC& dcMem);
+ virtual void DrawTabBorders(CDC& dcMem, CRect& rcTab);
+ virtual void OnCreate();
+ virtual void OnLButtonDown(WPARAM wParam, LPARAM lParam);
+ virtual void OnLButtonUp(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseLeave(WPARAM wParam, LPARAM lParam);
+ virtual void OnMouseMove(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNCHitTest(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void NotifyChanged();
+ virtual void Paint();
+ virtual void PreCreate(CREATESTRUCT& cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual void SetTabSize();
+ virtual void ShowListDialog();
+ virtual void ShowListMenu();
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTab(const CTab&); // Disable copy construction
+ CTab& operator = (const CTab&); // Disable assignment operator
+
+ SIZE GetMaxTabSize() const;
+ void ShowActiveView(CWnd* pView);
+
+ std::vector m_vTabPageInfo;
+ std::vector m_vTabViews;
+ CFont m_Font;
+ HIMAGELIST m_himlTab;
+ HMENU m_hListMenu;
+ CWnd* m_pActiveView;
+ BOOL m_bShowButtons; // Show or hide the close and list button
+ BOOL m_IsTracking;
+ BOOL m_IsClosePressed;
+ BOOL m_IsListPressed;
+ BOOL m_IsListMenuActive;
+ int m_nTabHeight;
+ };
+
+ ////////////////////////////////////////
+ // Declaration of the CTabbedMDI class
+ class CTabbedMDI : public CWnd
+ {
+ public:
+ CTabbedMDI();
+ virtual ~CTabbedMDI();
+ virtual CWnd* AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild = 0);
+ virtual void CloseActiveMDI();
+ virtual void CloseAllMDIChildren();
+ virtual void CloseMDIChild(int nTab);
+ virtual CWnd* GetActiveMDIChild() const;
+ virtual int GetActiveMDITab() const;
+ virtual CWnd* GetMDIChild(int nTab) const;
+ virtual int GetMDIChildCount() const;
+ virtual int GetMDIChildID(int nTab) const;
+ virtual LPCTSTR GetMDIChildTitle(int nTab) const;
+ virtual HMENU GetListMenu() const { return GetTab().GetListMenu(); }
+ virtual CTab& GetTab() const {return (CTab&)m_Tab;}
+ virtual BOOL LoadRegistrySettings(tString tsRegistryKeyName);
+ virtual void RecalcLayout();
+ virtual BOOL SaveRegistrySettings(tString tsRegistryKeyName);
+ virtual void SetActiveMDIChild(CWnd* pWnd);
+ virtual void SetActiveMDITab(int nTab);
+
+ protected:
+ virtual HWND Create(CWnd* pParent);
+ virtual CWnd* NewMDIChildFromID(int idMDIChild);
+ virtual void OnCreate();
+ virtual void OnDestroy(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam);
+ virtual void OnWindowPosChanged(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTabbedMDI(const CTabbedMDI&); // Disable copy construction
+ CTabbedMDI& operator = (const CTabbedMDI&); // Disable assignment operator
+
+ CTab m_Tab;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ /////////////////////////////////////////////////////////////
+ // Definitions for the CSelectDialog class nested within CTab
+ //
+ inline CTab::CSelectDialog::CSelectDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent) :
+ CDialog(lpTemplate, pParent), IDC_LIST(121)
+ {
+ }
+
+ inline BOOL CTab::CSelectDialog::OnInitDialog()
+ {
+ for (UINT u = 0; u < m_vItems.size(); ++u)
+ {
+ SendDlgItemMessage(IDC_LIST, LB_ADDSTRING, 0, (LPARAM) m_vItems[u].c_str());
+ }
+
+ return true;
+ }
+
+ inline void CTab::CSelectDialog::AddItem(LPCTSTR szString)
+ {
+ m_vItems.push_back(szString);
+ }
+
+ inline void CTab::CSelectDialog::OnOK()
+ {
+ int iSelect = (int)SendDlgItemMessage(IDC_LIST, LB_GETCURSEL, 0, 0);
+ if (iSelect != LB_ERR)
+ EndDialog(iSelect);
+ else
+ EndDialog(-2);
+ }
+
+
+ //////////////////////////////////////////////////////////
+ // Definitions for the CTab class
+ //
+ inline CTab::CTab() : m_hListMenu(NULL), m_pActiveView(NULL), m_bShowButtons(FALSE), m_IsTracking(FALSE), m_IsClosePressed(FALSE),
+ m_IsListPressed(FALSE), m_IsListMenuActive(FALSE), m_nTabHeight(0)
+ {
+ // Create and assign the image list
+ m_himlTab = ImageList_Create(16, 16, ILC_MASK|ILC_COLOR32, 0, 0);
+
+ // Set the tab control's font
+ NONCLIENTMETRICS info = {0};
+ info.cbSize = GetSizeofNonClientMetrics();
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
+ m_Font.CreateFontIndirect(&info.lfStatusFont);
+ }
+
+ inline CTab::~CTab()
+ {
+ ImageList_Destroy(m_himlTab);
+
+ if (IsMenu(m_hListMenu)) ::DestroyMenu(m_hListMenu);
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, HICON hIcon, UINT idTab)
+ {
+ assert(pView.get());
+ assert(lstrlen(szTabText) < MAX_MENU_STRING);
+
+ m_vTabViews.push_back(pView);
+
+ TabPageInfo tpi = {0};
+ tpi.pView = pView.get();
+ tpi.idTab = idTab;
+ lstrcpyn(tpi.szTabText, szTabText, MAX_MENU_STRING);
+ if (hIcon)
+ tpi.iImage = ImageList_AddIcon(GetImageList(), hIcon);
+ else
+ tpi.iImage = -1;
+
+ int iNewPage = (int)m_vTabPageInfo.size();
+ m_vTabPageInfo.push_back(tpi);
+
+ if (m_hWnd)
+ {
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = tpi.iImage;
+ tie.pszText = tpi.szTabText;
+ TabCtrl_InsertItem(m_hWnd, iNewPage, &tie);
+
+ SetTabSize();
+ SelectPage(iNewPage);
+ NotifyChanged();
+ }
+
+ return iNewPage;
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText, int idIcon, UINT idTab /* = 0*/)
+ {
+ HICON hIcon = (HICON)LoadImage(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(idIcon), IMAGE_ICON, 0, 0, LR_SHARED);
+ return AddTabPage(pView, szTabText, hIcon, idTab);
+ }
+
+ inline int CTab::AddTabPage(WndPtr pView, LPCTSTR szTabText)
+ {
+ return AddTabPage(pView, szTabText, (HICON)0, 0);
+ }
+
+ inline void CTab::DrawCloseButton(CDC& DrawDC)
+ {
+ // The close button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (!m_bShowButtons) return;
+ if (!GetActiveView()) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;
+
+ // Determine the close button's drawing position relative to the window
+ CRect rcClose = GetCloseRect();
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+ UINT uState = rcClose.PtInRect(pt)? m_IsClosePressed? 2: 1: 0;
+
+ // Draw the outer highlight for the close button
+ if (!IsRectEmpty(&rcClose))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcClose.left, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.bottom);
+ DrawDC.LineTo(rcClose.right, rcClose.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcClose.left, rcClose.top);
+ DrawDC.LineTo(rcClose.left, rcClose.bottom);
+ }
+ break;
+ }
+
+ // Manually draw close button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.left + 4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.right - 2, rcClose.bottom -3);
+
+ DrawDC.MoveTo(rcClose.left + 3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.right - 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -3, rcClose.top +4);
+ DrawDC.LineTo(rcClose.left + 3, rcClose.bottom -2);
+
+ DrawDC.MoveTo(rcClose.right -4, rcClose.top +3);
+ DrawDC.LineTo(rcClose.left + 2, rcClose.bottom -3);
+ }
+ }
+
+ inline void CTab::DrawListButton(CDC& DrawDC)
+ {
+ // The list button isn't displayed on Win95
+ if (GetWinVersion() == 1400) return;
+
+ if (!m_bShowButtons) return;
+ if (!GetActiveView()) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_FIXEDWIDTH)) return;
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)) return;
+
+ // Determine the list button's drawing position relative to the window
+ CRect rcList = GetListRect();
+
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+ UINT uState = rcList.PtInRect(pt)? 1: 0;
+ if (m_IsListMenuActive) uState = 2;
+
+ // Draw the outer highlight for the list button
+ if (!IsRectEmpty(&rcList))
+ {
+ switch (uState)
+ {
+ case 0:
+ {
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(232, 228, 220));
+
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ break;
+ }
+
+ case 1:
+ {
+ // Draw outline, white at top, black on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ }
+
+ break;
+ case 2:
+ {
+ // Draw outline, black on top, white on bottom
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
+ DrawDC.MoveTo(rcList.left, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.bottom);
+ DrawDC.LineTo(rcList.right, rcList.top);
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+ DrawDC.LineTo(rcList.left, rcList.top);
+ DrawDC.LineTo(rcList.left, rcList.bottom);
+ }
+ break;
+ }
+
+ // Manually draw list button
+ DrawDC.CreatePen(PS_SOLID, 1, RGB(64, 64, 64));
+
+ int MaxLength = (int)(0.65 * rcList.Width());
+ int topGap = 1 + rcList.Height()/3;
+ for (int i = 0; i <= MaxLength/2; i++)
+ {
+ int Length = MaxLength - 2*i;
+ DrawDC.MoveTo(rcList.left +1 + (rcList.Width() - Length)/2, rcList.top +topGap +i);
+ DrawDC.LineTo(rcList.left +1 + (rcList.Width() - Length)/2 + Length, rcList.top +topGap +i);
+ }
+ }
+ }
+
+ inline void CTab::DrawTabs(CDC& dcMem)
+ {
+ // Draw the tab buttons:
+ for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); ++i)
+ {
+ CRect rcItem;
+ TabCtrl_GetItemRect(m_hWnd, i, &rcItem);
+ if (!rcItem.IsRectEmpty())
+ {
+ if (i == TabCtrl_GetCurSel(m_hWnd))
+ {
+ dcMem.CreateSolidBrush(RGB(248,248,248));
+ dcMem.SetBkColor(RGB(248,248,248));
+ }
+ else
+ {
+ dcMem.CreateSolidBrush(RGB(200,200,200));
+ dcMem.SetBkColor(RGB(200,200,200));
+ }
+
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
+ dcMem.RoundRect(rcItem.left+1, rcItem.top, rcItem.right+2, rcItem.bottom, 6, 6);
+
+ if (rcItem.Width() >= 24)
+ {
+ TCHAR szText[30];
+ TCITEM tcItem = {0};
+ tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
+ tcItem.cchTextMax = 30;
+ tcItem.pszText = szText;
+ TabCtrl_GetItem(m_hWnd, i, &tcItem);
+ int xImage;
+ int yImage;
+ int yOffset = 0;
+ if (ImageList_GetIconSize(m_himlTab, &xImage, &yImage))
+ yOffset = (rcItem.Height() - yImage)/2;
+
+ // Draw the icon
+ ImageList_Draw(m_himlTab, tcItem.iImage, dcMem, rcItem.left+5, rcItem.top+yOffset, ILD_NORMAL);
+
+ // Draw the text
+ dcMem.SelectObject(&m_Font);
+
+ // Calculate the size of the text
+ CRect rcText = rcItem;
+
+ int iImageSize = 20;
+ int iPadding = 4;
+ if (tcItem.iImage >= 0)
+ rcText.left += iImageSize;
+
+ rcText.left += iPadding;
+ dcMem.DrawText(szText, -1, rcText, DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
+ }
+ }
+ }
+ }
+
+ inline void CTab::DrawTabBorders(CDC& dcMem, CRect& rcTab)
+ {
+ BOOL IsBottomTab = (BOOL)GetWindowLongPtr(GWL_STYLE) & TCS_BOTTOM;
+
+ // Draw a lighter rectangle touching the tab buttons
+ CRect rcItem;
+ TabCtrl_GetItemRect(m_hWnd, 0, &rcItem);
+ int left = rcItem.left +1;
+ int right = rcTab.right;
+ int top = rcTab.bottom;
+ int bottom = top + 3;
+
+ if (!IsBottomTab)
+ {
+ bottom = MAX(rcTab.top, m_nTabHeight +4);
+ top = bottom -3;
+ }
+
+ dcMem.CreateSolidBrush(RGB(248,248,248));
+ dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));
+ if (!rcItem.IsRectEmpty())
+ {
+ dcMem.Rectangle(left, top, right, bottom);
+
+ // Draw a darker line below the rectangle
+ dcMem.CreatePen(PS_SOLID, 1, RGB(160, 160, 160));
+ if (IsBottomTab)
+ {
+ dcMem.MoveTo(left-1, bottom);
+ dcMem.LineTo(right, bottom);
+ }
+ else
+ {
+ dcMem.MoveTo(left-1, top-1);
+ dcMem.LineTo(right, top-1);
+ }
+
+ // Draw a lighter line over the darker line for the selected tab
+ dcMem.CreatePen(PS_SOLID, 1, RGB(248,248,248));
+ TabCtrl_GetItemRect(m_hWnd, TabCtrl_GetCurSel(m_hWnd), &rcItem);
+ OffsetRect(&rcItem, 1, 1);
+
+ if (IsBottomTab)
+ {
+ dcMem.MoveTo(rcItem.left, bottom);
+ dcMem.LineTo(rcItem.right, bottom);
+ }
+ else
+ {
+ dcMem.MoveTo(rcItem.left, top-1);
+ dcMem.LineTo(rcItem.right, top-1);
+ }
+ }
+ }
+
+ inline CRect CTab::GetCloseRect() const
+ {
+ CRect rcClose;
+ if (GetShowButtons())
+ {
+ rcClose= GetClientRect();
+ int Gap = 2;
+ int cx = GetSystemMetrics(SM_CXSMICON) -1;
+ int cy = GetSystemMetrics(SM_CYSMICON) -1;
+ rcClose.right -= Gap;
+ rcClose.left = rcClose.right - cx;
+
+ if (GetTabsAtTop())
+ rcClose.top = Gap;
+ else
+ rcClose.top = MAX(Gap, rcClose.bottom - m_nTabHeight);
+
+ rcClose.bottom = rcClose.top + cy;
+ }
+ return rcClose;
+ }
+
+ inline HMENU CTab::GetListMenu()
+ {
+ if (IsMenu(m_hListMenu))
+ ::DestroyMenu(m_hListMenu);
+
+ m_hListMenu = CreatePopupMenu();
+
+ // Add the menu items
+ for(UINT u = 0; u < MIN(GetAllTabs().size(), 9); ++u)
+ {
+ TCHAR szMenuString[MAX_MENU_STRING+1];
+ TCHAR szTabText[MAX_MENU_STRING];
+ lstrcpyn(szTabText, GetAllTabs()[u].szTabText, MAX_MENU_STRING -4);
+ wsprintf(szMenuString, _T("&%d %s"), u+1, szTabText);
+ AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +u, szMenuString);
+ }
+ if (GetAllTabs().size() >= 10)
+ AppendMenu(m_hListMenu, MF_STRING, IDW_FIRSTCHILD +9, _T("More Windows"));
+
+ // Add a checkmark to the menu
+ int iSelected = GetCurSel();
+ if (iSelected < 9)
+ CheckMenuItem(m_hListMenu, iSelected, MF_BYPOSITION|MF_CHECKED);
+
+ return m_hListMenu;
+ }
+
+ inline CRect CTab::GetListRect() const
+ {
+ CRect rcList;
+ if (GetShowButtons())
+ {
+ CRect rcClose = GetCloseRect();
+ rcList = rcClose;
+ rcList.OffsetRect( -(rcClose.Width() + 2), 0);
+ rcList.InflateRect(-1, 0);
+ }
+ return rcList;
+ }
+
+ inline SIZE CTab::GetMaxTabSize() const
+ {
+ CSize Size;
+
+ for (int i = 0; i < TabCtrl_GetItemCount(m_hWnd); i++)
+ {
+ CClientDC dcClient(this);
+ dcClient.SelectObject(&m_Font);
+ std::vector vTitle(MAX_MENU_STRING, _T('\0'));
+ TCHAR* pszTitle = &vTitle.front();
+ TCITEM tcItem = {0};
+ tcItem.mask = TCIF_TEXT |TCIF_IMAGE;
+ tcItem.cchTextMax = MAX_MENU_STRING;
+ tcItem.pszText = pszTitle;
+ TabCtrl_GetItem(m_hWnd, i, &tcItem);
+ CSize TempSize = dcClient.GetTextExtentPoint32(pszTitle, lstrlen(pszTitle));
+
+ int iImageSize = 0;
+ int iPadding = 6;
+ if (tcItem.iImage >= 0)
+ iImageSize = 20;
+ TempSize.cx += iImageSize + iPadding;
+
+ if (TempSize.cx > Size.cx)
+ Size = TempSize;
+ }
+
+ return Size;
+ }
+
+ inline BOOL CTab::GetTabsAtTop() const
+ // Returns TRUE if the contol's tabs are placed at the top
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ return (!(dwStyle & TCS_BOTTOM));
+ }
+
+ inline int CTab::GetTextHeight() const
+ {
+ CClientDC dcClient(this);
+ dcClient.SelectObject(&m_Font);
+ CSize szText = dcClient.GetTextExtentPoint32(_T("Text"), lstrlen(_T("Text")));
+ return szText.cy;
+ }
+
+ inline int CTab::GetTabIndex(CWnd* pWnd) const
+ {
+ assert(pWnd);
+
+ for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)
+ {
+ if (m_vTabPageInfo[i].pView == pWnd)
+ return i;
+ }
+
+ return -1;
+ }
+
+ inline TabPageInfo CTab::GetTabPageInfo(UINT nTab) const
+ {
+ assert (nTab < m_vTabPageInfo.size());
+
+ return m_vTabPageInfo[nTab];
+ }
+
+ inline void CTab::NotifyChanged()
+ {
+ NMHDR nmhdr = {0};
+ nmhdr.hwndFrom = m_hWnd;
+ nmhdr.code = UWM_TAB_CHANGED;
+ GetParent()->SendMessage(WM_NOTIFY, 0L, (LPARAM)&nmhdr);
+ }
+
+ inline void CTab::OnCreate()
+ {
+ SetFont(&m_Font, TRUE);
+
+ // Assign ImageList unless we are owner drawn
+ if (!(GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))
+ TabCtrl_SetImageList(m_hWnd, m_himlTab);
+
+ for (int i = 0; i < (int)m_vTabPageInfo.size(); ++i)
+ {
+ // Add tabs for each view.
+ TCITEM tie = {0};
+ tie.mask = TCIF_TEXT | TCIF_IMAGE;
+ tie.iImage = m_vTabPageInfo[i].iImage;
+ tie.pszText = m_vTabPageInfo[i].szTabText;
+ TabCtrl_InsertItem(m_hWnd, i, &tie);
+ }
+
+ int HeightGap = 5;
+ SetTabHeight(MAX(20, (GetTextHeight() + HeightGap)));
+ SelectPage(0);
+ }
+
+ inline void CTab::OnLButtonDown(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+
+ if (GetCloseRect().PtInRect(pt))
+ {
+ m_IsClosePressed = TRUE;
+ SetCapture();
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ }
+ else
+ m_IsClosePressed = FALSE;
+
+ if (GetListRect().PtInRect(pt))
+ {
+ ShowListMenu();
+ }
+ }
+
+ inline void CTab::OnLButtonUp(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ ReleaseCapture();
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ if (m_IsClosePressed && GetCloseRect().PtInRect(pt))
+ {
+ RemoveTabPage(GetCurSel());
+ if (GetActiveView())
+ GetActiveView()->RedrawWindow();
+ }
+
+ m_IsClosePressed = FALSE;
+ }
+
+ inline void CTab::OnMouseLeave(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ DrawListButton(dc);
+
+ m_IsTracking = FALSE;
+ }
+
+ inline void CTab::OnMouseMove(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ if (!m_IsListMenuActive && m_IsListPressed)
+ {
+ m_IsListPressed = FALSE;
+ }
+
+ if (!m_IsTracking)
+ {
+ TRACKMOUSEEVENT TrackMouseEventStruct = {0};
+ TrackMouseEventStruct.cbSize = sizeof(TrackMouseEventStruct);
+ TrackMouseEventStruct.dwFlags = TME_LEAVE;
+ TrackMouseEventStruct.hwndTrack = m_hWnd;
+ _TrackMouseEvent(&TrackMouseEventStruct);
+ m_IsTracking = TRUE;
+ }
+
+ CClientDC dc(this);
+ DrawCloseButton(dc);
+ DrawListButton(dc);
+ }
+
+ inline LRESULT CTab::OnNCHitTest(WPARAM wParam, LPARAM lParam)
+ {
+ // Ensure we have an arrow cursor when the tab has no view window
+ if (0 == GetAllTabs().size())
+ SetCursor(LoadCursor(NULL, IDC_ARROW));
+
+ // Cause WM_LBUTTONUP and WM_LBUTTONDOWN messages to be sent for buttons
+ CPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ ScreenToClient(pt);
+ if (GetCloseRect().PtInRect(pt)) return HTCLIENT;
+ if (GetListRect().PtInRect(pt)) return HTCLIENT;
+
+ return CWnd::WndProcDefault(WM_NCHITTEST, wParam, lParam);
+ }
+
+ inline LRESULT CTab::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case TCN_SELCHANGE:
+ {
+ // Display the newly selected tab page
+ int nPage = GetCurSel();
+ ShowActiveView(m_vTabPageInfo[nPage].pView);
+ }
+ break;
+ }
+
+ return 0L;
+ }
+
+ inline void CTab::Paint()
+ {
+ // Microsoft's drawing for a tab control is rubbish, so we do our own.
+ // We use double buffering and regions to eliminate flicker
+
+ // Create the memory DC and bitmap
+ CClientDC dcView(this);
+ CMemDC dcMem(&dcView);
+ CRect rcClient = GetClientRect();
+ dcMem.CreateCompatibleBitmap(&dcView, rcClient.Width(), rcClient.Height());
+
+ if (0 == GetItemCount())
+ {
+ // No tabs, so simply display a grey background and exit
+ COLORREF rgbDialog = GetSysColor(COLOR_BTNFACE);
+ dcView.SolidFill(rgbDialog, rcClient);
+ return;
+ }
+
+ // Create a clipping region. Its the overall tab window's region,
+ // less the region belonging to the individual tab view's client area
+ CRgn rgnSrc1 = ::CreateRectRgn(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
+ CRect rcTab = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rcTab);
+ if (rcTab.Height() < 0)
+ rcTab.top = rcTab.bottom;
+ if (rcTab.Width() < 0)
+ rcTab.left = rcTab.right;
+
+ CRgn rgnSrc2 = ::CreateRectRgn(rcTab.left, rcTab.top, rcTab.right, rcTab.bottom);
+ CRgn rgnClip = ::CreateRectRgn(0, 0, 0, 0);
+ ::CombineRgn(rgnClip, rgnSrc1, rgnSrc2, RGN_DIFF);
+
+ // Use the region in the memory DC to paint the grey background
+ dcMem.SelectClipRgn(&rgnClip);
+ HWND hWndParent = ::GetParent(m_hWnd);
+ CDC dcParent = ::GetDC(hWndParent);
+ HBRUSH hBrush = (HBRUSH) SendMessage(hWndParent, WM_CTLCOLORDLG, (WPARAM)dcParent.GetHDC(), (LPARAM)hWndParent);
+ dcMem.SelectObject(FromHandle(hBrush));
+ dcMem.PaintRgn(&rgnClip);
+
+ // Draw the tab buttons on the memory DC:
+ DrawTabs(dcMem);
+
+ // Draw buttons and tab borders
+ DrawCloseButton(dcMem);
+ DrawListButton(dcMem);
+ DrawTabBorders(dcMem, rcTab);
+
+ // Now copy our from our memory DC to the window DC
+ dcView.SelectClipRgn(&rgnClip);
+ dcView.BitBlt(0, 0, rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
+ }
+
+ inline void CTab::PreCreate(CREATESTRUCT &cs)
+ {
+ // For Tabs on the bottom, add the TCS_BOTTOM style
+ cs.style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ }
+
+ inline void CTab::PreRegisterClass(WNDCLASS &wc)
+ {
+ wc.lpszClassName = WC_TABCONTROL;
+ }
+
+ inline void CTab::RecalcLayout()
+ {
+ if (IsWindow())
+ {
+ if (GetActiveView())
+ {
+ // Set the tab sizes
+ SetTabSize();
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+ GetActiveView()->SetWindowPos(NULL, rc, SWP_SHOWWINDOW);
+ }
+ else
+ RedrawWindow();
+ }
+ }
+
+ inline void CTab::RemoveTabPage(int nPage)
+ {
+ if ((nPage < 0) || (nPage > (int)m_vTabPageInfo.size() -1))
+ return;
+
+ // Remove the tab
+ TabCtrl_DeleteItem(m_hWnd, nPage);
+
+ // Remove the TapPageInfo entry
+ std::vector::iterator itTPI = m_vTabPageInfo.begin() + nPage;
+ CWnd* pView = (*itTPI).pView;
+ int iImage = (*itTPI).iImage;
+ if (iImage >= 0)
+ TabCtrl_RemoveImage(m_hWnd, iImage);
+
+ if (pView == m_pActiveView)
+ m_pActiveView = 0;
+
+ (*itTPI).pView->Destroy();
+ m_vTabPageInfo.erase(itTPI);
+
+ std::vector::iterator itView;
+ for (itView = m_vTabViews.begin(); itView < m_vTabViews.end(); ++itView)
+ {
+ if ((*itView).get() == pView)
+ {
+ m_vTabViews.erase(itView);
+ break;
+ }
+ }
+
+ if (IsWindow())
+ {
+ if (m_vTabPageInfo.size() > 0)
+ {
+ SetTabSize();
+ SelectPage(0);
+ }
+ else
+ ShowActiveView(NULL);
+
+ NotifyChanged();
+ }
+ }
+
+ inline void CTab::SelectPage(int nPage)
+ {
+ if ((nPage >= 0) && (nPage < GetItemCount()))
+ {
+ if (nPage != GetCurSel())
+ SetCurSel(nPage);
+
+ ShowActiveView(m_vTabPageInfo[nPage].pView);
+ }
+ }
+
+ inline void CTab::SetFixedWidth(BOOL bEnabled)
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ if (bEnabled)
+ SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_FIXEDWIDTH);
+ else
+ SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_FIXEDWIDTH);
+
+ RecalcLayout();
+ }
+
+ inline void CTab::SetOwnerDraw(BOOL bEnabled)
+ // Enable or disable owner draw
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ if (bEnabled)
+ {
+ SetWindowLongPtr(GWL_STYLE, dwStyle | TCS_OWNERDRAWFIXED);
+ TabCtrl_SetImageList(m_hWnd, NULL);
+ }
+ else
+ {
+ SetWindowLongPtr(GWL_STYLE, dwStyle & ~TCS_OWNERDRAWFIXED);
+ TabCtrl_SetImageList(m_hWnd, m_himlTab);
+ }
+
+ RecalcLayout();
+ }
+
+ inline void CTab::SetShowButtons(BOOL bShow)
+ {
+ m_bShowButtons = bShow;
+ RecalcLayout();
+ }
+
+ inline void CTab::SetTabIcon(int i, HICON hIcon)
+ // Changes or sets the tab's icon
+ {
+ assert (GetItemCount() > i);
+ TCITEM tci = {0};
+ tci.mask = TCIF_IMAGE;
+ GetItem(i, &tci);
+ if (tci.iImage >= 0)
+ {
+ ImageList_ReplaceIcon(GetImageList(), i, hIcon);
+ }
+ else
+ {
+ int iImage = ImageList_AddIcon(GetImageList(), hIcon);
+ tci.iImage = iImage;
+ TabCtrl_SetItem(m_hWnd, i, &tci);
+ m_vTabPageInfo[i].iImage = iImage;
+ }
+ }
+
+ inline void CTab::SetTabsAtTop(BOOL bTop)
+ // Positions the tabs at the top or botttom of the control
+ {
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(GWL_STYLE);
+
+ if (bTop)
+ dwStyle &= ~TCS_BOTTOM;
+ else
+ dwStyle |= TCS_BOTTOM;
+
+ SetWindowLongPtr(GWL_STYLE, dwStyle);
+ RecalcLayout();
+ }
+
+ inline void CTab::SetTabSize()
+ {
+ if (GetItemCount() > 0)
+ {
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+
+ int xGap = 2;
+ if (m_bShowButtons) xGap += GetCloseRect().Width() + GetListRect().Width() +2;
+
+ int nItemWidth = MIN( GetMaxTabSize().cx, (rc.Width() - xGap)/GetItemCount() );
+ nItemWidth = MAX(nItemWidth, 0);
+ SendMessage(TCM_SETITEMSIZE, 0L, MAKELPARAM(nItemWidth, m_nTabHeight));
+ NotifyChanged();
+ }
+ }
+
+ inline void CTab::SetTabText(UINT nTab, LPCTSTR szText)
+ {
+ // Allows the text to be changed on an existing tab
+ if (nTab < GetAllTabs().size())
+ {
+ TCITEM Item = {0};
+ std::vector vTChar(MAX_MENU_STRING+1, _T('\0'));
+ TCHAR* pTChar = &vTChar.front();
+ lstrcpyn(pTChar, szText, MAX_MENU_STRING);
+ Item.mask = TCIF_TEXT;
+ Item.pszText = pTChar;
+
+ if (TabCtrl_SetItem(m_hWnd, nTab, &Item))
+ lstrcpyn(m_vTabPageInfo[nTab].szTabText, pTChar, MAX_MENU_STRING);
+ }
+ }
+
+ inline void CTab::ShowActiveView(CWnd* pView)
+ // Sets or changes the View window displayed within the tab page
+ {
+ // Hide the old view
+ if (GetActiveView() && (GetActiveView()->IsWindow()))
+ GetActiveView()->ShowWindow(SW_HIDE);
+
+ // Assign the view window
+ m_pActiveView = pView;
+
+ if (m_pActiveView && m_hWnd)
+ {
+ if (!m_pActiveView->IsWindow())
+ {
+ // The tab control is already created, so create the new view too
+ GetActiveView()->Create(this);
+ }
+
+ // Position the View over the tab control's display area
+ CRect rc = GetClientRect();
+ TabCtrl_AdjustRect(m_hWnd, FALSE, &rc);
+ GetActiveView()->SetWindowPos(HWND_TOP, rc, SWP_SHOWWINDOW);
+ GetActiveView()->SetFocus();
+ }
+ }
+
+ inline void CTab::ShowListMenu()
+ // Displays the list of windows in a popup menu
+ {
+ if (!m_IsListPressed)
+ {
+ m_IsListPressed = TRUE;
+ HMENU hMenu = GetListMenu();
+
+ CPoint pt(GetListRect().left, GetListRect().top + GetTabHeight());
+ ClientToScreen(pt);
+
+ // Choosing the frame's hwnd for the menu's messages will automatically theme the popup menu
+ HWND MenuHwnd = GetAncestor()->GetHwnd();
+ int nPage = 0;
+ m_IsListMenuActive = TRUE;
+ nPage = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, MenuHwnd, NULL) - IDW_FIRSTCHILD;
+ if ((nPage >= 0) && (nPage < 9)) SelectPage(nPage);
+ if (nPage == 9) ShowListDialog();
+ m_IsListMenuActive = FALSE;
+ }
+
+ CClientDC dc(this);
+ DrawListButton(dc);
+ }
+
+ inline void CTab::ShowListDialog()
+ {
+ // Definition of a dialog template which displays a List Box
+ unsigned char dlg_Template[] =
+ {
+ 0x01,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xc8,0x00,0xc8,0x90,0x03,
+ 0x00,0x00,0x00,0x00,0x00,0xdc,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x53,0x00,0x65,
+ 0x00,0x6c,0x00,0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x57,0x00,0x69,0x00,0x6e,
+ 0x00,0x64,0x00,0x6f,0x00,0x77,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x4d,
+ 0x00,0x53,0x00,0x20,0x00,0x53,0x00,0x68,0x00,0x65,0x00,0x6c,0x00,0x6c,0x00,0x20,
+ 0x00,0x44,0x00,0x6c,0x00,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x01,0x00,0x01,0x50,0x40,0x00,0x7a,0x00,0x25,0x00,0x0f,0x00,0x01,
+ 0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x4f,0x00,0x4b,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x50,0x7a,0x00,0x7a,0x00,0x25,
+ 0x00,0x0f,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0x80,0x00,0x43,0x00,0x61,0x00,0x6e,
+ 0x00,0x63,0x00,0x65,0x00,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x02,0x00,0x01,0x01,0x21,0x50,0x06,0x00,0x06,0x00,0xcf,0x00,0x6d,0x00,0x79,
+ 0x00,0x00,0x00,0xff,0xff,0x83,0x00,0x00,0x00,0x00,0x00
+ };
+
+ // Display the modal dialog. The dialog is defined in the dialog template rather
+ // than in the resource script (rc) file.
+ CSelectDialog MyDialog((LPCDLGTEMPLATE) dlg_Template);
+ for(UINT u = 0; u < GetAllTabs().size(); ++u)
+ {
+ MyDialog.AddItem(GetAllTabs()[u].szTabText);
+ }
+
+ int iSelected = (int)MyDialog.DoModal();
+ if (iSelected >= 0) SelectPage(iSelected);
+ }
+
+ inline void CTab::SwapTabs(UINT nTab1, UINT nTab2)
+ {
+ if ((nTab1 < GetAllTabs().size()) && (nTab2 < GetAllTabs().size()) && (nTab1 != nTab2))
+ {
+ int nPage = GetCurSel();
+ TabPageInfo T1 = GetTabPageInfo(nTab1);
+ TabPageInfo T2 = GetTabPageInfo(nTab2);
+
+ TCITEM Item1 = {0};
+ Item1.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;
+ GetItem(nTab1, &Item1);
+ TCITEM Item2 = {0};
+ Item2.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT;
+ GetItem(nTab2, &Item2);
+ TabCtrl_SetItem(m_hWnd, nTab1, &Item2);
+ TabCtrl_SetItem(m_hWnd, nTab2, &Item1);
+
+ m_vTabPageInfo[nTab1] = T2;
+ m_vTabPageInfo[nTab2] = T1;
+ SelectPage(nPage);
+ }
+ }
+
+ inline LRESULT CTab::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_PAINT:
+ if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)
+ {
+ // Remove all pending paint requests
+ PAINTSTRUCT ps;
+ BeginPaint(ps);
+ EndPaint(ps);
+
+ // Now call our local Paint
+ Paint();
+ return 0;
+ }
+ break;
+
+ case WM_ERASEBKGND:
+ if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED)
+ return 0;
+ break;
+ case WM_KILLFOCUS:
+ m_IsClosePressed = FALSE;
+ break;
+ case WM_LBUTTONDBLCLK:
+ case WM_LBUTTONDOWN:
+ OnLButtonDown(wParam, lParam);
+ break;
+ case WM_LBUTTONUP:
+ OnLButtonUp(wParam, lParam);
+ break;
+ case WM_MOUSEMOVE:
+ OnMouseMove(wParam, lParam);
+ break;
+ case WM_MOUSELEAVE:
+ OnMouseLeave(wParam, lParam);
+ break;
+ case WM_NCHITTEST:
+ return OnNCHitTest(wParam, lParam);
+
+ case WM_WINDOWPOSCHANGING:
+ // A little hack to reduce tab flicker
+ if (IsWindowVisible() && (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED))
+ {
+ LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam;
+ pWinPos->flags |= SWP_NOREDRAW;
+
+ Paint();
+ }
+
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ RecalcLayout();
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+ // Wrappers for Win32 Macros
+ inline void CTab::AdjustRect(BOOL fLarger, RECT *prc) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_AdjustRect(m_hWnd, fLarger, prc);
+ }
+
+ inline int CTab::GetCurFocus() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetCurFocus(m_hWnd);
+ }
+
+ inline int CTab::GetCurSel() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetCurSel(m_hWnd);
+ }
+
+ inline BOOL CTab::GetItem(int iItem, LPTCITEM pitem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetItem(m_hWnd, iItem, pitem);
+ }
+
+ inline int CTab::GetItemCount() const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_GetItemCount(m_hWnd);
+ }
+
+ inline int CTab::HitTest(TCHITTESTINFO& info) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_HitTest(m_hWnd, &info);
+ }
+
+ inline void CTab::SetCurFocus(int iItem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_SetCurFocus(m_hWnd, iItem);
+ }
+
+ inline int CTab::SetCurSel(int iItem) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetCurSel(m_hWnd, iItem);
+ }
+
+ inline DWORD CTab::SetItemSize(int cx, int cy) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetItemSize(m_hWnd, cx, cy);
+ }
+
+ inline int CTab::SetMinTabWidth(int cx) const
+ {
+ assert(::IsWindow(m_hWnd));
+ return TabCtrl_SetMinTabWidth(m_hWnd, cx);
+ }
+
+ inline void CTab::SetPadding(int cx, int cy) const
+ {
+ assert(::IsWindow(m_hWnd));
+ TabCtrl_SetPadding(m_hWnd, cx, cy);
+ }
+
+ ////////////////////////////////////////
+ // Definitions for the CTabbedMDI class
+ inline CTabbedMDI::CTabbedMDI()
+ {
+ GetTab().SetShowButtons(TRUE);
+ }
+
+ inline CTabbedMDI::~CTabbedMDI()
+ {
+ }
+
+ inline CWnd* CTabbedMDI::AddMDIChild(CWnd* pView, LPCTSTR szTabText, int idMDIChild /*= 0*/)
+ {
+ assert(pView);
+ assert(lstrlen(szTabText) < MAX_MENU_STRING);
+
+ GetTab().AddTabPage(WndPtr(pView), szTabText, 0, idMDIChild);
+
+ // Fake a WM_MOUSEACTIVATE to propogate focus change to dockers
+ if (IsWindow())
+ GetParent()->SendMessage(WM_MOUSEACTIVATE, (WPARAM)GetAncestor(), MAKELPARAM(HTCLIENT,WM_LBUTTONDOWN));
+
+ return pView;
+ }
+
+ inline void CTabbedMDI::CloseActiveMDI()
+ {
+ int nTab = GetTab().GetCurSel();
+ if (nTab >= 0)
+ GetTab().RemoveTabPage(nTab);
+
+ RecalcLayout();
+ }
+
+ inline void CTabbedMDI::CloseAllMDIChildren()
+ {
+ while (GetMDIChildCount() > 0)
+ {
+ GetTab().RemoveTabPage(0);
+ }
+ }
+
+ inline void CTabbedMDI::CloseMDIChild(int nTab)
+ {
+ GetTab().RemoveTabPage(nTab);
+
+ if (GetActiveMDIChild())
+ GetActiveMDIChild()->RedrawWindow();
+ }
+
+ inline HWND CTabbedMDI::Create(CWnd* pParent /* = NULL*/)
+ {
+ CLIENTCREATESTRUCT clientcreate ;
+ clientcreate.hWindowMenu = m_hWnd;
+ clientcreate.idFirstChild = IDW_FIRSTCHILD ;
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE | MDIS_ALLCHILDSTYLES;
+
+ // Create the MDICLIENT view window
+ if (!CreateEx(0, _T("MDICLIENT"), _T(""),
+ dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate))
+ throw CWinException(_T("CMDIClient::Create ... CreateEx failed"));
+
+ return m_hWnd;
+ }
+
+ inline CWnd* CTabbedMDI::GetActiveMDIChild() const
+ {
+ CWnd* pView = NULL;
+ int nTab = GetTab().GetCurSel();
+ if (nTab >= 0)
+ {
+ TabPageInfo tbi = GetTab().GetTabPageInfo(nTab);
+ pView = tbi.pView;
+ }
+
+ return pView;
+ }
+
+ inline int CTabbedMDI::GetActiveMDITab() const
+ {
+ return GetTab().GetCurSel();
+ }
+
+ inline CWnd* CTabbedMDI::GetMDIChild(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).pView;
+ }
+
+ inline int CTabbedMDI::GetMDIChildCount() const
+ {
+ return (int) GetTab().GetAllTabs().size();
+ }
+
+ inline int CTabbedMDI::GetMDIChildID(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).idTab;
+ }
+
+ inline LPCTSTR CTabbedMDI::GetMDIChildTitle(int nTab) const
+ {
+ assert(nTab >= 0);
+ assert(nTab < GetMDIChildCount());
+ return GetTab().GetTabPageInfo(nTab).szTabText;
+ }
+
+ inline BOOL CTabbedMDI::LoadRegistrySettings(tString tsRegistryKeyName)
+ {
+ BOOL bResult = FALSE;
+
+ if (0 != tsRegistryKeyName.size())
+ {
+ tString tsKey = _T("Software\\") + tsRegistryKeyName + _T("\\MDI Children");
+ HKEY hKey = 0;
+ RegOpenKeyEx(HKEY_CURRENT_USER, tsKey.c_str(), 0, KEY_READ, &hKey);
+ if (hKey)
+ {
+ DWORD dwType = REG_BINARY;
+ DWORD BufferSize = sizeof(TabPageInfo);
+ TabPageInfo tbi = {0};
+ int i = 0;
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+
+ // Fill the DockList vector from the registry
+ while (0 == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&tbi, &BufferSize))
+ {
+ CWnd* pWnd = NewMDIChildFromID(tbi.idTab);
+ if (pWnd)
+ {
+ AddMDIChild(pWnd, tbi.szTabText, tbi.idTab);
+ i++;
+ tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+ bResult = TRUE;
+ }
+ else
+ {
+ TRACE(_T("Failed to get TabbedMDI info from registry"));
+ bResult = FALSE;
+ break;
+ }
+ }
+
+ // Load Active MDI Tab from the registry
+ tsSubKey = _T("Active MDI Tab");
+ int nTab;
+ dwType = REG_DWORD;
+ BufferSize = sizeof(int);
+ if(ERROR_SUCCESS == RegQueryValueEx(hKey, tsSubKey.c_str(), NULL, &dwType, (LPBYTE)&nTab, &BufferSize))
+ SetActiveMDITab(nTab);
+ else
+ SetActiveMDITab(0);
+
+ RegCloseKey(hKey);
+ }
+ }
+
+ if (!bResult)
+ CloseAllMDIChildren();
+
+ return bResult;
+ }
+
+ inline CWnd* CTabbedMDI::NewMDIChildFromID(int /*idMDIChild*/)
+ {
+ // Override this function to create new MDI children from IDs as shown below
+ CWnd* pView = NULL;
+ /* switch(idTab)
+ {
+ case ID_SIMPLE:
+ pView = new CViewSimple;
+ break;
+ case ID_RECT:
+ pView = new CViewRect;
+ break;
+ default:
+ TRACE(_T("Unknown MDI child ID\n"));
+ break;
+ } */
+
+ return pView;
+ }
+
+ inline void CTabbedMDI::OnCreate()
+ {
+ GetTab().Create(this);
+ GetTab().SetFixedWidth(TRUE);
+ GetTab().SetOwnerDraw(TRUE);
+ }
+
+ inline void CTabbedMDI::OnDestroy(WPARAM /*wParam*/, LPARAM /*lParam*/ )
+ {
+ CloseAllMDIChildren();
+ }
+
+ inline LRESULT CTabbedMDI::OnNotify(WPARAM /*wParam*/, LPARAM lParam)
+ {
+ LPNMHDR pnmhdr = (LPNMHDR)lParam;
+ if (pnmhdr->code == UWM_TAB_CHANGED)
+ RecalcLayout();
+
+ return 0L;
+ }
+
+ inline void CTabbedMDI::OnWindowPosChanged(WPARAM /*wParam*/, LPARAM /*lParam*/)
+ {
+ RecalcLayout();
+ }
+
+ inline void CTabbedMDI::RecalcLayout()
+ {
+ if (GetTab().IsWindow())
+ {
+ if (GetTab().GetItemCount() >0)
+ {
+ CRect rcClient = GetClientRect();
+ GetTab().SetWindowPos(NULL, rcClient, SWP_SHOWWINDOW);
+ GetTab().UpdateWindow();
+ }
+ else
+ {
+ CRect rcClient = GetClientRect();
+ GetTab().SetWindowPos(NULL, rcClient, SWP_HIDEWINDOW);
+ Invalidate();
+ }
+ }
+ }
+
+ inline BOOL CTabbedMDI::SaveRegistrySettings(tString tsRegistryKeyName)
+ {
+ if (0 != tsRegistryKeyName.size())
+ {
+ tString tsKeyName = _T("Software\\") + tsRegistryKeyName;
+ HKEY hKey = NULL;
+ HKEY hKeyMDIChild = NULL;
+
+ try
+ {
+ if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, tsKeyName.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ RegDeleteKey(hKey, _T("MDI Children"));
+ if (ERROR_SUCCESS != RegCreateKeyEx(hKey, _T("MDI Children"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyMDIChild, NULL))
+ throw (CWinException(_T("RegCreateKeyEx Failed")));
+
+ for (int i = 0; i < GetMDIChildCount(); ++i)
+ {
+ TCHAR szNumber[16];
+ tString tsSubKey = _T("MDI Child ");
+ tsSubKey += _itot(i, szNumber, 10);
+ TabPageInfo pdi = GetTab().GetTabPageInfo(i);
+ if (ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, tsSubKey.c_str(), 0, REG_BINARY, (LPBYTE)&pdi, sizeof(TabPageInfo)))
+ throw (CWinException(_T("RegSetValueEx Failed")));
+ }
+
+ // Add Active Tab to the registry
+ tString tsSubKey = _T("Active MDI Tab");
+ int nTab = GetActiveMDITab();
+ if(ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, tsSubKey.c_str(), 0, REG_DWORD, (LPBYTE)&nTab, sizeof(int)))
+ throw (CWinException(_T("RegSetValueEx failed")));
+
+ RegCloseKey(hKeyMDIChild);
+ RegCloseKey(hKey);
+ }
+ catch (const CWinException& e)
+ {
+ // Roll back the registry changes by deleting the subkeys
+ if (hKey)
+ {
+ if (hKeyMDIChild)
+ {
+ RegDeleteKey(hKeyMDIChild, _T("MDI Children"));
+ RegCloseKey(hKeyMDIChild);
+ }
+
+ RegDeleteKey(HKEY_CURRENT_USER ,tsKeyName.c_str());
+ RegCloseKey(hKey);
+ }
+
+ e.what();
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+ }
+
+ inline void CTabbedMDI::SetActiveMDIChild(CWnd* pWnd)
+ {
+ assert(pWnd);
+ int nPage = GetTab().GetTabIndex(pWnd);
+ if (nPage >= 0)
+ GetTab().SelectPage(nPage);
+ }
+
+ inline void CTabbedMDI::SetActiveMDITab(int iTab)
+ {
+ assert(::IsWindow(m_hWnd));
+ assert(GetTab().IsWindow());
+ GetTab().SelectPage(iTab);
+ }
+
+ inline LRESULT CTabbedMDI::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_DESTROY:
+ OnDestroy(wParam, lParam);
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ OnWindowPosChanged(wParam, lParam);
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_TAB_H_
diff --git a/external/win32cpp/include/taskdialog.h b/external/win32cpp/include/taskdialog.h
new file mode 100644
index 0000000..2285d1e
--- /dev/null
+++ b/external/win32cpp/include/taskdialog.h
@@ -0,0 +1,811 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////
+// taskdialog.h
+// Declaration of the CTaskDialog class
+
+// A task dialog is a dialog box that can be used to display information
+// and receive simple input from the user. Like a message box, it is
+// formatted by the operating system according to parameters you set.
+// However, a task dialog has many more features than a message box.
+
+// NOTES:
+// Task Dialogs are only supported on Windows Vista and above.
+// Task Dialogs require XP themes enabled (use version 6 of Common Controls)
+// Task Dialogs are always modal.
+
+
+#ifndef _WIN32XX_TASKDIALOG_H_
+#define _WIN32XX_TASKDIALOG_H_
+
+#include "wincore.h"
+
+namespace Win32xx
+{
+
+ class CTaskDialog : public CWnd
+ {
+ public:
+ CTaskDialog();
+ virtual ~CTaskDialog() {}
+
+ void AddCommandControl(int nButtonID, LPCTSTR pszCaption);
+ void AddRadioButton(int nRadioButtonID, LPCTSTR pszCaption);
+ void AddRadioButtonGroup(int nIDRadioButtonsFirst, int nIDRadioButtonsLast);
+ void ClickButton(int nButtonID) const;
+ void ClickRadioButton(int nRadioButtonID) const;
+ LRESULT DoModal(CWnd* pParent = NULL);
+ void ElevateButton(int nButtonID, BOOL bElevated);
+ void EnableButton(int nButtonID, BOOL bEnabled);
+ void EnableRadioButton(int nButtonID, BOOL bEnabled);
+ TASKDIALOGCONFIG GetConfig() const;
+ TASKDIALOG_FLAGS GetOptions() const;
+ int GetSelectedButtonID() const;
+ int GetSelectedRadioButtonID() const;
+ BOOL GetVerificationCheckboxState() const;
+ static BOOL IsSupported();
+ void NavigateTo(CTaskDialog& TaskDialog) const;
+ void RemoveAllButtons();
+ void RemoveAllRadioButtons();
+ void Reset();
+ void SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons);
+ void SetContent(LPCTSTR pszContent);
+ void SetDefaultButton(int nButtonID);
+ void SetDefaultRadioButton(int nRadioButtonID);
+ void SetDialogWidth(UINT nWidth = 0);
+ void SetExpansionArea(LPCTSTR pszExpandedInfo, LPCTSTR pszExpandedLabel = _T(""), LPCTSTR pszCollapsedLabel = _T(""));
+ void SetFooterIcon(HICON hFooterIcon);
+ void SetFooterIcon(LPCTSTR lpszFooterIcon);
+ void SetFooterText(LPCTSTR pszFooter);
+ void SetMainIcon(HICON hMainIcon);
+ void SetMainIcon(LPCTSTR lpszMainIcon);
+ void SetMainInstruction(LPCTSTR pszMainInstruction);
+ void SetOptions(TASKDIALOG_FLAGS dwFlags);
+ void SetProgressBarMarquee(BOOL bEnabled = TRUE, int nMarqueeSpeed = 0);
+ void SetProgressBarPosition(int nProgressPos);
+ void SetProgressBarRange(int nMinRange, int nMaxRange);
+ void SetProgressBarState(int nNewState = PBST_NORMAL);
+ void SetVerificationCheckbox(BOOL bChecked);
+ void SetVerificationCheckboxText(LPCTSTR pszVerificationText);
+ void SetWindowTitle(LPCTSTR pszWindowTitle);
+ static HRESULT CALLBACK StaticTaskDialogProc(HWND hWnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData);
+ void StoreText(std::vector& vWChar, LPCTSTR pFromTChar);
+ void UpdateElementText(TASKDIALOG_ELEMENTS eElement, LPCTSTR pszNewText);
+
+
+ protected:
+ // Override these functions as required
+ virtual BOOL OnTDButtonClicked(int nButtonID);
+ virtual void OnTDConstructed();
+ virtual void OnTDCreated();
+ virtual void OnTDDestroyed();
+ virtual void OnTDExpandButtonClicked(BOOL bExpanded);
+ virtual void OnTDHelp();
+ virtual void OnTDHyperlinkClicked(LPCTSTR pszHref);
+ virtual void OnTDNavigatePage();
+ virtual BOOL OnTDRadioButtonClicked(int nRadioButtonID);
+ virtual BOOL OnTDTimer(DWORD dwTickCount);
+ virtual void OnTDVerificationCheckboxClicked(BOOL bChecked);
+ virtual LRESULT TaskDialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
+ virtual LRESULT TaskDialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CTaskDialog(const CTaskDialog&); // Disable copy construction
+ CTaskDialog& operator = (const CTaskDialog&); // Disable assignment operator
+
+ std::vector m_vButtons;
+ std::vector m_vRadioButtons;
+
+ std::vector< std::vector > m_vButtonsText; // A vector of WCHAR vectors
+ std::vector< std::vector > m_vRadioButtonsText; // A vector of WCHAR vectors
+
+ std::vector m_vWindowTitle;
+ std::vector m_vMainInstruction;
+ std::vector m_vContent;
+ std::vector m_vVerificationText;
+ std::vector m_vExpandedInformation;
+ std::vector m_vExpandedControlText;
+ std::vector m_vCollapsedControlText;
+ std::vector m_vFooter;
+
+ TASKDIALOGCONFIG m_tc;
+ int m_SelectedButtonID;
+ int m_SelectedRadioButtonID;
+ BOOL m_VerificationCheckboxState;
+ };
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ inline CTaskDialog::CTaskDialog() : m_SelectedButtonID(0), m_SelectedRadioButtonID(0), m_VerificationCheckboxState(FALSE)
+ {
+ ZeroMemory(&m_tc, sizeof(m_tc));
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pfCallback = CTaskDialog::StaticTaskDialogProc;
+ }
+
+ inline void CTaskDialog::AddCommandControl(int nButtonID, LPCTSTR pszCaption)
+ // Adds a command control or push button to the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ std::vector vButtonText;
+ StoreText(vButtonText, pszCaption);
+ m_vButtonsText.push_back(vButtonText); // m_vButtonsText is a vector of vector's
+
+ TASKDIALOG_BUTTON tdb;
+ tdb.nButtonID = nButtonID;
+ tdb.pszButtonText = &m_vButtonsText.back().front();
+
+ m_vButtons.push_back(tdb);
+ }
+
+ inline void CTaskDialog::AddRadioButton(int nRadioButtonID, LPCTSTR pszCaption)
+ // Adds a radio button to the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ std::vector vRadioButtonText;
+ StoreText(vRadioButtonText, pszCaption);
+ m_vRadioButtonsText.push_back(vRadioButtonText); // m_vRadioButtonsText is a vector of vector's
+
+ TASKDIALOG_BUTTON tdb;
+ tdb.nButtonID = nRadioButtonID;
+ tdb.pszButtonText = &m_vRadioButtonsText.back().front();
+
+ m_vRadioButtons.push_back(tdb);
+ }
+
+ inline void CTaskDialog::AddRadioButtonGroup(int nIDRadioButtonsFirst, int nIDRadioButtonsLast)
+ // Adds a range of radio buttons to the Task Dialog.
+ // Assumes the resource ID of the button and it's string match
+ {
+ assert (m_hWnd == NULL);
+ assert(nIDRadioButtonsFirst > 0);
+ assert(nIDRadioButtonsLast > nIDRadioButtonsFirst);
+
+ TASKDIALOG_BUTTON tdb;
+ for (int nID = nIDRadioButtonsFirst; nID <= nIDRadioButtonsLast; ++nID)
+ {
+ tdb.nButtonID = nID;
+ tdb.pszButtonText = MAKEINTRESOURCEW(nID);
+ m_vRadioButtons.push_back(tdb);
+ }
+ }
+
+ inline void CTaskDialog::ClickButton(int nButtonID) const
+ // Simulates the action of a button click in the Task Dialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_BUTTON, (WPARAM)nButtonID, 0);
+ }
+
+ inline void CTaskDialog::ClickRadioButton(int nRadioButtonID) const
+ // Simulates the action of a radio button click in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_RADIO_BUTTON, (WPARAM)nRadioButtonID, 0);
+ }
+
+ inline LRESULT CTaskDialog::DoModal(CWnd* pParent /* = NULL */)
+ // Creates and displays the Task Dialog.
+ {
+ assert (m_hWnd == NULL);
+
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pButtons = m_vButtons.empty()? NULL : &m_vButtons.front();
+ m_tc.cButtons = m_vButtons.size();
+ m_tc.pRadioButtons = m_vRadioButtons.empty()? NULL : &m_vRadioButtons.front();
+ m_tc.cRadioButtons = m_vRadioButtons.size();
+ m_tc.hwndParent = pParent? pParent->GetHwnd() : NULL;
+
+ // Ensure this thread has the TLS index set
+ TLSData* pTLSData = GetApp()->SetTlsIndex();
+
+ // Store the CWnd pointer in thread local storage
+ pTLSData->pCWnd = this;
+
+ // Declare a pointer to the TaskDialogIndirect function
+ HMODULE hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));
+ assert(hComCtl);
+ typedef HRESULT WINAPI TASKDIALOGINDIRECT(const TASKDIALOGCONFIG*, int*, int*, BOOL*);
+ TASKDIALOGINDIRECT* pTaskDialogIndirect = (TASKDIALOGINDIRECT*)::GetProcAddress(hComCtl, "TaskDialogIndirect");
+
+ // Call TaskDialogIndirect through our function pointer
+ LRESULT lr = (*pTaskDialogIndirect)(&m_tc, &m_SelectedButtonID, &m_SelectedRadioButtonID, &m_VerificationCheckboxState);
+
+ FreeLibrary(hComCtl);
+ return lr;
+ }
+
+ inline void CTaskDialog::ElevateButton(int nButtonID, BOOL bElevated)
+ // Adds a shield icon to indicate that the button's action requires elevated privilages.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE, (WPARAM)nButtonID, (LPARAM)bElevated);
+ }
+
+ inline void CTaskDialog::EnableButton(int nButtonID, BOOL bEnabled)
+ // Enables or disables a push button in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_ENABLE_BUTTON, (WPARAM)nButtonID, (LPARAM)bEnabled);
+ }
+ inline void CTaskDialog::EnableRadioButton(int nRadioButtonID, BOOL bEnabled)
+ // Enables or disables a radio button in the TaskDialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_ENABLE_RADIO_BUTTON, (WPARAM)nRadioButtonID, (LPARAM)bEnabled);
+ }
+
+ inline TASKDIALOGCONFIG CTaskDialog::GetConfig() const
+ // Returns the TASKDIALOGCONFIG structure for the Task Dialog.
+ {
+ return m_tc;
+ }
+
+ inline TASKDIALOG_FLAGS CTaskDialog::GetOptions() const
+ // Returns the Task Dialog's options. These are a combination of:
+ // TDF_ENABLE_HYPERLINKS
+ // TDF_USE_HICON_MAIN
+ // TDF_USE_HICON_FOOTER
+ // TDF_ALLOW_DIALOG_CANCELLATION
+ // TDF_USE_COMMAND_LINKS
+ // TDF_USE_COMMAND_LINKS_NO_ICON
+ // TDF_EXPAND_FOOTER_AREA
+ // TDF_EXPANDED_BY_DEFAULT
+ // TDF_VERIFICATION_FLAG_CHECKED
+ // TDF_SHOW_PROGRESS_BAR
+ // TDF_SHOW_MARQUEE_PROGRESS_BAR
+ // TDF_CALLBACK_TIMER
+ // TDF_POSITION_RELATIVE_TO_WINDOW
+ // TDF_RTL_LAYOUT
+ // TDF_NO_DEFAULT_RADIO_BUTTON
+ // TDF_CAN_BE_MINIMIZED
+ {
+ return m_tc.dwFlags;
+ }
+
+ inline int CTaskDialog::GetSelectedButtonID() const
+ // Returns the ID of the selected button.
+ {
+ assert (m_hWnd == NULL);
+ return m_SelectedButtonID;
+ }
+
+ inline int CTaskDialog::GetSelectedRadioButtonID() const
+ // Returns the ID of the selected radio button.
+ {
+ assert (m_hWnd == NULL);
+ return m_SelectedRadioButtonID;
+ }
+
+ inline BOOL CTaskDialog::GetVerificationCheckboxState() const
+ // Returns the state of the verification check box.
+ {
+ assert (m_hWnd == NULL);
+ return m_VerificationCheckboxState;
+ }
+
+ inline BOOL CTaskDialog::IsSupported()
+ // Returns true if TaskDialogs are supported on this system.
+ {
+ HMODULE hModule = ::LoadLibrary(_T("COMCTL32.DLL"));
+ assert(hModule);
+
+ BOOL bResult = (BOOL)::GetProcAddress(hModule, "TaskDialogIndirect");
+
+ ::FreeLibrary(hModule);
+ return bResult;
+ }
+
+ inline void CTaskDialog::NavigateTo(CTaskDialog& TaskDialog) const
+ // Replaces the information displayed by the task dialog.
+ {
+ assert(m_hWnd);
+ TASKDIALOGCONFIG tc = TaskDialog.GetConfig();
+ SendMessage(TDM_NAVIGATE_PAGE, 0, (LPARAM)&tc);
+ }
+
+ inline BOOL CTaskDialog::OnTDButtonClicked(int nButtonID)
+ // Called when the user selects a button or command link.
+ {
+ UNREFERENCED_PARAMETER(nButtonID);
+
+ // return TRUE to prevent the task dialog from closing
+ return FALSE;
+ }
+
+ inline void CTaskDialog::OnTDConstructed()
+ // Called when the task dialog is constructed, before it is displayed.
+ {}
+
+ inline void CTaskDialog::OnTDCreated()
+ // Called when the task dialog is displayed.
+ {}
+
+ inline void CTaskDialog::OnTDDestroyed()
+ // Called when the task dialog is destroyed.
+ {
+ }
+
+ inline void CTaskDialog::OnTDExpandButtonClicked(BOOL bExpanded)
+ // Called when the expand button is clicked.
+ {
+ UNREFERENCED_PARAMETER(bExpanded);
+ }
+
+ inline void CTaskDialog::OnTDHelp()
+ // Called when the user presses F1 on the keyboard.
+ {}
+
+ inline void CTaskDialog::OnTDHyperlinkClicked(LPCTSTR pszHref)
+ // Called when the user clicks on a hyperlink.
+ {
+ UNREFERENCED_PARAMETER(pszHref);
+ }
+
+ inline void CTaskDialog::OnTDNavigatePage()
+ // Called when a navigation has occurred.
+ {}
+
+ inline BOOL CTaskDialog::OnTDRadioButtonClicked(int nRadioButtonID)
+ // Called when the user selects a radio button.
+ {
+ UNREFERENCED_PARAMETER(nRadioButtonID);
+ return TRUE;
+ }
+
+ inline BOOL CTaskDialog::OnTDTimer(DWORD dwTickCount)
+ // Called every 200 milliseconds (aproximately) when the TDF_CALLBACK_TIMER flag is set.
+ {
+ UNREFERENCED_PARAMETER(dwTickCount);
+
+ // return TRUE to reset the tick count
+ return FALSE;
+ }
+
+ inline void CTaskDialog::OnTDVerificationCheckboxClicked(BOOL bChecked)
+ // Called when the user clicks the Task Dialog verification check box.
+ {
+ UNREFERENCED_PARAMETER(bChecked);
+ }
+
+ inline void CTaskDialog::RemoveAllButtons()
+ // Removes all push buttons from the task dialog.
+ {
+ assert (m_hWnd == NULL);
+ m_vButtons.clear();
+ m_vButtonsText.clear();
+ }
+
+ inline void CTaskDialog::RemoveAllRadioButtons()
+ // Removes all radio buttons from the task dialog.
+ {
+ assert (m_hWnd == NULL);
+ m_vRadioButtons.clear();
+ m_vRadioButtonsText.clear();
+ }
+
+ inline void CTaskDialog::Reset()
+ // Returns the dialog to its default state.
+ {
+ assert (m_hWnd == NULL);
+
+ RemoveAllButtons();
+ RemoveAllRadioButtons();
+ ZeroMemory(&m_tc, sizeof(m_tc));
+ m_tc.cbSize = sizeof(m_tc);
+ m_tc.pfCallback = CTaskDialog::StaticTaskDialogProc;
+
+ m_SelectedButtonID = 0;
+ m_SelectedRadioButtonID = 0;
+ m_VerificationCheckboxState = FALSE;
+
+ m_vWindowTitle.clear();
+ m_vMainInstruction.clear();
+ m_vContent.clear();
+ m_vVerificationText.clear();
+ m_vExpandedInformation.clear();
+ m_vExpandedControlText.clear();
+ m_vCollapsedControlText.clear();
+ m_vFooter.clear();
+ }
+
+ inline void CTaskDialog::SetCommonButtons(TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons)
+ // The dwCommonButtons parameter can be a combination of:
+ // TDCBF_OK_BUTTON OK button
+ // TDCBF_YES_BUTTON Yes button
+ // TDCBF_NO_BUTTON No button
+ // TDCBF_CANCEL_BUTTON Cancel button
+ // TDCBF_RETRY_BUTTON Retry button
+ // TDCBF_CLOSE_BUTTON Close button
+ {
+ assert (m_hWnd == NULL);
+ m_tc.dwCommonButtons = dwCommonButtons;
+ }
+
+ inline void CTaskDialog::SetContent(LPCTSTR pszContent)
+ // Sets the task dialog's primary content.
+ {
+ StoreText(m_vContent, pszContent);
+ m_tc.pszContent = &m_vContent.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_CONTENT, (LPARAM)(LPCWSTR)T2W(pszContent));
+ }
+
+ inline void CTaskDialog::SetDefaultButton(int nButtonID)
+ // Sets the task dialog's default button.
+ // Can be either a button ID or one of the common buttons
+ {
+ assert (m_hWnd == NULL);
+ m_tc.nDefaultButton = nButtonID;
+ }
+
+ inline void CTaskDialog::SetDefaultRadioButton(int nRadioButtonID)
+ // Sets the default radio button.
+ {
+ assert (m_hWnd == NULL);
+ m_tc.nDefaultRadioButton = nRadioButtonID;
+ }
+
+ inline void CTaskDialog::SetDialogWidth(UINT nWidth /*= 0*/)
+ // The width of the task dialog's client area. If 0, the
+ // task dialog manager will calculate the ideal width.
+ {
+ assert (m_hWnd == NULL);
+ m_tc.cxWidth = nWidth;
+ }
+
+ inline void CTaskDialog::SetExpansionArea(LPCTSTR pszExpandedInfo, LPCTSTR pszExpandedLabel /* = _T("")*/, LPCTSTR pszCollapsedLabel /* = _T("")*/)
+ // Sets the text in the expandable area of the Task Dialog.
+ {
+ StoreText(m_vExpandedInformation, pszExpandedInfo);
+ m_tc.pszExpandedInformation = &m_vExpandedInformation.front();
+
+ StoreText(m_vExpandedControlText, pszExpandedLabel);
+ m_tc.pszExpandedControlText = &m_vExpandedControlText.front();
+
+ StoreText(m_vCollapsedControlText, pszCollapsedLabel);
+ m_tc.pszCollapsedControlText = &m_vCollapsedControlText.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_EXPANDED_INFORMATION, (LPARAM)(LPCWSTR)T2W(pszExpandedInfo));
+ }
+
+ inline void CTaskDialog::SetFooterIcon(HICON hFooterIcon)
+ // Sets the icon that will be displayed in the Task Dialog's footer.
+ {
+ m_tc.hFooterIcon = hFooterIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_FOOTER, (LPARAM)hFooterIcon);
+ }
+
+ inline void CTaskDialog::SetFooterIcon(LPCTSTR lpszFooterIcon)
+ // Sets the icon that will be displayed in the Task Dialog's footer.
+ // Possible icons:
+ // TD_ERROR_ICON A stop-sign icon appears in the task dialog.
+ // TD_WARNING_ICON An exclamation-point icon appears in the task dialog.
+ // TD_INFORMATION_ICON An icon consisting of a lowercase letter i in a circle appears in the task dialog.
+ // TD_SHIELD_ICON A shield icon appears in the task dialog.
+ // or a value passed via MAKEINTRESOURCE
+ {
+ m_tc.pszFooterIcon = (LPCWSTR)lpszFooterIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_FOOTER, (LPARAM)lpszFooterIcon);
+ }
+
+ inline void CTaskDialog::SetFooterText(LPCTSTR pszFooter)
+ // Sets the text that will be displayed in the Task Dialog's footer.
+ {
+ StoreText(m_vFooter, pszFooter);
+ m_tc.pszFooter = &m_vFooter.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_FOOTER, (LPARAM)(LPCWSTR)T2W(pszFooter));
+ }
+
+ inline void CTaskDialog::SetMainIcon(HICON hMainIcon)
+ // Sets Task Dialog's main icon.
+ {
+ m_tc.hMainIcon = hMainIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_MAIN, (LPARAM)hMainIcon);
+ }
+
+ inline void CTaskDialog::SetMainIcon(LPCTSTR lpszMainIcon)
+ // Sets Task Dialog's main icon.
+ // Possible icons:
+ // TD_ERROR_ICON A stop-sign icon appears in the task dialog.
+ // TD_WARNING_ICON An exclamation-point icon appears in the task dialog.
+ // TD_INFORMATION_ICON An icon consisting of a lowercase letter i in a circle appears in the task dialog.
+ // TD_SHIELD_ICON A shield icon appears in the task dialog.
+ // or a value passed via MAKEINTRESOURCE
+ //
+ // Note: Some values of main icon will also generate a MessageBeep when the TaskDialog is created.
+ {
+ m_tc.pszMainIcon = (LPCWSTR)lpszMainIcon;
+
+ if (IsWindow())
+ SendMessage(TDM_UPDATE_ICON, (WPARAM)TDIE_ICON_MAIN, (LPARAM)lpszMainIcon);
+ }
+
+ inline void CTaskDialog::SetMainInstruction(LPCTSTR pszMainInstruction)
+ // Sets the Task Dialog's main instruction text.
+ {
+ StoreText(m_vMainInstruction, pszMainInstruction);
+ m_tc.pszMainInstruction = &m_vMainInstruction.front();
+
+ if (IsWindow())
+ SendMessage(TDM_SET_ELEMENT_TEXT, (WPARAM)TDE_FOOTER, (LPARAM)(LPCWSTR)T2W(pszMainInstruction));
+ }
+
+ inline void CTaskDialog::SetOptions(TASKDIALOG_FLAGS dwFlags)
+ // Sets the Task Dialog's options. These are a combination of:
+ // TDF_ENABLE_HYPERLINKS
+ // TDF_USE_HICON_MAIN
+ // TDF_USE_HICON_FOOTER
+ // TDF_ALLOW_DIALOG_CANCELLATION
+ // TDF_USE_COMMAND_LINKS
+ // TDF_USE_COMMAND_LINKS_NO_ICON
+ // TDF_EXPAND_FOOTER_AREA
+ // TDF_EXPANDED_BY_DEFAULT
+ // TDF_VERIFICATION_FLAG_CHECKED
+ // TDF_SHOW_PROGRESS_BAR
+ // TDF_SHOW_MARQUEE_PROGRESS_BAR
+ // TDF_CALLBACK_TIMER
+ // TDF_POSITION_RELATIVE_TO_WINDOW
+ // TDF_RTL_LAYOUT
+ // TDF_NO_DEFAULT_RADIO_BUTTON
+ // TDF_CAN_BE_MINIMIZED
+ {
+ assert (m_hWnd == NULL);
+ m_tc.dwFlags = dwFlags;
+ }
+
+ inline void CTaskDialog::SetProgressBarMarquee(BOOL bEnabled /* = TRUE*/, int nMarqueeSpeed /* = 0*/)
+ // Starts and stops the marquee display of the progress bar, and sets the speed of the marquee.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_MARQUEE, (WPARAM)bEnabled, (LPARAM)nMarqueeSpeed);
+ }
+
+ inline void CTaskDialog::SetProgressBarPosition(int nProgressPos)
+ // Sets the current position for a progress bar.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_POS, (WPARAM)nProgressPos, 0);
+ }
+
+ inline void CTaskDialog::SetProgressBarRange(int nMinRange, int nMaxRange)
+ // Sets the minimum and maximum values for the hosted progress bar.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_RANGE, 0, MAKELPARAM(nMinRange, nMaxRange));
+ }
+
+ inline void CTaskDialog::SetProgressBarState(int nNewState /* = PBST_NORMAL*/)
+ // Sets the current state of the progress bar. Possible states are:
+ // PBST_NORMAL
+ // PBST_PAUSE
+ // PBST_ERROR
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_SET_PROGRESS_BAR_STATE, (WPARAM)nNewState, 0);
+ }
+
+ inline void CTaskDialog::SetVerificationCheckbox(BOOL bChecked)
+ // Simulates a click on the verification checkbox of the Task Dialog, if it exists.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_CLICK_VERIFICATION, (WPARAM)bChecked, (LPARAM)bChecked);
+ }
+
+ inline void CTaskDialog::SetVerificationCheckboxText(LPCTSTR pszVerificationText)
+ // Sets the text for the verification check box.
+ {
+ assert (m_hWnd == NULL);
+ StoreText(m_vVerificationText, pszVerificationText);
+ m_tc.pszVerificationText = &m_vVerificationText.front();
+ }
+
+ inline void CTaskDialog::SetWindowTitle(LPCTSTR pszWindowTitle)
+ // Sets the Task Dialog's window title.
+ {
+ assert (m_hWnd == NULL);
+ StoreText(m_vWindowTitle, pszWindowTitle);
+ m_tc.pszWindowTitle = &m_vWindowTitle.front();
+ }
+
+ inline HRESULT CALLBACK CTaskDialog::StaticTaskDialogProc(HWND hWnd, UINT uNotification, WPARAM wParam, LPARAM lParam, LONG_PTR dwRefData)
+ // TaskDialogs direct their messages here.
+ {
+ UNREFERENCED_PARAMETER(dwRefData);
+
+ assert( GetApp() );
+
+ try
+ {
+ CTaskDialog* t = (CTaskDialog*)GetApp()->GetCWndFromMap(hWnd);
+ if (0 == t)
+ {
+ // The CTaskDialog pointer wasn't found in the map, so add it now
+
+ // Retrieve the pointer to the TLS Data
+ TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
+ if (NULL == pTLSData)
+ throw CWinException(_T("Unable to get TLS"));
+
+ // Retrieve pointer to CTaskDialog object from Thread Local Storage TLS
+ t = (CTaskDialog*)(pTLSData->pCWnd);
+ if (NULL == t)
+ throw CWinException(_T("Failed to route message"));
+
+ pTLSData->pCWnd = NULL;
+
+ // Store the CTaskDialog pointer in the HWND map
+ t->m_hWnd = hWnd;
+ t->AddToMap();
+ }
+
+ return t->TaskDialogProc(uNotification, wParam, lParam);
+ }
+
+ catch (const CWinException &e)
+ {
+ // Most CWinExceptions will end up here unless caught earlier.
+ e.what();
+ }
+
+ return 0L;
+
+ } // LRESULT CALLBACK StaticTaskDialogProc(...)
+
+ inline void CTaskDialog::StoreText(std::vector& vWChar, LPCTSTR pFromTChar)
+ {
+ // Stores a TChar string in a WCHAR vector
+
+ std::vector vTChar;
+
+ if (IS_INTRESOURCE(pFromTChar)) // support MAKEINTRESOURCE
+ {
+ tString ts = LoadString((UINT)pFromTChar);
+ int len = pFromTChar? ts.length() + 1 : 1;
+ vTChar.assign(len, _T('\0'));
+ vWChar.assign(len, _T('\0'));
+ if (pFromTChar)
+ lstrcpy( &vTChar.front(), ts.c_str());
+
+ }
+ else
+ {
+ int len = lstrlen(pFromTChar) +1;
+ vTChar.assign(len, _T('\0'));
+ vWChar.assign(len, _T('\0'));
+ lstrcpy( &vTChar.front(), pFromTChar);
+ }
+
+ lstrcpyW(&vWChar.front(), T2W(&vTChar.front()) );
+ }
+
+ inline LRESULT CTaskDialog::TaskDialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ // Handles the Task Dialog's notificaions.
+ {
+ switch(uMsg)
+ {
+ case TDN_BUTTON_CLICKED:
+ return OnTDButtonClicked((int)wParam);
+
+ case TDN_CREATED:
+ OnTDCreated();
+ break;
+ case TDN_DESTROYED:
+ Cleanup(); // Prepare this CWnd to be reused.
+ OnTDDestroyed();
+ break;
+ case TDN_DIALOG_CONSTRUCTED:
+ OnTDConstructed();
+ break;
+ case TDN_EXPANDO_BUTTON_CLICKED:
+ OnTDExpandButtonClicked((BOOL)wParam);
+ break;
+ case TDN_HELP:
+ OnTDHelp();
+ break;
+ case TDN_HYPERLINK_CLICKED:
+ OnTDHyperlinkClicked(W2T((LPCWSTR)lParam));
+ break;
+ case TDN_NAVIGATED:
+ OnTDNavigatePage();
+ break;
+ case TDN_RADIO_BUTTON_CLICKED:
+ OnTDRadioButtonClicked((int)wParam);
+ break;
+ case TDN_TIMER:
+ return OnTDTimer((DWORD)wParam);
+
+ case TDN_VERIFICATION_CLICKED:
+ OnTDVerificationCheckboxClicked((BOOL)wParam);
+ break;
+ }
+
+ return S_OK;
+ }
+
+ inline LRESULT CTaskDialog::TaskDialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ // Override this function in your class derrived from CDialog if you wish to handle messages
+ // A typical function might look like this:
+
+ // switch (uMsg)
+ // {
+ // case MESSAGE1: // Some Windows API message
+ // OnMessage1(); // A user defined function
+ // break; // Also do default processing
+ // case MESSAGE2:
+ // OnMessage2();
+ // return x; // Don't do default processing, but instead return
+ // // a value recommended by the Windows API documentation
+ // }
+
+ // Always pass unhandled messages on to TaskDialogProcDefault
+ return TaskDialogProcDefault(uMsg, wParam, lParam);
+ }
+
+ inline void CTaskDialog::UpdateElementText(TASKDIALOG_ELEMENTS eElement, LPCTSTR pszNewText)
+ // Updates a text element on the Task Dialog.
+ {
+ assert(m_hWnd);
+ SendMessage(TDM_UPDATE_ELEMENT_TEXT, (WPARAM)eElement, (LPARAM)(LPCWSTR)T2W(pszNewText));
+ }
+
+}
+
+
+
+#endif // _WIN32XX_TASKDIALOG_H_
\ No newline at end of file
diff --git a/external/win32cpp/include/thread.h b/external/win32cpp/include/thread.h
new file mode 100644
index 0000000..5564d88
--- /dev/null
+++ b/external/win32cpp/include/thread.h
@@ -0,0 +1,241 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+// The CThread class simplifies the use of threads with Win32++.
+// To use threads in your Win32++ application, inherit a class from
+// CThread, and override InitInstance. When your class is instanciated,
+// a new thread is started, and the InitInstance function is called to
+// run in the new thread.
+
+// If your thread is used to run one or more windows, InitInstance should
+// return TRUE, causing the MessageLoop function to be called. If your
+// thread doesn't require a MessageLoop, it should return FALSE. Threads
+// which don't run a message loop as sometimes referred to as "worker" threads.
+
+// Note: It is your job to end the thread before CThread ends!
+// To end a thread with a message loop, use PostQuitMessage on the thread.
+// To end a thread without a message loop, set an event, and end the thread
+// when the event is received.
+
+// Hint: It is never a good idea to use things like TerminateThread or ExitThread to
+// end your thread. These represent poor programming techniques, and are likely
+// to leak memory and resources.
+
+// More Hints for thread programming:
+// 1) Avoid using SendMessage between threads, as this will cause one thread to wait for
+// the other to respond. Use PostMessage between threads to avoid this problem.
+// 2) Access to variables and resources shared between threads need to be made thread safe.
+// Having one thread modify a resouce or variable while another thread is accessing it is
+// a recipe for disaster.
+// 3) Thread Local Storage (TLS) can be used to replace global variables to make them thread
+// safe. With TLS, each thread gets its own copy of the variable.
+// 4) Critical Sections can be used to make shared resources thread safe.
+// 5) Window messages (including user defined messages) can be posted between GUI threads to
+// communicate information between them.
+// 6) Events (created by CreateEvent) can be used to comunicate information between threads
+// (both GUI and worker threads).
+// 7) Avoid using sleep to synchronise threads. Generally speaking, the various wait
+// functions (e.g. WaitForSingleObject) will be better for this.
+
+// About Threads:
+// Each program that executes has a "process" allocated to it. A process has one or more
+// threads. Threads run independantly of each other. It is the job of the operating system
+// to manage the running of the threads, and do the task switching between threads as required.
+// Systems with multiple CPUs will be able to run as many threads simultaneously as there are
+// CPUs.
+
+// Threads behave like a program within a program. When the main thread starts, the application
+// runs the WinMain function and ends when WinMain ends. When another thread starts, it too
+// will run the function provided to it, and end when that function ends.
+
+
+#ifndef _WIN32XX_WINTHREAD_H_
+#define _WIN32XX_WINTHREAD_H_
+
+
+#include
+
+
+namespace Win32xx
+{
+
+ //////////////////////////////////////
+ // Declaration of the CThread class
+ //
+ class CThread
+ {
+ public:
+ CThread();
+ CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
+ virtual ~CThread();
+
+ // Overridables
+ virtual BOOL InitInstance();
+ virtual int MessageLoop();
+
+ // Operations
+ HANDLE GetThread() const;
+ int GetThreadID() const;
+ int GetThreadPriority() const;
+ DWORD ResumeThread() const;
+ BOOL SetThreadPriority(int nPriority) const;
+ DWORD SuspendThread() const;
+
+ private:
+ CThread(const CThread&); // Disable copy construction
+ CThread& operator = (const CThread&); // Disable assignment operator
+ void CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag);
+ static UINT WINAPI StaticThreadCallback(LPVOID pCThread);
+
+ HANDLE m_hThread; // Handle of this thread
+ UINT m_nThreadID; // ID of this thread
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ ///////////////////////////////////////
+ // Definitions for the CThread class
+ //
+ inline CThread::CThread() : m_hThread(0), m_nThreadID(0)
+ {
+ CreateThread(0, 0, CREATE_SUSPENDED);
+ }
+
+ inline CThread::CThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
+ : m_hThread(0), m_nThreadID(0)
+
+ {
+ // Valid argument values:
+ // pSecurityAttributes Either a pointer to SECURITY_ATTRIBUTES or 0
+ // stack_size Either the stack size or 0
+ // initflag Either CREATE_SUSPENDED or 0
+
+ CreateThread(pSecurityAttributes, stack_size, initflag);
+ }
+
+ inline CThread::~CThread()
+ {
+ // A thread's state is set to signalled when the thread terminates.
+ // If your thread is still running at this point, you have a bug.
+ if (0 != WaitForSingleObject(m_hThread, 0))
+ TRACE(_T("*** Error *** Ending CThread before ending its thread\n"));
+
+ // Close the thread's handle
+ ::CloseHandle(m_hThread);
+ }
+
+ inline void CThread::CreateThread(LPSECURITY_ATTRIBUTES pSecurityAttributes, unsigned stack_size, unsigned initflag)
+ {
+ // NOTE: By default, the thread is created in the default state.
+ m_hThread = (HANDLE)_beginthreadex(pSecurityAttributes, stack_size, CThread::StaticThreadCallback, (LPVOID) this, initflag, &m_nThreadID);
+
+ if (0 == m_hThread)
+ throw CWinException(_T("Failed to create thread"));
+ }
+
+ inline HANDLE CThread::GetThread() const
+ {
+ assert(m_hThread);
+ return m_hThread;
+ }
+
+ inline int CThread::GetThreadID() const
+ {
+ assert(m_hThread);
+ return m_nThreadID;
+ }
+
+ inline int CThread::GetThreadPriority() const
+ {
+ assert(m_hThread);
+ return ::GetThreadPriority(m_hThread);
+ }
+
+ inline BOOL CThread::InitInstance()
+ {
+ // Override this function to perform tasks when the thread starts.
+
+ // return TRUE to run a message loop, otherwise return FALSE.
+ // A thread with a window must run a message loop.
+ return FALSE;
+ }
+
+ inline int CThread::MessageLoop()
+ {
+ // Override this function if your thread needs a different message loop
+ return GetApp()->MessageLoop();
+ }
+
+ inline DWORD CThread::ResumeThread() const
+ {
+ assert(m_hThread);
+ return ::ResumeThread(m_hThread);
+ }
+
+ inline DWORD CThread::SuspendThread() const
+ {
+ assert(m_hThread);
+ return ::SuspendThread(m_hThread);
+ }
+
+ inline BOOL CThread::SetThreadPriority(int nPriority) const
+ {
+ assert(m_hThread);
+ return ::SetThreadPriority(m_hThread, nPriority);
+ }
+
+ inline UINT WINAPI CThread::StaticThreadCallback(LPVOID pCThread)
+ // When the thread starts, it runs this function.
+ {
+ // Get the pointer for this CMyThread object
+ CThread* pThread = (CThread*)pCThread;
+
+ if (pThread->InitInstance())
+ return pThread->MessageLoop();
+
+ return 0;
+ }
+
+}
+
+#endif // #define _WIN32XX_WINTHREAD_H_
+
diff --git a/external/win32cpp/include/toolbar.h b/external/win32cpp/include/toolbar.h
new file mode 100644
index 0000000..1ed005a
--- /dev/null
+++ b/external/win32cpp/include/toolbar.h
@@ -0,0 +1,1361 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+#ifndef _WIN32XX_TOOLBAR_H_
+#define _WIN32XX_TOOLBAR_H_
+
+#include "wincore.h"
+#include "gdi.h"
+#include "rebar.h"
+
+
+namespace Win32xx
+{
+
+ struct ToolBarTheme
+ {
+ BOOL UseThemes; // TRUE if themes are used
+ COLORREF clrHot1; // Colour 1 for hot button
+ COLORREF clrHot2; // Colour 2 for hot button
+ COLORREF clrPressed1; // Colour 1 for pressed button
+ COLORREF clrPressed2; // Colour 2 for pressed button
+ COLORREF clrOutline; // Colour for border outline
+ };
+
+
+ ////////////////////////////////////
+ // Declaration of the CToolBar class
+ //
+ class CToolBar : public CWnd
+ {
+ public:
+ CToolBar();
+ virtual ~CToolBar();
+
+ // Operations
+ virtual int AddBitmap(UINT ToolBarID);
+ virtual BOOL AddButton(UINT nID, BOOL bEnabled = TRUE);
+ virtual void Destroy();
+ virtual BOOL ReplaceBitmap(UINT NewToolBarID);
+ virtual BOOL SetBitmap(UINT nID);
+ virtual int SetButtons(const std::vector& vToolBarData) const;
+ virtual BOOL SetButtonText(int idButton, LPCTSTR szText);
+ virtual BOOL SetImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID);
+
+ // Wrappers for Win32 API functions
+ BOOL AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) const;
+ int AddString(UINT nStringID) const;
+ int AddStrings(LPCTSTR lpszStrings) const;
+ void Autosize() const;
+ void CheckButton(int idButton, BOOL fCheck) const;
+ int CommandToIndex(int idButton) const;
+ BOOL DeleteButton(int iButton) const;
+ BOOL DisableButton(int idButton) const;
+ BOOL EnableButton(int idButton) const;
+ BOOL GetButton(int iButton, LPTBBUTTON lpButton) const;
+ int GetButtonCount() const;
+ DWORD GetButtonSize() const;
+ UINT GetButtonState(int idButton) const;
+ BYTE GetButtonStyle(int idButton) const;
+ CString GetButtonText(int idButton) const;
+ int GetCommandID(int iIndex) const;
+ HIMAGELIST GetDisabledImageList() const;
+ int GetHotItem() const;
+ HIMAGELIST GetHotImageList() const;
+ HIMAGELIST GetImageList() const;
+ CRect GetItemRect(int iIndex) const;
+ CSize GetMaxSize() const;
+ DWORD GetPadding() const;
+ CRect GetRect(int idButton) const;
+ int GetRows() const;
+ int GetTextRows() const;
+ HWND GetToolTips() const;
+ BOOL HasText() const;
+ BOOL HideButton(int idButton, BOOL fShow) const;
+ int HitTest() const;
+ BOOL Indeterminate(int idButton, BOOL fIndeterminate) const;
+ BOOL InsertButton(int iButton, LPTBBUTTON lpButton) const;
+ BOOL IsButtonHidden(int idButton) const;
+ BOOL IsButtonHighlighted(int idButton) const;
+ BOOL IsButtonIndeterminate(int idButton) const;
+ BOOL IsButtonPressed(int idButton) const;
+ int MapAccelerator(TCHAR chAccel) const;
+ BOOL MarkButton(int idButton) const;
+ BOOL MoveButton(UINT uOldPos, UINT uNewPos) const;
+ BOOL PressButton(int idButton, BOOL fPress) const;
+ void SaveRestore(BOOL fSave, TBSAVEPARAMS* ptbsp) const;
+ BOOL SetBitmapSize(int cx, int cy) const;
+ BOOL SetButtonSize(int cx, int cy) const;
+ BOOL SetButtonState(int idButton, UINT State) const;
+ BOOL SetButtonStyle(int idButton, BYTE Style) const;
+ BOOL SetButtonWidth(int idButton, int nWidth) const;
+ BOOL SetCommandID(int iIndex, int idButton) const;
+ HIMAGELIST SetDisableImageList(HIMAGELIST himlNewDisabled) const;
+ DWORD SetDrawTextFlags(DWORD dwMask, DWORD dwDTFlags) const;
+ DWORD SetExtendedStyle(DWORD dwExStyle) const;
+ HIMAGELIST SetHotImageList(HIMAGELIST himlNewHot) const;
+ int SetHotItem(int iHot) const;
+ HIMAGELIST SetImageList(HIMAGELIST himlNew) const;
+ BOOL SetIndent(int iIndent) const;
+ BOOL SetMaxTextRows(int iMaxRows) const;
+ BOOL SetPadding(int cx, int cy) const;
+ void SetToolTips(HWND hwndToolTip) const;
+
+ // Attributes
+ std::vector& GetToolBarData() const {return (std::vector &)m_vToolBarData;}
+ ToolBarTheme& GetToolBarTheme() {return m_Theme;}
+ void SetToolBarTheme(ToolBarTheme& Theme);
+
+ protected:
+ // Overridables
+ virtual void OnCreate();
+ virtual void OnDestroy();
+ virtual void OnWindowPosChanging(WPARAM wParam, LPARAM lParam);
+ virtual LRESULT OnCustomDraw(NMHDR* pNMHDR);
+ virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam);
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void PreRegisterClass(WNDCLASS &wc);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CToolBar(const CToolBar&); // Disable copy construction
+ CToolBar& operator = (const CToolBar&); // Disable assignment operator
+
+ std::vector m_vToolBarData; // vector of resource IDs for toolbar buttons
+ std::map m_StringMap; // a map of strings used in SetButtonText
+ UINT m_OldToolBarID; // Bitmap Resource ID, used in AddBitmap/ReplaceBitmap
+ ToolBarTheme m_Theme; // The theme structure
+ BOOL m_bDrawArrowBkgrnd; // True if a seperate arrow background is to be drawn
+
+ }; // class CToolBar
+
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////
+ // Definitions for the CToolBar class
+ //
+ inline CToolBar::CToolBar() : m_OldToolBarID(0), m_bDrawArrowBkgrnd(FALSE)
+ {
+ ZeroMemory(&m_Theme, sizeof(ToolBarTheme));
+ }
+
+ inline CToolBar::~CToolBar()
+ {
+ }
+
+ inline int CToolBar::AddBitmap(UINT ToolBarID)
+ // Adds one or more images to the list of button images available for a toolbar.
+
+ // Note: AddBitmap supports a maximum colour depth of 8 bits (256 colours)
+ // For more colours, use an ImageList instead
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iNumButtons = 0;
+ std::vector::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ TBADDBITMAP tbab = {0};
+ tbab.hInst = GetApp()->GetResourceHandle();
+ tbab.nID = ToolBarID;
+ int iResult = (int)SendMessage(TB_ADDBITMAP, iNumButtons, (LPARAM)&tbab);
+
+ if (-1 != iResult)
+ m_OldToolBarID = ToolBarID;
+
+ return iResult;
+ }
+
+ inline BOOL CToolBar::AddButton(UINT nID, BOOL bEnabled /* = TRUE */)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ assert(::IsWindow(m_hWnd));
+
+ m_vToolBarData.push_back(nID);
+
+ // TBBUTTON structure for each button in the toolbar
+ TBBUTTON tbb = {0};
+
+ std::vector::iterator iter;
+ int iImages = 0;
+ for(iter = m_vToolBarData.begin(); iter < m_vToolBarData.end(); ++iter)
+ if (0 != *iter) iImages++;
+
+ ZeroMemory(&tbb, sizeof(TBBUTTON));
+
+ if (0 == nID)
+ {
+ tbb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbb.dwData = iImages -1;
+ tbb.iBitmap = iImages -1;
+ tbb.idCommand = nID;
+ tbb.fsState = bEnabled? TBSTATE_ENABLED : 0;
+ tbb.fsStyle = TBSTYLE_BUTTON;
+ }
+
+ // Add the button to the toolbar
+ return (BOOL)SendMessage(TB_ADDBUTTONS, 1L, (LPARAM)&tbb);
+ }
+
+ inline BOOL CToolBar::AddButtons(UINT uNumButtons, LPTBBUTTON lpButtons) const
+ // Adds one or more buttons to a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ADDBUTTONS, (LPARAM)uNumButtons, (WPARAM)lpButtons);
+ }
+
+ inline int CToolBar::AddString(UINT nStringID) const
+ // Adds a new string, passed as a resource ID, to the toolbar's internal list of strings.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_ADDSTRING, (LPARAM)GetApp()->GetResourceHandle(), (WPARAM)nStringID);
+ }
+
+ inline int CToolBar::AddStrings(LPCTSTR lpszStrings) const
+ // Adds a new string or strings to the list of strings available for a toolbar control.
+ // Strings in the buffer must be separated by a null character. You must ensure that the last string has two null terminators.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_ADDSTRING, 0L, (WPARAM)lpszStrings);
+ }
+
+ inline void CToolBar::Autosize() const
+ // Causes a toolbar to be resized.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_AUTOSIZE, 0L, 0L);
+ }
+
+ inline void CToolBar::CheckButton(int idButton, BOOL fCheck) const
+ // Checks or unchecks a given button in a toolbar.
+ // When a button is checked, it is displayed in the pressed state.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_CHECKBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG(fCheck, 0));
+ }
+
+ inline int CToolBar::CommandToIndex(int idButton) const
+ // Retrieves the zero-based index for the button associated with the specified command identifier
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // returns -1 on fail
+ return (int)SendMessage(TB_COMMANDTOINDEX, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::DeleteButton(int iButton) const
+ // Deletes a button from the toolbar.
+ // iButton is the Zero-based index of the button to delete.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_DELETEBUTTON, (WPARAM)iButton, 0L);
+ }
+
+ inline void CToolBar::Destroy()
+ // Allows CToolBar to be reused after the window is destroyed
+ {
+ CWnd::Destroy();
+ m_StringMap.clear();
+ }
+
+ inline BOOL CToolBar::DisableButton(int idButton) const
+ // Disables the specified button in a toolbar
+ // An example of idButton would be IDM_FILE_OPEN
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ENABLEBUTTON, (WPARAM)idButton, (LPARAM) MAKELONG(FALSE, 0));
+ }
+
+ inline BOOL CToolBar::EnableButton(int idButton) const
+ // Enables the specified button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ENABLEBUTTON, (WPARAM)idButton, (LPARAM) MAKELONG(TRUE,0 ));
+ }
+
+ inline BOOL CToolBar::GetButton(int iButton, LPTBBUTTON lpButton) const
+ // Recieves the TBBUTTON structure information from the specified button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_GETBUTTON, (LPARAM)iButton, (WPARAM)lpButton);
+ }
+
+ inline int CToolBar::GetButtonCount() const
+ // Retrieves a count of the buttons currently in the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+ }
+
+ inline DWORD CToolBar::GetButtonSize() const
+ // Retrieves the current width and height of toolbar buttons, in pixels.
+ // Returns a DWORD value that contains the width and height values in the low word and high word, respectively.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_GETBUTTONSIZE, 0L, 0L);
+ }
+
+ inline UINT CToolBar::GetButtonState(int idButton) const
+ // Get the state of an individual button
+ // TBSTATE_CHECKED The button has the TBSTYLE_CHECK style and is being clicked.
+ // TBSTATE_ELLIPSES The button's text is cut off and an ellipsis is displayed.
+ // TBSTATE_ENABLED The button accepts user input. A button that doesn't have this state is grayed.
+ // TBSTATE_HIDDEN The button is not visible and cannot receive user input.
+ // TBSTATE_INDETERMINATE The button is grayed.
+ // TBSTATE_MARKED The button is marked. The interpretation of a marked item is dependent upon the application.
+ // TBSTATE_PRESSED The button is being clicked.
+ // TBSTATE_WRAP The button is followed by a line break.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (UINT)SendMessage(TB_GETSTATE, (WPARAM) idButton, 0L);
+ }
+
+ inline BYTE CToolBar::GetButtonStyle(int idButton) const
+ // Get the the style of the toolbar control. The following button styles are supported:
+ // TBSTYLE_BUTTON Standard pushbutton (default)
+ // TBSTYLE_SEP Separator
+ // TBSTYLE_CHECK Auto check-box button
+ // TBSTYLE_GROUP Marks the start of a group of buttons
+ // TBSTYLE_CHECKGROUP Marks the start of a group of check-box buttons
+ // TBSTYLE_DROPDOWN Creates a drop-down list button
+ // TBSTYLE_AUTOSIZE The button's width will be calculated based on the text of the button, not on the size of the image
+ // TBSTYLE_NOPREFIX The button text will not have an accelerator prefix associated with it
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iIndex = CommandToIndex(idButton);
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, iIndex, (LPARAM) &tbb);
+
+ return tbb.fsStyle;
+ }
+
+ inline CString CToolBar::GetButtonText(int idButton) const
+ // Retrieves the display text of a button on a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int Length = (int)SendMessage(TB_GETBUTTONTEXT, idButton, 0);
+ CString str;
+ LPTSTR szStr = str.GetBuffer(Length +1);
+ SendMessage(TB_GETBUTTONTEXT, (LPARAM)idButton, (WPARAM)szStr);
+ str.ReleaseBuffer();
+ return str;
+ }
+
+ inline int CToolBar::GetCommandID(int iIndex) const
+ // Retrieves information about the specified button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, iIndex, (WPARAM) &tbb);
+
+ // returns zero if failed
+ return tbb.idCommand;
+ }
+
+ inline HIMAGELIST CToolBar::GetDisabledImageList() const
+ // Retrieves the image list that a toolbar control uses to display inactive buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::GetHotImageList() const
+ // Retrieves the image list that a toolbar control uses to display hot buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ }
+
+ inline int CToolBar::GetHotItem() const
+ // Retrieves the index of the hot item in a toolbar, or -1 if no hot item is set.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETHOTITEM, 0L, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::GetImageList() const
+ // Retrieves the image list that a toolbar control uses to display buttons in their default state.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+
+ inline CRect CToolBar::GetItemRect(int iIndex) const
+ // Retrieves the bounding rectangle of a button in a toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ int iCount = (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+
+ if (iCount >= iIndex)
+ SendMessage(TB_GETITEMRECT, (WPARAM)iIndex, (LPARAM)&rc);
+
+ return rc;
+ }
+
+ inline CSize CToolBar::GetMaxSize() const
+ // Retrieves the total size of all of the visible buttons and separators in the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ CSize sz;
+ SendMessage(TB_GETMAXSIZE, 0L, (LPARAM)&sz);
+
+ // This fixes a Windows bug calculating the size when TBSTYLE_DROPDOWN is used.
+ int xMaxSize = 0;
+ for (int i= 0 ; i < GetButtonCount(); ++i)
+ {
+ xMaxSize += GetItemRect(i).Width();
+ }
+
+ sz.cx = xMaxSize;
+ return sz;
+ }
+
+ inline DWORD CToolBar::GetPadding() const
+ // Returns a DWORD value that contains the horizontal padding in the low word and the vertical padding in the high word, in pixels.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_GETPADDING, 0L, 0L);
+ }
+
+ inline CRect CToolBar::GetRect(int idButton) const
+ // Retrieves the bounding rectangle for a specified toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ CRect rc;
+ SendMessage(TB_GETRECT, (WPARAM)idButton, (LPARAM)&rc);
+ return rc;
+ }
+
+ inline int CToolBar::GetRows() const
+ // Retrieves the number of rows of buttons in a toolbar with the TBSTYLE_WRAPABLE style.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETROWS, 0L, 0L);
+ }
+
+ inline int CToolBar::GetTextRows() const
+ // Retrieves the maximum number of text rows that can be displayed on a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_GETTEXTROWS, 0L, 0L);
+ }
+
+ inline HWND CToolBar::GetToolTips() const
+ // Retrieves the handle to the ToolTip control, if any, associated with the toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HWND)SendMessage(TB_GETTOOLTIPS, 0L, 0L);
+ }
+
+ inline BOOL CToolBar::HasText() const
+ {
+ assert(::IsWindow(m_hWnd));
+ BOOL bReturn = FALSE;
+
+ for (int i = 0 ; i < GetButtonCount(); ++i)
+ {
+ if (SendMessage(TB_GETBUTTONTEXT, GetCommandID(i), 0L) != -1)
+ bReturn = TRUE;
+ }
+
+ // return TRUE if any button has text
+ return bReturn;
+ }
+
+ inline BOOL CToolBar::HideButton(int idButton, BOOL fShow) const
+ //Hides or shows the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_HIDEBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG (fShow, 0));
+ }
+
+ inline int CToolBar::HitTest() const
+ // Determines where a point lies in a toolbar control.
+
+ // We do our own hit test since TB_HITTEST is a bit buggy,
+ // and also doesn't work at all on earliest versions of Win95
+ {
+ assert(::IsWindow(m_hWnd));
+ CPoint pt = GetCursorPos();
+ ScreenToClient(pt);
+
+ int nButtons = (int)SendMessage(TB_BUTTONCOUNT, 0L, 0L);
+ int iButton = -1;
+
+ for (int i = 0 ; i < nButtons; ++i)
+ {
+ CRect rc = GetItemRect(i);
+ if (rc.PtInRect(pt))
+ iButton = i;
+ }
+
+ return iButton;
+ }
+
+ inline BOOL CToolBar::Indeterminate(int idButton, BOOL fIndeterminate) const
+ //Hides or shows the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_INDETERMINATE, (WPARAM)idButton, (LPARAM)MAKELONG (fIndeterminate, 0));
+ }
+
+ inline BOOL CToolBar::InsertButton(int iButton, LPTBBUTTON lpButton) const
+ // Inserts a button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_INSERTBUTTON, (WPARAM)iButton, (LPARAM)lpButton);
+ }
+
+ inline BOOL CToolBar::IsButtonHidden(int idButton) const
+ // Determines whether the specified button in a toolbar is hidden.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONHIDDEN, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonHighlighted(int idButton) const
+ // Checks the highlight state of a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONHIGHLIGHTED, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonIndeterminate(int idButton) const
+ // Determines whether the specified button in a toolbar is indeterminate.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONINDETERMINATE, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::IsButtonPressed(int idButton) const
+ // Determines whether the specified button in a toolbar is pressed.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_ISBUTTONPRESSED, (WPARAM)idButton, 0L);
+ }
+
+ inline int CToolBar::MapAccelerator(TCHAR chAccel) const
+ // Determines whether the specified button in a toolbar is pressed.
+ {
+ assert(::IsWindow(m_hWnd));
+ int uButtonID;
+ int idButton;
+ if (SendMessage(TB_MAPACCELERATOR, (WPARAM)chAccel, (LPARAM)&uButtonID))
+ idButton = uButtonID;
+ else
+ idButton = -1;
+
+ return idButton;
+ }
+
+ inline BOOL CToolBar::MarkButton(int idButton) const
+ // Sets the highlight state of a given button in a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_MARKBUTTON, (WPARAM)idButton, 0L);
+ }
+
+ inline BOOL CToolBar::MoveButton(UINT uOldPos, UINT uNewPos) const
+ // Moves a button from one index to another.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_MOVEBUTTON, (WPARAM)uOldPos, (LPARAM)uNewPos);
+ }
+
+
+ inline void CToolBar::OnCreate()
+ {
+ // We must send this message before sending the TB_ADDBITMAP or TB_ADDBUTTONS message
+ SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0L);
+
+ // allows buttons to have a separate dropdown arrow
+ // Note: TBN_DROPDOWN notification is sent by a toolbar control when the user clicks a dropdown button
+ SendMessage(TB_SETEXTENDEDSTYLE, 0L, TBSTYLE_EX_DRAWDDARROWS);
+
+ // Turn of Double click processing (i.e. treat a double click as two single clicks)
+ DWORD dwStyle = (DWORD)GetClassLongPtr(GCL_STYLE);
+ dwStyle &= ~CS_DBLCLKS;
+ SetClassLongPtr(GCL_STYLE, dwStyle);
+
+ // Add extra styles for toolbars inside a rebar
+ if (lstrcmp(GetParent()->GetClassName(), _T("ReBarWindow32")) == 0)
+ {
+ DWORD style = (DWORD)GetWindowLongPtr(GWL_STYLE);
+ style |= CCS_NODIVIDER | CCS_NORESIZE;
+ SetWindowLongPtr(GWL_STYLE, style);
+ }
+
+ SetButtons(m_vToolBarData);
+
+ // Set rows of text to zero
+ SendMessage(TB_SETMAXTEXTROWS, 0L, 0L);
+ }
+
+ inline LRESULT CToolBar::OnCustomDraw(NMHDR* pNMHDR)
+ // With CustomDraw we manually control the drawing of each toolbar button
+ {
+ LPNMTBCUSTOMDRAW lpNMCustomDraw = (LPNMTBCUSTOMDRAW)pNMHDR;
+
+ switch (lpNMCustomDraw->nmcd.dwDrawStage)
+ {
+ // Begin paint cycle
+ case CDDS_PREPAINT:
+ // Send NM_CUSTOMDRAW item draw, and post-paint notification messages.
+ return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYPOSTPAINT ;
+
+ // An item is about to be drawn
+ case CDDS_ITEMPREPAINT:
+ {
+ CDC* pDrawDC = FromHandle(lpNMCustomDraw->nmcd.hdc);
+ CRect rcRect = lpNMCustomDraw->nmcd.rc;
+ int nState = lpNMCustomDraw->nmcd.uItemState;
+ DWORD dwItem = (DWORD)lpNMCustomDraw->nmcd.dwItemSpec;
+ DWORD dwTBStyle = (DWORD)SendMessage(TB_GETSTYLE, 0L, 0L);
+ int nStyle = GetButtonStyle(dwItem);
+
+ int nButton = (int)SendMessage(TB_COMMANDTOINDEX, (WPARAM) dwItem, 0L);
+ TBBUTTON tbb = {0};
+ SendMessage(TB_GETBUTTON, nButton, (LPARAM)&tbb);
+ int iImage = (int)tbb.dwData;
+
+ // Calculate text size
+ std::vector vText(MAX_MENU_STRING, _T('\0'));
+ TCHAR* pszText = &vText[0];
+ CSize TextSize;
+ if (HasText()) // Does any button have text?
+ {
+ pDrawDC->SelectObject(GetFont());
+ if (SendMessage(TB_GETBUTTONTEXT, dwItem, (LPARAM)pszText)> 0)
+ {
+ TextSize = pDrawDC->GetTextExtentPoint32(pszText, lstrlen(pszText));
+ }
+ }
+
+ // Draw outline rectangle
+ if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED))
+ {
+ pDrawDC->CreatePen(PS_SOLID, 1, m_Theme.clrOutline);
+ pDrawDC->MoveTo(rcRect.left, rcRect.top);
+ pDrawDC->LineTo(rcRect.left, rcRect.bottom-1);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.bottom-1);
+ pDrawDC->LineTo(rcRect.right-1, rcRect.top);
+ pDrawDC->LineTo(rcRect.left, rcRect.top);
+ }
+
+ // Draw filled gradient background
+ rcRect.InflateRect(-1, -1);
+ if ((nState & (CDIS_SELECTED|CDIS_CHECKED)) || (GetButtonState(dwItem) & TBSTATE_PRESSED))
+ {
+ pDrawDC->GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcRect, FALSE);
+ }
+ else if (nState & CDIS_HOT)
+ {
+ pDrawDC->GradientFill(m_Theme.clrHot1, m_Theme.clrHot2, rcRect, FALSE);
+ }
+
+ // Get the appropriate image list depending on the button state
+ HIMAGELIST himlToolBar;
+ if (nState & CDIS_DISABLED)
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ }
+ else if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED))
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ if (0 == himlToolBar)
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+ else
+ {
+ himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ }
+
+ BOOL IsWin95 = (1400 == (GetWinVersion()) || (2400 == GetWinVersion()));
+
+ // Calculate image position
+ int cxImage = 0;
+ int cyImage = 0;
+ ImageList_GetIconSize(himlToolBar, &cxImage, &cyImage);
+
+ int yImage = (rcRect.bottom - rcRect.top - cyImage - TextSize.cy +2)/2;
+ int xImage = (rcRect.right + rcRect.left - cxImage)/2 + ((nState & (CDIS_SELECTED|CDIS_CHECKED))? 1:0);
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xImage = rcRect.left + (IsXPThemed()?2:4) + ((nState & CDIS_SELECTED)? 1:0);
+ yImage = (rcRect.bottom -rcRect.top - cyImage +2)/2 + ((nState & (CDIS_SELECTED|CDIS_CHECKED))? 1:0);
+ }
+
+ // Handle the TBSTYLE_DROPDOWN and BTNS_WHOLEDROPDOWN styles
+ if ((nStyle & TBSTYLE_DROPDOWN) || ((nStyle & 0x0080) && (!IsWin95)))
+ {
+ // Calculate the dropdown arrow position
+ int xAPos = (nStyle & TBSTYLE_DROPDOWN)? rcRect.right -6 : (rcRect.right + rcRect.left + cxImage + 4)/2;
+ int yAPos = (nStyle & TBSTYLE_DROPDOWN)? (rcRect.bottom - rcRect.top +1)/2 : (cyImage)/2;
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xAPos = (nStyle & TBSTYLE_DROPDOWN)?rcRect.right -6:rcRect.right -5;
+ yAPos = (rcRect.bottom - rcRect.top +1)/2 + ((nStyle & TBSTYLE_DROPDOWN)?0:1);
+ }
+
+ xImage -= (nStyle & TBSTYLE_DROPDOWN)?((dwTBStyle & TBSTYLE_LIST)? (IsXPThemed()?-4:0):6):((dwTBStyle & TBSTYLE_LIST)? 0:4);
+
+ // Draw separate background for dropdown arrow
+ if ((m_bDrawArrowBkgrnd) && (nState & CDIS_HOT))
+ {
+ CRect rcArrowBkgnd = rcRect;
+ rcArrowBkgnd.left = rcArrowBkgnd.right - 13;
+ pDrawDC->GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcArrowBkgnd, FALSE);
+ }
+
+ m_bDrawArrowBkgrnd = FALSE;
+
+ // Manually draw the dropdown arrow
+ pDrawDC->CreatePen(PS_SOLID, 1, RGB(0,0,0));
+ for (int i = 2; i >= 0; --i)
+ {
+ pDrawDC->MoveTo(xAPos -i-1, yAPos - i+1);
+ pDrawDC->LineTo(xAPos +i, yAPos - i+1);
+ }
+
+ // Draw line between icon and dropdown arrow
+ if ((nStyle & TBSTYLE_DROPDOWN) && ((nState & CDIS_SELECTED) || nState & CDIS_HOT))
+ {
+ pDrawDC->CreatePen(PS_SOLID, 1, m_Theme.clrOutline);
+ pDrawDC->MoveTo(rcRect.right - 13, rcRect.top);
+ pDrawDC->LineTo(rcRect.right - 13, rcRect.bottom);
+ }
+ }
+
+ // Draw the button image
+ if (xImage > 0)
+ {
+ ImageList_Draw(himlToolBar, iImage, *pDrawDC, xImage, yImage, ILD_TRANSPARENT);
+ }
+
+ //Draw Text
+ if (lstrlen(pszText) > 0)
+ {
+ int iWidth = rcRect.right - rcRect.left - ((nStyle & TBSTYLE_DROPDOWN)?13:0);
+ CRect rcText(0, 0, MIN(TextSize.cx, iWidth), TextSize.cy);
+
+ int xOffset = (rcRect.right + rcRect.left - rcText.right + rcText.left - ((nStyle & TBSTYLE_DROPDOWN)? 11 : 1))/2;
+ int yOffset = yImage + cyImage +1;
+
+ if (dwTBStyle & TBSTYLE_LIST)
+ {
+ xOffset = rcRect.left + cxImage + ((nStyle & TBSTYLE_DROPDOWN)?(IsXPThemed()?10:6): 6) + ((nState & CDIS_SELECTED)? 1:0);
+ yOffset = (2+rcRect.bottom - rcRect.top - rcText.bottom + rcText.top)/2 + ((nState & CDIS_SELECTED)? 1:0);
+ rcText.right = MIN(rcText.right, rcRect.right - xOffset);
+ }
+
+ OffsetRect(&rcText, xOffset, yOffset);
+
+ int iMode = pDrawDC->SetBkMode(TRANSPARENT);
+ pDrawDC->SelectObject(GetFont());
+
+ if (nState & (CDIS_DISABLED))
+ {
+ // Draw text twice for embossed look
+ rcText.OffsetRect(1, 1);
+ pDrawDC->SetTextColor(RGB(255,255,255));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT);
+ rcText.OffsetRect(-1, -1);
+ pDrawDC->SetTextColor(GetSysColor(COLOR_GRAYTEXT));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT);
+ }
+ else
+ {
+ pDrawDC->SetTextColor(GetSysColor(COLOR_BTNTEXT));
+ pDrawDC->DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT | DT_END_ELLIPSIS);
+ }
+ pDrawDC->SetBkMode(iMode);
+ }
+ }
+ return CDRF_SKIPDEFAULT; // No further drawing
+ }
+ return 0L;
+ }
+
+ inline void CToolBar::OnDestroy()
+ {
+ HIMAGELIST himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarHot = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarDis = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ ImageList_Destroy(himlToolBar);
+ ImageList_Destroy(himlToolBarHot);
+ ImageList_Destroy(himlToolBarDis);
+ }
+
+ inline LRESULT CToolBar::OnNotifyReflect(WPARAM wParam, LPARAM lParam)
+ // Notifications sent to the parent window are reflected back here
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case NM_CUSTOMDRAW:
+ {
+ if (m_Theme.UseThemes)
+ return OnCustomDraw((LPNMHDR) lParam);
+ }
+ break;
+
+ case TBN_DROPDOWN:
+ {
+ int iItem = ((LPNMTOOLBAR) lParam)->iItem;
+
+ // a boolean expression
+ m_bDrawArrowBkgrnd = (GetButtonStyle(iItem) & TBSTYLE_DROPDOWN);
+ }
+ break;
+ }
+ return 0L;
+ }
+
+ inline void CToolBar::OnWindowPosChanging(WPARAM wParam, LPARAM lParam)
+ {
+ UNREFERENCED_PARAMETER(wParam);
+
+ // Adjust size for toolbars inside a rebar
+ CWnd* pParent = GetParent();
+ if (lstrcmp(pParent->GetClassName(), _T("ReBarWindow32")) == 0)
+ {
+ ReBarTheme* pTheme = (ReBarTheme*)pParent->SendMessage(UWM_GETREBARTHEME, 0, 0);
+
+ if (pTheme && pTheme->UseThemes && pTheme->ShortBands)
+ {
+ LPWINDOWPOS pWinPos = (LPWINDOWPOS)lParam;
+ pWinPos->cx = GetMaxSize().cx+2;
+ }
+ }
+ }
+
+ inline void CToolBar::PreCreate(CREATESTRUCT &cs)
+ {
+ // Sets the CREATESTRUCT parameters prior to window creation
+ cs.style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT;
+ }
+
+ inline void CToolBar::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = TOOLBARCLASSNAME;
+ }
+
+ inline BOOL CToolBar::PressButton(int idButton, BOOL fPress) const
+ // Presses or releases the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_PRESSBUTTON, (WPARAM)idButton, (LPARAM)MAKELONG(fPress, 0));
+ }
+
+ inline BOOL CToolBar::ReplaceBitmap(UINT NewToolBarID)
+ // Replaces an existing bitmap with a new bitmap.
+
+ // Note: ReplaceBitmap supports a maximum colour depth of 8 bits (256 colours)
+ // For more colours, use an ImageList instead
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iNumButtons = 0;
+ std::vector::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ TBREPLACEBITMAP tbrb = {0};
+ tbrb.hInstNew = GetApp()->GetResourceHandle();
+ tbrb.hInstOld = GetApp()->GetResourceHandle();
+ tbrb.nIDNew = NewToolBarID;
+ tbrb.nIDOld = m_OldToolBarID;
+ tbrb.nButtons = iNumButtons;
+
+ BOOL bResult = (BOOL)SendMessage(TB_REPLACEBITMAP, iNumButtons, (LPARAM)&tbrb);
+ if (bResult)
+ m_OldToolBarID = NewToolBarID;
+
+ return bResult;
+ }
+
+ inline void CToolBar::SaveRestore(BOOL fSave, TBSAVEPARAMS* ptbsp) const
+ // Presses or releases the specified button in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_PRESSBUTTON, (WPARAM)fSave, (LPARAM)ptbsp);
+ }
+
+ inline BOOL CToolBar::SetBitmap(UINT nID)
+ // Set the button images
+ {
+ assert(::IsWindow(m_hWnd));
+
+ CBitmap Bitmap(nID);
+ assert (Bitmap.GetHandle());
+ BITMAP bm = Bitmap.GetBitmapData();
+
+ int iNumButtons = 0;
+ std::vector::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ int iImageWidth = bm.bmWidth / iNumButtons;
+ int iImageHeight = bm.bmHeight;
+
+ // Set the bitmap size first
+ SetBitmapSize(iImageWidth, iImageHeight);
+
+ BOOL bResult = FALSE;
+ if (m_OldToolBarID)
+ bResult = ReplaceBitmap(nID);
+ else
+ bResult = (BOOL)AddBitmap(nID);
+
+ return bResult;
+ }
+
+ inline BOOL CToolBar::SetBitmapSize(int cx, int cy) const
+ // Sets the size of the bitmapped images to be added to a toolbar.
+
+ // Needs to be used when the image size is not the default 16 x 15
+ // Call this function before using AddBitmap or ReplaceBitmap
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETBITMAPSIZE, 0L, MAKELONG(cx, cy));
+ }
+
+ inline int CToolBar::SetButtons(const std::vector& vToolBarData) const
+ // Assigns a resource ID to each toolbar button
+ {
+ assert(::IsWindow(m_hWnd));
+
+ int iImages = 0;
+ UINT iNumButtons = (UINT)vToolBarData.size();
+
+ // Remove any existing buttons
+ while (SendMessage(TB_BUTTONCOUNT, 0L, 0L) > 0)
+ {
+ if(!SendMessage(TB_DELETEBUTTON, 0L, 0L))
+ break;
+ }
+
+ if (iNumButtons > 0)
+ {
+ // TBBUTTON structure for each button in the toolbar
+ TBBUTTON tbb = {0};
+
+ for (UINT j = 0 ; j < iNumButtons; ++j)
+ {
+ ZeroMemory(&tbb, sizeof(TBBUTTON));
+
+ if (0 == vToolBarData[j])
+ {
+ tbb.fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbb.dwData = iImages;
+ tbb.iBitmap = iImages;
+ tbb.idCommand = vToolBarData[j];
+ tbb.fsState = TBSTATE_ENABLED;
+ tbb.fsStyle = TBSTYLE_BUTTON;
+ }
+
+ // Add the button to the toolbar
+ if (SendMessage(TB_ADDBUTTONS, 1L, (LPARAM)&tbb))
+ iImages++;
+ else
+ break;
+ }
+ }
+
+ return iImages;
+ }
+
+ inline BOOL CToolBar::SetButtonSize(int cx, int cy) const
+ // Sets the size of the buttons to be added to a toolbar
+ // The size can be set only before adding any buttons to the toolbar
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETBUTTONSIZE, 0L, MAKELONG(cx, cy));
+ }
+
+ inline BOOL CToolBar::SetButtonState(int idButton, UINT State) const
+ {
+ // Set the state of an individual button
+ // TBSTATE_CHECKED The button has the TBSTYLE_CHECK style and is being clicked.
+ // TBSTATE_ELLIPSES The button's text is cut off and an ellipsis is displayed.
+ // TBSTATE_ENABLED The button accepts user input. A button that doesn't have this state is grayed.
+ // TBSTATE_HIDDEN The button is not visible and cannot receive user input.
+ // TBSTATE_INDETERMINATE The button is grayed.
+ // TBSTATE_MARKED The button is marked. The interpretation of a marked item is dependent upon the application.
+ // TBSTATE_PRESSED The button is being clicked.
+ // TBSTATE_WRAP The button is followed by a line break.
+
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETSTATE, (WPARAM) idButton, (LPARAM)MAKELONG (State, 0));
+ }
+
+ inline BOOL CToolBar::SetButtonStyle(int idButton, BYTE Style) const
+ // The the style of the toolbar control. The following button styles are supported:
+ // TBSTYLE_BUTTON Standard pushbutton (default)
+ // TBSTYLE_SEP Separator
+ // TBSTYLE_CHECK Auto check-box button
+ // TBSTYLE_GROUP Marks the start of a group of buttons
+ // TBSTYLE_CHECKGROUP Marks the start of a group of check-box buttons
+ // TBSTYLE_DROPDOWN Creates a drop-down list button
+ // TBSTYLE_AUTOSIZE The button's width will be calculated based on the text of the button, not on the size of the image
+ // TBSTYLE_NOPREFIX The button text will not have an accelerator prefix associated with it
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TBBUTTONINFO tbbi = {0};
+ tbbi.cbSize = sizeof(TBBUTTONINFO);
+ tbbi.dwMask = TBIF_STYLE;
+ tbbi.fsStyle = Style;
+
+ // Note: TB_SETBUTTONINFO requires comctl32.dll version 4.71 or later
+ // i.e. Win95 with IE4 / NT with IE4 or later
+ return (BOOL)SendMessage(TB_SETBUTTONINFO, idButton, (LPARAM) &tbbi);
+ }
+
+ inline BOOL CToolBar::SetButtonText(int idButton, LPCTSTR szText)
+ // This rather convoluted approach to setting toolbar button text supports
+ // all versions of Windows, including Win95 with COMCTL32.DLL version 4.0
+ {
+ assert(::IsWindow(m_hWnd));
+ int iIndex = CommandToIndex(idButton);
+ assert(-1 != iIndex);
+
+ BOOL Succeeded = TRUE;
+ tString sString = szText;
+ std::map::iterator m;
+ int iString;
+
+ // Check to see if the string is already added
+ m = m_StringMap.find(sString);
+ if (m_StringMap.end() == m)
+ {
+ if (0 == m_StringMap.size())
+ {
+ // Place a blank string first in the string table, in case some
+ // buttons don't have text
+ TCHAR szString[3] = _T(" ");
+ szString[2] = _T('\0'); // Double-null terminate
+ SendMessage(TB_ADDSTRING, 0L, (LPARAM)szString);
+ }
+
+ // No index for this string exists, so create it now
+ TCHAR szBuf[80] = _T("");
+ lstrcpyn(szBuf, szText, 79);
+ szBuf[lstrlen(szBuf)+1] = _T('\0'); // Double-null terminate
+
+ iString = (int)SendMessage(TB_ADDSTRING, 0L, (LPARAM)szBuf);
+ if (-1 == iString )
+ Succeeded = FALSE;
+
+ // Save the string its index in our map
+ m_StringMap.insert(std::make_pair(sString, iString));
+ }
+ else
+ {
+ // String found, use the index from our map
+ iString = m->second;
+ }
+
+ if (Succeeded)
+ {
+ TBBUTTON tbb = {0};
+ Succeeded = (BOOL)SendMessage(TB_GETBUTTON, iIndex, (LPARAM)&tbb);
+
+ tbb.iString = iString;
+
+ // Turn off ToolBar drawing
+ SendMessage(WM_SETREDRAW, FALSE, 0L);
+
+ if (Succeeded)
+ Succeeded = (BOOL)SendMessage(TB_DELETEBUTTON, iIndex, 0L);
+
+ if (Succeeded)
+ Succeeded = (BOOL)SendMessage(TB_INSERTBUTTON, iIndex, (LPARAM)&tbb);
+
+ // Ensure the button now includes some text rows
+ if (0 == SendMessage(TB_GETTEXTROWS, 0L, 0L))
+ SendMessage(TB_SETMAXTEXTROWS, 1L, 0L);
+
+ // Turn on ToolBar drawing
+ SendMessage(WM_SETREDRAW, TRUE, 0L);
+ }
+ // Redraw button
+ CRect r = GetItemRect(iIndex);
+ InvalidateRect(&r, TRUE);
+
+ return Succeeded;
+ }
+
+ inline BOOL CToolBar::SetButtonWidth(int idButton, int nWidth) const
+ // The set button width can adjust the width of the button after it is created.
+ // This is useful when replacing a button with a ComboBox or other control.
+ // Note: TB_SETBUTTONINFO requires comctl32.dll version 4.71 or later
+ // i.e. Win95 with IE4 / NT with IE4 or later
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TBBUTTONINFO tbbi = {0};
+ tbbi.cbSize = sizeof(TBBUTTONINFO);
+ tbbi.dwMask = TBIF_SIZE;
+ tbbi.cx = (WORD)nWidth;
+ BOOL bResult = (BOOL)SendMessage(TB_SETBUTTONINFO, (WPARAM)idButton, (LPARAM)&tbbi);
+
+ // Send a changed message to the parent (used by the rebar)
+ SIZE MaxSize = GetMaxSize();
+ GetParent()->SendMessage(UWM_TOOLBAR_RESIZE, (WPARAM)m_hWnd, (LPARAM)&MaxSize);
+
+ return bResult;
+ }
+
+ inline BOOL CToolBar::SetCommandID(int iIndex, int idButton) const
+ // Sets the command identifier of a toolbar button
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETCMDID, iIndex, idButton);
+ }
+
+ inline HIMAGELIST CToolBar::SetDisableImageList(HIMAGELIST himlNewDisabled) const
+ // Sets the image list that the toolbar control will use to display disabled buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlNewDisabled);
+ }
+
+ inline DWORD CToolBar::SetDrawTextFlags(DWORD dwMask, DWORD dwDTFlags) const
+ // Sets the text drawing flags for the toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_SETDRAWTEXTFLAGS, (WPARAM)dwMask, (LPARAM)dwDTFlags);
+ }
+
+ inline DWORD CToolBar::SetExtendedStyle(DWORD dwExStyle) const
+ // Sets the text drawing flags for the toolbar.
+ // Extended styles include: TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_HIDECLIPPEDBUTTONS, TBSTYLE_EX_DOUBLEBUFFER and TBSTYLE_EX_MIXEDBUTTONS
+ {
+ assert(::IsWindow(m_hWnd));
+ return (DWORD)SendMessage(TB_SETEXTENDEDSTYLE, 0L, (LPARAM)dwExStyle);
+ }
+
+ inline HIMAGELIST CToolBar::SetHotImageList(HIMAGELIST himlNewHot) const
+ // Sets the image list that the toolbar control will use to display hot buttons.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETHOTIMAGELIST, 0L, (LPARAM)himlNewHot);
+ }
+
+ inline int CToolBar::SetHotItem(int iHot) const
+ // Sets the hot item in a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (int)SendMessage(TB_SETHOTITEM, (WPARAM)iHot, 0L);
+ }
+
+ inline HIMAGELIST CToolBar::SetImageList(HIMAGELIST himlNew) const
+ // Sets the image list that the toolbar will use to display buttons that are in their default state.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (HIMAGELIST)SendMessage(TB_SETIMAGELIST, 0L, (LPARAM)himlNew);
+ }
+
+ inline BOOL CToolBar::SetImages(COLORREF crMask, UINT ToolBarID, UINT ToolBarHotID, UINT ToolBarDisabledID)
+ // Either sets the imagelist or adds/replaces bitmap depending on ComCtl32.dll version
+ // Assumes the width of the button image = bitmap_size / buttons
+ // Assumes buttons have been already been added via AdddToolBarButton
+ // The colour mask is often grey RGB(192,192,192) or magenta (255,0,255);
+ // The color mask is ignored for 32bit bitmap resources
+ // The Hot and disiabled bitmap resources can be 0
+ {
+ assert(::IsWindow(m_hWnd));
+
+ // ToolBar ImageLists require Comctl32.dll version 4.7 or later
+ if (400 == GetComCtlVersion())
+ {
+ // We are using COMCTL32.DLL version 4.0, so we can't use an imagelist.
+ // Instead we simply set the bitmap.
+ return SetBitmap(ToolBarID);
+ }
+
+ int iNumButtons = 0;
+ std::vector::iterator iter;
+ for (iter = GetToolBarData().begin(); iter < GetToolBarData().end(); ++iter)
+ if ((*iter) != 0) ++iNumButtons;
+
+ if (iNumButtons > 0)
+ {
+ // Set the button images
+ CBitmap Bitmap(ToolBarID);
+ assert(Bitmap.GetHandle());
+
+ BITMAP bm = Bitmap.GetBitmapData();
+ int iImageWidth = bm.bmWidth / iNumButtons;
+ int iImageHeight = bm.bmHeight;
+
+ HIMAGELIST himlToolBar = (HIMAGELIST)SendMessage(TB_GETIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarHot = (HIMAGELIST)SendMessage(TB_GETHOTIMAGELIST, 0L, 0L);
+ HIMAGELIST himlToolBarDis = (HIMAGELIST)SendMessage(TB_GETDISABLEDIMAGELIST, 0L, 0L);
+ ImageList_Destroy(himlToolBar);
+ ImageList_Destroy(himlToolBarHot);
+ ImageList_Destroy(himlToolBarDis);
+
+ himlToolBar = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBar);
+
+ ImageList_AddMasked(himlToolBar, Bitmap, crMask);
+ SendMessage(TB_SETIMAGELIST, 0L, (LPARAM)himlToolBar);
+
+ if (ToolBarHotID)
+ {
+ CBitmap BitmapHot(ToolBarHotID);
+ assert(BitmapHot);
+
+ himlToolBarHot = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBarHot);
+
+ ImageList_AddMasked(himlToolBarHot, BitmapHot, crMask);
+ SendMessage(TB_SETHOTIMAGELIST, 0L, (LPARAM)himlToolBarHot);
+ }
+
+ if (ToolBarDisabledID)
+ {
+ CBitmap BitmapDisabled(ToolBarDisabledID);
+ assert(BitmapDisabled);
+
+ himlToolBarDis = ImageList_Create(iImageWidth, iImageHeight, ILC_COLOR32 | ILC_MASK, iNumButtons, 0);
+ assert(himlToolBarDis);
+
+ ImageList_AddMasked(himlToolBarDis, BitmapDisabled, crMask);
+ SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlToolBarDis);
+ }
+ else
+ {
+ himlToolBarDis = CreateDisabledImageList(himlToolBar);
+ SendMessage(TB_SETDISABLEDIMAGELIST, 0L, (LPARAM)himlToolBarDis);
+ }
+
+ // Inform the parent of the change (rebar needs this)
+ SIZE MaxSize = GetMaxSize();
+ GetParent()->SendMessage(UWM_TOOLBAR_RESIZE, (WPARAM)m_hWnd, (LPARAM)&MaxSize);
+ }
+
+ return TRUE;
+ }
+
+ inline BOOL CToolBar::SetIndent(int iIndent) const
+ // Sets the indentation for the first button in a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETINDENT, (WPARAM)iIndent, 0L);
+ }
+
+ inline BOOL CToolBar::SetMaxTextRows(int iMaxRows) const
+ // Sets the maximum number of text rows displayed on a toolbar button.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETMAXTEXTROWS, (WPARAM)iMaxRows, 0L);
+ }
+
+ inline BOOL CToolBar::SetPadding(int cx, int cy) const
+ // Sets the padding for a toolbar control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return (BOOL)SendMessage(TB_SETPADDING, 0L, (WPARAM)MAKELONG(cx, cy));
+ }
+
+ inline void CToolBar::SetToolBarTheme(ToolBarTheme& Theme)
+ {
+ m_Theme.UseThemes = Theme.UseThemes;
+ m_Theme.clrHot1 = Theme.clrHot1;
+ m_Theme.clrHot2 = Theme.clrHot2;
+ m_Theme.clrPressed1 = Theme.clrPressed1;
+ m_Theme.clrPressed2 = Theme.clrPressed2;
+ m_Theme.clrOutline = Theme.clrOutline;
+
+ if (IsWindow())
+ Invalidate();
+ }
+
+ inline void CToolBar::SetToolTips(HWND hwndToolTip) const
+ // Associates a ToolTip control with a toolbar.
+ {
+ assert(::IsWindow(m_hWnd));
+ SendMessage(TB_SETTOOLTIPS, (WPARAM)hwndToolTip, 0L);
+ }
+
+ inline LRESULT CToolBar::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ OnDestroy();
+ break;
+ case UWM_GETTOOLBARTHEME:
+ {
+ ToolBarTheme& tt = GetToolBarTheme();
+ return (LRESULT)&tt;
+ }
+ case WM_WINDOWPOSCHANGING:
+ OnWindowPosChanging(wParam, lParam);
+ break;
+ }
+
+ // pass unhandled messages on for default processing
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_TOOLBAR_H_
diff --git a/external/win32cpp/include/treeview.h b/external/win32cpp/include/treeview.h
new file mode 100644
index 0000000..4186e9c
--- /dev/null
+++ b/external/win32cpp/include/treeview.h
@@ -0,0 +1,624 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+
+
+#ifndef _WIN32XX_TREEVIEW_H_
+#define _WIN32XX_TREEVIEW_H_
+
+#include "wincore.h"
+#include "commctrl.h"
+
+// Disable macros from Windowsx.h
+#undef GetNextSibling
+#undef GetPrevSibling
+
+namespace Win32xx
+{
+
+ class CTreeView : public CWnd
+ {
+ public:
+ CTreeView() {}
+ virtual ~CTreeView() {}
+ virtual void PreRegisterClass(WNDCLASS &wc);
+
+// Attributes
+ COLORREF GetBkColor() const;
+ HTREEITEM GetChild(HTREEITEM hItem) const;
+ UINT GetCount() const;
+ HTREEITEM GetDropHiLightItem() const;
+ HWND GetEditControl() const;
+ HTREEITEM GetFirstVisible() const;
+ HIMAGELIST GetImageList(int iImageType) const;
+ UINT GetIndent() const;
+ COLORREF GetInsertMarkColor() const;
+ BOOL GetItem(TVITEM& Item) const;
+ DWORD_PTR GetItemData(HTREEITEM hItem) const;
+ int GetItemHeight() const;
+ BOOL GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage ) const;
+ BOOL GetItemRect(HTREEITEM hItem, CRect& rc, BOOL bTextOnly) const;
+ tString GetItemText(HTREEITEM hItem, UINT nTextMax /* = 260 */) const;
+ HTREEITEM GetLastVisible() const;
+ HTREEITEM GetNextItem(HTREEITEM hItem, UINT nCode) const;
+ HTREEITEM GetNextSibling(HTREEITEM hItem) const;
+ HTREEITEM GetNextVisible(HTREEITEM hItem) const;
+ HTREEITEM GetParentItem(HTREEITEM hItem) const;
+ HTREEITEM GetPrevSibling(HTREEITEM hItem) const;
+ HTREEITEM GetPrevVisible(HTREEITEM hItem) const;
+ HTREEITEM GetRootItem() const;
+ int GetScrollTime() const;
+ HTREEITEM GetSelection() const;
+ COLORREF GetTextColor() const;
+ HWND GetToolTips() const;
+ UINT GetVisibleCount() const;
+ BOOL ItemHasChildren(HTREEITEM hItem) const;
+ COLORREF SetBkColor(COLORREF clrBk) const;
+ HIMAGELIST SetImageList(HIMAGELIST himl, int nType) const;
+ void SetIndent(int indent) const;
+ BOOL SetInsertMark(HTREEITEM hItem, BOOL fAfter = TRUE) const;
+ COLORREF SetInsertMarkColor(COLORREF clrInsertMark) const;
+ BOOL SetItem(TVITEM& Item) const;
+ BOOL SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR szText, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) const;
+ BOOL SetItemData(HTREEITEM hItem, DWORD_PTR dwData) const;
+ int SetItemHeight(SHORT cyItem) const;
+ BOOL SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) const;
+ BOOL SetItemText(HTREEITEM hItem, LPCTSTR szText) const;
+ UINT SetScrollTime(UINT uScrollTime) const;
+ COLORREF SetTextColor(COLORREF clrText) const;
+ HWND SetToolTips(HWND hwndTooltip) const;
+
+// Operations
+ HIMAGELIST CreateDragImage(HTREEITEM hItem) const;
+ BOOL DeleteAllItems() const;
+ BOOL DeleteItem(HTREEITEM hItem) const;
+ HWND EditLabel(HTREEITEM hItem) const;
+ BOOL EndEditLabelNow(BOOL fCancel) const;
+ BOOL EnsureVisible(HTREEITEM hItem) const;
+ BOOL Expand(HTREEITEM hItem, UINT nCode) const;
+ HTREEITEM HitTest(TVHITTESTINFO& ht) const;
+ HTREEITEM InsertItem(TVINSERTSTRUCT& tvIS) const;
+ BOOL Select(HTREEITEM hitem, UINT flag) const;
+ BOOL SelectDropTarget(HTREEITEM hItem) const;
+ BOOL SelectItem(HTREEITEM hItem) const;
+ BOOL SelectSetFirstVisible(HTREEITEM hItem) const;
+ BOOL SortChildren(HTREEITEM hItem, BOOL fRecurse) const;
+ BOOL SortChildrenCB(TVSORTCB& sort, BOOL fRecurse) const;
+
+ private:
+ CTreeView(const CTreeView&); // Disable copy construction
+ CTreeView& operator = (const CTreeView&); // Disable assignment operator
+
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+
+ inline void CTreeView::PreRegisterClass(WNDCLASS &wc)
+ {
+ // Set the Window Class
+ wc.lpszClassName = WC_TREEVIEW;
+ }
+
+// Attributes
+ inline COLORREF CTreeView::GetBkColor() const
+ // Retrieves the current background color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetBkColor( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetChild(HTREEITEM hItem) const
+ // Retrieves the first child item of the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetChild(m_hWnd, hItem);
+ }
+
+ inline UINT CTreeView::GetCount() const
+ // Retrieves a count of the items in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetCount( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetDropHiLightItem() const
+ // Retrieves the tree-view item that is the target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetDropHilight(m_hWnd);
+ }
+
+ inline HWND CTreeView::GetEditControl() const
+ // Retrieves the handle to the edit control being used to edit a tree-view item's text.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetEditControl( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetFirstVisible() const
+ // Retrieves the first visible item in a tree-view control window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetFirstVisible(m_hWnd);
+ }
+
+ inline HIMAGELIST CTreeView::GetImageList(int iImageType) const
+ // Retrieves the handle to the normal or state image list associated with a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetImageList( m_hWnd, iImageType );
+ }
+
+ inline UINT CTreeView::GetIndent() const
+ // Retrieves the amount, in pixels, that child items are indented relative to their parent items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetIndent( m_hWnd );
+ }
+
+ inline COLORREF CTreeView::GetInsertMarkColor() const
+ // Retrieves the color used to draw the insertion mark for the tree view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetInsertMarkColor( m_hWnd );
+ }
+
+ inline BOOL CTreeView::GetItem(TVITEM& Item) const
+ // Retrieves some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItem( m_hWnd, &Item );
+ }
+
+ inline DWORD_PTR CTreeView::GetItemData(HTREEITEM hItem) const
+ // Retrieves a tree-view item's application data.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_PARAM;
+ tvi.hItem = hItem;
+ TreeView_GetItem( m_hWnd, &tvi );
+ return tvi.lParam;
+ }
+
+ inline int CTreeView::GetItemHeight() const
+ // Retrieves the current height of the tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItemHeight( m_hWnd );
+ }
+
+ inline BOOL CTreeView::GetItemImage(HTREEITEM hItem, int& nImage, int& nSelectedImage ) const
+ // Retrieves the index of the tree-view item's image and selected image.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ tvi.hItem = hItem;
+ BOOL bResult = TreeView_GetItem( m_hWnd, &tvi );
+ nImage = tvi.iImage;
+ nSelectedImage = tvi.iSelectedImage;
+ return bResult;
+ }
+
+ inline BOOL CTreeView::GetItemRect(HTREEITEM hItem, CRect& rc, BOOL bTextOnly) const
+ // Retrieves the bounding rectangle for a tree-view item and indicates whether the item is visible.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetItemRect( m_hWnd, hItem, &rc, bTextOnly );
+ }
+
+ inline tString CTreeView::GetItemText(HTREEITEM hItem, UINT nTextMax /* = 260 */) const
+ // Retrieves the text for a tree-view item.
+ // Note: Although the tree-view control allows any length string to be stored
+ // as item text, only the first 260 characters are displayed.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ tString t;
+ if (nTextMax > 0)
+ {
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = TVIF_TEXT;
+ tvi.cchTextMax = nTextMax;
+ std::vector vTChar(nTextMax +1, _T('\0'));
+ TCHAR* pTCharArray = &vTChar.front();
+ tvi.pszText = pTCharArray;
+ ::SendMessage(m_hWnd, TVM_GETITEM, 0L, (LPARAM)&tvi);
+ t = tvi.pszText;
+ }
+ return t;
+ }
+
+ inline HTREEITEM CTreeView::GetLastVisible() const
+ // Retrieves the last expanded item in a tree-view control.
+ // This does not retrieve the last item visible in the tree-view window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetLastVisible(m_hWnd);
+ }
+
+ inline HTREEITEM CTreeView::GetNextItem(HTREEITEM hItem, UINT nCode) const
+ // Retrieves the tree-view item that bears the specified relationship to a specified item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextItem( m_hWnd, hItem, nCode);
+ }
+
+ inline HTREEITEM CTreeView::GetNextSibling(HTREEITEM hItem) const
+ // Retrieves the next sibling item of a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetNextVisible(HTREEITEM hItem) const
+ // Retrieves the next visible item that follows a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetNextVisible(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetParentItem(HTREEITEM hItem) const
+ // Retrieves the parent item of the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetParent(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetPrevSibling(HTREEITEM hItem) const
+ // Retrieves the previous sibling item of a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetPrevSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetPrevVisible(HTREEITEM hItem) const
+ // Retrieves the first visible item that precedes a specified item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetPrevSibling(m_hWnd, hItem);
+ }
+
+ inline HTREEITEM CTreeView::GetRootItem() const
+ // Retrieves the topmost or very first item of the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetRoot(m_hWnd);
+ }
+
+ inline int CTreeView::GetScrollTime() const
+ // Retrieves the maximum scroll time for the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetScrollTime( m_hWnd );
+ }
+
+ inline HTREEITEM CTreeView::GetSelection() const
+ // Retrieves the currently selected item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetSelection(m_hWnd);
+ }
+
+ inline COLORREF CTreeView::GetTextColor() const
+ // Retrieves the current text color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetTextColor( m_hWnd );
+ }
+
+ inline HWND CTreeView::GetToolTips() const
+ // Retrieves the handle to the child ToolTip control used by a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetToolTips( m_hWnd );
+ }
+
+ inline UINT CTreeView::GetVisibleCount() const
+ // Obtains the number of items that can be fully visible in the client window of a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_GetVisibleCount( m_hWnd );
+ }
+
+ inline BOOL CTreeView::ItemHasChildren(HTREEITEM hItem) const
+ // Returns true of the tree-view item has one or more children
+ {
+ assert(::IsWindow(m_hWnd));
+
+ if (TreeView_GetChild( m_hWnd, hItem ))
+ return TRUE;
+
+ return FALSE;
+ }
+
+ inline COLORREF CTreeView::SetBkColor(COLORREF clrBk) const
+ // Sets the background color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetBkColor( m_hWnd, clrBk );
+ }
+
+ inline HIMAGELIST CTreeView::SetImageList(HIMAGELIST himl, int nType) const
+ // Sets the normal or state image list for a tree-view control
+ // and redraws the control using the new images.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetImageList( m_hWnd, himl, nType );
+ }
+
+ inline void CTreeView::SetIndent(int indent) const
+ // Sets the width of indentation for a tree-view control
+ // and redraws the control to reflect the new width.
+ {
+ assert(::IsWindow(m_hWnd));
+ TreeView_SetIndent( m_hWnd, indent );
+ }
+
+ inline BOOL CTreeView::SetInsertMark(HTREEITEM hItem, BOOL fAfter/* = TRUE*/) const
+ // Sets the insertion mark in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetInsertMark( m_hWnd, hItem, fAfter );
+ }
+
+ inline COLORREF CTreeView::SetInsertMarkColor(COLORREF clrInsertMark) const
+ // Sets the color used to draw the insertion mark for the tree view.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetInsertMarkColor( m_hWnd, clrInsertMark );
+ }
+
+ inline BOOL CTreeView::SetItem(TVITEM& Item) const
+ // Sets some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetItem( m_hWnd, &Item );
+ }
+
+ inline BOOL CTreeView::SetItem(HTREEITEM hItem, UINT nMask, LPCTSTR szText, int nImage, int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam) const
+ // Sets some or all of a tree-view item's attributes.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = nMask;
+ tvi.pszText = (LPTSTR)szText;
+ tvi.iImage = nImage;
+ tvi.iSelectedImage = nSelectedImage;
+ tvi.state = nState;
+ tvi.stateMask = nStateMask;
+ tvi.lParam = lParam;
+ return TreeView_SetItem( m_hWnd, &tvi );
+ }
+
+ inline BOOL CTreeView::SetItemData(HTREEITEM hItem, DWORD_PTR dwData) const
+ // Sets the tree-view item's application data.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.mask = TVIF_PARAM;
+ tvi.lParam = dwData;
+ return TreeView_SetItem( m_hWnd, &tvi );
+ }
+
+ inline int CTreeView::SetItemHeight(SHORT cyItem) const
+ // Sets the height of the tree-view items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetItemHeight( m_hWnd, cyItem );
+ }
+
+ inline BOOL CTreeView::SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage) const
+ // Sets the tree-view item's application image.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.iImage = nImage;
+ tvi.iSelectedImage = nSelectedImage;
+ tvi.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+ return TreeView_SetItem(m_hWnd, &tvi );
+ }
+
+ inline BOOL CTreeView::SetItemText(HTREEITEM hItem, LPCTSTR szText) const
+ // Sets the tree-view item's application text.
+ {
+ assert(::IsWindow(m_hWnd));
+
+ TVITEM tvi = {0};
+ tvi.hItem = hItem;
+ tvi.pszText = (LPTSTR)szText;
+ tvi.mask = TVIF_TEXT;
+ return TreeView_SetItem(m_hWnd, &tvi );
+ }
+
+ inline UINT CTreeView::SetScrollTime(UINT uScrollTime) const
+ // Sets the maximum scroll time for the tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetScrollTime( m_hWnd, uScrollTime );
+ }
+
+ inline COLORREF CTreeView::SetTextColor(COLORREF clrText) const
+ // Sets the text color of the control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetTextColor( m_hWnd, clrText );
+ }
+
+ inline HWND CTreeView::SetToolTips(HWND hwndTooltip) const
+ // Sets a tree-view control's child ToolTip control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SetToolTips( m_hWnd, hwndTooltip );
+ }
+
+ // Operations
+
+ inline HIMAGELIST CTreeView::CreateDragImage(HTREEITEM hItem) const
+ // Creates a dragging bitmap for the specified item in a tree-view control.
+ // It also creates an image list for the bitmap and adds the bitmap to the image list.
+ // An application can display the image when dragging the item by using the image list functions.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_CreateDragImage( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::DeleteAllItems() const
+ // Deletes all items from a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_DeleteAllItems( m_hWnd );
+ }
+
+ inline BOOL CTreeView::DeleteItem(HTREEITEM hItem) const
+ // Removes an item and all its children from a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_DeleteItem( m_hWnd, hItem );
+ }
+
+ inline HWND CTreeView::EditLabel(HTREEITEM hItem) const
+ // Begins in-place editing of the specified item's text, replacing the text of the item
+ // with a single-line edit control containing the text.
+ // The specified item is implicitly selected and focused.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EditLabel( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::EndEditLabelNow(BOOL fCancel) const
+ // Ends the editing of a tree-view item's label.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EndEditLabelNow(m_hWnd, fCancel);
+ }
+
+ inline BOOL CTreeView::EnsureVisible(HTREEITEM hItem) const
+ // Ensures that a tree-view item is visible, expanding the parent item or
+ // scrolling the tree-view control, if necessary.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_EnsureVisible( m_hWnd, hItem );
+ }
+
+ inline BOOL CTreeView::Expand(HTREEITEM hItem, UINT nCode) const
+ // The TreeView_Expand macro expands or collapses the list of child items associated
+ // with the specified parent item, if any.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_Expand( m_hWnd, hItem, nCode );
+ }
+
+ inline HTREEITEM CTreeView::HitTest(TVHITTESTINFO& ht) const
+ // Determines the location of the specified point relative to the client area of a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_HitTest( m_hWnd, &ht );
+ }
+
+ inline HTREEITEM CTreeView::InsertItem(TVINSERTSTRUCT& tvIS) const
+ // Inserts a new item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_InsertItem( m_hWnd, &tvIS );
+ }
+
+ inline BOOL CTreeView::Select(HTREEITEM hitem, UINT flag) const
+ // Selects the specified tree-view item, scrolls the item into view, or redraws
+ // the item in the style used to indicate the target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_Select(m_hWnd, hitem, flag );
+ }
+
+ inline BOOL CTreeView::SelectDropTarget(HTREEITEM hItem) const
+ // Redraws a specified tree-view control item in the style used to indicate the
+ // target of a drag-and-drop operation.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectDropTarget(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SelectItem(HTREEITEM hItem) const
+ // Selects the specified tree-view item.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectItem(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SelectSetFirstVisible(HTREEITEM hItem) const
+ // Scrolls the tree-view control vertically to ensure that the specified item is visible.
+ // If possible, the specified item becomes the first visible item at the top of the control's window.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SelectSetFirstVisible(m_hWnd, hItem);
+ }
+
+ inline BOOL CTreeView::SortChildren(HTREEITEM hItem, BOOL fRecurse) const
+ // Sorts the child items of the specified parent item in a tree-view control.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SortChildren( m_hWnd, hItem, fRecurse );
+ }
+
+ inline BOOL CTreeView::SortChildrenCB(TVSORTCB& sort, BOOL fRecurse) const
+ // Sorts tree-view items using an application-defined callback function that compares the items.
+ {
+ assert(::IsWindow(m_hWnd));
+ return TreeView_SortChildrenCB( m_hWnd, &sort, fRecurse );
+ }
+
+
+} // namespace Win32xx
+
+#endif // #ifndef _WIN32XX_TREEVIEW_H_
+
diff --git a/external/win32cpp/include/wceframe.h b/external/win32cpp/include/wceframe.h
new file mode 100644
index 0000000..f3aa67e
--- /dev/null
+++ b/external/win32cpp/include/wceframe.h
@@ -0,0 +1,420 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////
+// WceFrame.h
+// Definitions for the CCmdBar and CWceFrame
+
+// These classes are provide a frame window for use on Window CE devices such
+// as Pocket PCs. The frame uses CommandBar (a control unique to the Windows CE
+// operating systems) to display the menu and toolbar.
+//
+// Use the PocketPCWceFrame generic application as the starting point for your own
+// frame based applications on the Pocket PC.
+//
+// Refer to the Scribble demo application for an example of how these classes
+// can be used.
+
+
+#ifndef _WIN32XX_WCEFRAME_H_
+#define _WIN32XX_WCEFRAME_H_
+
+
+#include "wincore.h"
+#include
+#include
+#include "default_resource.h"
+
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #define SHELL_AYGSHELL
+#endif
+
+#ifdef SHELL_AYGSHELL
+ #include
+ #pragma comment(lib, "aygshell.lib")
+#endif // SHELL_AYGSHELL
+
+#if (_WIN32_WCE < 0x500 && defined(SHELL_AYGSHELL)) || _WIN32_WCE == 420
+ #pragma comment(lib, "ccrtrtti.lib")
+#endif
+
+
+namespace Win32xx
+{
+
+ ////////////////////////////////////
+ // Declaration of the CCmdBar class
+ //
+ class CCmdBar : public CWnd
+ {
+ public:
+ CCmdBar();
+ virtual ~CCmdBar();
+ virtual BOOL AddAdornments(DWORD dwFlags);
+ virtual int AddBitmap(int idBitmap, int iNumImages, int iImageWidth, int iImageHeight);
+ virtual BOOL AddButtons(int nButtons, TBBUTTON* pTBButton);
+ virtual HWND Create(HWND hwndParent);
+ virtual int GetHeight() const;
+ virtual HWND InsertComboBox(int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton);
+ virtual BOOL IsVisible();
+ virtual BOOL Show(BOOL fShow);
+
+ private:
+
+#ifdef SHELL_AYGSHELL
+ SHMENUBARINFO m_mbi;
+#endif
+
+ };
+
+
+ //////////////////////////////////////
+ // Declaration of the CWceFrame class
+ // A mini frame based on CCmdBar
+ class CWceFrame : public CWnd
+ {
+ public:
+ CWceFrame();
+ virtual ~CWceFrame();
+ virtual void AddToolBarButton(UINT nID);
+ CRect GetViewRect() const;
+ CCmdBar& GetMenuBar() const {return (CCmdBar&)m_MenuBar;}
+ virtual void OnActivate(WPARAM wParam, LPARAM lParam);
+ virtual void OnCreate();
+ virtual void PreCreate(CREATESTRUCT &cs);
+ virtual void RecalcLayout();
+ virtual void SetButtons(const std::vector ToolBarData);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ protected:
+ std::vector m_ToolBarData;
+
+ private:
+ CCmdBar m_MenuBar;
+ tString m_tsAppName;
+
+#ifdef SHELL_AYGSHELL
+ SHACTIVATEINFO m_sai;
+#endif
+
+ };
+
+ //////////////////////////////////////////
+ // Definitions for the CCmdBar class
+ // This class wraps CommandBar_Create which
+ // creates a CommandBar at the top of the window
+ inline CCmdBar::CCmdBar()
+ {
+ }
+
+ inline CCmdBar::~CCmdBar()
+ {
+ if (IsWindow())
+ ::CommandBar_Destroy(m_hWnd);
+ }
+
+
+ inline BOOL CCmdBar::AddAdornments(DWORD dwFlags)
+ {
+ BOOL bReturn = CommandBar_AddAdornments(m_hWnd, dwFlags, 0);
+
+ if (!bReturn)
+ throw CWinException(_T("AddAdornments failed"));
+
+ return bReturn;
+ }
+
+ inline int CCmdBar::AddBitmap(int idBitmap, int iNumImages, int iImageWidth, int iImageHeight)
+ {
+ HINSTANCE hInst = GetApp()->GetInstanceHandle();
+ return CommandBar_AddBitmap(m_hWnd, hInst, idBitmap, iNumImages, iImageWidth, iImageHeight);
+ }
+
+ inline BOOL CCmdBar::AddButtons(int nButtons, TBBUTTON* pTBButton)
+ {
+ BOOL bReturn = CommandBar_AddButtons(m_hWnd, nButtons, pTBButton);
+ if (!bReturn)
+ throw CWinException(_T("Failed to add buttons to commandbar"));
+
+ return bReturn;
+ }
+
+ inline HWND CCmdBar::Create(HWND hParent)
+ {
+#ifdef SHELL_AYGSHELL
+ SHMENUBARINFO mbi;
+
+ memset(&mbi, 0, sizeof(SHMENUBARINFO));
+ mbi.cbSize = sizeof(SHMENUBARINFO);
+ mbi.hwndParent = hParent;
+ mbi.nToolBarId = IDW_MAIN;
+ mbi.hInstRes = GetApp()->GetInstanceHandle();
+ mbi.nBmpId = 0;
+ mbi.cBmpImages = 0;
+
+ if (SHCreateMenuBar(&mbi))
+ {
+ m_hWnd = mbi.hwndMB;
+ }
+ else
+ throw CWinException(_T("Failed to create MenuBar"));
+
+#else
+ m_hWnd = CommandBar_Create(GetApp()->GetInstanceHandle(), hParent, IDW_MENUBAR);
+
+ if (m_hWnd == NULL)
+ throw CWinException(_T("Failed to create CommandBar"));
+
+ CommandBar_InsertMenubar(m_hWnd, GetApp()->GetInstanceHandle(), IDW_MAIN, 0);
+#endif
+ return m_hWnd;
+ }
+
+ inline int CCmdBar::GetHeight() const
+ {
+ return CommandBar_Height(m_hWnd);
+ }
+
+ inline HWND CCmdBar::InsertComboBox(int iWidth, UINT dwStyle, WORD idComboBox, WORD iButton)
+ {
+ HINSTANCE hInst = GetApp()->GetInstanceHandle();
+ HWND hWnd = CommandBar_InsertComboBox(m_hWnd, hInst, iWidth, dwStyle, idComboBox, iButton);
+
+ if (!hWnd)
+ throw CWinException(_T("InsertComboBox failed"));
+
+ return hWnd;
+ }
+
+ inline BOOL CCmdBar::IsVisible()
+ {
+ return ::CommandBar_IsVisible(m_hWnd);
+ }
+
+ inline BOOL CCmdBar::Show(BOOL fShow)
+ {
+ return ::CommandBar_Show(m_hWnd, fShow);
+ }
+
+
+ /////////////////////////////////////////
+ // Definitions for the CWceFrame class
+ // This class creates a simple frame using CCmdBar
+ inline CWceFrame::CWceFrame()
+ {
+#ifdef SHELL_AYGSHELL
+ // Initialize the shell activate info structure
+ memset (&m_sai, 0, sizeof (m_sai));
+ m_sai.cbSize = sizeof (m_sai);
+#endif
+ }
+
+ inline CWceFrame::~CWceFrame()
+ {
+ }
+
+ inline void CWceFrame::AddToolBarButton(UINT nID)
+ // Adds Resource IDs to toolbar buttons.
+ // A resource ID of 0 is a separator
+ {
+ m_ToolBarData.push_back(nID);
+ }
+
+ inline CRect CWceFrame::GetViewRect() const
+ {
+ CRect r;
+ ::GetClientRect(m_hWnd, &r);
+
+#ifndef SHELL_AYGSHELL
+ // Reduce the size of the client rectange, by the commandbar height
+ r.top += m_MenuBar.GetHeight();
+#endif
+
+ return r;
+ }
+
+ inline void CWceFrame::OnCreate()
+ {
+ // Create the Commandbar
+ m_MenuBar.Create(m_hWnd);
+
+ // Set the keyboard accelerators
+ HACCEL hAccel = LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ GetApp()->SetAccelerators(hAccel, this);
+
+ // Add the toolbar buttons
+ if (m_ToolBarData.size() > 0)
+ SetButtons(m_ToolBarData);
+
+#ifndef SHELL_AYGSHELL
+ // Add close button
+ m_MenuBar.AddAdornments(0);
+#endif
+
+ }
+
+ inline void CWceFrame::OnActivate(WPARAM wParam, LPARAM lParam)
+ {
+#ifdef SHELL_AYGSHELL
+ // Notify shell of our activate message
+ SHHandleWMActivate(m_hWnd, wParam, lParam, &m_sai, FALSE);
+
+ UINT fActive = LOWORD(wParam);
+ if ((fActive == WA_ACTIVE) || (fActive == WA_CLICKACTIVE))
+ {
+ // Reposition the window when it's activated
+ RecalcLayout();
+ }
+#endif
+ }
+
+ inline void CWceFrame::PreCreate(CREATESTRUCT &cs)
+ {
+ cs.style = WS_VISIBLE;
+ m_tsAppName = _T("Win32++ Application");
+
+ // Choose a unique class name for this app
+ if (LoadString(IDW_MAIN) != _T(""))
+ {
+ m_tsAppName = LoadString(IDW_MAIN);
+ }
+
+ cs.lpszClass = m_tsAppName.c_str();
+ }
+
+/* inline BOOL CWceFrame::PreTranslateMessage(MSG* pMsg)
+ {
+ HACCEL hAccelTable = ::LoadAccelerators(GetApp()->GetResourceHandle(), MAKEINTRESOURCE(IDW_MAIN));
+ if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)
+ {
+ if (TranslateAccelerator(m_hWnd, hAccelTable, pMsg))
+ return TRUE;
+ }
+ return CWnd::PreTranslateMessage(pMsg);
+ } */
+
+ inline void CWceFrame::RecalcLayout()
+ {
+ HWND hwndCB = m_MenuBar.GetHwnd();
+ if (hwndCB)
+ {
+ CRect rc; // Desktop window size
+ CRect rcMenuBar; // MenuBar window size
+
+ ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
+ ::GetWindowRect(hwndCB, &rcMenuBar);
+ rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top);
+
+ MoveWindow(rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE);
+ }
+
+ ShowWindow(TRUE);
+ UpdateWindow();
+ }
+
+ inline void CWceFrame::SetButtons(const std::vector ToolBarData)
+ // Define the resource IDs for the toolbar like this in the Frame's constructor
+ // m_ToolBarData.push_back ( 0 ); // Separator
+ // m_ToolBarData.clear();
+ // m_ToolBarData.push_back ( IDM_FILE_NEW );
+ // m_ToolBarData.push_back ( IDM_FILE_OPEN );
+ // m_ToolBarData.push_back ( IDM_FILE_SAVE );
+
+ {
+ int iImages = 0;
+ int iNumButtons = (int)ToolBarData.size();
+
+
+ if (iNumButtons > 0)
+ {
+ // Create the TBBUTTON array for each button
+ std::vector vTBB(iNumButtons);
+ TBBUTTON* tbbArray = &vTBB.front();
+
+ for (int j = 0 ; j < iNumButtons; j++)
+ {
+ ZeroMemory(&tbbArray[j], sizeof(TBBUTTON));
+
+ if (ToolBarData[j] == 0)
+ {
+ tbbArray[j].fsStyle = TBSTYLE_SEP;
+ }
+ else
+ {
+ tbbArray[j].iBitmap = iImages++;
+ tbbArray[j].idCommand = ToolBarData[j];
+ tbbArray[j].fsState = TBSTATE_ENABLED;
+ tbbArray[j].fsStyle = TBSTYLE_BUTTON;
+ tbbArray[j].iString = -1;
+ }
+ }
+
+ // Add the bitmap
+ GetMenuBar().AddBitmap(IDW_MAIN, iImages , 16, 16);
+
+ // Add the buttons
+ GetMenuBar().AddButtons(iNumButtons, tbbArray);
+ }
+ }
+
+ inline LRESULT CWceFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch (uMsg)
+ {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ break;
+ case WM_ACTIVATE:
+ OnActivate(wParam, lParam);
+ break;
+
+#ifdef SHELL_AYGSHELL
+
+ case WM_SETTINGCHANGE:
+ SHHandleWMSettingChange(m_hWnd, wParam, lParam, &m_sai);
+ break;
+#endif
+
+ }
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+
+} // namespace Win32xx
+
+#endif // _WIN32XX_WCEFRAME_H_
+
diff --git a/external/win32cpp/include/wcestddef.h b/external/win32cpp/include/wcestddef.h
new file mode 100644
index 0000000..f7b2283
--- /dev/null
+++ b/external/win32cpp/include/wcestddef.h
@@ -0,0 +1,58 @@
+
+#pragma once
+
+#pragma comment(linker, "/nodefaultlib:libc.lib")
+#pragma comment(linker, "/nodefaultlib:libcd.lib")
+
+
+#include
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #define SHELL_AYGSHELL
+#endif
+
+#ifdef _CE_DCOM
+ #define _ATL_APARTMENT_THREADED
+#endif
+
+#if defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)
+ #ifndef _DEVICE_RESOLUTION_AWARE
+ #define _DEVICE_RESOLUTION_AWARE
+ #endif
+#endif
+
+
+#if _WIN32_WCE == 420 || _WIN32_WCE == 0x420
+ // For Pocket PC 2003
+ #pragma comment(lib, "ccrtrtti.lib")
+#endif
+
+#if _MSC_VER >= 1300
+
+ // NOTE - this value is not strongly correlated to the Windows CE OS version being targeted
+ #undef WINVER
+ #define WINVER _WIN32_WCE
+
+ #ifdef _DEVICE_RESOLUTION_AWARE
+ #include "DeviceResolutionAware.h"
+ #endif
+
+ #if _WIN32_WCE < 0x500 && ( defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP) )
+ #ifdef _X86_
+ #if defined(_DEBUG)
+ #pragma comment(lib, "libcmtx86d.lib")
+ #else
+ #pragma comment(lib, "libcmtx86.lib")
+ #endif
+ #endif
+ #endif
+
+ #include
+
+#endif// _MSC_VER >= 1300
+
+#ifdef SHELL_AYGSHELL
+ #include
+ #pragma comment(lib, "aygshell.lib")
+#endif // SHELL_AYGSHELL
+
+// TODO: reference additional headers your program requires here
diff --git a/external/win32cpp/include/webbrowser.h b/external/win32cpp/include/webbrowser.h
new file mode 100644
index 0000000..5a5b5f4
--- /dev/null
+++ b/external/win32cpp/include/webbrowser.h
@@ -0,0 +1,760 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+#ifndef _WIN32XX_WEBBROWSER_H_
+#define _WIN32XX_WEBBROWSER_H_
+
+#include
+#include
+
+
+namespace Win32xx
+{
+ ///////////////////////////////////////////////////
+ // Declaration of the CAXWindow class
+ // This class implements an ActiveX control container
+ class CAXWindow : public IOleClientSite, public IOleInPlaceSite, public IOleInPlaceFrame,
+ public IOleControlSite, public IDispatch
+ {
+ public:
+ CAXWindow();
+ virtual ~CAXWindow();
+ virtual void Activate(BOOL fFocus);
+ virtual void CreateControl(BSTR bstrClsid);
+ virtual void CreateControl(CLSID clsid);
+ virtual void Remove();
+ virtual void SetParent(HWND hWndParent);
+ virtual void SetLocation(int x, int y, int width, int height);
+ virtual void SetVisible(BOOL fVisible);
+ virtual void SetStatusWindow(HWND hWndStatus);
+ virtual void TranslateKey(MSG msg);
+ IDispatch* GetDispatch();
+ IUnknown* GetUnknown();
+
+ // IUnknown Methods
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject);
+ STDMETHODIMP_(ULONG) AddRef();
+ STDMETHODIMP_(ULONG) Release();
+
+ // IOleClientSite Methods
+ STDMETHODIMP SaveObject();
+ STDMETHODIMP GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMk);
+ STDMETHODIMP GetContainer(LPOLECONTAINER* ppContainer);
+ STDMETHODIMP ShowObject();
+ STDMETHODIMP OnShowWindow(BOOL fShow);
+ STDMETHODIMP RequestNewObjectLayout();
+
+ // IOleWindow Methods
+ STDMETHODIMP GetWindow(HWND* phwnd);
+ STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
+
+ // IOleInPlaceSite Methods
+ STDMETHODIMP CanInPlaceActivate();
+ STDMETHODIMP OnInPlaceActivate();
+ STDMETHODIMP OnUIActivate();
+ STDMETHODIMP GetWindowContext(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo);
+ STDMETHODIMP Scroll(SIZE scrollExtent);
+ STDMETHODIMP OnUIDeactivate(BOOL fUndoable);
+ STDMETHODIMP OnInPlaceDeactivate();
+ STDMETHODIMP DiscardUndoState();
+ STDMETHODIMP DeactivateAndUndo();
+ STDMETHODIMP OnPosRectChange(LPCRECT lprcPosRect);
+
+ // IOleInPlaceUIWindow Methods
+ STDMETHODIMP GetBorder(LPRECT lprectBorder);
+ STDMETHODIMP RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths);
+ STDMETHODIMP SetBorderSpace(LPCBORDERWIDTHS lpborderwidths);
+ STDMETHODIMP SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR lpszObjName);
+
+ // IOleInPlaceFrame Methods
+ STDMETHODIMP InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
+ STDMETHODIMP SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject);
+ STDMETHODIMP RemoveMenus(HMENU hmenuShared);
+ STDMETHODIMP SetStatusText(LPCOLESTR pszStatusText);
+ STDMETHODIMP EnableModeless(BOOL fEnable);
+ STDMETHODIMP TranslateAccelerator(LPMSG lpmsg, WORD wID);
+
+ // IOleControlSite Methods
+ STDMETHODIMP OnControlInfoChanged();
+ STDMETHODIMP LockInPlaceActive(BOOL fLock);
+ STDMETHODIMP GetExtendedControl(IDispatch** ppDisp);
+ STDMETHODIMP TransformCoords(POINTL* pptlHimetric, POINTF* pptfContainer, DWORD dwFlags);
+ STDMETHODIMP TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers);
+ STDMETHODIMP OnFocus(BOOL fGotFocus);
+ STDMETHODIMP ShowPropertyFrame();
+
+ // IDispatch Methods
+ STDMETHODIMP GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgdispid);
+ STDMETHODIMP GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo** pptinfo);
+ STDMETHODIMP GetTypeInfoCount(unsigned int* pctinfo);
+ STDMETHODIMP Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexecinfo, unsigned int* puArgErr);
+
+ private:
+ ULONG m_cRefs; // ref count
+ HWND m_hWnd; // window handle of the container
+ HWND m_hWndStatus; // status window handle
+ IUnknown* m_pUnk; // IUnknown of contained object
+ CRect m_rcControl; // size of control
+ };
+
+
+ ///////////////////////////////////////////////
+ // Declaration of the CWebBrowser class
+ // This class uses an AciveX Container provided by
+ // CAXWindow to host the IWebBrower2 interface.
+ class CWebBrowser : public CWnd
+ {
+ public:
+ CWebBrowser();
+ virtual ~CWebBrowser();
+ virtual void AddWebBrowserControl(void);
+ virtual CAXWindow& GetAXWindow() const { return (CAXWindow&)m_AXContainer; }
+ virtual IWebBrowser2* GetIWebBrowser2() const { return m_pIWebBrowser2; }
+ virtual void Navigate(LPCTSTR str);
+
+ protected:
+ virtual void OnCreate();
+ virtual void OnSize(int width, int height);
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+ private:
+ CAXWindow m_AXContainer; // The ActiveX Container
+ IWebBrowser2* m_pIWebBrowser2;// Interface to the ActiveX web browser control
+ };
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+namespace Win32xx
+{
+ /////////////////////////////////////////
+ // Definitions for the CAXWindow class
+ //
+ inline CAXWindow::CAXWindow() : m_cRefs(1), m_hWnd(NULL), m_pUnk(NULL)
+ {
+ }
+
+ inline CAXWindow::~CAXWindow()
+ {
+ }
+
+ inline void CAXWindow::CreateControl(BSTR bstrClsid)
+ {
+ CLSID clsid;
+ CLSIDFromString(bstrClsid, &clsid);
+ CreateControl(clsid);
+ }
+
+ inline void CAXWindow::Activate(BOOL fFocus)
+ {
+ if (!m_pUnk)
+ return;
+
+ if (fFocus)
+ {
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ pioo->DoVerb(OLEIVERB_UIACTIVATE, NULL, this, 0, m_hWnd, &m_rcControl);
+ pioo->Release();
+ }
+ }
+
+ inline void CAXWindow::CreateControl(CLSID clsid)
+ {
+ CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&m_pUnk);
+
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ pioo->SetClientSite(this);
+ pioo->Release();
+
+ IPersistStreamInit* ppsi;
+ hr = m_pUnk->QueryInterface(IID_IPersistStreamInit, (void**)&ppsi);
+ if (SUCCEEDED(hr))
+ {
+ ppsi->InitNew();
+ ppsi->Release();
+ }
+ }
+
+ inline STDMETHODIMP_(ULONG) CAXWindow::AddRef()
+ {
+ return ++m_cRefs;
+ }
+
+ inline STDMETHODIMP CAXWindow::CanInPlaceActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::ContextSensitiveHelp(BOOL fEnterMode)
+ {
+ UNREFERENCED_PARAMETER(fEnterMode);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::DeactivateAndUndo()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::DiscardUndoState()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::EnableModeless(BOOL fEnable)
+ {
+ UNREFERENCED_PARAMETER(fEnable);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetBorder(LPRECT lprectBorder)
+ {
+ UNREFERENCED_PARAMETER(lprectBorder);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetContainer(LPOLECONTAINER* ppContainer)
+ {
+ UNREFERENCED_PARAMETER(ppContainer);
+ return E_NOINTERFACE;
+ }
+
+ inline IDispatch* CAXWindow::GetDispatch()
+ {
+ if (!m_pUnk)
+ return NULL;
+
+ HRESULT hr;
+ IDispatch* pdisp;
+
+ hr = m_pUnk->QueryInterface(IID_IDispatch, (void**)&pdisp);
+ return pdisp;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetExtendedControl(IDispatch** ppDisp)
+ {
+ if (ppDisp == NULL)
+ return E_INVALIDARG;
+
+ *ppDisp = (IDispatch*)this;
+ (*ppDisp)->AddRef();
+
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetIDsOfNames(REFIID riid, OLECHAR** rgszNames, unsigned int cNames, LCID lcid, DISPID* rgdispid)
+ {
+ UNREFERENCED_PARAMETER((IID)riid); // IID cast required for the MinGW compiler
+ UNREFERENCED_PARAMETER(rgszNames);
+ UNREFERENCED_PARAMETER(cNames);
+ UNREFERENCED_PARAMETER(lcid);
+
+ *rgdispid = DISPID_UNKNOWN;
+ return DISP_E_UNKNOWNNAME;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMk)
+ {
+ UNREFERENCED_PARAMETER(dwAssign);
+ UNREFERENCED_PARAMETER(dwWhichMoniker);
+ UNREFERENCED_PARAMETER(ppMk);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetTypeInfo(unsigned int itinfo, LCID lcid, ITypeInfo** pptinfo)
+ {
+ UNREFERENCED_PARAMETER(itinfo);
+ UNREFERENCED_PARAMETER(lcid);
+ UNREFERENCED_PARAMETER(pptinfo);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetTypeInfoCount(unsigned int* pctinfo)
+ {
+ UNREFERENCED_PARAMETER(pctinfo);
+ return E_NOTIMPL;
+ }
+
+ inline IUnknown* CAXWindow::GetUnknown()
+ {
+ if (!m_pUnk)
+ return NULL;
+
+ m_pUnk->AddRef();
+ return m_pUnk;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetWindow(HWND* lphwnd)
+ {
+ if (!IsWindow(m_hWnd))
+ return S_FALSE;
+
+ *lphwnd = m_hWnd;
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::GetWindowContext (IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppIIPUIWin,
+ LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
+ {
+ *ppFrame = (IOleInPlaceFrame*)this;
+ *ppIIPUIWin = NULL;
+
+ RECT rect;
+ GetClientRect(m_hWnd, &rect);
+ lprcPosRect->left = 0;
+ lprcPosRect->top = 0;
+ lprcPosRect->right = rect.right;
+ lprcPosRect->bottom = rect.bottom;
+
+ CopyRect(lprcClipRect, lprcPosRect);
+
+ lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
+ lpFrameInfo->fMDIApp = FALSE;
+ lpFrameInfo->hwndFrame = m_hWnd;
+ lpFrameInfo->haccel = 0;
+ lpFrameInfo->cAccelEntries = 0;
+
+ (*ppFrame)->AddRef();
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ UNREFERENCED_PARAMETER(lpMenuWidths);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexecinfo, unsigned int* puArgErr)
+ {
+ UNREFERENCED_PARAMETER(dispid);
+ UNREFERENCED_PARAMETER((IID)riid); // IID cast required for the MinGW compiler
+ UNREFERENCED_PARAMETER(lcid);
+ UNREFERENCED_PARAMETER(wFlags);
+ UNREFERENCED_PARAMETER(pdispparams);
+ UNREFERENCED_PARAMETER(pvarResult);
+ UNREFERENCED_PARAMETER(pexecinfo);
+ UNREFERENCED_PARAMETER(puArgErr);
+ return DISP_E_MEMBERNOTFOUND;
+ }
+
+ inline STDMETHODIMP CAXWindow::LockInPlaceActive(BOOL fLock)
+ {
+ UNREFERENCED_PARAMETER(fLock);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnControlInfoChanged()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnFocus(BOOL fGotFocus)
+ {
+ UNREFERENCED_PARAMETER(fGotFocus);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnInPlaceActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnInPlaceDeactivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnPosRectChange(LPCRECT lprcPosRect)
+ {
+ UNREFERENCED_PARAMETER(lprcPosRect);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnShowWindow(BOOL fShow)
+ {
+ UNREFERENCED_PARAMETER(fShow);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnUIActivate()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::OnUIDeactivate(BOOL fUndoable)
+ {
+ UNREFERENCED_PARAMETER(fUndoable);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::QueryInterface(REFIID riid, void** ppvObject)
+ {
+ if (!ppvObject)
+ return E_POINTER;
+
+ if (IsEqualIID(riid, IID_IOleClientSite))
+ *ppvObject = (IOleClientSite*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceSite))
+ *ppvObject = (IOleInPlaceSite*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceFrame))
+ *ppvObject = (IOleInPlaceFrame*)this;
+ else if (IsEqualIID(riid, IID_IOleInPlaceUIWindow))
+ *ppvObject = (IOleInPlaceUIWindow*)this;
+ else if (IsEqualIID(riid, IID_IOleControlSite))
+ *ppvObject = (IOleControlSite*)this;
+ else if (IsEqualIID(riid, IID_IOleWindow))
+ *ppvObject = this;
+ else if (IsEqualIID(riid, IID_IDispatch))
+ *ppvObject = (IDispatch*)this;
+ else if (IsEqualIID(riid, IID_IUnknown))
+ *ppvObject = this;
+ else
+ {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+
+ AddRef();
+ return S_OK;
+ }
+
+ inline STDMETHODIMP_(ULONG) CAXWindow::Release()
+ {
+ return --m_cRefs;
+ }
+
+ inline void CAXWindow::Remove()
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (SUCCEEDED(hr))
+ {
+ pioo->Close(OLECLOSE_NOSAVE);
+ pioo->SetClientSite(NULL);
+ pioo->Release();
+ }
+
+ IOleInPlaceObject* pipo;
+ hr = m_pUnk->QueryInterface(IID_IOleInPlaceObject, (void**)&pipo);
+ if (SUCCEEDED(hr))
+ {
+ pipo->UIDeactivate();
+ pipo->InPlaceDeactivate();
+ pipo->Release();
+ }
+
+ m_pUnk->Release();
+ m_pUnk = NULL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RemoveMenus(HMENU hmenuShared)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RequestBorderSpace(LPCBORDERWIDTHS lpborderwidths)
+ {
+ UNREFERENCED_PARAMETER(lpborderwidths);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::RequestNewObjectLayout()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SaveObject()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::Scroll(SIZE scrollExtent)
+ {
+ UNREFERENCED_PARAMETER(scrollExtent);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR lpszObjName)
+ {
+ UNREFERENCED_PARAMETER(pActiveObject);
+ UNREFERENCED_PARAMETER(lpszObjName);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetBorderSpace(LPCBORDERWIDTHS lpborderwidths)
+ {
+ UNREFERENCED_PARAMETER(lpborderwidths);
+ return E_NOTIMPL;
+ }
+
+ inline void CAXWindow::SetLocation(int x, int y, int width, int height)
+ {
+ m_rcControl.SetRect(x, y, x + width, y + height);
+
+ if (!m_pUnk)
+ return;
+
+ IOleInPlaceObject* pipo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleInPlaceObject, (void**)&pipo);
+ if (FAILED(hr))
+ return;
+
+ pipo->SetObjectRects(&m_rcControl, &m_rcControl);
+ pipo->Release();
+ }
+
+ inline STDMETHODIMP CAXWindow::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject)
+ {
+ UNREFERENCED_PARAMETER(hmenuShared);
+ UNREFERENCED_PARAMETER(holemenu);
+ UNREFERENCED_PARAMETER(hwndActiveObject);
+ return E_NOTIMPL;
+ }
+
+ inline void CAXWindow::SetParent(HWND hWndParent)
+ {
+ m_hWnd = hWndParent;
+ }
+
+ inline STDMETHODIMP CAXWindow::SetStatusText(LPCOLESTR pszStatusText)
+ {
+ if (NULL == pszStatusText)
+ return E_POINTER;
+
+ #ifndef _UNICODE
+ char status[MAX_PATH];
+ // Convert the Wide string to char
+ WideCharToMultiByte(CP_ACP, 0, pszStatusText, -1, status, MAX_PATH, NULL, NULL);
+
+ if (IsWindow(m_hWndStatus))
+ SendMessage(m_hWndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)status);
+ #else
+ if (IsWindow(m_hWndStatus))
+ SendMessage(m_hWndStatus, SB_SETTEXT, (WPARAM)0, (LPARAM)pszStatusText);
+ #endif
+
+ return (S_OK);
+ }
+
+ inline void CAXWindow::SetStatusWindow(HWND hWndStatus)
+ {
+ m_hWndStatus = hWndStatus;
+ }
+
+ inline void CAXWindow::SetVisible(BOOL fVisible)
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleObject* pioo;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleObject, (void**)&pioo);
+ if (FAILED(hr))
+ return;
+
+ if (fVisible)
+ {
+ pioo->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, this, 0, m_hWnd, &m_rcControl);
+ pioo->DoVerb(OLEIVERB_SHOW, NULL, this, 0, m_hWnd, &m_rcControl);
+ }
+ else
+ pioo->DoVerb(OLEIVERB_HIDE, NULL, this, 0, m_hWnd, NULL);
+
+ pioo->Release();
+ }
+
+ inline STDMETHODIMP CAXWindow::ShowObject()
+ {
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::ShowPropertyFrame()
+ {
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::TransformCoords(POINTL* pptlHimetric, POINTF* pptfContainer, DWORD dwFlags)
+ {
+ UNREFERENCED_PARAMETER(pptlHimetric);
+ UNREFERENCED_PARAMETER(pptfContainer);
+ UNREFERENCED_PARAMETER(dwFlags);
+ return E_NOTIMPL;
+ }
+
+ inline STDMETHODIMP CAXWindow::TranslateAccelerator(LPMSG lpmsg, WORD wID)
+ {
+ UNREFERENCED_PARAMETER(lpmsg);
+ UNREFERENCED_PARAMETER(wID);
+ return S_OK;
+ }
+
+ inline STDMETHODIMP CAXWindow::TranslateAccelerator(LPMSG pMsg, DWORD grfModifiers)
+ {
+ UNREFERENCED_PARAMETER(pMsg);
+ UNREFERENCED_PARAMETER(grfModifiers);
+ return S_FALSE;
+ }
+
+ inline void CAXWindow::TranslateKey(MSG msg)
+ {
+ if (!m_pUnk)
+ return;
+
+ IOleInPlaceActiveObject* pao;
+ HRESULT hr = m_pUnk->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&pao);
+ if (FAILED(hr))
+ return;
+
+ pao->TranslateAccelerator(&msg);
+ pao->Release();
+ }
+
+
+ ////////////////////////////////////////
+ // Definitions for the CWebBrowser class
+ //
+ inline CWebBrowser::CWebBrowser() : m_pIWebBrowser2(0)
+ {
+ OleInitialize(NULL);
+ }
+
+ inline CWebBrowser::~CWebBrowser()
+ {
+ if (m_pIWebBrowser2)
+ {
+ m_pIWebBrowser2->Stop();
+ m_pIWebBrowser2->Release();
+ }
+
+ OleUninitialize();
+ }
+
+ inline void CWebBrowser::AddWebBrowserControl()
+ {
+ GetAXWindow().CreateControl(CLSID_WebBrowser);
+ GetAXWindow().SetParent(m_hWnd);
+ GetAXWindow().SetVisible(TRUE);
+ GetAXWindow().Activate(TRUE);
+
+ IUnknown* pUnk = GetAXWindow().GetUnknown();
+ if(pUnk)
+ {
+ // Store the pointer to the WebBrowser control
+ HRESULT hr = pUnk->QueryInterface(IID_IWebBrowser2, (void**)&m_pIWebBrowser2);
+ pUnk->Release();
+
+ // Navigate to an empty page
+ if (SUCCEEDED(hr))
+ {
+ VARIANT vURL;
+ vURL.vt = VT_BSTR;
+ vURL.bstrVal = SysAllocString(L"about:blank");
+ VARIANT ve1, ve2, ve3, ve4;
+ ve1.vt = VT_EMPTY;
+ ve2.vt = VT_EMPTY;
+ ve3.vt = VT_EMPTY;
+ ve4.vt = VT_EMPTY;
+
+ m_pIWebBrowser2->Navigate2(&vURL, &ve1, &ve2, &ve3, &ve4);
+
+ VariantClear(&vURL);
+ }
+ }
+ }
+
+ inline void CWebBrowser::Navigate(LPCTSTR pTChar)
+ {
+ // Navigate to our web page
+ VARIANT vURL;
+ vURL.vt = VT_BSTR;
+ vURL.bstrVal = SysAllocString(T2W(pTChar));
+ VARIANT ve1, ve2, ve3, ve4;
+ ve1.vt = VT_EMPTY;
+ ve2.vt = VT_EMPTY;
+ ve3.vt = VT_EMPTY;
+ ve4.vt = VT_EMPTY;
+
+ GetIWebBrowser2()->Navigate2(&vURL, &ve1, &ve2, &ve3, &ve4);
+
+ VariantClear(&vURL); // Also frees memory allocated by SysAllocateString
+ }
+
+ inline void CWebBrowser::OnCreate()
+ {
+ AddWebBrowserControl();
+ }
+
+ inline void CWebBrowser::OnSize(int width, int height)
+ {
+ // position the container
+ GetAXWindow().SetLocation(0, 0, width, height);
+ }
+
+ inline LRESULT CWebBrowser::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ switch(uMsg)
+ {
+ case WM_SIZE:
+ OnSize(LOWORD(lParam), HIWORD(lParam));
+ break;
+ case WM_DESTROY:
+ GetAXWindow().Remove();
+ break;
+ }
+
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);
+ }
+
+}
+
+#endif // _WIN32XX_WEBBROWSER_H_
+
diff --git a/external/win32cpp/include/wincore.h b/external/win32cpp/include/wincore.h
new file mode 100644
index 0000000..d6b1f9b
--- /dev/null
+++ b/external/win32cpp/include/wincore.h
@@ -0,0 +1,2977 @@
+// Win32++ Version 7.2
+// Released: 5th AUgust 2011
+//
+// David Nash
+// email: dnash@bigpond.net.au
+// url: https://sourceforge.net/projects/win32-framework
+//
+//
+// Copyright (c) 2005-2011 David Nash
+//
+// Permission is hereby granted, free of charge, to
+// any person obtaining a copy of this software and
+// associated documentation files (the "Software"),
+// to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify,
+// merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice
+// shall be included in all copies or substantial portions
+// of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
+// OR OTHER DEALINGS IN THE SOFTWARE.
+//
+////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////
+// wincore.h
+// Declaration of the following classes:
+// CWinApp, CWnd, CWinException, CCriticalSection,
+// CPoint, CRect, and CSize
+//
+// This file contains the declarations for the core set of classes required to
+// create simple windows using Win32++.
+//
+// 1) CCriticalSection: This class is used internally to manage thread access
+// to shared resources. You can also use this class to lock and
+// release your own critical sections.
+//
+// 2) CWinException: This class is used internally by Win32++ to handle
+// exceptions. You can also use it to throw and catch exceptions.
+//
+// 3) WinApp: This class is used start Win32++ and run the message loop. You
+// should inherit from this class to start Win32++ in your own
+// application.
+//
+// 4) CWnd: This class is used to represent a window. It provides a means
+// of creating the window, and handling its messages. Inherit
+// from this class to define and control windows.
+//
+//
+// Note: This header file (or another Win32++ header file which includes it)
+// should be included before all other header files. It sets some
+// important macros which need to be set before including Windows.h
+// Including this file first also allows it to disable some pointless
+// warning messages (see below).
+
+
+
+#ifndef _WIN32XX_WINCORE_H_
+#define _WIN32XX_WINCORE_H_
+
+
+// Remove pointless warning messages
+#ifdef _MSC_VER
+ #pragma warning (disable : 4996) // function or variable may be unsafe (deprecated)
+ #ifndef _CRT_SECURE_NO_WARNINGS
+ #define _CRT_SECURE_NO_WARNINGS // eliminate deprecation warnings for VS2005/VS2010
+ #endif
+ #if _MSC_VER < 1500
+ #pragma warning (disable : 4511) // copy operator could not be generated
+ #pragma warning (disable : 4512) // assignment operator could not be generated
+ #pragma warning (disable : 4702) // unreachable code (bugs in Microsoft's STL)
+ #pragma warning (disable : 4786) // identifier was truncated
+ #endif
+#endif
+
+#ifdef __BORLANDC__
+ #pragma option -w-8019 // code has no effect
+ #pragma option -w-8026 // functions with exception specifiations are not expanded inline
+ #pragma option -w-8027 // function not expanded inline
+ #define STRICT 1
+#endif
+
+#ifdef __GNUC__
+ #pragma GCC diagnostic ignored "-Wmissing-braces"
+ #pragma GCC diagnostic ignored "-Wunused-value"
+#endif
+
+#ifdef _WIN32_WCE
+ #include "wcestddef.h"
+#endif
+
+#define _WINSOCKAPI_ // Prevent winsock.h #include's.
+
+#include
+#include
+#include
+#include
+#include