Index: base/applications/win32++demo/CMakeLists.txt =================================================================== --- base/applications/win32++demo/CMakeLists.txt (revision 0) +++ base/applications/win32++demo/CMakeLists.txt (working copy) @@ -0,0 +1,18 @@ +set_cpp(WITH_EXCEPTIONS WITH_RTTI WITH_STL) + +add_definitions(-DWIN32) + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/win32++) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +list(APPEND SOURCE + main.cpp + FrameApp.cpp + Mainfrm.cpp + View.cpp + Resource.rc) + +add_executable(win32++demo ${SOURCE}) +set_module_type(win32++demo win32gui UNICODE) +add_importlibs(win32++demo advapi32 comctl32 comdlg32 user32 gdi32 winmm shell32 msvcrt kernel32) +add_cd_file(TARGET win32++demo DESTINATION reactos/system32 FOR all) Index: base/applications/win32++demo/FrameApp.cpp =================================================================== --- base/applications/win32++demo/FrameApp.cpp (revision 0) +++ base/applications/win32++demo/FrameApp.cpp (working copy) @@ -0,0 +1,31 @@ +////////////////////////////////////////////// +//FrameApp.cpp + +#include "stdafx.h" +#include "FrameApp.h" + + +// Definitions for the CFrameApp class +CFrameApp::CFrameApp() +{ +} + +CFrameApp::~CFrameApp() +{ +} + +BOOL CFrameApp::InitInstance() +{ + //Create the Frame Window + if (!m_Frame.Create()) + { + // We get here if the Frame creation fails + + ::MessageBox(NULL, _T("Failed to create Frame window"), _T("ERROR"), MB_ICONERROR); + return FALSE; // returning FALSE ends the application + } + + return TRUE; +} + + Index: base/applications/win32++demo/FrameApp.h =================================================================== --- base/applications/win32++demo/FrameApp.h (revision 0) +++ base/applications/win32++demo/FrameApp.h (working copy) @@ -0,0 +1,29 @@ +////////////////////////////////////////////////// +// FrameApp.h + +#ifndef FRAMEAPP_H +#define FRAMEAPP_H + +#include "Mainfrm.h" + + +// Declaration of the CFrameApp class +class CFrameApp : public CWinApp +{ +public: + CFrameApp(); + virtual ~CFrameApp(); + virtual BOOL InitInstance(); + CMainFrame& GetMainFrame() { return m_Frame; } + +private: + CMainFrame m_Frame; +}; + + +// a useful function that returns a reference to the CFrameApp object +inline CFrameApp& GetFrameApp() { return *((CFrameApp*)GetApp()); } + + +#endif // define FRAMEAPP_H + Index: base/applications/win32++demo/Mainfrm.cpp =================================================================== --- base/applications/win32++demo/Mainfrm.cpp (revision 0) +++ base/applications/win32++demo/Mainfrm.cpp (working copy) @@ -0,0 +1,168 @@ +//////////////////////////////////////////////////// +// Mainfrm.cpp + +#include "stdafx.h" +#include "resource.h" +#include "mainfrm.h" + + +// Definitions for the CMainFrame class +CMainFrame::CMainFrame() +{ + // Constructor for CMainFrame. Its called after CFrame's constructor + + //Set m_View as the view window of the frame + SetView(m_View); + + // Set the registry key name, and load the initial window position + // Use a registry key name like "CompanyName\\Application" + LoadRegistrySettings(_T("Win32++\\Frame")); +} + +CMainFrame::~CMainFrame() +{ + // Destructor for CMainFrame. +} + +BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // OnCommand responds to menu and and toolbar input + + UNREFERENCED_PARAMETER(lParam); + + switch(LOWORD(wParam)) + { + case IDM_FILE_OPEN: + // Refer to the tutorial for an example of OnFileOpen + OnFileOpen(); + return TRUE; + case IDM_FILE_SAVE: + // Refer to the tutorial for an example of OnFileSave + OnFileSave(); + return TRUE; + case IDM_FILE_SAVEAS: + // Refer to the tutorial for an example of OnFileSaveAs + OnFileSave(); + return TRUE; + case IDM_FILE_PRINT: + OnFilePrint(); + return TRUE; + case IDM_FILE_EXIT: + // End the application + ::PostMessage(m_hWnd, WM_CLOSE, 0, 0); + return TRUE; + case IDW_VIEW_STATUSBAR: + OnViewStatusBar(); + return TRUE; + case IDW_VIEW_TOOLBAR: + OnViewToolBar(); + return TRUE; + case IDM_HELP_ABOUT: + // Display the help dialog + OnHelp(); + return TRUE; + } + + return FALSE; +} + +void CMainFrame::OnCreate() +{ + // OnCreate controls the way the frame is created. + // Overriding CFrame::Oncreate is optional. + // The default for the following variables is TRUE + + // m_bShowIndicatorStatus = FALSE; // Don't show statusbar indicators + // m_bShowMenuStatus = FALSE; // Don't show toolbar or menu status + // m_bUseReBar = FALSE; // Don't use rebars + m_bUseThemes = FALSE; // Don't use themes + // m_bUseToolBar = FALSE; // Don't use a toolbar + + // call the base class function + CFrame::OnCreate(); +} + +void CMainFrame::OnInitialUpdate() +{ + // The frame is now created. + // Place any additional startup code here. + + TRACE("Frame created\n"); +} + +void CMainFrame::OnFileOpen() +{ + // Bring up the dialog, and open the file + CFile File; + CString str = File.OpenFileDialog(0, 0, 0, 0); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +void CMainFrame::OnFileSave() +{ + CFile File; + CString str = File.SaveFileDialog(0, 0, 0, 0, 0); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +void CMainFrame::OnFilePrint() +{ + // Bring up a dialog to choose the printer + PRINTDLG pd = {0}; + pd.lStructSize = sizeof( pd ); + pd.Flags = PD_RETURNDC; + pd.hwndOwner = m_hWnd; + + // Retrieve the printer DC + PrintDlg( &pd ); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +LRESULT CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam) +{ + // Process notification messages sent by child windows +// switch(((LPNMHDR)lParam)->code) +// { + //Add case statments for each notification message here +// } + + // Some notifications should return a value when handled + return CFrame::OnNotify(wParam, lParam); +} + +void CMainFrame::SetupToolBar() +{ + // 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, FALSE ); // disabled button + AddToolBarButton( IDM_EDIT_COPY, FALSE ); // disabled button + AddToolBarButton( IDM_EDIT_PASTE, FALSE ); // disabled button + + AddToolBarButton( 0 ); // Separator + AddToolBarButton( IDM_FILE_PRINT ); + + AddToolBarButton( 0 ); // Separator + AddToolBarButton( IDM_HELP_ABOUT ); +} + +LRESULT CMainFrame::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +// switch (uMsg) +// { +// Add case statements for each messages to be handled here +// } + + // pass unhandled messages on for default processing + return WndProcDefault(uMsg, wParam, lParam); +} + Index: base/applications/win32++demo/Mainfrm.h =================================================================== --- base/applications/win32++demo/Mainfrm.h (revision 0) +++ base/applications/win32++demo/Mainfrm.h (working copy) @@ -0,0 +1,32 @@ +///////////////////////////////////////////// +// Mainfrm.h + +#ifndef MAINFRM_H +#define MAINFRM_H + +#include "View.h" + +// Declaration of the CMainFrame class +class CMainFrame : public CFrame +{ +public: + CMainFrame(void); + virtual ~CMainFrame(); + +protected: + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnCreate(); + virtual void OnFileOpen(); + virtual void OnFilePrint(); + virtual void OnFileSave(); + virtual void OnInitialUpdate(); + virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); + virtual void SetupToolBar(); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + +private: + CView m_View; +}; + +#endif //MAINFRM_H + Index: base/applications/win32++demo/Resource.rc =================================================================== --- base/applications/win32++demo/Resource.rc (revision 0) +++ base/applications/win32++demo/Resource.rc (working copy) @@ -0,0 +1,199 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "res/Win32++.manifest" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDW_MAIN MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "New...", IDM_FILE_NEW + MENUITEM "&Open...", IDM_FILE_OPEN + MENUITEM "&Save", IDM_FILE_SAVE + MENUITEM "Save &As...", IDM_FILE_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print", IDM_FILE_PRINT + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_FILE_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "Undo\tCtrl+Z", IDM_EDIT_UNDO, GRAYED + MENUITEM "Redo\tShift+Ctrl+Z", IDM_EDIT_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cut\tCtrl+X", IDM_EDIT_CUT, GRAYED + MENUITEM "Copy\tCtrl+C", IDM_EDIT_COPY, GRAYED + MENUITEM "Paste\tCtrl+V", IDM_EDIT_PASTE, GRAYED + MENUITEM "Delete\tDel", IDM_EDIT_DELETE, GRAYED + 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDW_MAIN ICON "res/Star.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_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Shell Dlg", 400, 0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,68,49,50,14 + CTEXT "Frame Application",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 + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDW_MAIN "Frame Window" + IDW_VIEW_TOOLBAR "Show or hide the tool bar" + IDW_VIEW_STATUSBAR "Show or hide the status bar" +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" + IDM_EDIT_UNDO "Undo the last action" + IDM_EDIT_REDO "Redo the previously undone action" +END + +STRINGTABLE +BEGIN + 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" + IDM_HELP_ABOUT "Display Information about this program" +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 + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + Index: base/applications/win32++demo/StdAfx.cpp =================================================================== --- base/applications/win32++demo/StdAfx.cpp (revision 0) +++ base/applications/win32++demo/StdAfx.cpp (working copy) @@ -0,0 +1,15 @@ +////////////////////////////////////////////// +// StdAfx.cpp + +// This file is used for precompiled hearders. Precompiled headers allow +// programs to be recompiled more quickly + +// To use precompiled headers, do the following: +// 1) Add the set of rarely changed headers to stdafx.h +// 2) Include stdafx.h in each cpp file. It must be included first. +// 3) Add stdafx.cpp to your project. +// 4) Turn on precompiled hearders in the project + + +#include "stdafx.h" + Index: base/applications/win32++demo/View.cpp =================================================================== --- base/applications/win32++demo/View.cpp (revision 0) +++ base/applications/win32++demo/View.cpp (working copy) @@ -0,0 +1,70 @@ +////////////////////////////////////////////// +// View.cpp +// Definitions for the CView class + +#include "stdafx.h" +#include "view.h" + + +CView::CView() +{ +} + +void CView::OnDraw(CDC* pDC) +{ + CRect rc = GetClientRect(); + + // Centre some text in our view window + pDC->DrawText(_T("View Window"), -1, rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); +} + +void CView::OnInitialUpdate() +{ + // OnInitialUpdate is called immediately after the window is created + TRACE("View window created\n"); +} + +void CView::PreCreate(CREATESTRUCT &cs) +{ + // Here we set the defaults used by the create function for the view window + // Preforming this is optional, but doing so allows us to + // take more precise control over the window we create. + + // Set the extended style + cs.dwExStyle = WS_EX_CLIENTEDGE; +} + +void CView::PreRegisterClass(WNDCLASS &wc) +{ + // Here we set the Window class parameters. + // Preforming this is optional, but doing so allows us to + // take more precise control over the type of window we create. + + // Set the Window Class name + wc.lpszClassName = _T("View"); + + // Set a background brush to white + wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + + // Set the default cursor + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + + // Set the class style (not to be confused with the window styles set in PreCreate) + wc.style = CS_DBLCLKS; // Generate left button double click messages +} + +LRESULT CView::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SIZE: + Invalidate(); + break; // Also do default processing + } + + // pass unhandled messages on for default processing + return WndProcDefault(uMsg, wParam, lParam); +} + + + Index: base/applications/win32++demo/View.h =================================================================== --- base/applications/win32++demo/View.h (revision 0) +++ base/applications/win32++demo/View.h (working copy) @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////// +// View.h + +#ifndef VIEW_H +#define VIEW_H + + + +// Declaration of the CView class +class CView : public CWnd +{ +public: + CView(); + virtual ~CView(){} + +protected: + virtual void OnDraw(CDC* pDC); + virtual void OnInitialUpdate(); + virtual void PreCreate(CREATESTRUCT &cs); + virtual void PreRegisterClass(WNDCLASS &wc); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + + +#endif // VIEW_H Index: base/applications/win32++demo/main.cpp =================================================================== --- base/applications/win32++demo/main.cpp (revision 0) +++ base/applications/win32++demo/main.cpp (working copy) @@ -0,0 +1,31 @@ +/////////////////////////////////////// +// main.cpp + +#include "stdafx.h" +#include "FrameApp.h" + + +INT WINAPI +_tWinMain(IN HINSTANCE hInstance, + IN HINSTANCE hPrevInstance, + IN LPTSTR lpCmdLine, + IN INT nCmdShow) +{ + try + { + // Start Win32++ + CFrameApp theApp; + + // Run the application + return theApp.Run(); + } + + // catch all exceptions inherited from std::exception + catch (std::exception &e) + { + // Process the exception and quit + e.what(); + return -1; + } +} + Index: base/applications/win32++demo/res/Star.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Star.ico =================================================================== --- base/applications/win32++demo/res/Star.ico (revision 0) +++ base/applications/win32++demo/res/Star.ico (working copy) Property changes on: base/applications/win32++demo/res/Star.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== --- base/applications/win32++demo/res/Toolbar.bmp (revision 0) +++ base/applications/win32++demo/res/Toolbar.bmp (working copy) Property changes on: base/applications/win32++demo/res/Toolbar.bmp ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Win32++.manifest =================================================================== --- base/applications/win32++demo/res/Win32++.manifest (revision 0) +++ base/applications/win32++demo/res/Win32++.manifest (working copy) @@ -0,0 +1,31 @@ + + + + + + + + + + + +Adds XP Theme style to any program + + + + + + + Index: base/applications/win32++demo/resource.h =================================================================== --- base/applications/win32++demo/resource.h (revision 0) +++ base/applications/win32++demo/resource.h (working copy) @@ -0,0 +1,34 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc +// + +// include the Resource IDs defined by Win32++ +#include "default_resource.h" + +#define IDM_FILE_NEW 101 +#define IDM_FILE_OPEN 102 +#define IDM_FILE_SAVE 103 +#define IDM_FILE_SAVEAS 104 +#define IDM_FILE_PRINT 105 +#define IDM_FILE_CLOSE 106 +#define IDM_FILE_EXIT 107 +#define IDM_EDIT_UNDO 110 +#define IDM_EDIT_REDO 111 +#define IDM_EDIT_CUT 112 +#define IDM_EDIT_COPY 113 +#define IDM_EDIT_PASTE 114 +#define IDM_EDIT_DELETE 115 +#define IDM_HELP_ABOUT 120 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 130 +#endif +#endif Index: base/applications/win32++demo/stdafx.h =================================================================== --- base/applications/win32++demo/stdafx.h (revision 0) +++ base/applications/win32++demo/stdafx.h (working copy) @@ -0,0 +1,58 @@ +////////////////////////////////////////////// +// StdAfx.h + +// This file is used for precompiled headers +// Rarely modified header files should be included. + +// Based on code provided by Lynn Allan + + +#ifndef STDAFX_H +#define STDAFX_H + + +// Predefinitions for windows.h go here +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include "targetver.h" // Set the supported window features + +// Specify Win32xx specific predefinitions here +//#define NO_USING_NAMESPACE // Don't use Win32xx namespace + +typedef unsigned char byte; + +#if defined(_MSC_VER) && _MSC_VER == 1200 // For Visual Studio 6 + #pragma warning (disable : 4786) // identifier was truncated + #pragma warning (disable : 4702) // unreachable code (bugs in Microsoft's STL) +#endif + +// Rarely modified header files should be included here +#include +#include +#include +#include // Add support for stringstream +#include +#include +#include +#include + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +//#include +#include + + +#endif Index: base/applications/win32++demo/targetver.h =================================================================== --- base/applications/win32++demo/targetver.h (revision 0) +++ base/applications/win32++demo/targetver.h (working copy) @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////// +// targetver.h is used to define the Windows API macros that target the +// version of the Windows operating system you wish to support. + + +// For Windows 95 +//#define WINVER 0x0400 +//#define _WIN32_WINDOWS 0x0400 +//#define _WIN32_IE 0x0300 + +// For Windows 98 +//#define WINVER 0x0410 +//#define _WIN32_WINDOWS 0x0410 +//#define _WIN32_IE 0x0401 + +// For Windows NT4 +//#define WINVER 0x0400 +//#define _WIN32_WINNT 0x0400 +//#define _WIN32_IE 0x0200 +//#define NTDDI_VERSION 0x05000000 + +// For Windows ME +//#define WINVER 0x0500 +//#define _WIN32_WINNT 0x0500 +//#define _WIN32_IE 0x0500 + +// For Windows 2000 +//#define WINVER 0x0500 +//#define _WIN32_WINNT 0x0500 +//#define _WIN32_IE 0x0500 +//#define NTDDI_VERSION 0x05000000 + +// For Windows XP +//#define WINVER 0x0501 +//#define _WIN32_WINNT 0x0501 +//#define _WIN32_IE 0x0501 +//#define NTDDI_VERSION 0x05010000 + +// For Windows Vista +//#define WINVER 0x0600 +//#define _WIN32_WINNT 0x0600 +//#define _WIN32_IE 0x0600 +//#define NTDDI_VERSION 0x06000000 + +// For Windows 7 +//#define WINVER 0x0601 +//#define _WIN32_WINNT 0x0601 +//#define _WIN32_IE 0x0601 +//#define NTDDI_VERSION 0x06010000 + + +// Users of Visual Studio 10 can do this instead +// #include "SDKDDKver.h" Index: base/applications/win32++demo/CMakeLists.txt =================================================================== --- base/applications/win32++demo/CMakeLists.txt (revision 0) +++ base/applications/win32++demo/CMakeLists.txt (working copy) @@ -0,0 +1,18 @@ +set_cpp(WITH_EXCEPTIONS WITH_RTTI WITH_STL) + +add_definitions(-DWIN32) + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/win32++) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +list(APPEND SOURCE + main.cpp + FrameApp.cpp + Mainfrm.cpp + View.cpp + Resource.rc) + +add_executable(win32++demo ${SOURCE}) +set_module_type(win32++demo win32gui UNICODE) +add_importlibs(win32++demo advapi32 comctl32 comdlg32 user32 gdi32 winmm shell32 msvcrt kernel32) +add_cd_file(TARGET win32++demo DESTINATION reactos/system32 FOR all) Index: base/applications/win32++demo/FrameApp.cpp =================================================================== --- base/applications/win32++demo/FrameApp.cpp (revision 0) +++ base/applications/win32++demo/FrameApp.cpp (working copy) @@ -0,0 +1,31 @@ +////////////////////////////////////////////// +//FrameApp.cpp + +#include "stdafx.h" +#include "FrameApp.h" + + +// Definitions for the CFrameApp class +CFrameApp::CFrameApp() +{ +} + +CFrameApp::~CFrameApp() +{ +} + +BOOL CFrameApp::InitInstance() +{ + //Create the Frame Window + if (!m_Frame.Create()) + { + // We get here if the Frame creation fails + + ::MessageBox(NULL, _T("Failed to create Frame window"), _T("ERROR"), MB_ICONERROR); + return FALSE; // returning FALSE ends the application + } + + return TRUE; +} + + Index: base/applications/win32++demo/FrameApp.h =================================================================== --- base/applications/win32++demo/FrameApp.h (revision 0) +++ base/applications/win32++demo/FrameApp.h (working copy) @@ -0,0 +1,29 @@ +////////////////////////////////////////////////// +// FrameApp.h + +#ifndef FRAMEAPP_H +#define FRAMEAPP_H + +#include "Mainfrm.h" + + +// Declaration of the CFrameApp class +class CFrameApp : public CWinApp +{ +public: + CFrameApp(); + virtual ~CFrameApp(); + virtual BOOL InitInstance(); + CMainFrame& GetMainFrame() { return m_Frame; } + +private: + CMainFrame m_Frame; +}; + + +// a useful function that returns a reference to the CFrameApp object +inline CFrameApp& GetFrameApp() { return *((CFrameApp*)GetApp()); } + + +#endif // define FRAMEAPP_H + Index: base/applications/win32++demo/main.cpp =================================================================== --- base/applications/win32++demo/main.cpp (revision 0) +++ base/applications/win32++demo/main.cpp (working copy) @@ -0,0 +1,31 @@ +/////////////////////////////////////// +// main.cpp + +#include "stdafx.h" +#include "FrameApp.h" + + +INT WINAPI +_tWinMain(IN HINSTANCE hInstance, + IN HINSTANCE hPrevInstance, + IN LPTSTR lpCmdLine, + IN INT nCmdShow) +{ + try + { + // Start Win32++ + CFrameApp theApp; + + // Run the application + return theApp.Run(); + } + + // catch all exceptions inherited from std::exception + catch (std::exception &e) + { + // Process the exception and quit + e.what(); + return -1; + } +} + Index: base/applications/win32++demo/Mainfrm.cpp =================================================================== --- base/applications/win32++demo/Mainfrm.cpp (revision 0) +++ base/applications/win32++demo/Mainfrm.cpp (working copy) @@ -0,0 +1,168 @@ +//////////////////////////////////////////////////// +// Mainfrm.cpp + +#include "stdafx.h" +#include "resource.h" +#include "mainfrm.h" + + +// Definitions for the CMainFrame class +CMainFrame::CMainFrame() +{ + // Constructor for CMainFrame. Its called after CFrame's constructor + + //Set m_View as the view window of the frame + SetView(m_View); + + // Set the registry key name, and load the initial window position + // Use a registry key name like "CompanyName\\Application" + LoadRegistrySettings(_T("Win32++\\Frame")); +} + +CMainFrame::~CMainFrame() +{ + // Destructor for CMainFrame. +} + +BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // OnCommand responds to menu and and toolbar input + + UNREFERENCED_PARAMETER(lParam); + + switch(LOWORD(wParam)) + { + case IDM_FILE_OPEN: + // Refer to the tutorial for an example of OnFileOpen + OnFileOpen(); + return TRUE; + case IDM_FILE_SAVE: + // Refer to the tutorial for an example of OnFileSave + OnFileSave(); + return TRUE; + case IDM_FILE_SAVEAS: + // Refer to the tutorial for an example of OnFileSaveAs + OnFileSave(); + return TRUE; + case IDM_FILE_PRINT: + OnFilePrint(); + return TRUE; + case IDM_FILE_EXIT: + // End the application + ::PostMessage(m_hWnd, WM_CLOSE, 0, 0); + return TRUE; + case IDW_VIEW_STATUSBAR: + OnViewStatusBar(); + return TRUE; + case IDW_VIEW_TOOLBAR: + OnViewToolBar(); + return TRUE; + case IDM_HELP_ABOUT: + // Display the help dialog + OnHelp(); + return TRUE; + } + + return FALSE; +} + +void CMainFrame::OnCreate() +{ + // OnCreate controls the way the frame is created. + // Overriding CFrame::Oncreate is optional. + // The default for the following variables is TRUE + + // m_bShowIndicatorStatus = FALSE; // Don't show statusbar indicators + // m_bShowMenuStatus = FALSE; // Don't show toolbar or menu status + // m_bUseReBar = FALSE; // Don't use rebars + m_bUseThemes = FALSE; // Don't use themes + // m_bUseToolBar = FALSE; // Don't use a toolbar + + // call the base class function + CFrame::OnCreate(); +} + +void CMainFrame::OnInitialUpdate() +{ + // The frame is now created. + // Place any additional startup code here. + + TRACE("Frame created\n"); +} + +void CMainFrame::OnFileOpen() +{ + // Bring up the dialog, and open the file + CFile File; + CString str = File.OpenFileDialog(0, 0, 0, 0); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +void CMainFrame::OnFileSave() +{ + CFile File; + CString str = File.SaveFileDialog(0, 0, 0, 0, 0); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +void CMainFrame::OnFilePrint() +{ + // Bring up a dialog to choose the printer + PRINTDLG pd = {0}; + pd.lStructSize = sizeof( pd ); + pd.Flags = PD_RETURNDC; + pd.hwndOwner = m_hWnd; + + // Retrieve the printer DC + PrintDlg( &pd ); + + // TODO: + // Add your own code here. Refer to the tutorial for additional information +} + +LRESULT CMainFrame::OnNotify(WPARAM wParam, LPARAM lParam) +{ + // Process notification messages sent by child windows +// switch(((LPNMHDR)lParam)->code) +// { + //Add case statments for each notification message here +// } + + // Some notifications should return a value when handled + return CFrame::OnNotify(wParam, lParam); +} + +void CMainFrame::SetupToolBar() +{ + // 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, FALSE ); // disabled button + AddToolBarButton( IDM_EDIT_COPY, FALSE ); // disabled button + AddToolBarButton( IDM_EDIT_PASTE, FALSE ); // disabled button + + AddToolBarButton( 0 ); // Separator + AddToolBarButton( IDM_FILE_PRINT ); + + AddToolBarButton( 0 ); // Separator + AddToolBarButton( IDM_HELP_ABOUT ); +} + +LRESULT CMainFrame::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ +// switch (uMsg) +// { +// Add case statements for each messages to be handled here +// } + + // pass unhandled messages on for default processing + return WndProcDefault(uMsg, wParam, lParam); +} + Index: base/applications/win32++demo/Mainfrm.h =================================================================== --- base/applications/win32++demo/Mainfrm.h (revision 0) +++ base/applications/win32++demo/Mainfrm.h (working copy) @@ -0,0 +1,32 @@ +///////////////////////////////////////////// +// Mainfrm.h + +#ifndef MAINFRM_H +#define MAINFRM_H + +#include "View.h" + +// Declaration of the CMainFrame class +class CMainFrame : public CFrame +{ +public: + CMainFrame(void); + virtual ~CMainFrame(); + +protected: + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnCreate(); + virtual void OnFileOpen(); + virtual void OnFilePrint(); + virtual void OnFileSave(); + virtual void OnInitialUpdate(); + virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); + virtual void SetupToolBar(); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + +private: + CView m_View; +}; + +#endif //MAINFRM_H + Index: base/applications/win32++demo/res/Star.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Star.ico =================================================================== --- base/applications/win32++demo/res/Star.ico (revision 0) +++ base/applications/win32++demo/res/Star.ico (working copy) Property changes on: base/applications/win32++demo/res/Star.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== --- base/applications/win32++demo/res/Toolbar.bmp (revision 0) +++ base/applications/win32++demo/res/Toolbar.bmp (working copy) Property changes on: base/applications/win32++demo/res/Toolbar.bmp ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Win32++.manifest =================================================================== --- base/applications/win32++demo/res/Win32++.manifest (revision 0) +++ base/applications/win32++demo/res/Win32++.manifest (working copy) @@ -0,0 +1,31 @@ + + + + + + + + + + + +Adds XP Theme style to any program + + + + + + + Index: base/applications/win32++demo/res/Star.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Star.ico =================================================================== --- base/applications/win32++demo/res/Star.ico (revision 0) +++ base/applications/win32++demo/res/Star.ico (working copy) Property changes on: base/applications/win32++demo/res/Star.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: base/applications/win32++demo/res/Toolbar.bmp =================================================================== --- base/applications/win32++demo/res/Toolbar.bmp (revision 0) +++ base/applications/win32++demo/res/Toolbar.bmp (working copy) Property changes on: base/applications/win32++demo/res/Toolbar.bmp ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: base/applications/win32++demo/res/Win32++.manifest =================================================================== --- base/applications/win32++demo/res/Win32++.manifest (revision 0) +++ base/applications/win32++demo/res/Win32++.manifest (working copy) @@ -0,0 +1,31 @@ + + + + + + + + + + + +Adds XP Theme style to any program + + + + + + + Index: base/applications/win32++demo/resource.h =================================================================== --- base/applications/win32++demo/resource.h (revision 0) +++ base/applications/win32++demo/resource.h (working copy) @@ -0,0 +1,34 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Resource.rc +// + +// include the Resource IDs defined by Win32++ +#include "default_resource.h" + +#define IDM_FILE_NEW 101 +#define IDM_FILE_OPEN 102 +#define IDM_FILE_SAVE 103 +#define IDM_FILE_SAVEAS 104 +#define IDM_FILE_PRINT 105 +#define IDM_FILE_CLOSE 106 +#define IDM_FILE_EXIT 107 +#define IDM_EDIT_UNDO 110 +#define IDM_EDIT_REDO 111 +#define IDM_EDIT_CUT 112 +#define IDM_EDIT_COPY 113 +#define IDM_EDIT_PASTE 114 +#define IDM_EDIT_DELETE 115 +#define IDM_HELP_ABOUT 120 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 130 +#endif +#endif Index: base/applications/win32++demo/Resource.rc =================================================================== --- base/applications/win32++demo/Resource.rc (revision 0) +++ base/applications/win32++demo/Resource.rc (working copy) @@ -0,0 +1,199 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +///////////////////////////////////////////////////////////////////////////// +// +// RT_MANIFEST +// + +1 RT_MANIFEST "res/Win32++.manifest" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDW_MAIN MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "New...", IDM_FILE_NEW + MENUITEM "&Open...", IDM_FILE_OPEN + MENUITEM "&Save", IDM_FILE_SAVE + MENUITEM "Save &As...", IDM_FILE_SAVEAS + MENUITEM SEPARATOR + MENUITEM "&Print", IDM_FILE_PRINT + MENUITEM SEPARATOR + MENUITEM "E&xit", IDM_FILE_EXIT + END + POPUP "&Edit" + BEGIN + MENUITEM "Undo\tCtrl+Z", IDM_EDIT_UNDO, GRAYED + MENUITEM "Redo\tShift+Ctrl+Z", IDM_EDIT_REDO, GRAYED + MENUITEM SEPARATOR + MENUITEM "Cut\tCtrl+X", IDM_EDIT_CUT, GRAYED + MENUITEM "Copy\tCtrl+C", IDM_EDIT_COPY, GRAYED + MENUITEM "Paste\tCtrl+V", IDM_EDIT_PASTE, GRAYED + MENUITEM "Delete\tDel", IDM_EDIT_DELETE, GRAYED + 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 + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDW_MAIN ICON "res/Star.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_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "MS Shell Dlg", 400, 0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,68,49,50,14 + CTEXT "Frame Application",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 + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDW_MAIN "Frame Window" + IDW_VIEW_TOOLBAR "Show or hide the tool bar" + IDW_VIEW_STATUSBAR "Show or hide the status bar" +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" + IDM_EDIT_UNDO "Undo the last action" + IDM_EDIT_REDO "Redo the previously undone action" +END + +STRINGTABLE +BEGIN + 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" + IDM_HELP_ABOUT "Display Information about this program" +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 + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + Index: base/applications/win32++demo/StdAfx.cpp =================================================================== --- base/applications/win32++demo/StdAfx.cpp (revision 0) +++ base/applications/win32++demo/StdAfx.cpp (working copy) @@ -0,0 +1,15 @@ +////////////////////////////////////////////// +// StdAfx.cpp + +// This file is used for precompiled hearders. Precompiled headers allow +// programs to be recompiled more quickly + +// To use precompiled headers, do the following: +// 1) Add the set of rarely changed headers to stdafx.h +// 2) Include stdafx.h in each cpp file. It must be included first. +// 3) Add stdafx.cpp to your project. +// 4) Turn on precompiled hearders in the project + + +#include "stdafx.h" + Index: base/applications/win32++demo/stdafx.h =================================================================== --- base/applications/win32++demo/stdafx.h (revision 0) +++ base/applications/win32++demo/stdafx.h (working copy) @@ -0,0 +1,58 @@ +////////////////////////////////////////////// +// StdAfx.h + +// This file is used for precompiled headers +// Rarely modified header files should be included. + +// Based on code provided by Lynn Allan + + +#ifndef STDAFX_H +#define STDAFX_H + + +// Predefinitions for windows.h go here +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include "targetver.h" // Set the supported window features + +// Specify Win32xx specific predefinitions here +//#define NO_USING_NAMESPACE // Don't use Win32xx namespace + +typedef unsigned char byte; + +#if defined(_MSC_VER) && _MSC_VER == 1200 // For Visual Studio 6 + #pragma warning (disable : 4786) // identifier was truncated + #pragma warning (disable : 4702) // unreachable code (bugs in Microsoft's STL) +#endif + +// Rarely modified header files should be included here +#include +#include +#include +#include // Add support for stringstream +#include +#include +#include +#include + +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +//#include +#include + + +#endif Index: base/applications/win32++demo/targetver.h =================================================================== --- base/applications/win32++demo/targetver.h (revision 0) +++ base/applications/win32++demo/targetver.h (working copy) @@ -0,0 +1,53 @@ +/////////////////////////////////////////////////////////////////////// +// targetver.h is used to define the Windows API macros that target the +// version of the Windows operating system you wish to support. + + +// For Windows 95 +//#define WINVER 0x0400 +//#define _WIN32_WINDOWS 0x0400 +//#define _WIN32_IE 0x0300 + +// For Windows 98 +//#define WINVER 0x0410 +//#define _WIN32_WINDOWS 0x0410 +//#define _WIN32_IE 0x0401 + +// For Windows NT4 +//#define WINVER 0x0400 +//#define _WIN32_WINNT 0x0400 +//#define _WIN32_IE 0x0200 +//#define NTDDI_VERSION 0x05000000 + +// For Windows ME +//#define WINVER 0x0500 +//#define _WIN32_WINNT 0x0500 +//#define _WIN32_IE 0x0500 + +// For Windows 2000 +//#define WINVER 0x0500 +//#define _WIN32_WINNT 0x0500 +//#define _WIN32_IE 0x0500 +//#define NTDDI_VERSION 0x05000000 + +// For Windows XP +//#define WINVER 0x0501 +//#define _WIN32_WINNT 0x0501 +//#define _WIN32_IE 0x0501 +//#define NTDDI_VERSION 0x05010000 + +// For Windows Vista +//#define WINVER 0x0600 +//#define _WIN32_WINNT 0x0600 +//#define _WIN32_IE 0x0600 +//#define NTDDI_VERSION 0x06000000 + +// For Windows 7 +//#define WINVER 0x0601 +//#define _WIN32_WINNT 0x0601 +//#define _WIN32_IE 0x0601 +//#define NTDDI_VERSION 0x06010000 + + +// Users of Visual Studio 10 can do this instead +// #include "SDKDDKver.h" Index: base/applications/win32++demo/View.cpp =================================================================== --- base/applications/win32++demo/View.cpp (revision 0) +++ base/applications/win32++demo/View.cpp (working copy) @@ -0,0 +1,70 @@ +////////////////////////////////////////////// +// View.cpp +// Definitions for the CView class + +#include "stdafx.h" +#include "view.h" + + +CView::CView() +{ +} + +void CView::OnDraw(CDC* pDC) +{ + CRect rc = GetClientRect(); + + // Centre some text in our view window + pDC->DrawText(_T("View Window"), -1, rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE); +} + +void CView::OnInitialUpdate() +{ + // OnInitialUpdate is called immediately after the window is created + TRACE("View window created\n"); +} + +void CView::PreCreate(CREATESTRUCT &cs) +{ + // Here we set the defaults used by the create function for the view window + // Preforming this is optional, but doing so allows us to + // take more precise control over the window we create. + + // Set the extended style + cs.dwExStyle = WS_EX_CLIENTEDGE; +} + +void CView::PreRegisterClass(WNDCLASS &wc) +{ + // Here we set the Window class parameters. + // Preforming this is optional, but doing so allows us to + // take more precise control over the type of window we create. + + // Set the Window Class name + wc.lpszClassName = _T("View"); + + // Set a background brush to white + wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + + // Set the default cursor + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + + // Set the class style (not to be confused with the window styles set in PreCreate) + wc.style = CS_DBLCLKS; // Generate left button double click messages +} + +LRESULT CView::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SIZE: + Invalidate(); + break; // Also do default processing + } + + // pass unhandled messages on for default processing + return WndProcDefault(uMsg, wParam, lParam); +} + + + Index: base/applications/win32++demo/View.h =================================================================== --- base/applications/win32++demo/View.h (revision 0) +++ base/applications/win32++demo/View.h (working copy) @@ -0,0 +1,25 @@ +////////////////////////////////////////////////////// +// View.h + +#ifndef VIEW_H +#define VIEW_H + + + +// Declaration of the CView class +class CView : public CWnd +{ +public: + CView(); + virtual ~CView(){} + +protected: + virtual void OnDraw(CDC* pDC); + virtual void OnInitialUpdate(); + virtual void PreCreate(CREATESTRUCT &cs); + virtual void PreRegisterClass(WNDCLASS &wc); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); +}; + + +#endif // VIEW_H Index: include/reactos/libs/win32++/changes.txt =================================================================== --- include/reactos/libs/win32++/changes.txt (revision 0) +++ include/reactos/libs/win32++/changes.txt (working copy) @@ -0,0 +1,1430 @@ +Version 7.4 +=========== +Bug Fixes +* The dockbar's parent for dock containers was set incorrectly. The wrong + dockbar could be destroyed when a dock container was destroyed. +* Corrected variable initialisation in CMenuMetrics + +New Features and Enhancements +* TRACE now accepts both ANSI and Unicode strings. + + +Version 7.3 +=========== + +New Features and Enhancements +----------------------------- +* Adjusted the frame's appearance + - Updated the visual appearance of popup menus on systems using Windows Aero. On + systems with Aero, popup menus are rendered with Windows Visual Styles. Systems + without Areo continue to use the Win32++ theme for popup menus. + - Frames now honour the current window theme's menu and status fonts. + - the frame's appearence changes dynamically to reflect changes to the window theme. + - minor adjustment to the rebar theme colours for the "Modern" theme. + +* Extended CWebBrowser + The CWebBrower class has been extended to wrap the member functions of + iWebBrowser2. The Browser sample has been updated and now supports + Copy/Paste. + +* Added the following controls + - CDateTime + - CHeader + - CHotKey + - CIPAddress + - CMonthCalendar + - CTooltip + +* CString constructors now accept either ANSI or Unicode characters and converts + these to TCHAR as required. + +* Extended CDC + The CDC::DetachBitmap function has been added. This provides a convenient + way of detaching a bitmap from a memory DC created by CreateCompatibleBitmap. + The various CDC::CreateXXX functions now return void instead of a pointer + to the old GDI object. + + +Changes in detail +----------------- +- Added CDateTime +- Added CHeader +- Added CHotKey +- Added CIPAddress +- Added CMonthCalendar +- Added CTooltip + +- Added wndTop a special CWnd for use with SetWindowPos +- Added wndTopMost a special CWnd for use with SetWindowPos +- Added wndNoTopMost a special CWnd for use with SetWindowPos +- Added wndBottom a special CWnd for use with SetWindowPos + +- Added CDC::DetachBitmap +- Added CFrame::DrawMenuItem +- Added CFrame::DrawMenuItemBkgnd +- Added CFrame::MeasureMenuItem +- Added CGDIObject::DeleteObject +- Added CString::CString(LPCSTR pszText); +- Added CString::CString(LPCWSTR pszText); +- Added CString::operator += (LPCSTR szText) +- Added CString::operator += (LPCWSTR szText) +- Added CReBar::SetToolTips +- Added CWebBrowser::ExecWB +- Added CWebBrowser::GetApplication +- Added CWebBrowser::GetBusy +- Added CWebBrowser::GetContainer +- Added CWebBrowser::GetFullScreen +- Added CWebBrowser::GetHeight +- Added CWebBrowser::GetLeft +- Added CWebBrowser::GetLocationName +- Added CWebBrowser::GetLocationURL +- Added CWebBrowser::GetOffline +- Added CWebBrowser::GetProperty +- Added CWebBrowser::GetReadyState +- Added CWebBrowser::GetRegisterAsBrowser +- Added CWebBrowser::GetTheaterMode +- Added CWebBrowser::GetTop +- Added CWebBrowser::GetTopLevelContainer +- Added CWebBrowser::GetType +- Added CWebBrowser::GetVisible +- Added CWebBrowser::GetWidth +- Added CWebBrowser::GoBack +- Added CWebBrowser::GoForward +- Added CWebBrowser::GoHome +- Added CWebBrowser::GoSearch +- Added CWebBrowser::Navigate2 +- Added CWebBrowser::PutProperty +- Added CWebBrowser::Refresh +- Added CWebBrowser::Refresh2 +- Added CWebBrowser::SetFullScreen +- Added CWebBrowser::SetHeight +- Added CWebBrowser::SetLeft +- Added CWebBrowser::SetOffline +- Added CWebBrowser::SetRegisterAsBrowser +- Added CWebBrowser::SetTheaterMode +- Added CWebBrowser::SetTop +- Added CWebBrowser::SetVisible +- Added CWebBrowser::SetWidth +- Added CWebBrowser::Stop +- Modified CComboBoxEx::GetComboBoxControl now returns CWnd* +- Modified CComboBoxEx::GetEditCtrl now returns CEdit* +- Modified CDC::CreateBitmap now returns void +- Modified CDC::CreateCompatibleBitmap now returns void +- Modified CDC::CreateDIBSection now returns void +- Modified CDC::CreateBitmapIndirect now returns void +- Modified CDC::CreateDIBitmap now returns void +- Modified CDC::CreateMappedBitmap now returns void +- Modified CDC::CreatePatternBrush now returns void +- Modified CDC::CreateSolidBrush now returns void +- Modified CDC::CreateBrushIndirect now returns void +- Modified CDC::CreateHatchBrush now returns void +- Modified CDC::CreateDIBPatternBrush now returns void +- Modified CDC::CreateDIBPatternBrushPt now returns void +- Modified CDC::CreateFontIndirect now returns void +- Modified CDC::CreateFont now returns void +- Modified CDC::CreatePen now returns void +- Modified CDC::CreatePenIndirect now returns void +- Modified CDC::LoadBitmap now returns BOOL +- Modified CDC::LoadImage now returns BOOL +- Modified CDC::LoadOEMBitmap now returns BOOL +- Modified CDocker::GetCaption now returns CString +- Modified CDocker::LoadRegistrySettings now accepts CString +- Modified CDocker::SaveRegistrySettings now accepts CString +- Modified CFrame::GetMRUEntry now returns CString +- Modified CFrame::GetRegistryKeyName now returns CString +- Modified CListView::GetEditCtrl now returns CEdit* +- Modified CListView::GetItemText now returns CString +- Modified CListView::GetHeader now returns CHeader* +- Modified CListView::GetToolTips now returns CToolTip* +- Modified CListView::SetToolTips now accepts CToolTip* +- Modified CListView::EditLabel now returns CEdit* +- Modified CRebar::GetToolTips now returns CToolTip* +- Modified CStatusBar::GetPartText now returns CString +- Modified CToolBar::GetToolTips now returns CToolTip* +- Modified CToolBar::SetToolTips now accepts CToolTip* +- Modified CTreeView::GetEditCtrl now returns CEdit* +- Modified CTreeView::GetToolTips now returns CToolTip* +- Modified CTreeView::SetToolTips now accepts CToolTip* +- Modified CWnd::SetWindowPos now uses CWnd* for first argument +- Removed CString::b_str +- Removed CString(LPCTSTR pszText); +- Removed CString::operator += (LPCTSTR szText); +- Renamed CFrame::DrawCheckmark to DrawMenuCheckmark + + +Incompatibilities with previous versions +---------------------------------------- + + +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 OnDraw. Code that previously + overrode OnPaint will now need to override OnDraw instead. OnDraw 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. + + +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 +=========== +Bug Fixes: +- Fixed TCharToString +- Dockers can now be used as the view for CMDIChild + +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. + + +Other Changes +------------- +Removed CSplitter class + +Added RibbonFrame sample +Added RibbonSimple sample + +Added 'Compile VS2005 Express' tool +Added 'Compile VS2008 Express' tool +Added 'Compile VS2010 Express' tool + + +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. + + +Version 6.3 +=========== + +Major Changes +------------- +* Added support for docking. 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. + + +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. + +* 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. +* 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 Index: include/reactos/libs/win32++/controls.h =================================================================== --- include/reactos/libs/win32++/controls.h (revision 0) +++ include/reactos/libs/win32++/controls.h (working copy) @@ -0,0 +1,2067 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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, CDateTime, CIPAddress, +// CHeader, CHotKey, CMonthCalendar, CProgressBar, CScrollBar, +// CSlider, CSpinButton, and CToolTip. + + +#ifndef _WIN32XX_CONTROLS_H_ +#define _WIN32XX_CONTROLS_H_ + +#include "wincore.h" +#include "stdcontrols.h" + +namespace Win32xx +{ + + // Forward declarations + class CMonthCalendar; + class CToolTip; + + 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() { ::InitCommonControls(); } + + 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 CComboBox + { + public: + CComboBoxEx() + { + INITCOMMONCONTROLSEX icce; + icce.dwSize = sizeof(INITCOMMONCONTROLSEX); + icce.dwICC = ICC_USEREX_CLASSES; + ::InitCommonControlsEx(&icce); + } + virtual ~CComboBoxEx() {} + + int DeleteItem(int nIndex ) const; + CWnd* GetComboBoxCtrl() const; + CEdit* 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 CDateTime : public CWnd + { + public: + CDateTime() + { + INITCOMMONCONTROLSEX icce; + icce.dwSize = sizeof(INITCOMMONCONTROLSEX); + icce.dwICC = ICC_DATE_CLASSES; + ::InitCommonControlsEx(&icce); + } + virtual ~CDateTime() {} + + COLORREF GetMonthCalColor(int iColor) const; + COLORREF SetMonthCalColor(int iColor, COLORREF ref); + BOOL SetFormat(LPCTSTR pstrFormat); + CMonthCalendar* GetMonthCalCtrl() const; + CFont* GetMonthCalFont() const; + void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE); + DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const; + BOOL SetRange(DWORD flags, LPSYSTEMTIME lpSysTimeArray); + DWORD GetTime(LPSYSTEMTIME pTimeDest) const; + BOOL SetTime(DWORD flag, LPSYSTEMTIME pTimeNew = NULL); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = DATETIMEPICK_CLASS; } + }; + + class CHeader : public CWnd + { + public: + CHeader() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_WIN95_CLASSES; + ::InitCommonControlsEx(&icex); + } + virtual ~CHeader() {} + + // Attributes + HIMAGELIST GetImageList() const; + BOOL GetItem(int nPos, HDITEM* pHeaderItem) const; + int GetItemCount() const; + CRect GetItemRect(int nIndex) const; + BOOL GetOrderArray(LPINT piArray, int iCount); + int OrderToIndex(int nOrder) const; + HIMAGELIST SetImageList(HIMAGELIST himl); + BOOL SetItem(int nPos, HDITEM* pHeaderItem); + BOOL SetOrderArray(int iCount, LPINT piArray); + int GetBitmapMargin() const; + int SetBitmapMargin(int nWidth); + + // Operations + HIMAGELIST CreateDragImage(int nIndex); + BOOL DeleteItem(int nPos); + int InsertItem(int nPos, HDITEM* phdi); + BOOL Layout(HDLAYOUT* pHeaderLayout); +#ifdef Header_SetHotDivider + int SetHotDivider(CPoint pt); + int SetHotDivider(int nIndex); +#endif +#ifdef Header_ClearFilter + int ClearAllFilters(); + int ClearFilter(int nColumn); + int EditFilter(int nColumn, BOOL bDiscardChanges); + int SetFilterChangeTimeout(DWORD dwTimeOut); +#endif + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_HEADER ; } + }; + + class CHotKey : public CWnd + { + public: + CHotKey() { ::InitCommonControls(); } + virtual ~CHotKey() {} + + DWORD GetHotKey() const; + CString GetKeyName(UINT vk, BOOL fExtended) const; + void SetHotKey(DWORD dwKey); + void SetRules(WORD wInvalidComb, WORD wModifiers); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = HOTKEY_CLASS; } + }; + + class CIPAddress : public CWnd + { + public: + CIPAddress() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_INTERNET_CLASSES; + ::InitCommonControlsEx(&icex); + } + virtual ~CIPAddress() {} + + void ClearAddress(); + int GetAddress(BYTE& nField0, BYTE& nField1, BYTE& nField2, BYTE& nField3); + int GetAddress(DWORD* dwAddress); + BOOL IsBlank() const; + void SetAddress(BYTE nField0, BYTE nField1, BYTE nField2, BYTE nField3); + void SetAddress(DWORD dwAddress); + void SetFieldFocus(WORD nField); + void SetFieldRange(int nField, BYTE nLower, BYTE nUpper); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_IPADDRESS; } + + }; + + class CMonthCalendar : public CWnd + { + public: + CMonthCalendar() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_DATE_CLASSES; + InitCommonControlsEx(&icex); + } + virtual ~CMonthCalendar() {} + + // Attributes + COLORREF GetColor(int nRegion) const; + int GetFirstDayOfWeek(BOOL* pbLocal = NULL) const; + CRect GetMinReqRect() const; + int GetMonthDelta() const; + COLORREF SetColor(int nRegion, COLORREF ref); + BOOL SetFirstDayOfWeek(int iDay, int* lpnOld = NULL); + int SetMonthDelta(int iDelta); + + // Operations + BOOL GetCurSel(LPSYSTEMTIME pDateTime) const; + int GetMaxSelCount() const; + int GetMonthRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange, DWORD dwFlags) const; + DWORD GetRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const; + BOOL GetSelRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const; + BOOL GetToday(LPSYSTEMTIME pDateTime) const; + DWORD HitTest(PMCHITTESTINFO pMCHitTest); + BOOL SetCurSel(const LPSYSTEMTIME pDateTime); + BOOL SetDayState(int nMonths, LPMONTHDAYSTATE pStates); + BOOL SetMaxSelCount(int nMax); + BOOL SetRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange); + BOOL SetSelRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange); + void SetToday(const LPSYSTEMTIME pDateTime); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = MONTHCAL_CLASS; } + }; + + class CProgressBar : public CWnd + { + public: + CProgressBar() { ::InitCommonControls(); } + 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() { ::InitCommonControls(); } + 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; + CToolTip* 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(CToolTip* 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() { ::InitCommonControls(); } + 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); + }; + + class CToolTip : public CWnd + { + public: + CToolTip(); + virtual ~CToolTip(); + + //Attributes + int GetDelayTime(DWORD dwDuration) const; + void GetMargin(LPRECT lprc) const; + int GetMaxTipWidth() const; + void GetText(CString& str, CWnd* pWnd, UINT_PTR nIDTool = 0) const; + COLORREF GetTipBkColor() const; + COLORREF GetTipTextColor() const; + int GetToolCount() const; + BOOL GetToolInfo(TOOLINFO& ToolInfo, CWnd* pWnd, UINT_PTR nIDTool = 0) const; + void SetDelayTime(UINT nDelay); + void SetDelayTime(DWORD dwDuration, int iTime); + void SetMargin(LPRECT lprc); + int SetMaxTipWidth(int iWidth); + void SetTipBkColor(COLORREF clr); + void SetTipTextColor(COLORREF clr); + void SetToolInfo(LPTOOLINFO lpToolInfo); +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + CSize GetBubbleSize(LPTOOLINFO lpToolInfo) const; +#endif + + //Operations + void Activate(BOOL bActivate); + BOOL AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0); + BOOL AddTool(CWnd* pWnd, LPCTSTR lpszText = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0); + void DelTool(CWnd* pWnd, UINT_PTR nIDTool = 0); + BOOL HitTest(CWnd* pWnd, CPoint pt, LPTOOLINFO lpToolInfo) const; + void Pop(); + void RelayEvent(LPMSG lpMsg); + + void SetToolRect(CWnd* pWnd, UINT_PTR nIDTool, LPCRECT lpRect); + void Update(); + void UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT_PTR nIDTool = 0); + void UpdateTipText(UINT nIDText, CWnd* pWnd, UINT_PTR nIDTool = 0); + +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + BOOL AdjustRect(LPRECT lprc, BOOL bLarger = TRUE); + BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle); +#endif +#if (defined TTM_SETWINDOWTHEME) && (WINVER >= 0x0501) + HRESULT SetWindowTheme(LPCWSTR lpstrTheme); +#endif + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = TOOLTIPS_CLASS; ; } + virtual void PreCreate(CREATESTRUCT &cs) + { + cs.dwExStyle = WS_EX_TOOLWINDOW; + cs.style = WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP; + } + + private: + void LoadToolInfo(TOOLINFO& ti, CWnd* pWnd, UINT_PTR nIDTool) const; + }; + + +} // 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 CEdit* CComboBoxEx::GetEditCtrl() const + // Retrieves the handle to the edit control portion of the ComboBoxEx control. + { + assert(IsWindow()); + return (CEdit*)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 CDateTime class + // + inline COLORREF CDateTime::GetMonthCalColor(int iColor) const + { + assert(IsWindow()); + return (COLORREF)DateTime_GetMonthCalColor(m_hWnd, iColor); + } + + inline COLORREF CDateTime::SetMonthCalColor(int iColor, COLORREF clr) + { + assert(IsWindow()); + return (COLORREF)DateTime_SetMonthCalColor(m_hWnd, iColor, clr); + } + + inline BOOL CDateTime::SetFormat(LPCTSTR pszFormat) + { + assert(IsWindow()); + return DateTime_SetFormat(m_hWnd, pszFormat); + } + + inline CMonthCalendar* CDateTime::GetMonthCalCtrl() const + { + assert(IsWindow()); + return (CMonthCalendar*)FromHandle((HWND)DateTime_GetMonthCal(m_hWnd)); + } + + inline CFont* CDateTime::GetMonthCalFont() const + { + assert(IsWindow()); + return FromHandle((HFONT)DateTime_GetMonthCalFont(m_hWnd)); + } + + inline void CDateTime::SetMonthCalFont(HFONT hFont, BOOL bRedraw /*= TRUE*/) + { + assert(IsWindow()); + DateTime_SetMonthCalFont(m_hWnd, hFont, MAKELONG(bRedraw, 0)); + } + + inline DWORD CDateTime::GetRange(LPSYSTEMTIME lpSysTimeArray) const + { + assert(IsWindow()); + return DateTime_GetRange(m_hWnd, lpSysTimeArray); + } + + inline BOOL CDateTime::SetRange(DWORD flags, LPSYSTEMTIME lpSysTimeArray) + { + assert(IsWindow()); + return DateTime_SetRange(m_hWnd, flags, lpSysTimeArray); + } + + inline DWORD CDateTime::GetTime(LPSYSTEMTIME pTimeDest) const + { + assert(IsWindow()); + return DateTime_GetSystemtime(m_hWnd, pTimeDest); + } + + inline BOOL CDateTime::SetTime(DWORD flag, LPSYSTEMTIME pTimeNew /*= NULL*/) + { + assert(IsWindow()); + return DateTime_SetSystemtime(m_hWnd, flag, pTimeNew); + } + + + //////////////////////////////////////// + // Definitions for the CHotKey class + // + inline DWORD CHotKey::GetHotKey() const + { + assert(IsWindow()); + return (DWORD)SendMessage(HKM_GETHOTKEY, 0, 0); + } + + inline CString CHotKey::GetKeyName(UINT vk, BOOL fExtended) const + { + // Translate the virtual-key code to a scan code + LONG lScan = MapVirtualKey(vk, 0); + + // Construct an LPARAM with the scan code in Bits 16-23, and an extended flag in bit 24 + LPARAM lParam = lScan << 16; + if (fExtended) + lParam |= 0x01000000L; + + CString str; + int nBufferLen = 64; + int nStrLen = nBufferLen; + + // Loop until we have retrieved the entire string + while(nStrLen == nBufferLen) + { + nBufferLen *= 4; + LPTSTR pszStr = str.GetBuffer(nBufferLen); + nStrLen = ::GetKeyNameText((LONG)lParam, pszStr, nBufferLen + 1); + str.ReleaseBuffer(); + } + + return str; + } + + inline void CHotKey::SetHotKey(DWORD dwKey) + { + assert(IsWindow()); + SendMessage(HKM_SETHOTKEY, (WPARAM)dwKey, 0); + } + + inline void CHotKey::SetRules(WORD wInvalidComb, WORD wModifiers) + { + assert(IsWindow()); + SendMessage(HKM_SETRULES, wInvalidComb, wModifiers); + } + + + //////////////////////////////////////// + // Definitions for the CHeader class + // + inline HIMAGELIST CHeader::CreateDragImage(int nIndex) + { + assert(IsWindow()); + return Header_CreateDragImage(m_hWnd, nIndex); + } + + inline BOOL CHeader::DeleteItem(int nPos) + { + assert(IsWindow()); + return Header_DeleteItem(m_hWnd, nPos); + } + + inline HIMAGELIST CHeader::GetImageList() const + { + assert(IsWindow()); + return Header_GetImageList(m_hWnd); + } + + inline BOOL CHeader::GetItem(int nPos, HDITEM* pHeaderItem) const + { + assert(IsWindow()); + return Header_GetItem(m_hWnd, nPos, pHeaderItem); + } + + inline int CHeader::GetItemCount() const + { + assert(IsWindow()); + return Header_GetItemCount(m_hWnd); + } + + inline CRect CHeader::GetItemRect(int nIndex) const + { + assert(IsWindow()); + RECT rc; + Header_GetItemRect(m_hWnd, nIndex, &rc); + return rc; + } + + inline BOOL CHeader::GetOrderArray(LPINT piArray, int iCount) + { + assert(IsWindow()); + return Header_GetOrderArray(m_hWnd, piArray, iCount); + } + + inline int CHeader::InsertItem(int nPos, HDITEM* phdi) + { + assert(IsWindow()); + return Header_InsertItem(m_hWnd, nPos, phdi); + } + + inline BOOL CHeader::Layout(HDLAYOUT* pHeaderLayout) + { + assert(IsWindow()); + return Header_Layout(m_hWnd, pHeaderLayout); + } + + inline int CHeader::OrderToIndex(int nOrder) const + { + assert(IsWindow()); + return Header_OrderToIndex( m_hWnd, nOrder); + } + +#ifdef Header_SetHotDivider + inline int CHeader::SetHotDivider(CPoint pt) + { + assert(IsWindow()); + return Header_SetHotDivider(m_hWnd, TRUE, MAKELPARAM(pt.x, pt.y)); + } + + inline int CHeader::SetHotDivider(int nIndex) + { + assert(IsWindow()); + return Header_SetHotDivider(m_hWnd, FALSE, nIndex); + } +#endif + + inline HIMAGELIST CHeader::SetImageList(HIMAGELIST himl) + { + assert(IsWindow()); + return Header_SetImageList(m_hWnd, himl); + } + + inline BOOL CHeader::SetItem(int nPos, HDITEM* pHeaderItem) + { + assert(IsWindow()); + return Header_SetItem(m_hWnd, nPos, pHeaderItem); + } + + inline BOOL CHeader::SetOrderArray(int iCount, LPINT piArray) + { + assert(IsWindow()); + return Header_SetOrderArray(m_hWnd, iCount, piArray); + } + +#ifdef Header_ClearFilter + inline int CHeader::ClearFilter(int nColumn) + { + assert(IsWindow()); + return Header_ClearFilter(m_hWnd, nColumn); + } + + inline int CHeader::ClearAllFilters() + { + assert(IsWindow()); + return Header_ClearAllFilters(m_hWnd); + } + + inline int CHeader::EditFilter(int nColumn, BOOL bDiscardChanges) + { + assert(IsWindow()); + return Header_EditFilter(m_hWnd, nColumn, LPARAM MAKELPARAM(bDiscardChanges, 0)); + } + + inline int CHeader::GetBitmapMargin() const + { + assert(IsWindow()); + return Header_GetBitmapMargin(m_hWnd); + } + + inline int CHeader::SetBitmapMargin(int nWidth) + { + assert(IsWindow()); + return Header_SetBitmapMargin(m_hWnd, nWidth); + } + + inline int CHeader::SetFilterChangeTimeout(DWORD dwTimeOut) + { + assert(IsWindow()); + return Header_SetFilterChangeTimeout(m_hWnd, dwTimeOut); + } +#endif + + //////////////////////////////////////// + // Definitions for the CIPAddress class + // + inline void CIPAddress::ClearAddress() + { + assert(IsWindow()); + SendMessage(IPM_CLEARADDRESS, 0, 0); + } + + inline int CIPAddress::GetAddress(BYTE& nField0, BYTE& nField1, BYTE& nField2, BYTE& nField3) + { + DWORD dwAddr; + int iValue = GetAddress(&dwAddr); + nField0 = (BYTE)FIRST_IPADDRESS(dwAddr); + nField1 = (BYTE)SECOND_IPADDRESS(dwAddr); + nField2 = (BYTE)THIRD_IPADDRESS(dwAddr); + nField3 = (BYTE)FOURTH_IPADDRESS(dwAddr); + return iValue; + } + + inline int CIPAddress::GetAddress(DWORD* dwAddress) + { + assert(IsWindow()); + return (int)SendMessage(IPM_GETADDRESS, 0, (LPARAM)&dwAddress); + } + + inline BOOL CIPAddress::IsBlank() const + { + assert(IsWindow()); + return (BOOL)SendMessage(IPM_ISBLANK, 0, 0); + } + + inline void CIPAddress::SetAddress(BYTE nField0, BYTE nField1, BYTE nField2, BYTE nField3) + { + assert(IsWindow()); + SendMessage(IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(nField0, nField1, nField2, nField3)); + } + + inline void CIPAddress::SetAddress(DWORD dwAddress) + { + assert(IsWindow()); + SendMessage(IPM_SETADDRESS, 0, (LPARAM)dwAddress); + } + + inline void CIPAddress::SetFieldFocus(WORD nField) + { + assert(IsWindow()); + SendMessage(IPM_SETFOCUS, nField, 0); + } + + inline void CIPAddress::SetFieldRange(int nField, BYTE nLower, BYTE nUpper) + { + assert(IsWindow()); + SendMessage(IPM_SETRANGE, MAKEIPRANGE(nLower, nUpper), nField); + } + + + /////////////////////////////////////////// + // Definitions for the CMonthCalendar class + // + inline COLORREF CMonthCalendar::GetColor(int nRegion) const + { + assert(IsWindow()); + return (COLORREF)MonthCal_GetColor(m_hWnd, nRegion); + } + + inline BOOL CMonthCalendar::GetCurSel(LPSYSTEMTIME pDateTime) const + { + assert(IsWindow()); + return MonthCal_GetCurSel(m_hWnd, pDateTime); + } + + inline int CMonthCalendar::GetFirstDayOfWeek(BOOL* pbLocal /*= NULL*/) const + { + assert(IsWindow()); + DWORD dwValue = MonthCal_GetFirstDayOfWeek(m_hWnd); + + if (pbLocal) + *pbLocal = HIWORD(dwValue); + + return LOWORD(dwValue); + } + + inline int CMonthCalendar::GetMaxSelCount() const + { + assert(IsWindow()); + return MonthCal_GetMaxSelCount(m_hWnd); + } + + inline CRect CMonthCalendar::GetMinReqRect() const + { + assert(IsWindow()); + RECT rc; + MonthCal_GetMinReqRect(m_hWnd, &rc); + return rc; + } + + inline int CMonthCalendar::GetMonthDelta() const + { + assert(IsWindow()); + return MonthCal_GetMonthDelta(m_hWnd); + } + + inline int CMonthCalendar::GetMonthRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange, DWORD dwFlags) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + int nCount = MonthCal_GetMonthRange(m_hWnd, dwFlags, MinMax); + return nCount; + } + + inline DWORD CMonthCalendar::GetRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + DWORD dwValue = MonthCal_GetRange(m_hWnd, &MinMax); + memcpy(pMinRange, &MinMax[0], sizeof(SYSTEMTIME)); + memcpy(pMaxRange, &MinMax[1], sizeof(SYSTEMTIME)); + return dwValue; + } + + inline BOOL CMonthCalendar::GetSelRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + return (BOOL)MonthCal_GetSelRange(m_hWnd, &MinMax); + } + + inline BOOL CMonthCalendar::GetToday(LPSYSTEMTIME pDateTime) const + { + assert(IsWindow()); + return MonthCal_GetToday(m_hWnd, pDateTime); + } + + inline DWORD CMonthCalendar::HitTest(PMCHITTESTINFO pMCHitTest) + { + assert(IsWindow()); + return (DWORD)MonthCal_HitTest(m_hWnd, pMCHitTest); + } + + inline COLORREF CMonthCalendar::SetColor(int nRegion, COLORREF clr) + { + assert(IsWindow()); + return (COLORREF)MonthCal_SetColor(m_hWnd, nRegion, clr); + } + + inline BOOL CMonthCalendar::SetCurSel(const LPSYSTEMTIME pDateTime) + { + assert(IsWindow()); + return MonthCal_SetCurSel(m_hWnd, pDateTime); + } + + inline BOOL CMonthCalendar::SetDayState(int nMonths, LPMONTHDAYSTATE pStates) + { + assert(IsWindow()); + return (BOOL)MonthCal_SetDayState(m_hWnd, nMonths, pStates); + } + + inline BOOL CMonthCalendar::SetFirstDayOfWeek(int iDay, int* pnOld/* = NULL*/) + { + assert(IsWindow()); + DWORD dwValue = (DWORD)MonthCal_SetFirstDayOfWeek(m_hWnd, iDay); + + if(pnOld) + *pnOld = LOWORD(dwValue); + + return (BOOL)HIWORD(dwValue); + } + + inline BOOL CMonthCalendar::SetMaxSelCount(int nMax) + { + assert(IsWindow()); + return MonthCal_SetMaxSelCount(m_hWnd, nMax); + } + + inline int CMonthCalendar::SetMonthDelta(int iDelta) + { + assert(IsWindow()); + return MonthCal_SetMonthDelta(m_hWnd, iDelta); + } + + inline BOOL CMonthCalendar::SetRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange) + { + + SYSTEMTIME MinMax[2]; + DWORD dwLimit; + + if (pMinRange != NULL) + { + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + dwLimit = GDTR_MIN; + } + + if (pMaxRange) + { + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + dwLimit |= GDTR_MAX; + } + + return (BOOL)MonthCal_SetRange(m_hWnd, dwLimit, &MinMax); + } + + inline BOOL CMonthCalendar::SetSelRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange) + { + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + return (BOOL)MonthCal_SetSelRange(m_hWnd, &MinMax); + } + + inline void CMonthCalendar::SetToday(const LPSYSTEMTIME pDateTime) + { + assert(IsWindow()); + MonthCal_SetToday(m_hWnd, pDateTime); + } + + + //////////////////////////////////////// + // 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 CToolTip* CSlider::GetToolTips() const + // Retrieves the handle to the ToolTip control assigned to the trackbar, if any. + { + assert(IsWindow()); + return (CToolTip*)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(CToolTip* pToolTip) const + // Assigns a ToolTip control to the trackbar control. + { + assert(IsWindow()); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + SendMessage(TBM_SETTOOLTIPS, (WPARAM)hToolTip, 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)); + } + + //////////////////////////////////////// + // Definitions for the CToolTip class + // + + inline CToolTip::CToolTip() + {} + + inline CToolTip::~CToolTip() + {} + + inline void CToolTip::Activate(BOOL bActivate) + // Activates or deactivates a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_ACTIVATE, bActivate, 0); + } + + inline BOOL CToolTip::AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool /*= NULL*/, UINT_PTR nIDTool /*= 0*/) + // Registers a tool with a ToolTip control. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.hinst = GetApp()->GetResourceHandle(); + ti.lpszText = (LPTSTR)MAKEINTRESOURCE(nIDText); + if (lpRectTool) + ti.rect = *lpRectTool; + return (BOOL)SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti); + } + + inline BOOL CToolTip::AddTool(CWnd* pWnd, LPCTSTR lpszText /*= LPSTR_TEXTCALLBACK*/, LPCRECT lpRectTool /*= NULL*/, UINT_PTR nIDTool /*= 0*/) + // Registers a tool with a ToolTip control. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = (LPTSTR)lpszText; + if (lpRectTool) + ti.rect = *lpRectTool; + return (BOOL)SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti); + } + + inline void CToolTip::DelTool(CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Removes a tool from a ToolTip control. + { + assert(IsWindow()); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti); + } + + inline int CToolTip::GetDelayTime(DWORD dwDuration) const + // Retrieves the initial, pop-up, and reshow durations currently set for a ToolTip control. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETDELAYTIME, dwDuration, 0); + } + + inline void CToolTip::GetMargin(LPRECT lprc) const + // Retrieves the top, left, bottom, and right margins set for a ToolTip window. + { + assert(IsWindow()); + SendMessage(TTM_GETMARGIN, 0, (LPARAM)lprc); + } + + inline int CToolTip::GetMaxTipWidth() const + // Retrieves the maximum width for a ToolTip window. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETMAXTIPWIDTH, 0, 0); + } + + inline void CToolTip::GetText(CString& str, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) const + // Retrieves the information a ToolTip control maintains about a tool. + { + assert(IsWindow()); + assert(pWnd); + LPTSTR pszText = str.GetBuffer(80); // Maximum allowed Tooltip is 80 characters for Windows XP and below + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = pszText; + SendMessage(TTM_GETTEXT, 0, (LPARAM)&ti); + str.ReleaseBuffer(); + } + + inline COLORREF CToolTip::GetTipBkColor() const + // Retrieves the background color in a ToolTip window. + { + assert(IsWindow()); + return (COLORREF)SendMessage(TTM_GETTIPBKCOLOR, 0,0); + } + + inline COLORREF CToolTip::GetTipTextColor() const + // Retrieves the text color in a ToolTip window. + { + assert(IsWindow()); + return (COLORREF)SendMessage(TTM_GETTIPTEXTCOLOR, 0, 0); + } + + inline int CToolTip::GetToolCount() const + // Retrieves a count of the tools maintained by a ToolTip control. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETTOOLCOUNT, 0, 0); + } + + inline BOOL CToolTip::GetToolInfo(TOOLINFO& ToolInfo, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) const + // Retrieves the information that a ToolTip control maintains about a tool. + { + assert(IsWindow()); + assert(pWnd); + LoadToolInfo(ToolInfo, pWnd, nIDTool); + return (BOOL)SendMessage(TTM_GETTOOLINFO, 0, (LPARAM)&ToolInfo); + } + + inline BOOL CToolTip::HitTest(CWnd* pWnd, CPoint pt, LPTOOLINFO lpToolInfo) const + // Tests a point to determine whether it is within the bounding rectangle of the + // specified tool and, if it is, retrieves information about the tool. + { + assert(IsWindow()); + assert(pWnd); + assert(lpToolInfo); + TTHITTESTINFO hti = {0}; + hti.hwnd = pWnd->GetHwnd(); + hti.pt = pt; + hti.ti = *lpToolInfo; + return (BOOL)SendMessage(TTM_HITTEST, 0, (LPARAM)&hti); + } + + inline void CToolTip::LoadToolInfo(TOOLINFO& ti, CWnd* pWnd, UINT_PTR nIDTool) const + { + ZeroMemory(&ti, sizeof(TOOLINFO)); + ti.cbSize = sizeof(TOOLINFO); + HWND hWnd = pWnd->GetHwnd(); + if (nIDTool == 0) + { + ti.hwnd = ::GetParent(hWnd); + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; + ti.uId = (UINT)hWnd; + } + else + { + ti.hwnd = hWnd; + ti.uId = nIDTool; + } + } + + inline void CToolTip::Pop() + // Removes a displayed ToolTip window from view. + { + assert(IsWindow()); + SendMessage(TTM_POP, 0, 0); + } + + inline void CToolTip::RelayEvent(LPMSG lpMsg) + // Passes a mouse message to a ToolTip control for processing. + { + assert(IsWindow()); + SendMessage(TTM_RELAYEVENT, 0, (LPARAM)lpMsg); + } + + inline void CToolTip::SetDelayTime(UINT nDelay) + // Sets the initial delay for a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, nDelay); + } + + inline void CToolTip::SetDelayTime(DWORD dwDuration, int iTime) + // Sets the initial, pop-up, and reshow durations for a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETDELAYTIME, dwDuration, iTime); + } + + inline void CToolTip::SetMargin(LPRECT lprc) + // Sets the top, left, bottom, and right margins for a ToolTip window. + { + assert(IsWindow()); + assert(lprc); + SendMessage(TTM_SETMARGIN, 0, (LPARAM)lprc); + } + + inline int CToolTip::SetMaxTipWidth(int iWidth) + // Sets the maximum width for a ToolTip window. + { + assert(IsWindow()); + return (int)SendMessage(TTM_SETMAXTIPWIDTH, 0, iWidth); + } + + inline void CToolTip::SetTipBkColor(COLORREF clr) + // Sets the background color in a ToolTip window. + // Ignored when XP themes are active. + { + assert(IsWindow()); + SendMessage(TTM_SETTIPBKCOLOR, clr, 0); + } + + inline void CToolTip::SetTipTextColor(COLORREF clr) + // Sets the text color in a ToolTip window. + // Ignored when XP themes are active. + { + assert(IsWindow()); + SendMessage(TTM_SETTIPTEXTCOLOR, clr, 0); + } + + inline void CToolTip::SetToolInfo(LPTOOLINFO lpToolInfo) + // Sets the information that a ToolTip control maintains for a tool. + { + assert(IsWindow()); + SendMessage(TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo); + } + + inline void CToolTip::SetToolRect(CWnd* pWnd, UINT_PTR nIDTool, LPCRECT lpRect) + // Sets a new bounding rectangle for a tool. + { + assert(IsWindow()); + assert(pWnd); + assert(lpRect); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.rect = *lpRect; + SendMessage(TTM_NEWTOOLRECT, 0, (LPARAM)&ti); + } + + inline void CToolTip::Update() + // Forces the current tool to be redrawn. + { + assert(IsWindow()); + SendMessage(TTM_UPDATE, 0, 0); + } + + inline void CToolTip::UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Sets the ToolTip text for a tool. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = (LPTSTR)lpszText; + SendMessage(TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + } + + inline void CToolTip::UpdateTipText(UINT nIDText, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Sets the ToolTip text for a tool. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.hinst = GetApp()->GetResourceHandle(); + ti.lpszText = (LPTSTR)MAKEINTRESOURCE(nIDText); + SendMessage(TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + } + +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + inline BOOL CToolTip::AdjustRect(LPRECT lprc, BOOL bLarger /*= TRUE*/) + // Calculates a ToolTip control's text display rectangle from its window rectangle, or the + // ToolTip window rectangle needed to display a specified text display rectangle. + { + assert(IsWindow()); + return (BOOL)SendMessage(TTM_ADJUSTRECT, bLarger, (LPARAM)lprc); + } + + inline CSize CToolTip::GetBubbleSize(LPTOOLINFO lpToolInfo) const + // Returns the width and height of a ToolTip control. + { + assert(IsWindow()); + LRESULT lr = SendMessage(TTM_GETBUBBLESIZE, (LPARAM)lpToolInfo); + CSize sz(LOWORD(lr), HIWORD(lr)); + return sz; + } + + inline BOOL CToolTip::SetTitle(UINT uIcon, LPCTSTR lpstrTitle) + // Adds a standard icon and title string to a ToolTip. + { + assert(IsWindow()); + return (BOOL)SendMessage(TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle); + } +#endif + +#if (defined TTM_SETWINDOWTHEME) && (WINVER >= 0x0501) + inline HRESULT CToolTip::SetWindowTheme(LPCWSTR lpstrTheme) + // Sets the visual style of a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + return NULL; + } +#endif + + +} // namespace Win32xx + +#endif // define _WIN32XX_CONTROLS_H_ + Index: include/reactos/libs/win32++/copyright.txt =================================================================== --- include/reactos/libs/win32++/copyright.txt (revision 0) +++ include/reactos/libs/win32++/copyright.txt (working copy) @@ -0,0 +1,33 @@ +Win32++ Version 7.3 +Released: 30th November 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. Index: include/reactos/libs/win32++/cstring.h =================================================================== --- include/reactos/libs/win32++/cstring.h (revision 0) +++ include/reactos/libs/win32++/cstring.h (working copy) @@ -0,0 +1,965 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 both ANSI and Unicode characters and +// automatically converts these to TCHAR as required. +// +// 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: +// 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); + friend bool operator < (const CString& string1, const CString& string2); + friend bool operator > (const CString& string1, const CString& string2); + friend bool operator < (const CString& string1, LPCTSTR pszText); + friend bool operator > (const CString& string1, LPCTSTR pszText); + friend bool operator <= (const CString& string1, const CString& string2); + friend bool operator >= (const CString& string1, const CString& string2); + friend bool operator <= (const CString& string1, LPCTSTR pszText); + friend bool operator >= (const CString& string1, LPCTSTR pszText); + + public: + CString(); + ~CString(); + CString(const CString& str); + CString(LPCSTR pszText); + CString(LPCWSTR pszText); + CString(TCHAR ch, int nLength = 1); + CString(LPCTSTR pszText, int nLength); + + CString& operator = (const CString& str); + CString& operator = (const TCHAR ch); + CString& operator = (LPCSTR pszText); + CString& operator = (LPCWSTR pszText); + bool operator == (LPCTSTR pszText) const; + bool operator != (LPCTSTR pszText) const; + operator LPCTSTR() const; + TCHAR operator [] (int nIndex) const; + CString& operator += (const CString& str); + CString& operator += (LPCSTR szText); + CString& operator += (LPCWSTR szText); + + // Attributes + 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(LPCSTR pszText) + { + m_str.assign(A2T(pszText)); + } + + inline CString::CString(LPCWSTR pszText) + { + m_str.assign(W2T(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 = (LPCSTR pszText) + { + m_str.assign(A2T(pszText)); + return *this; + } + + inline CString& CString::operator = (LPCWSTR pszText) + { + m_str.assign(W2T(pszText)); + return *this; + } + + inline bool CString::operator == (LPCTSTR pszText) const + // Returns TRUE if the strings have the same content + { + assert(pszText); + return (0 == Compare(pszText)); + } + + inline bool CString::operator != (LPCTSTR pszText) const + // Returns TRUE if the strings have a different content + { + assert(pszText); + return Compare(pszText) != 0; + } + + inline CString::operator LPCTSTR() const + { + return m_str.c_str(); + } + + inline TCHAR CString::operator [] (int nIndex) const + { + assert(nIndex >= 0); + assert(nIndex < GetLength()); + return m_str[nIndex]; + } + + inline CString& CString::operator += (const CString& str) + { + m_str.append(str); + return *this; + } + + inline CString& CString::operator += (LPCSTR szText) + { + m_str.append(A2T(szText)); + return *this; + } + + inline CString& CString::operator += (LPCWSTR szText) + { + m_str.append(W2T(szText)); + 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; + + va_list args; + va_start(args, pszFormat); + str.FormatV(pszFormat, args); + va_end(args); + + 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)) + { + va_list args; + va_start(args, nFormatID); + str2.FormatV(str1.c_str(), args); + va_end(args); + + 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 _tcscmp(m_str.data(), 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. + { + CString str; + if (str.LoadString(nID)) + { + va_list args; + va_start(args, nID); + FormatV(str.c_str(), args); + va_end(args); + } + } + + 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; + + 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 (nLength != 0); + } +#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. + { + // Error 2285 with Borland 5.5 occurs here unless option -tWM is used instead of -tW + std::reverse(m_str.begin(), m_str.end()); + } + + inline void CString::MakeUpper() + // Converts all the characters in this string to uppercase characters. + { + // Error 2285 with Borland 5.5 occurs here unless option -tWM is used instead of -tW + 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, 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; + } + + inline bool operator < (const CString& string1, const CString& string2) + { + return string1.Compare(string2) < 0; + } + + inline bool operator > (const CString& string1, const CString& string2) + { + return string1.Compare(string2) > 0; + } + + inline bool operator <= (const CString& string1, const CString& string2) + { + return string1.Compare(string2) <= 0; + } + + inline bool operator >= (const CString& string1, const CString& string2) + { + return string1.Compare(string2) >= 0; + } + + inline bool operator < (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) < 0; + } + + inline bool operator > (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) > 0; + } + + inline bool operator <= (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) <= 0; + } + + inline bool operator >= (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) >= 0; + } + + // Global LoadString + inline CString LoadString(UINT nID) + { + CString str; + str.LoadString(nID); + return str; + } + + +} // namespace Win32xx + +#endif//_WIN32XX_CSTRING_H_ Index: include/reactos/libs/win32++/default_resource.h =================================================================== --- include/reactos/libs/win32++/default_resource.h (revision 0) +++ include/reactos/libs/win32++/default_resource.h (working copy) @@ -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++. + + Index: include/reactos/libs/win32++/default_resource.rc =================================================================== --- include/reactos/libs/win32++/default_resource.rc (revision 0) +++ include/reactos/libs/win32++/default_resource.rc (working copy) @@ -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 + + Index: include/reactos/libs/win32++/dialog.h =================================================================== --- include/reactos/libs/win32++/dialog.h (revision 0) +++ include/reactos/libs/win32++/dialog.h (working copy) @@ -0,0 +1,887 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + +#define IDLE_TIMER_ID 300 + +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 WM_TIMER: + if (wParam == IDLE_TIMER_ID) + GetApp()->CleanupTemps(); + return 0L; + case UWM_CLEANUPTEMPS: + { + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + pTLSData->vTmpWnds.clear(); + } + break; + case WM_INITDIALOG: + { + // Center the dialog + CenterWindow(); + if (IsModal()) + SetTimer(IDLE_TIMER_ID, 1000, 0); + } + 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("\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("\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 + if ( IsWindow() ) + 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. + // If you need the dialog to create another window, put it in a + // different thread. + } + } + } + + 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(pWndPrev, rc, SWP_NOCOPYBITS); + (*iter).rcOld = rc; + } + } + } + +#endif // #ifndef _WIN32_WCE + +} // namespace Win32xx + + + +#endif // _WIN32XX_DIALOG_H_ + Index: include/reactos/libs/win32++/docking.h =================================================================== --- include/reactos/libs/win32++/docking.h (revision 0) +++ include/reactos/libs/win32++/docking.h (working copy) @@ -0,0 +1,4237 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CString m_strTooltip; + 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_strTabText; } + 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_strTabText = 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; + CString m_strTabText; + 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(LPCTSTR szRegistryKeyName); + virtual void RecalcDockLayout(); + virtual BOOL SaveRegistrySettings(LPCTSTR szRegistryKeyName); + 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(); + ::SelectObject(*pDC, 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("**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_NCLBUTTONDBLCLK: + 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("Missing docking resource: Target Centre\n"); + + if (bmLeft.GetHandle()) pDC->DrawBitmap(0, 29, 31, 29, bmLeft, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Left\n"); + + if (bmTop.GetHandle()) pDC->DrawBitmap(29, 0, 29, 31, bmTop, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Top\n"); + + if (bmRight.GetHandle()) pDC->DrawBitmap(55, 29, 31, 29, bmRight, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Right\n"); + + if (bmBottom.GetHandle()) pDC->DrawBitmap(29, 55, 29, 31, bmBottom, RGB(255,0,255)); + else TRACE("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(&wndTopMost, 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("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(&wndTopMost, 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(&wndTopMost, 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(&wndTopMost, 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(&wndTopMost, 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("**WARNING** Horizontal cursor resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITV), RT_GROUP_CURSOR)) + TRACE("**WARNING** Vertical cursor resource missing\n"); + } + + if (!(dwDockStyle & DS_NO_UNDOCK)) + { + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDCENTER), RT_BITMAP)) + TRACE("**WARNING** Docking center bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDLEFT), RT_BITMAP)) + TRACE("**WARNING** Docking left bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDRIGHT), RT_BITMAP)) + TRACE("**WARNING** Docking right bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDTOP), RT_BITMAP)) + TRACE("**WARNING** Docking top bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDBOTTOM), RT_BITMAP)) + TRACE("**WARNING** Docking center bottom resource missing\n"); + } + + if (dwDockStyle & DS_DOCKED_CONTAINER) + { + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP)) + TRACE("**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(0, 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("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("Error: Undocked dockers should not have a dock parent\n"); + bResult = FALSE; + } + + if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0) + { + TRACE("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("Error: Docking parent/Child information mismatch\n"); + bResult = FALSE; + } + if ((*iterChild)->GetParent() != (*iter).get()) + { + TRACE("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("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); + + // Delete any child containers this container might have + if (GetContainer()) + { + std::vector AllContainers = GetContainer()->GetAllContainers(); + std::vector::iterator iter; + for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter) + { + if (GetContainer() != (*iter).pContainer) + GetContainer()->RemoveContainer((*iter).pContainer); + } + } + + 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); + pDock->GetDockBar().SetParent(GetDockAncestor()); + } + } + + 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(); + } + + if (GetDockAncestor()->GetView() == pView) + pDock = GetDockAncestor(); + + 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(LPCTSTR szRegistryKeyName) + // Recreates the docker layout based on information stored in the registry. + // Assumes the DockAncestor window is already created. + { + BOOL bResult = FALSE; + + if (szRegistryKeyName) + { + std::vector vDockList; + std::vector vActiveContainers; + + CString strKey = _T("Software\\") + CString(szRegistryKeyName) + _T("\\Dock Windows"); + HKEY hKey = 0; + RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey); + if (hKey) + { + DWORD dwType = REG_BINARY; + DWORD BufferSize = sizeof(DockInfo); + DockInfo di; + int i = 0; + TCHAR szNumber[20]; + CString strSubKey = _T("DockChild"); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&di, &BufferSize)) + { + vDockList.push_back(di); + i++; + strSubKey = _T("DockChild"); + strSubKey += _itot(i, szNumber, 10); + } + + dwType = REG_DWORD; + BufferSize = sizeof(int); + int nID; + i = 0; + strSubKey = _T("ActiveContainer"); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&nID, &BufferSize)) + { + vActiveContainers.push_back(nID); + i++; + strSubKey = _T("ActiveContainer"); + strSubKey += _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("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("Failed to add dockers with parents from registry"); + bResult = FALSE; + } + + vDockList.erase(iter); + break; + } + } + + if (!bFound) + { + TRACE("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("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 = (DWORD)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 the docker'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(GetDockAncestor()); + + // 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(LPCTSTR szRegistryKeyName) + // 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 (szRegistryKeyName) + { + // 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); + } + + CString strKeyName = _T("Software\\") + CString(szRegistryKeyName); + HKEY hKey = NULL; + HKEY hKeyDock = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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]; + CString strSubKey = _T("DockChild"); + strSubKey += _itot((int)u, szNumber, 10); + if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 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]; + CString strSubKey = _T("ActiveContainer"); + strSubKey += _itot(i++, szNumber, 10); + int nID = GetDockFromView(pContainer)->GetDockID(); + if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 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, strKeyName); + 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; + + if (GetDockFromView(pContainer) == GetDockAncestor()) 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); + pDock->GetDockBar().SetParent(GetDockAncestor()); + 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(0, 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(0, 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_strTooltip = LoadString(nID); + lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str(); + } + else + m_strTooltip = _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_ + Index: include/reactos/libs/win32++/file.h =================================================================== --- include/reactos/libs/win32++/file.h (revision 0) +++ include/reactos/libs/win32++/file.h (working copy) @@ -0,0 +1,396 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 HighPosCur = 0; + LONG HighPosEnd = 0; + + DWORD LowPosCur = SetFilePointer(m_hFile, 0, &HighPosCur, FILE_CURRENT); + DWORD LowPosEnd = SetFilePointer(m_hFile, 0, &HighPosEnd, FILE_END); + SetFilePointer(m_hFile, LowPosCur, &HighPosCur, FILE_BEGIN); + + ULONGLONG Result = ((ULONGLONG)HighPosEnd << 32) + LowPosEnd; + 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("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 Index: include/reactos/libs/win32++/frame.h =================================================================== --- include/reactos/libs/win32++/frame.h (revision 0) +++ include/reactos/libs/win32++/frame.h (working copy) @@ -0,0 +1,3863 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 +#ifndef TMT_BORDERSIZE + #define TMT_BORDERSIZE 2403 +#endif +#ifndef TMT_CONTENTMARGINS + #define TMT_CONTENTMARGINS 3602 +#endif +#ifndef VSCLASS_MENU + #define VSCLASS_MENU L"MENU" +#endif +#ifndef ODS_NOACCEL + #define ODS_NOACCEL 0x0100 +#endif +#ifndef ODS_HOTLIGHT + #define ODS_HOTLIGHT 0x0040 +#endif +#ifndef ODS_INACTIVE + #define ODS_INACTIVE 0x0080 +#endif +#ifndef DT_HIDEPREFIX + #define DT_HIDEPREFIX 0x00100000 +#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 + }; + + // define some structs and enums from uxtheme.h and vssym32.h + typedef struct _MARGINS + { + int cxLeftWidth; // width of left border that retains its size + int cxRightWidth; // width of right border that retains its size + int cyTopHeight; // height of top border that retains its size + int cyBottomHeight; // height of bottom border that retains its size + } MARGINS, *PMARGINS; + + class CMargins : public MARGINS + { + public: + CMargins(int cxLeft, int cxRight, int cyTop, int cyBottom) + { + cxLeftWidth = cxLeft; cxRightWidth = cxRight; + cyTopHeight = cyTop; cyBottomHeight = cyBottom; + } + CMargins() + { + cxLeftWidth = 0; cxRightWidth = 0; + cyTopHeight = 0; cyBottomHeight = 0; + } + int Width() const { return cxLeftWidth + cxRightWidth; } + int Height() const { return cyTopHeight + cyBottomHeight; } + void SetMargins(int cxLeft, int cxRight, int cyTop, int cyBottom) + { + cxLeftWidth = cxLeft; cxRightWidth = cxRight; + cyTopHeight = cyTop; cyBottomHeight = cyBottom; + } + }; + + enum THEMESIZE + { + TS_MIN, // minimum size + TS_TRUE, // size without stretching + TS_DRAW // size that theme mgr will use to draw part + }; + + enum POPUPCHECKSTATES + { + MC_CHECKMARKNORMAL = 1, + MC_CHECKMARKDISABLED = 2, + MC_BULLETNORMAL = 3, + MC_BULLETDISABLED = 4, + }; + + enum POPUPCHECKBACKGROUNDSTATES + { + MCB_DISABLED = 1, + MCB_NORMAL = 2, + MCB_BITMAP = 3, + }; + + enum POPUPITEMSTATES + { + MPI_NORMAL = 1, + MPI_HOT = 2, + MPI_DISABLED = 3, + MPI_DISABLEDHOT = 4, + }; + + enum POPUPSUBMENUSTATES + { + MSM_NORMAL = 1, + MSM_DISABLED = 2, + }; + + enum MENUPARTS + { + MENU_MENUITEM_TMSCHEMA = 1, + MENU_MENUDROPDOWN_TMSCHEMA = 2, + MENU_MENUBARITEM_TMSCHEMA = 3, + MENU_MENUBARDROPDOWN_TMSCHEMA = 4, + MENU_CHEVRON_TMSCHEMA = 5, + MENU_SEPARATOR_TMSCHEMA = 6, + MENU_BARBACKGROUND = 7, + MENU_BARITEM = 8, + MENU_POPUPBACKGROUND = 9, + MENU_POPUPBORDERS = 10, + MENU_POPUPCHECK = 11, + MENU_POPUPCHECKBACKGROUND = 12, + MENU_POPUPGUTTER = 13, + MENU_POPUPITEM = 14, + MENU_POPUPSEPARATOR = 15, + MENU_POPUPSUBMENU = 16, + MENU_SYSTEMCLOSE = 17, + MENU_SYSTEMMAXIMIZE = 18, + MENU_SYSTEMMINIMIZE = 19, + MENU_SYSTEMRESTORE = 20, + }; + + + // Forward declaration of CFrame. Its defined later. + class CFrame; + + struct MenuItemData + // Each Dropdown menu item has this data + { + HMENU hMenu; + MENUITEMINFO mii; + UINT nPos; + std::vector vItemText; + + MenuItemData() : hMenu(0), nPos(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); } + LPTSTR GetItemText() {return &vItemText[0];} + }; + + + //////////////////////////////////// + // 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 CMenuMetrics class + // This class is used by CFrame to retrieve the size of the components + // used to perform owner-drawing of menu items. Windows Visual Styles + // are used to render menu items for systems running Aero (Vista and above). + // Win32++ custom themes are used to render menu items for systems without Aero. + class CMenuMetrics + { + public: + CMenuMetrics(CFrame* pFrame); + ~CMenuMetrics(); + + CRect GetCheckBackgroundRect(CRect rcItem); + CRect GetCheckRect(CRect rcItem); + CRect GetGutterRect(CRect rcItem); + CRect GetSelectionRect(CRect rcItem); + CRect GetSeperatorRect(CRect rcItem); + CRect GetTextRect(CRect rcItem); + CSize GetTextSize(MenuItemData* pmd); + void Initialize(); + int ToItemStateId(UINT uItemState); + int ToCheckBackgroundStateId(int iStateId); + int ToCheckStateId(UINT fType, int iStateId); + + // Wrappers for Windows API functions + HRESULT CloseThemeData(); + HRESULT DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect); + HRESULT DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect); + HRESULT GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz); + HRESULT GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal); + HRESULT GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins); + HRESULT GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect); + BOOL IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId); + HANDLE OpenThemeData(HWND hwnd, LPCWSTR pszClassList); + + HANDLE m_hTheme; // Theme handle + CFrame* m_pFrame; // Pointer to the frame window + HMODULE m_hmodUXTheme; // Module handle to the UXTheme dll + + CMargins m_marCheck; // Check margins + CMargins m_marCheckBackground; // Check background margins + CMargins m_marItem; // Item margins + CMargins m_marText; // Text margins + + CSize m_sizeCheck; // Check size metric + CSize m_sizeSeparator; // Separator size metric + + private: + typedef HRESULT WINAPI CLOSETHEMEDATA(HANDLE); + typedef HRESULT WINAPI DRAWTHEMEBACKGROUND(HANDLE, HDC, int, int, const RECT*, const RECT*); + typedef HRESULT WINAPI DRAWTHEMETEXT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, LPCRECT); + typedef HRESULT WINAPI GETTHEMEPARTSIZE(HANDLE, HDC, int, int, LPCRECT, THEMESIZE, SIZE*); + typedef HRESULT WINAPI GETTHEMEINT(HANDLE, int, int, int, int*); + typedef HRESULT WINAPI GETTHEMEMARGINS(HANDLE, HDC, int, int, int, LPRECT, MARGINS*); + typedef HRESULT WINAPI GETTHEMETEXTEXTENT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPCRECT, LPCRECT); + typedef HRESULT WINAPI ISTHEMEBGPARTTRANSPARENT(HANDLE, int, int); + typedef HANDLE WINAPI OPENTHEMEDATA(HWND, LPCWSTR); + + // Pointers to functions defined in uxTheme.dll + CLOSETHEMEDATA* m_pfnCloseThemeData; + DRAWTHEMEBACKGROUND* m_pfnDrawThemeBackground; + DRAWTHEMETEXT* m_pfnDrawThemeText; + GETTHEMEPARTSIZE* m_pfnGetThemePartSize; + GETTHEMEINT* m_pfnGetThemeInt; + GETTHEMEMARGINS* m_pfnGetThemeMargins; + GETTHEMETEXTEXTENT* m_pfnGetThemeTextExtent; + ISTHEMEBGPARTTRANSPARENT* m_pfnIsThemeBGPartTransparent; + OPENTHEMEDATA* m_pfnOpenThemeData; + }; + + + ////////////////////////////////// + // Declaration of the CFrame class + // + class CFrame : public CWnd + { + friend class CMenuBar; + typedef Shared_Ptr ItemDataPtr; + + public: + CFrame(); + virtual ~CFrame(); + + // Override these functions as required + virtual void AdjustFrameRect(RECT rcView) const; + virtual CString GetThemeName() 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; } + CString GetRegistryKeyName() const { return m_strKeyName; } + CWnd* GetView() const { return m_pView; } + CString 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); + 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 DrawMenuItem(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemText(LPDRAWITEMSTRUCT pdis); + virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem); + virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName); + virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0); + virtual void MeasureMenuItem(MEASUREITEMSTRUCT *pmis); + 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, + }; + + Shared_Ptr m_pMenuMetrics; // Smart pointer for CMenuMetrics + CString m_strStatusText; // CString 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_bUseToolBar; // set to TRUE if the toolbar is used + 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 MenuItemData pointers + std::vector m_vMRUEntries; // Vector of CStrings for MRU entires + std::vector m_vMenuIcons; // vector of menu icon resource IDs + 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 + CFont m_fntMenuBar; // MenuBar font + CFont m_fntStatusBar; // StatusBar font + 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; + CString m_strKeyName; // CString for Registry key name + CString m_strTooltip; // CString for tool tips + CString m_XPThemeName; // CString for Windows Theme Name + 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 DrawDC(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; + DrawDC.DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL); + + DrawDC.Detach(); + return CDRF_SKIPDEFAULT; // No further drawing + } + + else if (nState & (CDIS_HOT | CDIS_SELECTED)) + { + if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED)) + { + DrawDC.GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE); + } + else if (nState & CDIS_HOT) + { + DrawDC.GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE); + } + + // Draw border + DrawDC.CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline); + DrawDC.MoveTo(rcRect.left, rcRect.bottom); + DrawDC.LineTo(rcRect.left, rcRect.top); + DrawDC.LineTo(rcRect.right-1, rcRect.top); + DrawDC.LineTo(rcRect.right-1, rcRect.bottom); + DrawDC.MoveTo(rcRect.right-1, rcRect.bottom); + DrawDC.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 + CFont* pFont = GetFont(); + ::SelectObject(DrawDC, pFont->GetHandle()); + + rcRect.bottom += 1; + int iMode = DrawDC.SetBkMode(TRANSPARENT); + DrawDC.DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE); + + DrawDC.SetBkMode(iMode); + DrawDC.Detach(); + return CDRF_SKIPDEFAULT; // No further drawing + } + DrawDC.Detach(); + } + return CDRF_DODEFAULT ; // Do default drawing + + // Painting cycle has completed + case CDDS_POSTPAINT: + // Draw MDI Minimise, Restore and Close buttons + { + CDC DrawDC(lpNMCustomDraw->nmcd.hdc); + DrawAllMDIButtons(DrawDC); + DrawDC.Detach(); + } + 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(...) + + + inline CMenuMetrics::CMenuMetrics(CFrame* pFrame) : m_hTheme(0), m_hmodUXTheme(0), m_pfnCloseThemeData(0), m_pfnDrawThemeBackground(0), + m_pfnDrawThemeText(0), m_pfnGetThemePartSize(0), m_pfnGetThemeInt(0), m_pfnGetThemeMargins(0), + m_pfnGetThemeTextExtent(0), m_pfnIsThemeBGPartTransparent(0), m_pfnOpenThemeData(0) + { + assert(pFrame); + m_pFrame = pFrame; + + Initialize(); + } + + inline void CMenuMetrics::Initialize() + { + assert(m_pFrame); + + if (!m_hmodUXTheme) + m_hmodUXTheme = ::LoadLibrary(_T("UXTHEME.DLL")); + + if (m_hmodUXTheme) + { + m_pfnCloseThemeData = (CLOSETHEMEDATA*)::GetProcAddress(m_hmodUXTheme, "CloseThemeData"); + m_pfnDrawThemeBackground = (DRAWTHEMEBACKGROUND*)::GetProcAddress(m_hmodUXTheme, "DrawThemeBackground"); + m_pfnDrawThemeText = (DRAWTHEMETEXT*)::GetProcAddress(m_hmodUXTheme, "DrawThemeText"); + m_pfnGetThemePartSize = (GETTHEMEPARTSIZE*)::GetProcAddress(m_hmodUXTheme, "GetThemePartSize"); + m_pfnGetThemeInt = (GETTHEMEINT*)::GetProcAddress(m_hmodUXTheme, "GetThemeInt"); + m_pfnGetThemeMargins = (GETTHEMEMARGINS*)::GetProcAddress(m_hmodUXTheme, "GetThemeMargins"); + m_pfnGetThemeTextExtent = (GETTHEMETEXTEXTENT*)::GetProcAddress(m_hmodUXTheme, "GetThemeTextExtent"); + m_pfnIsThemeBGPartTransparent = (ISTHEMEBGPARTTRANSPARENT*)::GetProcAddress(m_hmodUXTheme, "IsThemeBackgroundPartiallyTransparent"); + m_pfnOpenThemeData = (OPENTHEMEDATA*)::GetProcAddress(m_hmodUXTheme, "OpenThemeData"); + } + + if (m_hTheme) + { + CloseThemeData(); + m_hTheme = 0; + } + + m_hTheme = OpenThemeData(*m_pFrame, VSCLASS_MENU); + + if (m_hTheme) + { + int iBorderSize = 0; // Border space between item text and accelerator + int iBgBorderSize = 0; // Border space between item text and gutter + GetThemePartSize(NULL, MENU_POPUPCHECK, 0, NULL, TS_TRUE, &m_sizeCheck); + GetThemePartSize(NULL, MENU_POPUPSEPARATOR, 0, NULL, TS_TRUE, &m_sizeSeparator); + GetThemeInt(MENU_POPUPITEM, 0, TMT_BORDERSIZE, &iBorderSize); + GetThemeInt(MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &iBgBorderSize); + GetThemeMargins(NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &m_marCheck); + GetThemeMargins(NULL, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, NULL, &m_marCheckBackground); + GetThemeMargins(NULL, MENU_POPUPITEM, 0, TMT_CONTENTMARGINS, NULL, &m_marItem); + + // Popup text margins + m_marText = m_marItem; + m_marText.cxRightWidth = iBorderSize; + m_marText.cxLeftWidth = iBgBorderSize; + } + else + { + m_sizeCheck.SetSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + m_sizeSeparator.SetSize(1, 7); + m_marCheck.SetMargins(4, 4, 2, 2); + m_marCheckBackground.SetMargins(0, 0, 0, 0); + m_marItem.SetMargins(0, 0, 0, 0); + m_marText.SetMargins(8, 16, 0, 0); + } + } + + inline CMenuMetrics::~CMenuMetrics() + { + if (m_hTheme) + CloseThemeData(); + + if (m_hmodUXTheme) + ::FreeLibrary(m_hmodUXTheme); + } + + inline HRESULT CMenuMetrics::CloseThemeData() + { + if (m_pfnCloseThemeData) + return (*m_pfnCloseThemeData)(m_hTheme); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect) + { + if (m_pfnDrawThemeBackground) + return (*m_pfnDrawThemeBackground)(m_hTheme, hdc, iPartId, iStateId, pRect, pClipRect); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect) + { + if (m_pfnDrawThemeText) + return (*m_pfnDrawThemeText)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz) + { + if (m_pfnGetThemePartSize) + return (*m_pfnGetThemePartSize)(m_hTheme, hdc, iPartId, iStateId, prc, eSize, psz); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal) + { + if (m_pfnGetThemeInt) + return (*m_pfnGetThemeInt)(m_hTheme, iPartId, iStateId, iPropId, piVal); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins) + { + if (m_pfnGetThemeMargins) + return (*m_pfnGetThemeMargins)(m_hTheme, hdc, iPartId, iStateId, iPropId, prc, pMargins); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) + { + if (m_pfnGetThemeTextExtent) + return (*m_pfnGetThemeTextExtent)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, pBoundingRect, pExtentRect); + + return E_NOTIMPL; + } + + inline BOOL CMenuMetrics::IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId) + { + if (m_pfnIsThemeBGPartTransparent) + return (*m_pfnIsThemeBGPartTransparent)(m_hTheme, iPartId, iStateId); + + return E_NOTIMPL; + } + + inline HANDLE CMenuMetrics::OpenThemeData(HWND hwnd, LPCWSTR pszClassList) + { + if (m_pfnOpenThemeData) + return (*m_pfnOpenThemeData)(hwnd, pszClassList); + + return NULL; + } + + inline CRect CMenuMetrics::GetCheckBackgroundRect(CRect rcItem) + { + int x = rcItem.left + m_marCheckBackground.cxLeftWidth; + int y = rcItem.top + m_marCheckBackground.cyTopHeight; + int cx = m_sizeCheck.cx + m_marCheck.Width(); + int cy = m_sizeCheck.cy + m_marCheck.Height(); + + return CRect(x, y, x + cx, y + cy); + } + + inline CRect CMenuMetrics::GetGutterRect(CRect rcItem) + { + int x = rcItem.left; + int y = rcItem.top; + int cx = m_marItem.cxLeftWidth + m_marCheckBackground.Width() + m_marCheck.Width() + m_sizeCheck.cx; + int cy = rcItem.Height(); + + return CRect(x, y, x + cx, y + cy); + } + + inline CRect CMenuMetrics::GetCheckRect(CRect rcItem) + { + int x = rcItem.left + m_marCheckBackground.cxLeftWidth + m_marCheck.cxLeftWidth; + int y = rcItem.top + m_marCheckBackground.cyTopHeight + m_marCheck.cyTopHeight; + + return CRect(x, y, x + m_sizeCheck.cx, y + m_sizeCheck.cy); + } + + inline CRect CMenuMetrics::GetSelectionRect(CRect rcItem) + { + int x = rcItem.left + m_marItem.cxLeftWidth; + int y = rcItem.top; + + return CRect(x, y, rcItem.right - m_marItem.cxRightWidth, y + rcItem.Height()); + } + + inline CRect CMenuMetrics::GetSeperatorRect(CRect rcItem) + { + int left = GetGutterRect(rcItem).right; + int top = rcItem.top; + int right = rcItem.right - m_marItem.cxRightWidth; + int bottom = rcItem.top + m_sizeSeparator.cy; + + return CRect(left, top, right, bottom); + } + + inline CSize CMenuMetrics::GetTextSize(MenuItemData* pmd) + { + CSize sizeText; + assert(m_pFrame); + CClientDC DesktopDC(NULL); + LPCTSTR szItemText = pmd->GetItemText(); + + if (IsAeroThemed()) + { + CRect rcText; + GetThemeTextExtent(DesktopDC, MENU_POPUPITEM, 0, T2W(szItemText), lstrlen(szItemText), + DT_LEFT | DT_SINGLELINE, NULL, &rcText); + + sizeText.SetSize(rcText.right + m_marText.Width(), rcText.bottom + m_marText.Height()); + } + else + { + // 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; + + // Calculate the size of the text + DesktopDC.CreateFontIndirect(&nm.lfMenuFont); + sizeText = DesktopDC.GetTextExtentPoint32(szItemText, lstrlen(szItemText)); + // sizeText.cx += m_marText.Width(); + sizeText.cx += m_marText.cxRightWidth; + sizeText.cy += m_marText.Height(); + } + + if (_tcschr(szItemText, _T('\t'))) + sizeText.cx += 8; // Add POST_TEXT_GAP if the text includes a tab + + return sizeText; + } + + inline CRect CMenuMetrics::GetTextRect(CRect rcItem) + { + int left = GetGutterRect(rcItem).Width() + m_marText.cxLeftWidth; + int top = rcItem.top + m_marText.cyTopHeight; + int right = rcItem.right - m_marItem.cxRightWidth - m_marText.cxRightWidth; + int bottom = rcItem.bottom - m_marText.cyBottomHeight; + + return CRect(left, top, right, bottom); + } + + inline int CMenuMetrics::ToItemStateId(UINT uItemState) + { + const bool fDisabled = ((uItemState & (ODS_INACTIVE | ODS_DISABLED)) != 0); + const bool fHot = ((uItemState & (ODS_HOTLIGHT | ODS_SELECTED)) != 0); + POPUPITEMSTATES iState; + + if (fDisabled) + iState = (fHot ? MPI_DISABLEDHOT : MPI_DISABLED); + else if (fHot) + iState = MPI_HOT; + else + iState= MPI_NORMAL; + + return iState; + } + + inline int CMenuMetrics::ToCheckBackgroundStateId(int iStateId) + { + POPUPCHECKBACKGROUNDSTATES iStateIdCheckBackground; + + // Determine the check background state. + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheckBackground = MCB_DISABLED; + else + iStateIdCheckBackground = MCB_NORMAL; + + return iStateIdCheckBackground; + } + + inline int CMenuMetrics::ToCheckStateId(UINT fType, int iStateId) + { + POPUPCHECKSTATES iStateIdCheck; + + if (fType & MFT_RADIOCHECK) + { + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheck = MC_BULLETDISABLED; + else + iStateIdCheck = MC_BULLETNORMAL; + } + else + { + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheck = MC_CHECKMARKDISABLED; + else + iStateIdCheck = MC_CHECKMARKNORMAL; + } + + return iStateIdCheck; + } + + + /////////////////////////////////// + // Definitions for the CFrame class + // + inline CFrame::CFrame() : m_pMenuMetrics(0), m_strStatusText(_T("Ready")), m_bShowIndicatorStatus(TRUE), m_bShowMenuStatus(TRUE), + m_bUseReBar(FALSE), m_bUseThemes(TRUE), m_bUseToolBar(TRUE), m_bShowStatusBar(TRUE), m_bShowToolBar(TRUE), + m_himlMenu(0), m_himlMenuDis(0), 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'); + + NONCLIENTMETRICS nm = {0}; + nm.cbSize = GetSizeofNonClientMetrics(); + SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0); + m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont); + m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont); + } + + 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) + { + // Create a new ImageList if required + if (NULL == m_himlMenu) + { + if (m_himlMenu) ImageList_Destroy(m_himlMenu); + m_himlMenu = ImageList_Create(16, 16, 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("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("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("Warning ... No resource IDs assigned to the toolbar\n"); + } + } + + inline void CFrame::DrawMenuItem(LPDRAWITEMSTRUCT pdis) + { + MenuItemData* pmid = (MenuItemData*)pdis->itemData; + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + MenuTheme tm = GetMenuTheme(); + CDC DrawDC(pdis->hDC); + + if (IsAeroThemed() && m_pMenuMetrics->IsThemeBackgroundPartiallyTransparent(MENU_POPUPITEM, iStateId)) + { + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPBACKGROUND, 0, &pdis->rcItem, NULL); + } + + // Draw the gutter + CRect rcGutter = m_pMenuMetrics->GetGutterRect(pdis->rcItem); + if (IsAeroThemed()) + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPGUTTER, 0, &rcGutter, NULL); + else + DrawDC.GradientFill(tm.clrPressed1, tm.clrPressed2, rcGutter, TRUE); + + if (pmid->mii.fType & MFT_SEPARATOR) + { + // Draw the separator + if (IsAeroThemed()) + { + CRect rcSeparator = m_pMenuMetrics->GetSeperatorRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL); + } + else + { + CRect rc = pdis->rcItem; + CRect rcSep = pdis->rcItem; + rcSep.left = m_pMenuMetrics->GetGutterRect(rc).Width() + 2; + DrawDC.SolidFill(RGB(255,255,255), rcSep); + rcSep.top += (rc.bottom - rc.top)/2; + DrawDC.DrawEdge(rcSep, EDGE_ETCHED, BF_TOP); + } + } + else + { + // Draw the item background + DrawMenuItemBkgnd(pdis); + + // Draw Checkmark or icon + if (pmid->mii.fState & MFS_CHECKED) + DrawMenuItemCheckmark(pdis); + else + DrawMenuItemIcon(pdis); + + // Draw the text. + DrawMenuItemText(pdis); + } + + if (IsAeroThemed()) + { + // Draw the Submenu arrow + if (pmid->mii.hSubMenu) + { + CRect rcSubMenu = pdis->rcItem; + rcSubMenu.left = pdis->rcItem.right - m_pMenuMetrics->m_marItem.cxRightWidth - m_pMenuMetrics->m_marText.cxRightWidth;; + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSUBMENU, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcSubMenu, NULL); + } + + // Suppress further drawing to prevent an incorrect Submenu arrow being drawn + CRect rc = pdis->rcItem; + ::ExcludeClipRect(pdis->hDC, rc.left, rc.top, rc.right, rc.bottom); + } + + DrawDC.Detach(); + } + + inline void CFrame::DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis) + { + // Draw the item background + CRect rcSelection = m_pMenuMetrics->GetSelectionRect(pdis->rcItem); + if (IsAeroThemed()) + { + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPITEM, iStateId, &rcSelection, NULL); + } + else + { + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + BOOL bSelected = pdis->itemState & ODS_SELECTED; + CRect rcDraw = pdis->rcItem; + CDC* pDrawDC = FromHandle(pdis->hDC); + MenuTheme tm = GetMenuTheme(); + + if ((bSelected) && (!bDisabled)) + { + // draw selected item background + pDrawDC->CreateSolidBrush(tm.clrHot1); + pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline); + pDrawDC->Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom); + } + else + { + // draw non-selected item background + rcDraw.left = m_pMenuMetrics->GetGutterRect(pdis->rcItem).Width(); + pDrawDC->SolidFill(RGB(255,255,255), rcDraw); + } + } + } + + inline void CFrame::DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis) + // Draws the checkmark or radiocheck transparently + { + CRect rc = pdis->rcItem; + UINT fType = ((MenuItemData*)pdis->itemData)->mii.fType; + MenuTheme tm = GetMenuTheme(); + CRect rcBk; + CDC* pDrawDC = FromHandle(pdis->hDC); + + if (IsAeroThemed()) + { + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + MenuItemData* pmid = (MenuItemData*)pdis->itemData; + CRect rcCheckBackground = m_pMenuMetrics->GetCheckBackgroundRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECKBACKGROUND, m_pMenuMetrics->ToCheckBackgroundStateId(iStateId), &rcCheckBackground, NULL); + CRect rcCheck = m_pMenuMetrics->GetCheckRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECK, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcCheck, NULL); + } + else + { + // Draw the checkmark's background rectangle first + int Iconx = m_pMenuMetrics->m_sizeCheck.cx; + int Icony = m_pMenuMetrics->m_sizeCheck.cy; + int left = m_pMenuMetrics->m_marCheck.cxLeftWidth; + int top = rc.top + (rc.Height() - Icony)/2; + rcBk.SetRect(left, top, left + Iconx, top + Icony); + + pDrawDC->CreateSolidBrush(tm.clrHot2); + pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline); + + // Draw the checkmark's background rectangle + pDrawDC->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; + + 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); + pDrawDC->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); + pDrawDC->BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCAND); + } + } + } + + inline void CFrame::DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis) + { + if (!m_himlMenu) + return; + + // Get icon size + int Iconx = m_pMenuMetrics->m_sizeCheck.cx; + int Icony = m_pMenuMetrics->m_sizeCheck.cy; + + // get the drawing rectangle + CRect rc = pdis->rcItem; + int left = m_pMenuMetrics->m_marCheck.cxLeftWidth; + 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 ) + { + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + if ((bDisabled) && (m_himlMenuDis)) + ImageList_Draw(m_himlMenuDis, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT); + else + ImageList_Draw(m_himlMenu, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT); + } + } + + inline void CFrame::DrawMenuItemText(LPDRAWITEMSTRUCT pdis) + { + LPCTSTR ItemText = ((MenuItemData*)pdis->itemData)->GetItemText(); + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + COLORREF colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : COLOR_MENUTEXT); + + // Calculate the text rect size + CRect rcText = m_pMenuMetrics->GetTextRect(pdis->rcItem); + + // 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 + if (IsAeroThemed()) + { + ULONG uAccel = ((pdis->itemState & ODS_NOACCEL) ? DT_HIDEPREFIX : 0); + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + + // Draw the item text before the tab + m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(ItemText), nTab, DT_SINGLELINE | DT_LEFT | DT_TOP | uAccel, 0, &rcText); + + // Draw text after tab, right aligned + if(nTab != -1) + m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(&ItemText[nTab + 1]), -1, DT_SINGLELINE | DT_RIGHT | DT_TOP | uAccel, 0, &rcText); + } + else + { + SetTextColor(pdis->hDC, colorText); + int iMode = SetBkMode(pdis->hDC, TRANSPARENT); + DrawText(pdis->hDC, ItemText, nTab, rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER); + + // Draw text after tab, right aligned + if(nTab != -1) + DrawText(pdis->hDC, &ItemText[nTab + 1], -1, rcText, DT_SINGLELINE | DT_RIGHT | DT_VCENTER); + + SetBkMode(pdis->hDC, iMode); + } + } + + 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 CString CFrame::GetMRUEntry(UINT nIndex) + { + CString strPathName; + if (nIndex < m_vMRUEntries.size()) + { + strPathName = m_vMRUEntries[nIndex]; + + // Now put the selected entry at Index 0 + AddMRUEntry(strPathName); + } + return strPathName; + } + + 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 CString CFrame::GetThemeName() const + { + // Returns the XP theme name + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + WCHAR ThemeName[31] = L""; + 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, ThemeName, 30, 0, 0); + + ::FreeLibrary(hMod); + } + + return CString(ThemeName); + } + + 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_strKeyName.IsEmpty()); // KeyName must be set before calling LoadRegistryMRUSettings + HKEY hKey = NULL; + BOOL bRet = FALSE; + + try + { + m_nMaxMRU = MIN(nMaxMRU, 16); + std::vector vMRUEntries; + CString strKey = _T("Software\\") + m_strKeyName + _T("\\Recent Files"); + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 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("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_strKeyName = szKeyName; + + CString strKey = _T("Software\\") + m_strKeyName + _T("\\Frame Settings"); + HKEY hKey = 0; + BOOL bRet = FALSE; + + try + { + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 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("Failed to load values from registry, using defaults!\n"); + e.what(); + + if (hKey) + RegCloseKey(hKey); + } + + return bRet; + } + + inline void CFrame::MeasureMenuItem(MEASUREITEMSTRUCT *pmis) + { + int cxTotal = 0; + int cyMax = 0; + + MenuItemData* pmid = (MenuItemData*)pmis->itemData; + assert(::IsMenu(pmid->hMenu)); // Does itemData contain a valid MenuItemData struct? + + // Add icon/check width + cxTotal += m_pMenuMetrics->m_sizeCheck.cx + m_pMenuMetrics->m_marCheckBackground.Width() + m_pMenuMetrics->m_marCheck.Width(); + + if (pmid->mii.fType & MFT_SEPARATOR) + { + // separator height + cyMax = m_pMenuMetrics->m_sizeSeparator.cy + m_pMenuMetrics->m_marItem.Height(); + } + else + { + // Add check background horizontal padding. + cxTotal += m_pMenuMetrics->m_marCheckBackground.cxLeftWidth + m_pMenuMetrics->m_marCheckBackground.cxRightWidth; + + // Add selection margin padding. + cxTotal += m_pMenuMetrics->m_marItem.cxLeftWidth + m_pMenuMetrics->m_marItem.cxRightWidth; + + // Account for text size + CSize sizeText = m_pMenuMetrics->GetTextSize(pmid); + cxTotal += sizeText.cx; + cyMax = MAX(cyMax, sizeText.cy); + + // Account for icon or check height + cyMax = MAX(cyMax, m_pMenuMetrics->m_sizeCheck.cy + m_pMenuMetrics->m_marCheckBackground.Height() + m_pMenuMetrics->m_marCheck.Height()); + } + + // Return the composite sizes. + pmis->itemWidth = cxTotal; + pmis->itemHeight = cyMax; + } + + 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); + m_pMenuMetrics = new CMenuMetrics(this); + + UpdateMRUMenu(); + + // Create the ToolBar + if (m_bUseToolBar) + { + CreateToolBar(); + ShowToolBar(m_bShowToolBar); + } + else + { + GetFrameMenu().CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED); + GetFrameMenu().EnableMenuItem(IDW_VIEW_TOOLBAR, MF_GRAYED); + } + + // Create the status bar + GetStatusBar().Create(this); + GetStatusBar().SetFont(&m_fntStatusBar, FALSE); + 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 + OnSysColorChange(); + 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); + + if (!IsRectEmpty(&pdis->rcItem)) + DrawMenuItem(pdis); + + return TRUE; + } + + inline void CFrame::OnExitMenuLoop() + { + if (m_bUseThemes) + { + 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]->mii.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_bUseThemes) + { + CMenu* pMenu = FromHandle((HMENU)wParam); + + for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i) + { + MenuItemData* pItem = new MenuItemData; // deleted in OnExitMenuLoop + m_vMenuItemData.push_back(ItemDataPtr(pItem)); // Store pItem in smart pointer for later automatic deletion + + MENUITEMINFO mii = {0}; + mii.cbSize = GetSizeofMenuItemInfo(); + + // Use old fashioned MIIM_TYPE instead of MIIM_FTYPE for MS VC6 compatibility + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU |MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA; + mii.dwTypeData = pItem->GetItemText(); // assign TCHAR pointer, text is assigned by GetMenuItemInfo + 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) + { + pItem->hMenu = *pMenu; + pItem->nPos = i; + pItem->mii = mii; + mii.dwItemData = (DWORD_PTR)pItem; + mii.fType |= MFT_OWNERDRAW; + 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); + + MeasureMenuItem(pmis); + 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_strStatusText = LoadString(nID); + else + m_strStatusText = _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_strTooltip = LoadString(nID); + lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str(); + } + else + m_strTooltip = _T(""); + } + } + } + break; + } // switch LPNMHDR + + return 0L; + + } // CFrame::Onotify(...) + + inline void CFrame::OnSetFocus() + { + SetStatusText(); + } + + inline void CFrame::OnSysColorChange() + { + // Honour theme color changes + if (GetReBar().IsWindow()) + { + 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); + m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont); + GetStatusBar().SetFont(&m_fntStatusBar, TRUE); + SetStatusText(); + + + if (GetMenuBar().IsWindow()) + { + // Update the MenuBar font and button size + m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont); + GetMenuBar().SetFont(&m_fntMenuBar, TRUE); + GetMenuBar().SetMenu(GetFrameMenu()); + + // Update the MenuBar band size + int nBand = GetReBar().GetBand(GetMenuBar()); + REBARBANDINFO rbbi = {0}; + CClientDC dcMenuBar(&GetMenuBar()); + dcMenuBar.SelectObject(GetMenuBar().GetFont()); + CSize sizeMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText"))); + int MenuBar_Height = sizeMenuBar.cy + 6; + rbbi.fMask = RBBIM_CHILDSIZE; + rbbi.cyMinChild = MenuBar_Height; + rbbi.cyMaxChild = MenuBar_Height; + GetReBar().SetBandInfo(nBand, rbbi); + } + + if (m_XPThemeName != GetThemeName()) + SetTheme(); + m_pMenuMetrics->Initialize(); + + // 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_strStatusText = LoadString(nID); + else + m_strStatusText = _T("Ready"); + + if (GetStatusBar().IsWindow()) + SetStatusText(); + } + m_nOldID = nID; + } + } + else + { + if (m_nOldID != -1) + { + m_strStatusText = _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_strKeyName.IsEmpty()) + { + CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Frame Settings"); + HKEY hKey = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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("Failed to save registry settings\n"); + + if (hKey) + { + // Roll back the registry changes by deleting this subkey + RegDeleteKey(HKEY_CURRENT_USER ,strKeyName); + RegCloseKey(hKey); + } + + e.what(); + return FALSE; + } + + // Store the MRU entries in the registry + if (m_nMaxMRU > 0) + { + CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Recent Files"); + HKEY hKey = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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); + CString strPathName; + if (i < m_vMRUEntries.size()) + strPathName = m_vMRUEntries[i]; + + if (ERROR_SUCCESS != RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (LPBYTE)strPathName.c_str(), (1 + strPathName.GetLength() )*sizeof(TCHAR))) + throw CWinException(_T("RegSetValueEx failed")); + } + + RegCloseKey(hKey); + } + + catch (const CWinException& e) + { + TRACE("Failed to save registry MRU settings\n"); + + if (hKey) + { + // Roll back the registry changes by deleting this subkey + RegDeleteKey(HKEY_CURRENT_USER ,strKeyName); + 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_strStatusText); + } + } + + 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) + { + // Retrieve the XP theme name + m_XPThemeName = GetThemeName(); + + enum Themetype{ Modern, Grey, Blue, Silver, Olive }; + + int Theme = Grey; + if (GetWinVersion() < 2600) // Not for Vista and above + { + if (m_XPThemeName == _T("NormalColor")) + Theme = Blue; + if (m_XPThemeName == _T("Metallic")) + Theme = Silver; + if (m_XPThemeName == _T("HomeStead")) + 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(225, 230, 255), RGB(240, 242, 250), RGB(248, 248, 248), 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); + m_bShowStatusBar = TRUE; + } + else + { + m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED); + GetStatusBar().ShowWindow(SW_HIDE); + m_bShowStatusBar = FALSE; + } + + // 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); + m_bShowToolBar = TRUE; + } + else + { + m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED); + if (IsReBarUsed()) + GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), FALSE); + else + GetToolBar().ShowWindow(SW_HIDE); + m_bShowToolBar = FALSE; + } + + 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 + CString strMRUArray[16]; + UINT MaxMRUArrayIndex = 0; + if (m_vMRUEntries.size() > 0) + { + for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n) + { + strMRUArray[n] = m_vMRUEntries[n]; + if (strMRUArray[n].GetLength() > MAX_MENU_STRING - 10) + { + // Truncate the string if its too long + strMRUArray[n].Delete(0, strMRUArray[n].GetLength() - MAX_MENU_STRING +10); + strMRUArray[n] = _T("... ") + strMRUArray[n]; + } + + // Prefix the string with its number + TCHAR tVal[5]; + wsprintf(tVal, _T("%d "), n+1); + strMRUArray[n] = tVal + strMRUArray[n]; + MaxMRUArrayIndex = n; + } + } + else + { + strMRUArray[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)strMRUArray[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("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_ Index: include/reactos/libs/win32++/gdi.h =================================================================== --- include/reactos/libs/win32++/gdi.h (revision 0) +++ include/reactos/libs/win32++/gdi.h (working copy) @@ -0,0 +1,3992 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); +// 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); +// 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); + void DeleteObject(); + 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 + void CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors); + void CreateCompatibleBitmap(CDC* pDC, int cx, int cy); + void CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits, + HANDLE hSection, DWORD dwOffset); + + CBitmap DetachBitmap(); + BITMAP GetBitmapData() const; + BOOL LoadBitmap(UINT nID); + BOOL LoadBitmap(LPCTSTR lpszName); + BOOL LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad); + BOOL LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad); + BOOL LoadOEMBitmap(UINT nIDBitmap); // for OBM_/OCR_/OIC + +#ifndef _WIN32_WCE + void CreateBitmapIndirect(LPBITMAP pBitmap); + void CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit, + BITMAPINFO& bmi, UINT fuUsage); + void CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/); +#endif + + // Create and Select Brushes + void CreatePatternBrush(CBitmap* pBitmap); + void CreateSolidBrush(COLORREF rbg); + LOGBRUSH GetLogBrush() const; + +#ifndef _WIN32_WCE + void CreateBrushIndirect(LPLOGBRUSH pLogBrush); + void CreateHatchBrush(int fnStyle, COLORREF rgb); + void CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec); + void CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage); +#endif + + // Create and Select Fonts + void CreateFontIndirect(LPLOGFONT plf); + LOGFONT GetLogFont() const; + +#ifndef _WIN32_WCE + void 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 + void CreatePen(int nStyle, int nWidth, COLORREF rgb); + void 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 void CGDIObject::DeleteObject() + { + assert(m_pData); + + if (m_pData->hGDIObject) + { + ::DeleteObject(Detach()); + } + } + + 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 == 0) + 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 void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline CBitmap CDC::DetachBitmap() + // Provides a convenient method of detaching a bitmap from a memory device context. + // Returns the CBitmap detached from the DC. + // Useage: CBitmap MyBitmap = MyMemDC.DetachBitmap(); + { + // Create a stock bitmap to replace the current one. + CBitmap* pBitmap = new CBitmap; + pBitmap->CreateBitmap(1, 1, 1, 1, 0); + m_pData->m_vGDIObjects.push_back(pBitmap); + + // Select our new stock bitmap into the device context + HBITMAP hBitmap = (HBITMAP)::SelectObject(*this, *pBitmap); + + // Detach the bitmap from our internally managed GDIObjects + std::vector::iterator it; + for (it = m_pData->m_vGDIObjects.begin(); it < m_pData->m_vGDIObjects.end(); ++it) + { + if((*it)->GetHandle() == hBitmap) + (*it)->Detach(); + } + + // Create a local CBitmap. We can return this by value because it is reference counted + CBitmap Bitmap(hBitmap); + return Bitmap; + } + + 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; + } + } + } + + 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 BOOL CDC::LoadBitmap(UINT nID) + // Loads a bitmap from the resource and selects it into the device context + { + return LoadBitmap(MAKEINTRESOURCE(nID)); + } + + inline BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + + inline BOOL 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 BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + + inline BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap);; + } +#endif // !_WIN32_WCE + + + // Brush functions +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *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 void 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); + ::SelectObject(m_pData->hDC, *pFont); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *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 void 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); + ::SelectObject(m_pData->hDC, *pPen); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *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); + 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 Bitmap = MemDC.DetachBitmap(); + ImageList_AddMasked(himlDisabled, Bitmap, 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_ + Index: include/reactos/libs/win32++/info.txt =================================================================== --- include/reactos/libs/win32++/info.txt (revision 0) +++ include/reactos/libs/win32++/info.txt (working copy) @@ -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 Index: include/reactos/libs/win32++/listview.h =================================================================== --- include/reactos/libs/win32++/listview.h (revision 0) +++ include/reactos/libs/win32++/listview.h (working copy) @@ -0,0 +1,870 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CEdit* GetEditControl( ) const; + DWORD GetExtendedStyle( ) const; + CHeader* 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; + CString 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; + CToolTip* 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; + CToolTip* SetToolTips ( CToolTip* pToolTip ) 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; + CEdit* 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 CEdit* 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 (CEdit*)FromHandle(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 CHeader* CListView::GetHeader( ) const + // Retrieves the handle to the header control used by a list-view control. + { + assert(::IsWindow(m_hWnd)); + return (CHeader*)FromHandle(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 CString 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)); + + CString 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 CToolTip* CListView::GetToolTips( ) const + // Retrieves the ToolTip control that the list-view control uses to display ToolTips. + { + assert(::IsWindow(m_hWnd)); + return(CToolTip*)FromHandle(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 CToolTip* CListView::SetToolTips( CToolTip* pToolTip ) const + // Sets the ToolTip control that the list-view control will use to display ToolTips. + { + assert(::IsWindow(m_hWnd)); + assert(pToolTip); + + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + return (CToolTip*) FromHandle( (HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hToolTip, 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 CEdit* CListView::EditLabel( int iItem ) const + // Begins in-place editing of the specified list-view item's text. + { + assert(::IsWindow(m_hWnd)); + return (CEdit*)FromHandle( 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_ + Index: include/reactos/libs/win32++/mdi.h =================================================================== --- include/reactos/libs/win32++/mdi.h (revision 0) +++ include/reactos/libs/win32++/mdi.h (working copy) @@ -0,0 +1,784 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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) + { + CString strMenuItem ( (*v)->GetWindowText() ); + + if (strMenuItem.GetLength() > MAX_MENU_STRING -10) + { + // Truncate the string if its too long + strMenuItem.Delete(strMenuItem.GetLength() - MAX_MENU_STRING +10); + strMenuItem += _T(" ..."); + } + + TCHAR szMenuString[MAX_MENU_STRING+1]; + wsprintf(szMenuString, _T("&%d %s"), nWindow+1, strMenuItem.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_ + Index: include/reactos/libs/win32++/menu.h =================================================================== --- include/reactos/libs/win32++/menu.h (revision 0) +++ include/reactos/libs/win32++/menu.h (working copy) @@ -0,0 +1,600 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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_ + Index: include/reactos/libs/win32++/propertysheet.h =================================================================== --- include/reactos/libs/win32++/propertysheet.h (revision 0) +++ include/reactos/libs/win32++/propertysheet.h (working copy) @@ -0,0 +1,960 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + + CString 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); + + CString 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; + 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.Empty(); + m_PSP.dwFlags &= ~PSP_USETITLE; + } + + m_PSP.pszTitle = m_Title; + } + + 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.Empty(); + + m_PSH.pszCaption = m_Title; + } + + 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_ Index: include/reactos/libs/win32++/rebar.h =================================================================== --- include/reactos/libs/win32++/rebar.h (revision 0) +++ include/reactos/libs/win32++/rebar.h (working copy) @@ -0,0 +1,718 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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" +#include "controls.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; + CToolTip* 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); + void SetToolTips(CToolTip* pToolTip) const; + + 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 CToolTip* CReBar::GetToolTips() const + // Retrieves the handle to any ToolTip control associated with the rebar control. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*)FromHandle( (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 void CReBar::SetToolTips(CToolTip* pToolTip) const + // Associates a ToolTip control with the rebar control. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : (HWND)0; + SendMessage(RB_SETTOOLTIPS, WPARAM(hToolTip), 0); + } + + 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_ Index: include/reactos/libs/win32++/release notes.txt =================================================================== --- include/reactos/libs/win32++/release notes.txt (revision 0) +++ include/reactos/libs/win32++/release notes.txt (working copy) @@ -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 Index: include/reactos/libs/win32++/ribbon.h =================================================================== --- include/reactos/libs/win32++/ribbon.h (revision 0) +++ include/reactos/libs/win32++/ribbon.h (working copy) @@ -0,0 +1,527 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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("Ribbon Created Succesfully\n"); + else + throw CWinException("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) + { + CString strCurrentFile = (*iter); + WCHAR wszCurrentFile[MAX_PATH] = {0L}; + lstrcpynW(wszCurrentFile, T2W(strCurrentFile), 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_ + Index: include/reactos/libs/win32++/shared_ptr.h =================================================================== --- include/reactos/libs/win32++/shared_ptr.h (revision 0) +++ include/reactos/libs/win32++/shared_ptr.h (working copy) @@ -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_ Index: include/reactos/libs/win32++/socket.h =================================================================== --- include/reactos/libs/win32++/socket.h (revision 0) +++ include/reactos/libs/win32++/socket.h (working copy) @@ -0,0 +1,778 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); + + CString m_ErrorMessage; + 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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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_ErrorMessage = _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_ErrorMessage = Message; + ::LocalFree(Message); + } + + return m_ErrorMessage; + } + + inline int CSocket::GetPeerName(struct sockaddr* name, int* namelen) + { + int Result = ::getpeername(m_Socket, name, namelen); + if (0 != Result) + TRACE("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("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("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("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("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("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("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("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("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("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("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("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("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("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("*** 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_ + Index: include/reactos/libs/win32++/statusbar.h =================================================================== --- include/reactos/libs/win32++/statusbar.h (revision 0) +++ include/reactos/libs/win32++/statusbar.h (working copy) @@ -0,0 +1,226 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); + CString 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 CString CStatusBar::GetPartText(int iPart) const + { + assert(::IsWindow(m_hWnd)); + CString 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_ Index: include/reactos/libs/win32++/stdcontrols.h =================================================================== --- include/reactos/libs/win32++/stdcontrols.h (revision 0) +++ include/reactos/libs/win32++/stdcontrols.h (working copy) @@ -0,0 +1,1001 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 PreRegisterClass(WNDCLASS &wc); + }; + + 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::PreRegisterClass(WNDCLASS &wc) + { + // Set the Window Class + wc.lpszClassName = _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_ + Index: include/reactos/libs/win32++/tab.h =================================================================== --- include/reactos/libs/win32++/tab.h (revision 0) +++ include/reactos/libs/win32++/tab.h (working copy) @@ -0,0 +1,1682 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 SetFont(CFont* pFont, BOOL bRedraw = 1); + 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(CString strRegistryKeyName); + virtual void RecalcLayout(); + virtual BOOL SaveRegistrySettings(CString strRegistryKeyName); + 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 + ::SelectObject(dcMem, 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); + ::SelectObject(dcClient, 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); + ::SelectObject(dcClient, 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); + ::SelectObject(dcMem, 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::SetFont(CFont* pFont, BOOL bRedraw /* = 1 */) + { + assert(pFont); + m_Font = *pFont; + int HeightGap = 5; + SetTabHeight( MAX(20, GetTextHeight() + HeightGap) ); + CWnd::SetFont(pFont, bRedraw); + } + + 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(0, 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); + int nLength = 30; + std::vector vTChar1( nLength+1, _T('\0') ); // vector for TCHAR array + std::vector vTChar2( nLength+1, _T('\0') ); // vector for TCHAR array + + TCITEM Item1 = {0}; + Item1.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT; + Item1.cchTextMax = nLength; + Item1.pszText = &vTChar1.front(); + GetItem(nTab1, &Item1); + + TCITEM Item2 = {0}; + Item2.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT; + Item2.cchTextMax = nLength; + Item2.pszText = &vTChar2.front(); + 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_DESTROY: + // Required for Windows NT + { + for (int i = GetItemCount()-1; i >= 0; --i) + { + RemoveTabPage(i); + } + } + break; + case WM_PAINT: + if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED) + { + // Remove all pending paint requests + PAINTSTRUCT ps; + ::BeginPaint(m_hWnd, &ps); + ::EndPaint(m_hWnd, &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; + } + + 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(CString strRegistryKeyName) + { + BOOL bResult = FALSE; + + if (!strRegistryKeyName.IsEmpty()) + { + CString strKey = _T("Software\\") + strRegistryKeyName + _T("\\MDI Children"); + HKEY hKey = 0; + RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey); + if (hKey) + { + DWORD dwType = REG_BINARY; + DWORD BufferSize = sizeof(TabPageInfo); + TabPageInfo tbi = {0}; + int i = 0; + TCHAR szNumber[16]; + CString strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&tbi, &BufferSize)) + { + CWnd* pWnd = NewMDIChildFromID(tbi.idTab); + if (pWnd) + { + AddMDIChild(pWnd, tbi.szTabText, tbi.idTab); + i++; + strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + bResult = TRUE; + } + else + { + TRACE("Failed to get TabbedMDI info from registry"); + bResult = FALSE; + break; + } + } + + // Load Active MDI Tab from the registry + strSubKey = _T("Active MDI Tab"); + int nTab; + dwType = REG_DWORD; + BufferSize = sizeof(int); + if(ERROR_SUCCESS == RegQueryValueEx(hKey, strSubKey, 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("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(CString strRegistryKeyName) + { + if (!strRegistryKeyName.IsEmpty()) + { + CString strKeyName = _T("Software\\") + strRegistryKeyName; + HKEY hKey = NULL; + HKEY hKeyMDIChild = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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]; + CString strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + TabPageInfo pdi = GetTab().GetTabPageInfo(i); + if (ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 0, REG_BINARY, (LPBYTE)&pdi, sizeof(TabPageInfo))) + throw (CWinException(_T("RegSetValueEx Failed"))); + } + + // Add Active Tab to the registry + CString strSubKey = _T("Active MDI Tab"); + int nTab = GetActiveMDITab(); + if(ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 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, strKeyName); + 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_ Index: include/reactos/libs/win32++/taskdialog.h =================================================================== --- include/reactos/libs/win32++/taskdialog.h (revision 0) +++ include/reactos/libs/win32++/taskdialog.h (working copy) @@ -0,0 +1,810 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + { + CString cs = LoadString((UINT)pFromTChar); + int len = pFromTChar? cs.GetLength() + 1 : 1; + vTChar.assign(len, _T('\0')); + vWChar.assign(len, _T('\0')); + if (pFromTChar) + lstrcpy( &vTChar.front(), cs); + } + 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 Index: include/reactos/libs/win32++/thread.h =================================================================== --- include/reactos/libs/win32++/thread.h (revision 0) +++ include/reactos/libs/win32++/thread.h (working copy) @@ -0,0 +1,241 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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("*** 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_ + Index: include/reactos/libs/win32++/toolbar.h =================================================================== --- include/reactos/libs/win32++/toolbar.h (revision 0) +++ include/reactos/libs/win32++/toolbar.h (working copy) @@ -0,0 +1,1367 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CToolTip* 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(CToolTip* pToolTip) 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 CToolTip* CToolBar::GetToolTips() const + // Retrieves the handle to the ToolTip control, if any, associated with the toolbar. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*)FromHandle( (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 DrawDC(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? + { + DrawDC.SelectObject(GetFont()); + if (SendMessage(TB_GETBUTTONTEXT, dwItem, (LPARAM)pszText)> 0) + { + TextSize = DrawDC.GetTextExtentPoint32(pszText, lstrlen(pszText)); + } + } + + // Draw outline rectangle + if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED)) + { + DrawDC.CreatePen(PS_SOLID, 1, m_Theme.clrOutline); + DrawDC.MoveTo(rcRect.left, rcRect.top); + DrawDC.LineTo(rcRect.left, rcRect.bottom-1); + DrawDC.LineTo(rcRect.right-1, rcRect.bottom-1); + DrawDC.LineTo(rcRect.right-1, rcRect.top); + DrawDC.LineTo(rcRect.left, rcRect.top); + } + + // Draw filled gradient background + rcRect.InflateRect(-1, -1); + if ((nState & (CDIS_SELECTED|CDIS_CHECKED)) || (GetButtonState(dwItem) & TBSTATE_PRESSED)) + { + DrawDC.GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcRect, FALSE); + } + else if (nState & CDIS_HOT) + { + DrawDC.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; + DrawDC.GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcArrowBkgnd, FALSE); + } + + m_bDrawArrowBkgrnd = FALSE; + + // Manually draw the dropdown arrow + DrawDC.CreatePen(PS_SOLID, 1, RGB(0,0,0)); + for (int i = 2; i >= 0; --i) + { + DrawDC.MoveTo(xAPos -i-1, yAPos - i+1); + DrawDC.LineTo(xAPos +i, yAPos - i+1); + } + + // Draw line between icon and dropdown arrow + if ((nStyle & TBSTYLE_DROPDOWN) && ((nState & CDIS_SELECTED) || nState & CDIS_HOT)) + { + DrawDC.CreatePen(PS_SOLID, 1, m_Theme.clrOutline); + DrawDC.MoveTo(rcRect.right - 13, rcRect.top); + DrawDC.LineTo(rcRect.right - 13, rcRect.bottom); + } + } + + // Draw the button image + if (xImage > 0) + { + ImageList_Draw(himlToolBar, iImage, DrawDC, 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 = DrawDC.SetBkMode(TRANSPARENT); + DrawDC.SelectObject(GetFont()); + + if (nState & (CDIS_DISABLED)) + { + // Draw text twice for embossed look + rcText.OffsetRect(1, 1); + DrawDC.SetTextColor(RGB(255,255,255)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT); + rcText.OffsetRect(-1, -1); + DrawDC.SetTextColor(GetSysColor(COLOR_GRAYTEXT)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT); + } + else + { + DrawDC.SetTextColor(GetSysColor(COLOR_BTNTEXT)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT | DT_END_ELLIPSIS); + } + DrawDC.SetBkMode(iMode); + + } + DrawDC.Detach(); + } + 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) && (GetComCtlVersion() > 470)) + 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; + CString 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 (GetComCtlVersion() < 470) + { + // 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(CToolTip* pToolTip) const + // Associates a ToolTip control with a toolbar. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : (HWND)0; + SendMessage(TB_SETTOOLTIPS, (WPARAM)hToolTip, 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_ Index: include/reactos/libs/win32++/treeview.h =================================================================== --- include/reactos/libs/win32++/treeview.h (revision 0) +++ include/reactos/libs/win32++/treeview.h (working copy) @@ -0,0 +1,625 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CEdit* 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; + CString 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; + CToolTip* 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; + CToolTip* SetToolTips(CToolTip* pToolTip) 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 CEdit* 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 (CEdit*)FromHandle(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 CString 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)); + + CString 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_GetPrevVisible(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 CToolTip* CTreeView::GetToolTips() const + // Retrieves the handle to the child ToolTip control used by a tree-view control. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*) FromHandle( 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 CToolTip* CTreeView::SetToolTips(CToolTip* pToolTip) const + // Sets a tree-view control's child ToolTip control. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + return (CToolTip*) FromHandle( TreeView_SetToolTips( m_hWnd, hToolTip ) ); + } + + // 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_ + Index: include/reactos/libs/win32++/wceframe.h =================================================================== --- include/reactos/libs/win32++/wceframe.h (revision 0) +++ include/reactos/libs/win32++/wceframe.h (working copy) @@ -0,0 +1,409 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CString m_strAppName; + +#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_strAppName = _T("Win32++ Application"); + + // Choose a unique class name for this app + if (LoadString(IDW_MAIN) != _T("")) + { + m_strAppName = LoadString(IDW_MAIN); + } + + cs.lpszClass = m_strAppName; + } + + 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_ + Index: include/reactos/libs/win32++/wcestddef.h =================================================================== --- include/reactos/libs/win32++/wcestddef.h (revision 0) +++ include/reactos/libs/win32++/wcestddef.h (working copy) @@ -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 Index: include/reactos/libs/win32++/webbrowser.h =================================================================== --- include/reactos/libs/win32++/webbrowser.h (revision 0) +++ include/reactos/libs/win32++/webbrowser.h (working copy) @@ -0,0 +1,1220 @@ +// Win32++ Version 7.3 +// Released: 30th November 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 +#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(); + + + //Attributes + LPDISPATCH GetApplication() const; + CAXWindow& GetAXWindow() const { return (CAXWindow&)m_AXContainer; } + BOOL GetBusy() const; + LPDISPATCH GetContainer() const; + BOOL GetFullScreen() const; + long GetHeight() const; + IWebBrowser2* GetIWebBrowser2() const { return m_pIWebBrowser2; } + long GetLeft() const; + CString GetLocationName() const; + CString GetLocationURL() const; + BOOL GetOffline() const; + READYSTATE GetReadyState() const; + BOOL GetRegisterAsBrowser() const; + BOOL GetTheaterMode() const; + long GetTop() const; + BOOL GetTopLevelContainer() const; + CString GetType() const; + BOOL GetVisible() const; + long GetWidth() const; + void SetFullScreen(BOOL bNewValue); + void SetHeight(long nNewValue); + void SetLeft(long nNewValue); + void SetOffline(BOOL bNewValue); + void SetRegisterAsBrowser(BOOL bNewValue); + void SetTheaterMode(BOOL bNewValue); + void SetTop(long nNewValue); + void SetVisible(BOOL bNewValue); + void SetWidth(long nNewValue); + + // Operations + void AddWebBrowserControl(void); + void ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT* pvaIn, VARIANT* pvaOut); + BOOL GetProperty(LPCTSTR pszProperty, CString& strValue); + VARIANT GetProperty( LPCTSTR pszProperty); + void GoBack(); + void GoForward(); + void GoHome(); + void GoSearch(); + void Navigate(LPCTSTR pszURL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL, + LPCTSTR pszHeaders = NULL, LPVOID pvPostData = NULL, DWORD dwPostDataLen = 0); + void Navigate2(LPITEMIDLIST pIDL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL); + void Navigate2(LPCTSTR pszURL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL, + LPCTSTR pszHeaders = NULL, LPVOID lpvPostData = NULL, DWORD dwPostDataLen = 0); + void PutProperty(LPCTSTR pszPropertyName, const VARIANT& vtValue); + void PutProperty(LPCTSTR pszPropertyName, double dValue); + void PutProperty(LPCTSTR pszPropertyName, long lValue); + void PutProperty(LPCTSTR pszPropertyName, LPCTSTR lpszValue); + void PutProperty(LPCTSTR pszPropertyName, short nValue); + void Refresh(); + void Refresh2(int nLevel); + void Stop(); + + 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 +{ + ///////////////////////////////////////// + // Global functions + // + inline UINT GetPidlLength(LPITEMIDLIST pidl) + { + assert(pidl); + UINT cbPidl = sizeof(pidl->mkid.cb); + while(pidl && pidl->mkid.cb) + { + cbPidl += pidl->mkid.cb; + + // Walk to next item + BYTE* ptr = (BYTE*)pidl; + ptr += pidl->mkid.cb; + pidl = (LPITEMIDLIST)ptr; + } + + return cbPidl; + } + + + ///////////////////////////////////////// + // Definitions for the CAXWindow class + // + inline CAXWindow::CAXWindow() : m_cRefs(1), m_hWnd(NULL), m_pUnk(NULL) + { + } + + inline CAXWindow::~CAXWindow() + { + if (m_pUnk) + m_pUnk->Release(); + + Release(); + } + + 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(); + } + + } + + 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)) + { + m_pIWebBrowser2->Navigate((OLECHAR*)L"about:blank", 0, 0, 0, 0); + } + } + } + + 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); + } + + inline LPDISPATCH CWebBrowser::GetApplication() const + // Retrieves the automation object for the application that is hosting the WebBrowser Control. + { + LPDISPATCH Value; + GetIWebBrowser2()->get_Application(&Value); + return Value; + } + + inline BOOL CWebBrowser::GetBusy() const + // Retrieves a value that indicates whether the object is engaged in a navigation or downloading operation. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Busy(&bValue); + return (BOOL)bValue; + } + + inline LPDISPATCH CWebBrowser::GetContainer() const + // Retrieves an object reference to a container. + { + LPDISPATCH Value; + GetIWebBrowser2()->get_Container(&Value); + return Value; + } + + inline BOOL CWebBrowser::GetFullScreen() const + // Retrieves a value that indicates whether Internet Explorer is in full-screen mode or normal window mode. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_FullScreen(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetHeight() const + // Retrieves the height of the object. + { + long lValue; + GetIWebBrowser2()->get_Height(&lValue); + return lValue; + } + + inline long CWebBrowser::GetLeft() const + // Retrieves the coordinate of the left edge of the object. + { + long lValue; + GetIWebBrowser2()->get_Left(&lValue); + return lValue; + } + + inline CString CWebBrowser::GetLocationName() const + // Retrieves the path or title of the resource that is currently displayed. + { + BSTR bstr; + GetIWebBrowser2()->get_LocationName(&bstr); + CString str(bstr); + SysFreeString(bstr); + return str; + } + + inline CString CWebBrowser::GetLocationURL() const + // Retrieves the URL of the resource that is currently displayed. + { + BSTR bstr; + GetIWebBrowser2()->get_LocationURL(&bstr); + CString str(bstr); + SysFreeString(bstr); + return str; + } + + inline BOOL CWebBrowser::GetOffline() const + // Retrieves a value that indicates whether the object is operating in offline mode. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Offline(&bValue); + return (BOOL)bValue; + } + + inline READYSTATE CWebBrowser::GetReadyState() const + // Retrieves the ready state of the object. + { + READYSTATE rsValue; + GetIWebBrowser2()->get_ReadyState(&rsValue); + return rsValue; + } + + inline BOOL CWebBrowser::GetRegisterAsBrowser() const + // Retrieves a value that indicates whether the object is registered as a top-level browser window. + { + VARIANT_BOOL bValue = VARIANT_FALSE; +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x600) + GetIWebBrowser2()->get_RegisterAsBrowser(&bValue); +#endif + return (BOOL)bValue; + } + + inline BOOL CWebBrowser::GetTheaterMode() const + // Retrieves the theater mode state of the object. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_TheaterMode(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetTop() const + // Retrieves the coordinate of the top edge of the object. + { + long lValue; + GetIWebBrowser2()->get_Top(&lValue); + return lValue; + } + + inline BOOL CWebBrowser::GetTopLevelContainer() const + //Retrieves a value that indicates whether the object is a top-level container. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_TopLevelContainer(&bValue); + return (BOOL)bValue; + } + + inline CString CWebBrowser::GetType() const + // Retrieves the user type name of the contained document object. + { + BSTR bString; + GetIWebBrowser2()->get_Type(&bString); + CString str(bString); + SysFreeString(bString); + return str; + } + + inline BOOL CWebBrowser::GetVisible() const + // Retrieves a value that indicates whether the object is visible or hidden. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Visible(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetWidth() const + // Retrieves the width of the object. + { + long lValue; + GetIWebBrowser2()->get_Width(&lValue); + return lValue; + } + + inline void CWebBrowser::SetFullScreen(BOOL bNewValue) + // Sets a value that indicates whether Internet Explorer is in full-screen mode or normal window mode. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_FullScreen(vBool); + } + + inline void CWebBrowser::SetHeight(long nNewValue) + // Sets the height of the object. + { + GetIWebBrowser2()->put_Height(nNewValue); + } + + inline void CWebBrowser::SetLeft(long nNewValue) + // Sets the coordinate of the left edge of the object. + { + GetIWebBrowser2()->put_Left(nNewValue); + } + + inline void CWebBrowser::SetOffline(BOOL bNewValue) + // Sets a value that indicates whether the object is operating in offline mode. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_Offline(vBool); + } + + inline void CWebBrowser::SetRegisterAsBrowser(BOOL bNewValue) + // Sets a value that indicates whether the object is registered as a top-level browser window. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_RegisterAsBrowser(vBool); + } + + inline void CWebBrowser::SetTheaterMode(BOOL bNewValue) + // Sets the theatre mode state of the object. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_TheaterMode(vBool); + } + + inline void CWebBrowser::SetTop(long nNewValue) + // Sets the coordinate of the top edge of the object. + { + GetIWebBrowser2()->put_Top(nNewValue); + } + + inline void CWebBrowser::SetVisible(BOOL bNewValue) + // Sets a value that indicates whether the object is visible or hidden. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_Visible(vBool); + } + + inline void CWebBrowser::SetWidth(long nNewValue) + // Sets the width of the object. + { + GetIWebBrowser2()->put_Width(nNewValue); + } + + inline void CWebBrowser::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT* pvaIn, VARIANT* pvaOut) + // Executes a command using the IOleCommandTarget interface. + { + GetIWebBrowser2()->ExecWB(cmdID, cmdexecopt, pvaIn, pvaOut); + } + + inline BOOL CWebBrowser::GetProperty(LPCTSTR pszProperty, CString& strValue) + // Gets the value associated with the specified property name. + { + VARIANT v; + HRESULT hResult = GetIWebBrowser2()->GetProperty(T2BSTR(pszProperty), &v); + if (v.vt == VT_EMPTY) + strValue.Empty(); + else + strValue = BSTR2T(v.bstrVal); + + return (hResult == S_OK); + } + + inline VARIANT CWebBrowser::GetProperty( LPCTSTR pszProperty ) + // Gets the value associated with the specified property name. + { + VARIANT v; + GetIWebBrowser2()->GetProperty( T2BSTR(pszProperty), &v ); + return v; + } + + inline void CWebBrowser::GoBack() + // Navigates backward one item in the history list. + { + GetIWebBrowser2()->GoBack(); + } + + inline void CWebBrowser::GoForward() + // Navigates forward one item in the history list. + { + GetIWebBrowser2()->GoForward(); + } + + inline void CWebBrowser::GoHome() + // Navigates to the current home or start page. + { + GetIWebBrowser2()->GoHome(); + } + + inline void CWebBrowser::GoSearch() + // Navigates to the current search page. + { + GetIWebBrowser2()->GoSearch(); + } + + inline void CWebBrowser::Navigate(LPCTSTR pszURL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/, + LPCTSTR pszHeaders /*= NULL*/, LPVOID pvPostData /*= NULL*/, DWORD dwPostDataLen /*= 0*/) + // Navigates to a resource identified by a URL or to a file identified by a full path. + { + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + SAFEARRAY* psa = SafeArrayCreateVector(VT_UI1, 0, dwPostDataLen); + CopyMemory(psa->pvData, pvPostData, dwPostDataLen); + VARIANT PostData; + PostData.vt = VT_ARRAY|VT_UI1; + PostData.parray = psa; + + VARIANT Headers; + Headers.vt = VT_BSTR; + Headers.bstrVal = SysAllocString(T2W(pszHeaders)); + BSTR url = SysAllocString(T2W(pszURL)); + + GetIWebBrowser2()->Navigate(url, &Flags, &TargetFrameName, &PostData, &Headers); + + VariantClear(&Flags); + VariantClear(&TargetFrameName); + VariantClear(&PostData); + VariantClear(&Headers); + } + + inline void CWebBrowser::Navigate2(LPITEMIDLIST pIDL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/) + // Navigates the browser to a location specified by a pointer to an item identifier list (PIDL) for an entity in the Microsoft Windows Shell namespace. + { + UINT cb = GetPidlLength(pIDL); + LPSAFEARRAY psa = SafeArrayCreateVector(VT_UI1, 0, cb); + VARIANT PIDL; + PIDL.vt = VT_ARRAY|VT_UI1; + PIDL.parray = psa; + CopyMemory(psa->pvData, pIDL, cb); + + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + GetIWebBrowser2()->Navigate2(&PIDL, &Flags, &TargetFrameName, 0, 0); + + VariantClear(&PIDL); + VariantClear(&Flags); + VariantClear(&TargetFrameName); + } + + inline void CWebBrowser::Navigate2(LPCTSTR pszURL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/, + LPCTSTR pszHeaders /*= NULL*/, LPVOID pvPostData /*= NULL*/, DWORD dwPostDataLen /*= 0*/) + // Navigates the browser to a location that is expressed as a URL. + { + VARIANT URL; + URL.vt = VT_BSTR; + URL.bstrVal = SysAllocString(T2W(pszURL)); + + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + // Store the pidl in a SafeArray, and assign the SafeArray to a VARIANT + SAFEARRAY* psa = SafeArrayCreateVector(VT_UI1, 0, dwPostDataLen); + CopyMemory(psa->pvData, pvPostData, dwPostDataLen); + VARIANT PostData; + PostData.vt = VT_ARRAY|VT_UI1; + PostData.parray = psa; + + VARIANT Headers; + Headers.vt = VT_BSTR; + Headers.bstrVal = SysAllocString(T2W(pszHeaders)); + + GetIWebBrowser2()->Navigate2(&URL, &Flags, &TargetFrameName, &PostData, &Headers); + + VariantClear(&URL); + VariantClear(&Flags); + VariantClear(&TargetFrameName); + VariantClear(&PostData); + VariantClear(&Headers); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszProperty, const VARIANT& vtValue) + // Sets the value of a property associated with the object. + { + GetIWebBrowser2()->PutProperty(T2BSTR(pszProperty), vtValue); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, double dValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.dblVal = dValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, long lValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.lVal= lValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, LPCTSTR lpszValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_BSTR; + v.bstrVal= SysAllocString(T2W(lpszValue)); + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, short nValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.iVal = nValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::Refresh() + // Reloads the file that is currently displayed in the object. + { + GetIWebBrowser2()->Refresh(); + } + + inline void CWebBrowser::Refresh2(int nLevel) + // Reloads the file that is currently displayed with the specified refresh level. + { + VARIANT v; + v.vt = VT_I4; + v.intVal = nLevel; + GetIWebBrowser2()->Refresh2(&v); + VariantClear(&v); + } + + inline void CWebBrowser::Stop() + // Cancels a pending navigation or download, and stops dynamic page elements, such as background sounds and animations. + { + GetIWebBrowser2()->Stop(); + } + + +} + +#endif // _WIN32XX_WEBBROWSER_H_ + Index: include/reactos/libs/win32++/wincore.h =================================================================== --- include/reactos/libs/win32++/wincore.h (revision 0) +++ include/reactos/libs/win32++/wincore.h (working copy) @@ -0,0 +1,3022 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + #pragma option -w-8030 // Temporary used for 'rhs' + #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 +#include +#include +#include +#include +#include +#include "shared_ptr.h" +//#include "winutils.h" // included later in this file +//#include "cstring.h" // included later in this file +//#include "gdi.h" // included later in this file +//#include "menu.h" // included later in this file + +// For compilers lacking Win64 support +#ifndef GetWindowLongPtr + #define GetWindowLongPtr GetWindowLong + #define SetWindowLongPtr SetWindowLong + #define GWLP_WNDPROC GWL_WNDPROC + #define GWLP_HINSTANCE GWL_HINSTANCE + #define GWLP_ID GWL_ID + #define GWLP_USERDATA GWL_USERDATA + #define DWLP_DLGPROC DWL_DLGPROC + #define DWLP_MSGRESULT DWL_MSGRESULT + #define DWLP_USER DWL_USER + #define DWORD_PTR DWORD + #define LONG_PTR LONG + #define ULONG_PTR LONG +#endif +#ifndef GetClassLongPtr + #define GetClassLongPtr GetClassLong + #define SetClassLongPtr SetClassLong + #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND + #define GCLP_HCURSOR GCL_HCURSOR + #define GCLP_HICON GCL_HICON + #define GCLP_HICONSM GCL_HICONSM + #define GCLP_HMODULE GCL_HMODULE + #define GCLP_MENUNAME GCL_MENUNAME + #define GCLP_WNDPROC GCL_WNDPROC +#endif + + +// Messages defined by Win32++ +#define UWM_POPUPMENU (WM_APP + 1) // Message - creates the menubar popup menu +#define UWM_DOCK_START (WM_APP + 2) // Notification - about to start undocking +#define UWM_DOCK_MOVE (WM_APP + 3) // Notification - undocked docker is being moved +#define UWM_DOCK_END (WM_APP + 4) // Notification - docker has been docked +#define UWM_BAR_START (WM_APP + 5) // Notification - docker bar selected for move +#define UWM_BAR_MOVE (WM_APP + 6) // Notification - docker bar moved +#define UWM_BAR_END (WM_APP + 7) // Notification - end of docker bar move +#define UWM_UNDOCKED (WM_APP + 8) // Notification - sent by docker when undocked +#define UWM_FRAMELOSTFOCUS (WM_APP + 9) // Notification - sent by frame to view window when focus lost +#define UWM_FRAMEGOTFOCUS (WM_APP + 10) // Notification - sent by frame to view window when focus acquired +#define UWM_DOCK_DESTROYED (WM_APP + 11) // Message - posted when docker is destroyed +#define UWM_TAB_CHANGED (WM_APP + 12) // Notification - tab layout changed +#define UWM_TOOLBAR_RESIZE (WM_APP + 13) // Message - sent by toolbar to parent. Used by the rebar +#define UWM_UPDATE_COMMAND (WM_APP + 14) // Message - sent before a menu is displayed. Used by OnUpdate +#define UWM_DOCK_ACTIVATED (WM_APP + 15) // Message - sent to dock ancestor when a docker is activated or deactivated. +#define UWM_GETMENUTHEME (WM_APP + 16) // Message - returns a pointer to MenuTheme +#define UWM_GETREBARTHEME (WM_APP + 17) // Message - returns a pointer to CToolBar +#define UWM_GETTOOLBARTHEME (WM_APP + 18) // Message - returns a pointer to ToolBarTheme +#define UWM_CLEANUPTEMPS (WM_APP + 19) // Message - posted to cleanup temporary CDCs + + +// Automatically include the Win32xx namespace +// define NO_USING_NAMESPACE to skip this step +namespace Win32xx {} +#ifndef NO_USING_NAMESPACE + using namespace Win32xx; +#endif + +// Required for WinCE +#ifndef TLS_OUT_OF_INDEXES + #define TLS_OUT_OF_INDEXES ((DWORD_PTR) -1) +#endif +#ifndef WM_PARENTNOTIFY + #define WM_PARENTNOTIFY 0x0210 +#endif + + +namespace Win32xx +{ + + //////////////////////////////////////////////// + // Forward declarations. + // These classes are defined later or elsewhere + class CDC; + class CGDIObject; + class CMenu; + class CWinApp; + class CWnd; + class CBitmap; + class CBrush; + class CFont; + class CPalette; + class CPen; + class CRgn; + + // tString is a TCHAR std::string + typedef std::basic_string tString; + + // tStringStream is a TCHAR std::stringstream + typedef std::basic_stringstream tStringStream; + + // Some useful smart pointers + typedef Shared_Ptr DCPtr; + typedef Shared_Ptr GDIPtr; + typedef Shared_Ptr MenuPtr; + typedef Shared_Ptr WndPtr; + typedef Shared_Ptr BitmapPtr; + typedef Shared_Ptr BrushPtr; + typedef Shared_Ptr FontPtr; + typedef Shared_Ptr PalettePtr; + typedef Shared_Ptr PenPtr; + typedef Shared_Ptr RgnPtr; + + enum Constants // Defines the maximum size for TCHAR strings + { + MAX_MENU_STRING = 80, + MAX_STRING_SIZE = 255, + }; + + struct CompareHDC // The comparison function object used by CWinApp::m_mapHDC + { + bool operator()(HDC const a, const HDC b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareGDI // The comparison function object used by CWinApp::m_mapGDI + { + bool operator()(HGDIOBJ const a, const HGDIOBJ b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareHMENU // The comparison function object used by CWinApp::m_mapHMENU + { + bool operator()(HMENU const a, const HMENU b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareHWND // The comparison function object used by CWinApp::m_mapHWND + { + bool operator()(HWND const a, const HWND b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct TLSData // Used for Thread Local Storage (TLS) + { + CWnd* pCWnd; // pointer to CWnd object for Window creation + CWnd* pMenuBar; // pointer to CMenuBar object used for the WH_MSGFILTER hook + HHOOK hHook; // WH_MSGFILTER hook for CMenuBar and Modeless Dialogs + + std::vector vTmpDCs; // A vector of temporary CDC pointers + std::vector vTmpGDIs; // A vector of temporary CGDIObject pointers + std::vector vTmpWnds; // A vector of temporary CWnd pointers + TLSData() : pCWnd(0), pMenuBar(0), hHook(0) {} + +#ifndef _WIN32_WCE + std::vector vTmpMenus; // A vector of temporary CMenu pointers +#endif + }; + + + ///////////////////////////////////////// + // Declarations for the CCriticalSection class + // This class is used for thread synchronisation + class CCriticalSection + { + public: + CCriticalSection() { ::InitializeCriticalSection(&m_cs); } + ~CCriticalSection() { ::DeleteCriticalSection(&m_cs); } + + void Lock() { ::EnterCriticalSection(&m_cs); } + void Release() { ::LeaveCriticalSection(&m_cs); } + + private: + CCriticalSection ( const CCriticalSection& ); + CCriticalSection& operator = ( const CCriticalSection& ); + + CRITICAL_SECTION m_cs; + }; + + + //////////////////////////////////////// + // Declaration of the CWinException class + // + // Note: Each function guarantees not to throw an exception + + class CWinException : public std::exception + { + public: + CWinException(LPCTSTR pszText) throw (); + ~CWinException() throw() {} + DWORD GetError() const throw (); + LPCTSTR GetErrorString() const throw (); + const char * what () const throw (); + + private: + DWORD m_Error; + LPCTSTR m_pszText; + TCHAR m_szErrorString[MAX_STRING_SIZE]; + }; + + + /////////////////////////////////// + // Declaration of the CWinApp class + // + class CWinApp + { + // Provide these access to CWinApp's private members: + friend class CDC; + friend class CDialog; + friend class CGDIObject; + friend class CMenu; + friend class CMenuBar; + friend class CPropertyPage; + friend class CPropertySheet; + friend class CTaskDialog; + friend class CWnd; + friend CWinApp* GetApp(); + friend CGDIObject* FromHandle(HGDIOBJ hObject); + friend CBitmap* FromHandle(HBITMAP hBitmap); + friend CBrush* FromHandle(HBRUSH hBrush); + friend CFont* FromHandle(HFONT hFont); + friend CPalette* FromHandle(HPALETTE hPalette); + friend CPen* FromHandle(HPEN hPen); + friend CRgn* FromHandle(HRGN hRgn); + friend CDC* FromHandle(HDC hDC); + friend CWnd* FromHandle(HWND hWnd); +#ifndef _WIN32_WCE + friend CMenu* FromHandle(HMENU hMenu); +#endif + + typedef Shared_Ptr TLSDataPtr; + + public: + CWinApp(); + virtual ~CWinApp(); + + HACCEL GetAccelerators() const { return m_hAccel; } + HINSTANCE GetInstanceHandle() const { return m_hInstance; } + HINSTANCE GetResourceHandle() const { return (m_hResource ? m_hResource : m_hInstance); } + void SetAccelerators(HACCEL hAccel, CWnd* pWndAccel); + void SetResourceHandle(HINSTANCE hResource); + + // These are the functions you might wish to override + virtual BOOL InitInstance(); + virtual int MessageLoop(); + virtual BOOL OnIdle(LONG lCount); + virtual BOOL PreTranslateMessage(MSG Msg); + virtual int Run(); + + private: + CWinApp(const CWinApp&); // Disable copy construction + CWinApp& operator = (const CWinApp&); // Disable assignment operator + CDC* GetCDCFromMap(HDC hDC); + CGDIObject* GetCGDIObjectFromMap(HGDIOBJ hObject); + CMenu* GetCMenuFromMap(HMENU hMenu); + CWnd* GetCWndFromMap(HWND hWnd); + + void AddTmpDC(CDC* pDC); + void AddTmpGDI(CGDIObject* pObject); + CMenu* AddTmpMenu(HMENU hMenu); + CWnd* AddTmpWnd(HWND hWnd); + void CleanupTemps(); + DWORD GetTlsIndex() const {return m_dwTlsIndex;} + void SetCallback(); + TLSData* SetTlsIndex(); + static CWinApp* SetnGetThis(CWinApp* pThis = 0); + + std::map m_mapHDC; // maps device context handles to CDC objects + std::map m_mapGDI; // maps GDI handles to CGDIObjects. + std::map m_mapHMENU; // maps menu handles to CMenu objects + std::map m_mapHWND; // maps window handles to CWnd objects + std::vector m_vTLSData; // vector of TLSData smart pointers, one for each thread + CCriticalSection m_csMapLock; // thread synchronisation for m_mapHWND + CCriticalSection m_csTLSLock; // thread synchronisation for m_vTLSData + CCriticalSection m_csAppStart; // thread synchronisation for application startup + HINSTANCE m_hInstance; // handle to the applications instance + HINSTANCE m_hResource; // handle to the applications resources + DWORD m_dwTlsIndex; // Thread Local Storage index + WNDPROC m_Callback; // callback address of CWnd::StaticWndowProc + HACCEL m_hAccel; // handle to the accelerator table + CWnd* m_pWndAccel; // handle to the window for accelerator keys + + }; + +} + +#include "winutils.h" +#include "cstring.h" + + +namespace Win32xx +{ + //////////////////////////////// + // Declaration of the CWnd class + // + class CWnd + { + friend class CMDIChild; + friend class CDialog; + friend class CPropertyPage; + friend class CTaskDialog; + friend class CWinApp; + + public: + CWnd(); // Constructor + CWnd(HWND hWnd) // Constructor + { + if (hWnd == HWND_TOP || hWnd == HWND_TOPMOST || hWnd == HWND_BOTTOM || hWnd == HWND_NOTOPMOST) + { + m_hWnd = hWnd; + } + else + Attach(hWnd); + } + virtual ~CWnd(); // Destructor + + // These virtual functions can be overridden + virtual BOOL Attach(HWND hWnd); + virtual BOOL AttachDlgItem(UINT nID, CWnd* pParent); + virtual void CenterWindow() const; + virtual HWND Create(CWnd* pParent = NULL); + virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL); + virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL); + virtual void Destroy(); + virtual HWND Detach(); + virtual HICON SetIconLarge(int nIcon); + virtual HICON SetIconSmall(int nIcon); + + // Attributes + HWND GetHwnd() const { return m_hWnd; } + WNDPROC GetPrevWindowProc() const { return m_PrevWindowProc; } + + // Wrappers for Win32 API functions + // These functions aren't virtual, and shouldn't be overridden + CDC* BeginPaint(PAINTSTRUCT& ps) const; + BOOL BringWindowToTop() const; + LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const; + BOOL CheckDlgButton(int nIDButton, UINT uCheck) const; + BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const; + CWnd* ChildWindowFromPoint(POINT pt) const; + BOOL ClientToScreen(POINT& pt) const; + BOOL ClientToScreen(RECT& rc) const; + LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const; + HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const; + HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const; + BOOL DrawMenuBar() const; + BOOL EnableWindow(BOOL bEnable = TRUE) const; + BOOL EndPaint(PAINTSTRUCT& ps) const; + CWnd* GetActiveWindow() const; + CWnd* GetAncestor(UINT gaFlag = 3 /*= GA_ROOTOWNER*/) const; + CWnd* GetCapture() const; + ULONG_PTR GetClassLongPtr(int nIndex) const; + CString GetClassName() const; + CRect GetClientRect() const; + CDC* GetDC() const; + CDC* GetDCEx(HRGN hrgnClip, DWORD flags) const; + CWnd* GetDesktopWindow() const; + CWnd* GetDlgItem(int nIDDlgItem) const; + UINT GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const; + CString GetDlgItemText(int nIDDlgItem) const; + CWnd* GetFocus() const; + CFont* GetFont() const; + HICON GetIcon(BOOL bBigIcon) const; + CWnd* GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const; + CWnd* GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const; + CWnd* GetParent() const; + BOOL GetScrollInfo(int fnBar, SCROLLINFO& si) const; + CRect GetUpdateRect(BOOL bErase) const; + int GetUpdateRgn(CRgn* pRgn, BOOL bErase) const; + CWnd* GetWindow(UINT uCmd) const; + CDC* GetWindowDC() const; + LONG_PTR GetWindowLongPtr(int nIndex) const; + CRect GetWindowRect() const; + CString GetWindowText() const; + int GetWindowTextLength() const; + void Invalidate(BOOL bErase = TRUE) const; + BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) const; + BOOL InvalidateRgn(CRgn* pRgn, BOOL bErase = TRUE) const; + BOOL IsChild(CWnd* pChild) const; + BOOL IsDialogMessage(LPMSG lpMsg) const; + UINT IsDlgButtonChecked(int nIDButton) const; + BOOL IsWindow() const; + BOOL IsWindowEnabled() const; + BOOL IsWindowVisible() const; + BOOL KillTimer(UINT_PTR uIDEvent) const; + int MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const; + void MapWindowPoints(CWnd* pWndTo, POINT& pt) const; + void MapWindowPoints(CWnd* pWndTo, RECT& rc) const; + void MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const; + BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) const; + BOOL MoveWindow(const RECT& rc, BOOL bRepaint = TRUE) const; + BOOL PostMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const; + BOOL PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const; + BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, CRgn* pRgn = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN) const; + int ReleaseDC(CDC* pDC) const; + BOOL ScreenToClient(POINT& Point) const; + BOOL ScreenToClient(RECT& rc) const; + LRESULT SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const; + LRESULT SendMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const; + LRESULT SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const; + BOOL SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const; + CWnd* SetActiveWindow() const; + CWnd* SetCapture() const; + ULONG_PTR SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const; + BOOL SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const; + BOOL SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const; + CWnd* SetFocus() const; + void SetFont(CFont* pFont, BOOL bRedraw = TRUE) const; + BOOL SetForegroundWindow() const; + HICON SetIcon(HICON hIcon, BOOL bBigIcon) const; + CWnd* SetParent(CWnd* pWndParent) const; + BOOL SetRedraw(BOOL bRedraw = TRUE) const; + int SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const; + UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const; + LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const; + BOOL SetWindowPos(const CWnd* pInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const; + BOOL SetWindowPos(const CWnd* pInsertAfter, const RECT& rc, UINT uFlags) const; + int SetWindowRgn(CRgn* pRgn, BOOL bRedraw = TRUE) const; + BOOL SetWindowText(LPCTSTR lpString) const; + HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const; + BOOL ShowWindow(int nCmdShow = SW_SHOWNORMAL) const; + BOOL UpdateWindow() const; + BOOL ValidateRect(LPCRECT prc) const; + BOOL ValidateRgn(CRgn* pRgn) const; + static CWnd* WindowFromPoint(POINT pt); + + #ifndef _WIN32_WCE + BOOL CloseWindow() const; + int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const; + int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const; + BOOL DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const; + BOOL DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const; + BOOL DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const; + BOOL DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const; + BOOL EnableScrollBar(UINT uSBflags, UINT uArrows) const; + CWnd* GetLastActivePopup() const; + CMenu* GetMenu() const; + int GetScrollPos(int nBar) const; + BOOL GetScrollRange(int nBar, int& MinPos, int& MaxPos) const; + CMenu* GetSystemMenu(BOOL bRevert) const; + CWnd* GetTopWindow() const; + BOOL GetWindowPlacement(WINDOWPLACEMENT& pWndpl) const; + BOOL HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const; + BOOL IsIconic() const; + BOOL IsZoomed() const; + BOOL LockWindowUpdate() const; + BOOL OpenIcon() const; + void Print(CDC* pDC, DWORD dwFlags) const; + BOOL SetMenu(CMenu* pMenu) const; + BOOL ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const; + int ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const; + int SetScrollPos(int nBar, int nPos, BOOL bRedraw) const; + BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const; + BOOL SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const; + BOOL ShowOwnedPopups(BOOL fShow) const; + BOOL ShowScrollBar(int nBar, BOOL bShow) const; + BOOL ShowWindowAsync(int nCmdShow) const; + BOOL UnLockWindowUpdate() const; + CWnd* WindowFromDC(CDC* pDC) const; + + #ifndef WIN32_LEAN_AND_MEAN + void DragAcceptFiles(BOOL fAccept) const; + #endif + #endif + + static LRESULT CALLBACK StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + operator HWND() const { return m_hWnd; } + + protected: + // Override these functions as required + virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnCreate(); + virtual void OnDraw(CDC* pDC); + virtual BOOL OnEraseBkgnd(CDC* pDC); + virtual void OnInitialUpdate(); + virtual void OnMenuUpdate(UINT nID); + virtual LRESULT OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam); + virtual void PreCreate(CREATESTRUCT& cs); + virtual void PreRegisterClass(WNDCLASS& wc); + virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam); + + HWND m_hWnd; // handle to this object's window + + private: + CWnd(const CWnd&); // Disable copy construction + CWnd& operator = (const CWnd&); // Disable assignment operator + void AddToMap(); + void Cleanup(); + LRESULT MessageReflect(HWND hwndParent, UINT uMsg, WPARAM wParam, LPARAM lParam); + BOOL RegisterClass(WNDCLASS& wc); + BOOL RemoveFromMap(); + void Subclass(HWND hWnd); + + Shared_Ptr m_pwc; // defines initialisation parameters for PreRegisterClass + Shared_Ptr m_pcs; // defines initialisation parameters for PreCreate and Create + WNDPROC m_PrevWindowProc; // pre-subclassed Window Procedure + BOOL m_IsTmpWnd; // True if this CWnd is a TmpWnd + + }; // class CWnd + + // Special CWnd objects used by SetWindowPos + static const CWnd wndTop(HWND_TOP); + static const CWnd wndTopMost(HWND_TOPMOST); + static const CWnd wndBottom(HWND_BOTTOM); + static const CWnd wndNoTopMost(HWND_NOTOPMOST); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#include "gdi.h" +#include "menu.h" + +namespace Win32xx +{ + + ////////////////////////////////////////// + // Definitions for the CWinException class + // + inline CWinException::CWinException(LPCTSTR pszText) throw () : m_Error(::GetLastError()), m_pszText(pszText) + { + memset(m_szErrorString, 0, MAX_STRING_SIZE * sizeof(TCHAR)); + + if (m_Error != 0) + { + DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + ::FormatMessage(dwFlags, NULL, m_Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), m_szErrorString, MAX_STRING_SIZE-1, NULL); + } + } + + inline DWORD CWinException::GetError() const throw () + { + return m_Error; + } + + inline LPCTSTR CWinException::GetErrorString() const throw () + { + return m_szErrorString; + } + + inline const char * CWinException::what() const throw () + { + // Sends the last error string to the debugger (typically displayed in the IDE's output window). + ::OutputDebugString(m_szErrorString); + return "CWinException thrown"; + } + + + //////////////////////////////////// + // Definitions for the CWinApp class + // + + // To begin Win32++, inherit your application class from this one. + // You must run only one instance of the class inherited from this. + inline CWinApp::CWinApp() : m_Callback(NULL), m_hAccel(0), m_pWndAccel(0) + { + try + { + m_csAppStart.Lock(); + assert( 0 == SetnGetThis() ); // Test if this is the first instance of CWinApp + + m_dwTlsIndex = ::TlsAlloc(); + if (m_dwTlsIndex == TLS_OUT_OF_INDEXES) + { + // We only get here in the unlikely event that all TLS indexes are already allocated by this app + // At least 64 TLS indexes per process are allowed. Win32++ requires only one TLS index. + m_csAppStart.Release(); + throw CWinException(_T("CWinApp::CWinApp Failed to allocate TLS Index")); + } + + SetnGetThis(this); + m_csAppStart.Release(); + + // Set the instance handle + #ifdef _WIN32_WCE + m_hInstance = (HINSTANCE)GetModuleHandle(0); + #else + MEMORY_BASIC_INFORMATION mbi = {0}; + VirtualQuery( (LPCVOID)SetnGetThis, &mbi, sizeof(mbi) ); + assert(mbi.AllocationBase); + m_hInstance = (HINSTANCE)mbi.AllocationBase; + #endif + + m_hResource = m_hInstance; + SetCallback(); + + // Assign the special CWnds used by SetWindowPos + m_csMapLock.Lock(); + m_mapHWND.insert(std::make_pair(HWND_TOP, (CWnd*)&wndTop)); + m_mapHWND.insert(std::make_pair(HWND_TOPMOST, (CWnd*)&wndTopMost)); + m_mapHWND.insert(std::make_pair(HWND_NOTOPMOST, (CWnd*)&wndNoTopMost)); + m_mapHWND.insert(std::make_pair(HWND_BOTTOM, (CWnd*)&wndBottom)); + GetApp()->m_csMapLock.Release(); + } + + catch (const CWinException &e) + { + e.what(); + throw; + } + } + + inline CWinApp::~CWinApp() + { + std::vector::iterator iter; + for (iter = m_vTLSData.begin(); iter < m_vTLSData.end(); ++iter) + { + (*iter)->vTmpDCs.clear(); +#ifndef _WIN32_WCE + (*iter)->vTmpMenus.clear(); +#endif + (*iter)->vTmpWnds.clear(); + } + + // Check that all CWnd windows are destroyed + std::map::iterator m; + for (m = m_mapHWND.begin(); m != m_mapHWND.end(); ++m) + { + HWND hWnd = (*m).first; + if (::IsWindow(hWnd)) + ::DestroyWindow(hWnd); + } + m_mapHWND.clear(); + m_mapGDI.clear(); + m_mapHDC.clear(); + m_mapHMENU.clear(); + + // Do remaining tidy up + if (m_dwTlsIndex != TLS_OUT_OF_INDEXES) + { + ::TlsSetValue(GetTlsIndex(), NULL); + ::TlsFree(m_dwTlsIndex); + } + + SetnGetThis((CWinApp*)-1); + } + + inline void CWinApp::AddTmpDC(CDC* pDC) + { + // The TmpMenus are created by GetSybMenu. + // They are removed by CleanupTemps + assert(pDC); + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpDCs.push_back(pDC); // save pDC as a smart pointer + } + + inline void CWinApp::AddTmpGDI(CGDIObject* pObject) + { + // The temporary CGDIObjects are removed by CleanupTemps + assert(pObject); + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpGDIs.push_back(pObject); // save pObject as a smart pointer + } + +#ifndef _WIN32_WCE + inline CMenu* CWinApp::AddTmpMenu(HMENU hMenu) + { + // The TmpMenus are created by GetSybMenu. + // They are removed by CleanupTemps + assert(::IsMenu(hMenu)); + assert(!GetCMenuFromMap(hMenu)); + + CMenu* pMenu = new CMenu; + pMenu->m_hMenu = hMenu; + m_csMapLock.Lock(); + m_mapHMENU.insert(std::make_pair(hMenu, pMenu)); + m_csMapLock.Release(); + pMenu->m_IsTmpMenu = TRUE; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpMenus.push_back(pMenu); // save pMenu as a smart pointer + return pMenu; + } +#endif + + inline CWnd* CWinApp::AddTmpWnd(HWND hWnd) + { + // TmpWnds are created if required to support functions like CWnd::GetParent. + // They are removed by CleanupTemps + // assert(::IsWindow(hWnd)); + assert(!GetCWndFromMap(hWnd)); + + CWnd* pWnd = new CWnd; + pWnd->m_hWnd = hWnd; + pWnd->AddToMap(); + pWnd->m_IsTmpWnd = TRUE; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpWnds.push_back(pWnd); // save pWnd as a smart pointer + return pWnd; + } + + inline void CWinApp::CleanupTemps() + // Removes all Temporary CWnds and CMenus belonging to this thread + { + // Retrieve the pointer to the TLS Data + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + assert(pTLSData); + + pTLSData->vTmpDCs.clear(); + pTLSData->vTmpGDIs.clear(); + pTLSData->vTmpWnds.clear(); + + + #ifndef _WIN32_WCE + pTLSData->vTmpMenus.clear(); + #endif + } + + inline CDC* CWinApp::GetCDCFromMap(HDC hDC) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CDC pointer mapped to this HDC + CDC* pDC = 0; + m_csMapLock.Lock(); + m = m_mapHDC.find(hDC); + + if (m != m_mapHDC.end()) + pDC = m->second; + + m_csMapLock.Release(); + return pDC; + } + + inline CGDIObject* CWinApp::GetCGDIObjectFromMap(HGDIOBJ hObject) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CGDIObject pointer mapped to this HGDIOBJ + CGDIObject* pObject = 0; + m_csMapLock.Lock(); + m = m_mapGDI.find(hObject); + + if (m != m_mapGDI.end()) + pObject = m->second; + + m_csMapLock.Release(); + return pObject; + } + + inline CMenu* CWinApp::GetCMenuFromMap(HMENU hMenu) + { + std::map::iterator m; + + // Find the CMenu pointer mapped to this HMENU + CMenu* pMenu = 0; + m_csMapLock.Lock(); + m = m_mapHMENU.find(hMenu); + + if (m != m_mapHMENU.end()) + pMenu = m->second; + + m_csMapLock.Release(); + return pMenu; + } + + inline CWnd* CWinApp::GetCWndFromMap(HWND hWnd) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CWnd pointer mapped to this HWND + CWnd* pWnd = 0; + m_csMapLock.Lock(); + m = m_mapHWND.find(hWnd); + + if (m != m_mapHWND.end()) + pWnd = m->second; + + m_csMapLock.Release(); + return pWnd; + } + + inline BOOL CWinApp::InitInstance() + { + // InitInstance contains the initialization code for your application + // You should override this function with the code to run when the application starts. + + // return TRUE to indicate success. FALSE will end the application + return TRUE; + } + + inline int CWinApp::MessageLoop() + { + // This gets any messages queued for the application, and dispatches them. + MSG Msg = {0}; + int status = 1; + LONG lCount = 0; + + while (status != 0) + { + // While idle, perform idle processing until OnIdle returns FALSE + while (!::PeekMessage(&Msg, 0, 0, 0, PM_NOREMOVE) && OnIdle(lCount) == TRUE) + { + ++lCount; + } + + lCount = 0; + + // Now wait until we get a message + if ((status = ::GetMessage(&Msg, NULL, 0, 0)) == -1) + return -1; + + if (!PreTranslateMessage(Msg)) + { + ::TranslateMessage(&Msg); + ::DispatchMessage(&Msg); + } + } + + return LOWORD(Msg.wParam); + } + + inline BOOL CWinApp::OnIdle(LONG lCount) + { + if (lCount == 0) + CleanupTemps(); + + return FALSE; + } + + inline BOOL CWinApp::PreTranslateMessage(MSG Msg) + { + // This functions is called by the MessageLoop. It processes the + // keyboard accelerator keys and calls CWnd::PreTranslateMessage for + // keyboard and mouse events. + + BOOL Processed = FALSE; + + // only pre-translate mouse and keyboard input events + if ((Msg.message >= WM_KEYFIRST && Msg.message <= WM_KEYLAST) || + (Msg.message >= WM_MOUSEFIRST && Msg.message <= WM_MOUSELAST)) + { + // Process keyboard accelerators + if (m_pWndAccel && ::TranslateAccelerator(*m_pWndAccel, m_hAccel, &Msg)) + Processed = TRUE; + else + { + // Search the chain of parents for pretranslated messages. + for (HWND hWnd = Msg.hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) + { + CWnd* pWnd = GetCWndFromMap(hWnd); + if (pWnd) + { + Processed = pWnd->PreTranslateMessage(&Msg); + if(Processed) + break; + } + } + } + } + + return Processed; + } + + inline int CWinApp::Run() + { + // InitInstance runs the App's initialization code + if (InitInstance()) + { + // Dispatch the window messages + return MessageLoop(); + } + else + { + TRACE("InitInstance failed! Terminating program\n"); + ::PostQuitMessage(-1); + return -1; + } + } + + inline void CWinApp::SetAccelerators(HACCEL hAccel, CWnd* pWndAccel) + // nID is the resource ID of the accelerator table + // pWndAccel is the window pointer for translated messages + { + assert (hAccel); + assert (pWndAccel); + + m_pWndAccel = pWndAccel; + m_hAccel = hAccel; + } + + inline void CWinApp::SetCallback() + { + // Registers a temporary window class so we can get the callback + // address of CWnd::StaticWindowProc. + // This technique works for all Window versions, including WinCE. + + WNDCLASS wcDefault = {0}; + + LPCTSTR szClassName = _T("Win32++ Temporary Window Class"); + wcDefault.hInstance = GetInstanceHandle(); + wcDefault.lpfnWndProc = CWnd::StaticWindowProc; + wcDefault.lpszClassName = szClassName; + + ::RegisterClass(&wcDefault); + + // Retrieve the class information + ZeroMemory(&wcDefault, sizeof(wcDefault)); + ::GetClassInfo(GetInstanceHandle(), szClassName, &wcDefault); + + // Save the callback address of CWnd::StaticWindowProc + assert(wcDefault.lpfnWndProc); // Assert fails when running UNICODE build on ANSI OS. + m_Callback = wcDefault.lpfnWndProc; + ::UnregisterClass(szClassName, GetInstanceHandle()); + } + + inline CWinApp* CWinApp::SetnGetThis(CWinApp* pThis /*= 0*/) + { + // This function stores the 'this' pointer in a static variable. + // Once stored, it can be used later to return the 'this' pointer. + // CWinApp's Destructor calls this function with a value of -1. + + static CWinApp* pWinApp = 0; + + if ((CWinApp*)-1 == pThis) + pWinApp = 0; + else if (0 == pWinApp) + pWinApp = pThis; + + return pWinApp; + } + + inline void CWinApp::SetResourceHandle(HINSTANCE hResource) + { + // This function can be used to load a resource dll. + // A resource dll can be used to define resources in different languages. + // To use this function, place code like this in InitInstance + // + // HINSTANCE hResource = LoadLibrary(_T("MyResourceDLL.dll")); + // SetResourceHandle(hResource); + + m_hResource = hResource; + } + + inline TLSData* CWinApp::SetTlsIndex() + { + TLSData* pTLSData = (TLSData*)::TlsGetValue(GetTlsIndex()); + if (NULL == pTLSData) + { + pTLSData = new TLSData; + + m_csTLSLock.Lock(); + m_vTLSData.push_back(pTLSData); // store as a Shared_Ptr + m_csTLSLock.Release(); + + ::TlsSetValue(GetTlsIndex(), pTLSData); + } + + return pTLSData; + } + + + //////////////////////////////////////// + // Definitions for the CWnd class + // + inline CWnd::CWnd() : m_hWnd(NULL), m_PrevWindowProc(NULL), m_IsTmpWnd(FALSE) + { + // Note: m_hWnd is set in CWnd::CreateEx(...) + m_pcs = new CREATESTRUCT; // store the CREATESTRICT in a smart pointer + m_pwc = new WNDCLASS; // store the WNDCLASS in a smart pointer + ::ZeroMemory(m_pcs.get(), sizeof(CREATESTRUCT)); + ::ZeroMemory(m_pwc.get(), sizeof(WNDCLASS)); + } + + inline CWnd::~CWnd() + { + // Destroys the window for this object and cleans up resources. + Destroy(); + } + + inline void CWnd::AddToMap() + // Store the window handle and CWnd pointer in the HWND map + { + assert( GetApp() ); + GetApp()->m_csMapLock.Lock(); + + // assert(::IsWindow(m_hWnd)); + assert(!GetApp()->GetCWndFromMap(m_hWnd)); + + GetApp()->m_mapHWND.insert(std::make_pair(m_hWnd, this)); + GetApp()->m_csMapLock.Release(); + } + + inline BOOL CWnd::Attach(HWND hWnd) + // Subclass an existing window and attach it to a CWnd + { + assert( GetApp() ); + assert(::IsWindow(hWnd)); + + // Ensure this thread has the TLS index set + // Note: Perform the attach from the same thread as the window's message loop + GetApp()->SetTlsIndex(); + + // Cleanup any previous attachment + if (m_PrevWindowProc) + Detach(); + CWnd* pWnd = GetApp()->GetCWndFromMap(hWnd); + if (pWnd) + pWnd->Cleanup(); + + Subclass(hWnd); // Set the window's callback to CWnd::StaticWindowProc + AddToMap(); // Store the CWnd pointer in the HWND map + OnCreate(); + OnInitialUpdate(); + + return TRUE; + } + + inline BOOL CWnd::AttachDlgItem(UINT nID, CWnd* pParent) + // Converts a dialog item to a CWnd object + { + assert(pParent->IsWindow()); + + HWND hWnd = ::GetDlgItem(pParent->GetHwnd(), nID); + return Attach(hWnd); + } + + inline void CWnd::CenterWindow() const + // Centers this window over it's parent + { + + // required for multi-monitor support with Dev-C++ and VC6 + #ifndef _WIN32_WCE + #ifndef MONITOR_DEFAULTTONEAREST + #define MONITOR_DEFAULTTONEAREST 0x00000002 + #endif + #ifndef HMONITOR + DECLARE_HANDLE(HMONITOR); + #endif + #ifndef MONITORINFO + typedef struct tagMONITORINFO + { + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; + } MONITORINFO, *LPMONITORINFO; + #endif // MONITOR_DEFAULTTONEAREST + #endif // _WIN32_WCE + + assert(::IsWindow(m_hWnd)); + + CRect rc = GetWindowRect(); + CRect rcParent; + CRect rcDesktop; + + // Get screen dimensions excluding task bar + ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0); + + // Get the parent window dimensions (parent could be the desktop) + if (GetParent() != NULL) rcParent = GetParent()->GetWindowRect(); + else rcParent = rcDesktop; + + #ifndef _WIN32_WCE + // Import the GetMonitorInfo and MonitorFromWindow functions + HMODULE hUser32 = LoadLibrary(_T("USER32.DLL")); + typedef BOOL (WINAPI* LPGMI)(HMONITOR hMonitor, LPMONITORINFO lpmi); + typedef HMONITOR (WINAPI* LPMFW)(HWND hwnd, DWORD dwFlags); + LPMFW pfnMonitorFromWindow = (LPMFW)::GetProcAddress(hUser32, "MonitorFromWindow"); + #ifdef _UNICODE + LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoW"); + #else + LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoA"); + #endif + + // Take multi-monitor systems into account + if (pfnGetMonitorInfo && pfnMonitorFromWindow) + { + HMONITOR hActiveMonitor = pfnMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi = { sizeof(mi), 0}; + + if(pfnGetMonitorInfo(hActiveMonitor, &mi)) + { + rcDesktop = mi.rcWork; + if (GetParent() == NULL) rcParent = mi.rcWork; + } + } + FreeLibrary(hUser32); + #endif + + // Calculate point to center the dialog over the portion of parent window on this monitor + rcParent.IntersectRect(rcParent, rcDesktop); + int x = rcParent.left + (rcParent.Width() - rc.Width())/2; + int y = rcParent.top + (rcParent.Height() - rc.Height())/2; + + // Keep the dialog wholly on the monitor display + x = (x < rcDesktop.left)? rcDesktop.left : x; + x = (x > rcDesktop.right - rc.Width())? rcDesktop.right - rc.Width() : x; + y = (y < rcDesktop.top) ? rcDesktop.top: y; + y = (y > rcDesktop.bottom - rc.Height())? rcDesktop.bottom - rc.Height() : y; + + SetWindowPos(0, x, y, 0, 0, SWP_NOSIZE); + } + + inline void CWnd::Cleanup() + // Returns the CWnd to its default state + { + if ( GetApp() ) RemoveFromMap(); + m_hWnd = NULL; + m_PrevWindowProc = NULL; + m_IsTmpWnd = FALSE; + } + + inline HWND CWnd::Create(CWnd* pParent /* = NULL */) + // Creates the window. This is the default method of window creation. + { + + // Test if Win32++ has been started + assert( GetApp() ); + + // Set the WNDCLASS parameters + PreRegisterClass(*m_pwc); + if (m_pwc->lpszClassName) + { + RegisterClass(*m_pwc); + m_pcs->lpszClass = m_pwc->lpszClassName; + } + + // Set the CREATESTRUCT parameters + PreCreate(*m_pcs); + + // Set the Window Class Name + if (!m_pcs->lpszClass) + m_pcs->lpszClass = _T("Win32++ Window"); + + // Set Parent + HWND hWndParent = pParent? pParent->GetHwnd() : 0; + if (!hWndParent && m_pcs->hwndParent) + hWndParent = m_pcs->hwndParent; + + // Set the window style + DWORD dwStyle; + DWORD dwOverlappedStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + if (m_pcs->style) + dwStyle = m_pcs->style; + else + dwStyle = WS_VISIBLE | ((hWndParent)? WS_CHILD : dwOverlappedStyle); + + // Set window size and position + int x = (m_pcs->cx || m_pcs->cy)? m_pcs->x : CW_USEDEFAULT; + int cx = (m_pcs->cx || m_pcs->cy)? m_pcs->cx : CW_USEDEFAULT; + int y = (m_pcs->cx || m_pcs->cy)? m_pcs->y : CW_USEDEFAULT; + int cy = (m_pcs->cx || m_pcs->cy)? m_pcs->cy : CW_USEDEFAULT; + + // Create the window +#ifndef _WIN32_WCE + CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y, + cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams); +#else + CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y, + cx, cy, pParent, 0, m_pcs->lpCreateParams); +#endif + + return m_hWnd; + } + + inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/) + // Creates the window by specifying all the window creation parameters + { + int x = rc.left; + int y = rc.top; + int cx = rc.right - rc.left; + int cy = rc.bottom - rc.top; + return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, x, y, cx, cy, pParent, pMenu, lpParam); + } + + inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/) + // Creates the window by specifying all the window creation parameters + { + + assert( GetApp() ); // Test if Win32++ has been started + assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed + + try + { + // Prepare the CWnd if it has been reused + Destroy(); + + // Ensure a window class is registered + std::vector vTChar( MAX_STRING_SIZE+1, _T('\0') ); + TCHAR* ClassName = &vTChar[0]; + if (0 == lpszClassName || 0 == lstrlen(lpszClassName) ) + lstrcpyn (ClassName, _T("Win32++ Window"), MAX_STRING_SIZE); + else + // Create our own local copy of szClassName. + lstrcpyn(ClassName, lpszClassName, MAX_STRING_SIZE); + + WNDCLASS wc = {0}; + wc.lpszClassName = ClassName; + wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + + // Register the window class (if not already registered) + if (!RegisterClass(wc)) + throw CWinException(_T("Failed to register window class")); + + HWND hWndParent = pParent? pParent->GetHwnd() : 0; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + + // Store the CWnd pointer in thread local storage + pTLSData->pCWnd = this; + + // Create window +#ifdef _WIN32_WCE + m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, + hWndParent, 0, GetApp()->GetInstanceHandle(), lpParam); +#else + HMENU hMenu = pMenu? pMenu->GetHandle() : NULL; + m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, + hWndParent, hMenu, GetApp()->GetInstanceHandle(), lpParam); +#endif + + // Now handle window creation failure + if (!m_hWnd) + throw CWinException(_T("Failed to Create Window")); + + // Automatically subclass predefined window class types + ::GetClassInfo(GetApp()->GetInstanceHandle(), lpszClassName, &wc); + if (wc.lpfnWndProc != GetApp()->m_Callback) + { + Subclass(m_hWnd); + + // Send a message to force the HWND to be added to the map + SendMessage(WM_NULL, 0L, 0L); + + OnCreate(); // We missed the WM_CREATE message, so call OnCreate now + } + + // Clear the CWnd pointer from TLS + pTLSData->pCWnd = NULL; + } + + catch (const CWinException &e) + { + TRACE("\n*** Failed to create window ***\n"); + e.what(); // Display the last error message. + + // eat the exception (don't rethrow) + } + + // Window creation is complete. Now call OnInitialUpdate + OnInitialUpdate(); + + return m_hWnd; + } + + inline void CWnd::Destroy() + // Destroys the window and returns the CWnd back to its default state, ready for reuse. + { + if (m_IsTmpWnd) + m_hWnd = NULL; + + if (IsWindow()) + ::DestroyWindow(m_hWnd); + + // Return the CWnd to its default state + Cleanup(); + } + + inline HWND CWnd::Detach() + // Reverse an Attach + { + assert(::IsWindow(m_hWnd)); + assert(0 != m_PrevWindowProc); // Only a subclassed window can be detached + + SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)m_PrevWindowProc); + HWND hWnd = m_hWnd; + Cleanup(); + + return hWnd; + } + + inline LRESULT CWnd::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + // Pass messages on to the appropriate default window procedure + // CMDIChild and CMDIFrame override this function + { + return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); + } + + inline CWnd* CWnd::GetAncestor(UINT gaFlags /*= GA_ROOTOWNER*/) const + // The GetAncestor function retrieves a pointer to the ancestor (root parent) + // of the window. Supports Win95. + { + assert(::IsWindow(m_hWnd)); + HWND hWnd = m_hWnd; + + // Load the User32 DLL + typedef HWND WINAPI GETANCESTOR(HWND, UINT); + GETANCESTOR* pfnGetAncestor = NULL; + HMODULE hModule = ::LoadLibrary(_T("USER32.DLL")); + + if (hModule) + { + // Declare a pointer to the GetAncestor function +#ifndef _WIN32_WCE + pfnGetAncestor = (GETANCESTOR*)::GetProcAddress(hModule, "GetAncestor"); +#else + pfnGetAncestor = (GETANCESTOR*)::GetProcAddress(hModule, L"GetAncestor"); +#endif + + if (pfnGetAncestor) + hWnd = (*pfnGetAncestor)(m_hWnd, gaFlags); + + ::FreeLibrary(hModule); + } + + if (!pfnGetAncestor) + { + // Provide our own GetAncestor if necessary + HWND hWndParent = ::GetParent(hWnd); + while (::IsChild(hWndParent, hWnd)) + { + hWnd = hWndParent; + hWndParent = ::GetParent(hWnd); + } + } + + return FromHandle(hWnd); + } + + inline CString CWnd::GetClassName() const + // Retrieves the name of the class to which the specified window belongs. + { + assert(::IsWindow(m_hWnd)); + + CString str; + LPTSTR szStr = str.GetBuffer(MAX_STRING_SIZE+1); + ::GetClassName(m_hWnd, szStr, MAX_STRING_SIZE+1); + str.ReleaseBuffer(); + return str; + } + + inline CString CWnd::GetDlgItemText(int nIDDlgItem) const + // Retrieves the title or text associated with a control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + + int nLength = ::GetWindowTextLength(::GetDlgItem(m_hWnd, nIDDlgItem)); + CString str; + LPTSTR szStr = str.GetBuffer(nLength+1); + ::GetDlgItemText(m_hWnd, nIDDlgItem, szStr, nLength+1); + str.ReleaseBuffer(); + return str; + } + + inline CString CWnd::GetWindowText() const + // Retrieves the text of the window's title bar. + { + assert(::IsWindow(m_hWnd)); + + int nLength = ::GetWindowTextLength(m_hWnd); + CString str; + LPTSTR szStr = str.GetBuffer(nLength+1); + ::GetWindowText(m_hWnd, szStr, nLength+1); + str.ReleaseBuffer(); + return str; + } + + inline BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // Override this to handle WM_COMMAND messages, for example + + // switch (LOWORD(wParam)) + // { + // case IDM_FILE_NEW: + // OnFileNew(); + // TRUE; // return TRUE for handled commands + // } + + // return FALSE for unhandled commands + return FALSE; + } + + inline void CWnd::OnCreate() + { + // This function is called when a WM_CREATE message is recieved + // Override it in your derived class to automatically perform tasks + // during window creation. + } + + inline void CWnd::OnDraw(CDC* pDC) + // Called when part of the client area of the window needs to be drawn + { + UNREFERENCED_PARAMETER(pDC); + + // Override this function in your derived class to perform drawing tasks. + } + + inline BOOL CWnd::OnEraseBkgnd(CDC* pDC) + // Called when the background of the window's client area needs to be erased. + { + UNREFERENCED_PARAMETER(pDC); + + // Override this function in your derived class to perform drawing tasks. + + // Return Value: Return FALSE to also permit default erasure of the background + // Return TRUE to prevent default erasure of the background + + return FALSE; + } + + + inline void CWnd::OnInitialUpdate() + { + // This function is called automatically once the window is created + // Override it in your derived class to automatically perform tasks + // after window creation. + } + + inline LRESULT CWnd::MessageReflect(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + // A function used to call OnMessageReflect. You shouldn't need to call or + // override this function. + + HWND hWnd = NULL; + switch (uMsg) + { + case WM_COMMAND: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORDLG: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: + case WM_CHARTOITEM: + case WM_VKEYTOITEM: + case WM_HSCROLL: + case WM_VSCROLL: + hWnd = (HWND)lParam; + break; + + case WM_DRAWITEM: + case WM_MEASUREITEM: + case WM_DELETEITEM: + case WM_COMPAREITEM: + hWnd = ::GetDlgItem(hWndParent, (int)wParam); + break; + + case WM_PARENTNOTIFY: + switch(LOWORD(wParam)) + { + case WM_CREATE: + case WM_DESTROY: + hWnd = (HWND)lParam; + break; + } + } + + CWnd* Wnd = GetApp()->GetCWndFromMap(hWnd); + + if (Wnd != NULL) + return Wnd->OnMessageReflect(uMsg, wParam, lParam); + + return 0L; + } + + inline LRESULT CWnd::OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + // This function processes those special messages (see above) sent + // by some older controls, and reflects them back to the originating CWnd object. + // Override this function in your derrived class to handle these special messages. + + // Your overriding function should look like this ... + + // switch (uMsg) + // { + // Handle your reflected messages here + // } + + // return 0L for unhandled messages + return 0L; + } + + inline LRESULT CWnd::OnNotify(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // You can use either OnNotifyReflect or OnNotify to handle notifications + // Override OnNotifyReflect to handle notifications in the CWnd class that + // generated the notification. OR + // Override OnNotify to handle notifications in the PARENT of the CWnd class + // that generated the notification. + + // Your overriding function should look like this ... + + // switch (((LPNMHDR)lParam)->code) + // { + // Handle your notifications from the CHILD window here + // Return the value recommended by the Windows API documentation. + // For many notifications, the return value doesn't matter, but for some it does. + // } + + // return 0L for unhandled notifications + return 0L; + } + + inline LRESULT CWnd::OnNotifyReflect(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // Override OnNotifyReflect to handle notifications in the CWnd class that + // generated the notification. + + // Your overriding function should look like this ... + + // switch (((LPNMHDR)lParam)->code) + // { + // Handle your notifications from this window here + // Return the value recommended by the Windows API documentation. + // } + + // return 0L for unhandled notifications + return 0L; + } + + inline void CWnd::OnMenuUpdate(UINT nID) + // Called when menu items are about to be displayed + { + UNREFERENCED_PARAMETER(nID); + + // Override this function to modify the behaviour of menu items, + // such as adding or removing checkmarks + } + + inline void CWnd::PreCreate(CREATESTRUCT& cs) + // Called by CWnd::Create to set some window parameters + { + // Test if Win32++ has been started + assert(GetApp()); // Test if Win32++ has been started + + m_pcs->cx = cs.cx; + m_pcs->cy = cs.cy; + m_pcs->dwExStyle = cs.dwExStyle; + m_pcs->hInstance = GetApp()->GetInstanceHandle(); + m_pcs->hMenu = cs.hMenu; + m_pcs->hwndParent = cs.hwndParent; + m_pcs->lpCreateParams = cs.lpCreateParams; + m_pcs->lpszClass = cs.lpszClass; + m_pcs->lpszName = cs.lpszName; + m_pcs->style = cs.style; + m_pcs->x = cs.x; + m_pcs->y = cs.y; + + // Overide this function in your derived class to set the + // CREATESTRUCT values prior to window creation. + // The cs.lpszClass parameter should NOT be specified if the + // PreRegisterClass function is used to create a window class. + } + + inline void CWnd::PreRegisterClass(WNDCLASS& wc) + // Called by CWnd::Create to set some window parameters + // Useful for setting the background brush and cursor + { + // Test if Win32++ has been started + assert( GetApp() ); + + m_pwc->style = wc.style; + m_pwc->lpfnWndProc = CWnd::StaticWindowProc; + m_pwc->cbClsExtra = wc.cbClsExtra; + m_pwc->cbWndExtra = wc.cbWndExtra; + m_pwc->hInstance = GetApp()->GetInstanceHandle(); + m_pwc->hIcon = wc.hIcon; + m_pwc->hCursor = wc.hCursor; + m_pwc->hbrBackground = wc.hbrBackground; + m_pwc->lpszMenuName = wc.lpszMenuName; + m_pwc->lpszClassName = wc.lpszClassName; + + // Overide this function in your derived class to set the + // WNDCLASS values prior to window creation. + + // ADDITIONAL NOTES: + // 1) The lpszClassName must be set for this function to take effect. + // 2) The lpfnWndProc is always CWnd::StaticWindowProc. + // 3) No other defaults are set, so the following settings might prove useful + // wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + // wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + // wc.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); + // 4) The styles that can be set here are WNDCLASS styles. These are a different + // set of styles to those set by CREATESTRUCT (used in PreCreate). + // 5) RegisterClassEx is not used because its not supported on WinCE. + // To set a small icon for the window, use SetIconSmall. + } + + inline BOOL CWnd::PreTranslateMessage(MSG* pMsg) + { + UNREFERENCED_PARAMETER(pMsg); + + // Override this function if your class requires input messages to be + // translated before normal processing. Function which translate messages + // include TranslateAccelerator, TranslateMDISysAccel and IsDialogMessage. + // Return TRUE if the message is translated. + + return FALSE; + } + + inline BOOL CWnd::RegisterClass(WNDCLASS& wc) + // A private function used by the PreRegisterClass function to register a + // window class prior to window creation + { + assert( GetApp() ); + assert( (0 != lstrlen(wc.lpszClassName) && ( lstrlen(wc.lpszClassName) <= MAX_STRING_SIZE) ) ); + + // Check to see if this classname is already registered + WNDCLASS wcTest = {0}; + BOOL Done = FALSE; + + if (::GetClassInfo(GetApp()->GetInstanceHandle(), wc.lpszClassName, &wcTest)) + { + wc = wcTest; + Done = TRUE; + } + + if (!Done) + { + // Set defaults + wc.hInstance = GetApp()->GetInstanceHandle(); + wc.lpfnWndProc = CWnd::StaticWindowProc; + + // Register the WNDCLASS structure + if ( !::RegisterClass(&wc) ) + throw CWinException(_T("Failed to register window class")); + + Done = TRUE; + } + + return Done; + } + + inline BOOL CWnd::RemoveFromMap() + { + BOOL Success = FALSE; + + if (GetApp()) + { + + // Allocate an iterator for our HWND map + std::map::iterator m; + + CWinApp* pApp = GetApp(); + if (pApp) + { + // Erase the CWnd pointer entry from the map + pApp->m_csMapLock.Lock(); + for (m = pApp->m_mapHWND.begin(); m != pApp->m_mapHWND.end(); ++m) + { + if (this == m->second) + { + pApp->m_mapHWND.erase(m); + Success = TRUE; + break; + } + } + + pApp->m_csMapLock.Release(); + } + } + + return Success; + } + + inline HICON CWnd::SetIconLarge(int nIcon) + // Sets the large icon associated with the window + { + assert( GetApp() ); + assert(::IsWindow(m_hWnd)); + + HICON hIconLarge = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON, + ::GetSystemMetrics (SM_CXICON), ::GetSystemMetrics (SM_CYICON), 0)); + + if (hIconLarge) + SendMessage (WM_SETICON, WPARAM (ICON_BIG), LPARAM (hIconLarge)); + else + TRACE("**WARNING** SetIconLarge Failed\n"); + + return hIconLarge; + } + + inline HICON CWnd::SetIconSmall(int nIcon) + // Sets the small icon associated with the window + { + assert( GetApp() ); + assert(::IsWindow(m_hWnd)); + + HICON hIconSmall = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON, + ::GetSystemMetrics (SM_CXSMICON), ::GetSystemMetrics (SM_CYSMICON), 0)); + + if (hIconSmall) + SendMessage (WM_SETICON, WPARAM (ICON_SMALL), LPARAM (hIconSmall)); + else + TRACE("**WARNING** SetIconSmall Failed\n"); + + return hIconSmall; + } + + inline LRESULT CALLBACK CWnd::StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + // All CWnd windows direct their messages here. This function redirects the message + // to the CWnd's WndProc function. + { + assert( GetApp() ); + + CWnd* w = GetApp()->GetCWndFromMap(hWnd); + if (0 == w) + { + // The CWnd pointer wasn't found in the map, so add it now + + // Retrieve the pointer to the TLS Data + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + assert(pTLSData); + + // Retrieve pointer to CWnd object from Thread Local Storage TLS + w = pTLSData->pCWnd; + assert(w); // pTLSData->pCWnd is assigned in CreateEx + pTLSData->pCWnd = NULL; + + // Store the CWnd pointer in the HWND map + w->m_hWnd = hWnd; + w->AddToMap(); + } + + return w->WndProc(uMsg, wParam, lParam); + + } // LRESULT CALLBACK StaticWindowProc(...) + + inline void CWnd::Subclass(HWND hWnd) + // A private function used by CreateEx, Attach and AttachDlgItem + { + assert(::IsWindow(hWnd)); + + m_PrevWindowProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CWnd::StaticWindowProc); + m_hWnd = hWnd; + } + + inline LRESULT CWnd::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + // Override this function in your class derrived from CWnd to handle + // window 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 WndProcDefault + return WndProcDefault(uMsg, wParam, lParam); + } + + inline LRESULT CWnd::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam) + // All WndProc functions should pass unhandled window messages to this function + { + LRESULT lr = 0L; + + switch (uMsg) + { + case UWM_CLEANUPTEMPS: + { + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + pTLSData->vTmpWnds.clear(); + } + break; + 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; // Note: Some MDI commands require default processing + case WM_CREATE: + OnCreate(); + break; + // An example of how to end the application when the window closes + // If needed, put this in the class you inherit from CWnd + // case WM_DESTROY: + // ::PostQuitMessage(0); + // return 0L; + case WM_NOTIFY: + { + // Do Notification reflection if it came from a CWnd object + HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom; + CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom); + + if (lstrcmp(GetClassName(), _T("ReBarWindow32")) != 0) // Skip notification reflection for rebars to avoid double handling + { + 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); + if (lr) return lr; + } + break; + + case WM_PAINT: + { + // Subclassed controls expect to do their own painting. + // CustomDraw or OwnerDraw are normally used to modify the drawing of controls. + if (m_PrevWindowProc) break; + + 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); + } + } + return 0L; + + 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: + { + // if (m_PrevWindowProc) break; // Suppress for subclassed windows + + LRESULT lr = MessageReflect(m_hWnd, uMsg, wParam, lParam); + if (lr) return lr; // Message processed so return + } + break; // Do default processing when message not already processed + + case UWM_UPDATE_COMMAND: + OnMenuUpdate((UINT)wParam); // Perform menu updates + break; + + } // switch (uMsg) + + // Now hand all messages to the default procedure + if (m_PrevWindowProc) + return ::CallWindowProc(m_PrevWindowProc, m_hWnd, uMsg, wParam, lParam); + else + return FinalWindowProc(uMsg, wParam, lParam); + + } // LRESULT CWnd::WindowProc(...) + + + // + // Wrappers for Win32 API functions + // + + inline CDC* CWnd::BeginPaint(PAINTSTRUCT& ps) const + // The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with + // information about the painting. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::BeginPaint(m_hWnd, &ps)); + } + + inline BOOL CWnd::BringWindowToTop() const + // The BringWindowToTop function brings the specified window to the top + // of the Z order. If the window is a top-level window, it is activated. + { + assert(::IsWindow(m_hWnd)); + return ::BringWindowToTop(m_hWnd); + } + + inline LRESULT CWnd::CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const + { + assert(::IsWindow(m_hWnd)); + return ::CallWindowProc(lpPrevWndFunc, m_hWnd, Msg, wParam, lParam); + } + + inline BOOL CWnd::CheckDlgButton(int nIDButton, UINT uCheck) const + // The CheckDlgButton function changes the check state of a button control. + { + assert(::IsWindow(m_hWnd)); + return ::CheckDlgButton(m_hWnd, nIDButton, uCheck); + } + + inline BOOL CWnd::CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const + // The CheckRadioButton function adds a check mark to (checks) a specified radio button in a group + // and removes a check mark from (clears) all other radio buttons in the group. + { + assert(::IsWindow(m_hWnd)); + return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); + } + + inline CWnd* CWnd::ChildWindowFromPoint(POINT pt) const + // determines which, if any, of the child windows belonging to a parent window contains + // the specified point. The search is restricted to immediate child windows. + // Grandchildren, and deeper descendant windows are not searched. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::ChildWindowFromPoint(m_hWnd, pt)); + } + + inline BOOL CWnd::ClientToScreen(POINT& pt) const + // The ClientToScreen function converts the client-area coordinates of a specified point to screen coordinates. + { + assert(::IsWindow(m_hWnd)); + return ::ClientToScreen(m_hWnd, &pt); + } + + inline BOOL CWnd::ClientToScreen(RECT& rc) const + // The ClientToScreen function converts the client-area coordinates of a specified RECT to screen coordinates. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2); + } + + inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const + // The DeferWindowPos function updates the specified multiple-window – position structure for the window. + { + assert(::IsWindow(m_hWnd)); + return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const + // The DeferWindowPos function updates the specified multiple-window – position structure for the window. + { + assert(::IsWindow(m_hWnd)); + return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags); + } + + inline LRESULT CWnd::DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const + // This function provides default processing for any window messages that an application does not process. + { + assert(::IsWindow(m_hWnd)); + return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::DrawMenuBar() const + // The DrawMenuBar function redraws the menu bar of the specified window. If the menu bar changes after + // the system has created the window, this function must be called to draw the changed menu bar. + { + assert(::IsWindow(m_hWnd)); + return ::DrawMenuBar(m_hWnd); + } + + inline BOOL CWnd::EnableWindow(BOOL bEnable /*= TRUE*/) const + // The EnableWindow function enables or disables mouse and + // keyboard input to the window. + { + assert(::IsWindow(m_hWnd)); + return ::EnableWindow(m_hWnd, bEnable); + } + + inline BOOL CWnd::EndPaint(PAINTSTRUCT& ps) const + // The EndPaint function marks the end of painting in the specified window. This function is required for + // each call to the BeginPaint function, but only after painting is complete. + { + assert(::IsWindow(m_hWnd)); + return ::EndPaint(m_hWnd, &ps); + } + + inline CWnd* CWnd::GetActiveWindow() const + // The GetActiveWindow function retrieves a pointer to the active window attached to the calling + // thread's message queue. + { + return FromHandle( ::GetActiveWindow() ); + } + + inline CWnd* CWnd::GetCapture() const + // The GetCapture function retrieves a pointer to the window (if any) that has captured the mouse. + { + return FromHandle( ::GetCapture() ); + } + + inline ULONG_PTR CWnd::GetClassLongPtr(int nIndex) const + // The GetClassLongPtr function retrieves the specified value from the + // WNDCLASSEX structure associated with the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetClassLongPtr(m_hWnd, nIndex); + } + + inline CRect CWnd::GetClientRect() const + // The GetClientRect function retrieves the coordinates of a window's client area. + // The client coordinates specify the upper-left and lower-right corners of the + // client area. Because client coordinates are relative to the upper-left corner + // of a window's client area, the coordinates of the upper-left corner are (0,0). + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetClientRect(m_hWnd, &rc); + return rc; + } + + inline CDC* CWnd::GetDC() const + // The GetDC function retrieves a handle to a display device context (DC) for the + // client area of the window. + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetDC(m_hWnd), m_hWnd); + } + + inline CDC* CWnd::GetDCEx(HRGN hrgnClip, DWORD flags) const + // The GetDCEx function retrieves a handle to a display device context (DC) for the + // client area or entire area of a window + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetDCEx(m_hWnd, hrgnClip, flags), m_hWnd); + } + + inline CWnd* CWnd::GetDesktopWindow() const + // The GetDesktopWindow function retrieves a pointer to the desktop window. + { + return FromHandle( ::GetDesktopWindow() ); + } + + inline CWnd* CWnd::GetDlgItem(int nIDDlgItem) const + // The GetDlgItem function retrieves a handle to a control in the dialog box. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetDlgItem(m_hWnd, nIDDlgItem) ); + } + + inline UINT CWnd::GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const + // The GetDlgItemInt function translates the text of a specified control in a dialog box into an integer value. + { + assert(::IsWindow(m_hWnd)); + return ::GetDlgItemInt(m_hWnd, nIDDlgItem, lpTranslated, bSigned); + } + + inline CWnd* CWnd::GetFocus() const + // The GetFocus function retrieves a pointer to the window that has the keyboard focus, if the window + // is attached to the calling thread's message queue. + { + return FromHandle( ::GetFocus() ); + } + + inline CFont* CWnd::GetFont() const + // Retrieves the font with which the window is currently drawing its text. + { + assert(::IsWindow(m_hWnd)); + return FromHandle((HFONT)SendMessage(WM_GETFONT, 0, 0)); + } + + inline HICON CWnd::GetIcon(BOOL bBigIcon) const + // Retrieves a handle to the large or small icon associated with a window. + { + assert(::IsWindow(m_hWnd)); + return (HICON)SendMessage(WM_GETICON, (WPARAM)bBigIcon, 0); + } + + inline CWnd* CWnd::GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const + // The GetNextDlgGroupItem function retrieves a pointer to the first control in a group of controls that + // precedes (or follows) the specified control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + assert(pCtl); + return FromHandle(::GetNextDlgGroupItem(m_hWnd, pCtl->GetHwnd(), bPrevious)); + } + + inline CWnd* CWnd::GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const + // The GetNextDlgTabItem function retrieves a pointer to the first control that has the WS_TABSTOP style + // that precedes (or follows) the specified control. + { + assert(::IsWindow(m_hWnd)); + assert(pCtl); + return FromHandle(::GetNextDlgTabItem(m_hWnd, pCtl->GetHwnd(), bPrevious)); + } + + inline CWnd* CWnd::GetParent() const + // The GetParent function retrieves a pointer to the specified window's parent or owner. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetParent(m_hWnd) ); + } + + inline LONG_PTR CWnd::GetWindowLongPtr(int nIndex) const + // The GetWindowLongPtr function retrieves information about the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowLongPtr(m_hWnd, nIndex); + } + + inline BOOL CWnd::GetScrollInfo(int fnBar, SCROLLINFO& si) const + // The GetScrollInfo function 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(m_hWnd)); + return ::GetScrollInfo(m_hWnd, fnBar, &si); + } + + inline CRect CWnd::GetUpdateRect(BOOL bErase) const + // The GetUpdateRect function retrieves the coordinates of the smallest rectangle that completely + // encloses the update region of the specified window. + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetUpdateRect(m_hWnd, &rc, bErase); + return rc; + } + + inline int CWnd::GetUpdateRgn(CRgn* pRgn, BOOL bErase) const + // The GetUpdateRgn function retrieves the update region of a window by copying it into the specified region. + { + assert(::IsWindow(m_hWnd)); + assert(pRgn); + HRGN hRgn = (HRGN)pRgn->GetHandle(); + return ::GetUpdateRgn(m_hWnd, hRgn, bErase); + } + + inline CWnd* CWnd::GetWindow(UINT uCmd) const + // The GetWindow function retrieves a pointer to a window that has the specified + // relationship (Z-Order or owner) to the specified window. + // Possible uCmd values: GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST, + // GW_HWNDNEXT, GW_HWNDPREV, GW_OWNER + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetWindow(m_hWnd, uCmd) ); + } + + inline CDC* CWnd::GetWindowDC() const + // The GetWindowDC function retrieves the device context (DC) for the entire + // window, including title bar, menus, and scroll bars. + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetWindowDC(m_hWnd), m_hWnd); + } + + inline CRect CWnd::GetWindowRect() const + // retrieves the dimensions of the bounding rectangle of the window. + // The dimensions are given in screen coordinates that are relative to the + // upper-left corner of the screen. + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetWindowRect(m_hWnd, &rc); + return rc; + } + + inline int CWnd::GetWindowTextLength() const + // The GetWindowTextLength function retrieves the length, in characters, of the specified window's + // title bar text (if the window has a title bar). + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowTextLength(m_hWnd); + } + + inline void CWnd::Invalidate(BOOL bErase /*= TRUE*/) const + // The Invalidate function adds the entire client area the window's update region. + // The update region represents the portion of the window's client area that must be redrawn. + { + assert(::IsWindow(m_hWnd)); + ::InvalidateRect(m_hWnd, NULL, bErase); + } + + inline BOOL CWnd::InvalidateRect(LPCRECT lpRect, BOOL bErase /*= TRUE*/) const + // The InvalidateRect function adds a rectangle to the window's update region. + // The update region represents the portion of the window's client area that must be redrawn. + { + assert(::IsWindow(m_hWnd)); + return ::InvalidateRect(m_hWnd, lpRect, bErase); + } + + inline BOOL CWnd::InvalidateRgn(CRgn* pRgn, BOOL bErase /*= TRUE*/) const + // The InvalidateRgn function invalidates the client area within the specified region + // by adding it to the current update region of a window. The invalidated region, + // along with all other areas in the update region, is marked for painting when the + // next WM_PAINT message occurs. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::InvalidateRgn(m_hWnd, hRgn, bErase); + } + + inline BOOL CWnd::IsChild(CWnd* pChild) const + // The IsChild function tests whether a window is a child window or descendant window + // of a parent window's CWnd. + { + assert(::IsWindow(m_hWnd)); + return ::IsChild(m_hWnd, pChild->GetHwnd()); + } + + inline BOOL CWnd::IsDialogMessage(LPMSG lpMsg) const + // The IsDialogMessage function determines whether a message is intended for the specified dialog box and, + // if it is, processes the message. + { + assert(::IsWindow(m_hWnd)); + return ::IsDialogMessage(m_hWnd, lpMsg); + } + + inline UINT CWnd::IsDlgButtonChecked(int nIDButton) const + // The IsDlgButtonChecked function determines whether a button control has a check mark next to it + // or whether a three-state button control is grayed, checked, or neither. + { + assert(::IsWindow(m_hWnd)); + return ::IsDlgButtonChecked(m_hWnd, nIDButton); + } + + inline BOOL CWnd::IsWindowEnabled() const + // The IsWindowEnabled function determines whether the window is enabled + // for mouse and keyboard input. + { + assert(::IsWindow(m_hWnd)); + return ::IsWindowEnabled(m_hWnd); + } + + inline BOOL CWnd::IsWindowVisible() const + // The IsWindowVisible function retrieves the visibility state of the window. + { + assert(::IsWindow(m_hWnd)); + return ::IsWindowVisible(m_hWnd); + } + + inline BOOL CWnd::IsWindow() const + // The IsWindow function determines whether the window exists. + { + return ::IsWindow(m_hWnd); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, POINT& pt) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if(pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), &pt, 1); + } + else + ::MapWindowPoints(m_hWnd, NULL, &pt, 1); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, RECT& rc) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if(pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)&rc, 2); + } + else + ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if (pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)ptArray, nCount); + } + else + ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)ptArray, nCount); + } + + inline int CWnd::MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const + // The MessageBox function creates, displays, and operates a message box. + // Possible combinations of uType values include: MB_OK, MB_HELP, MB_OKCANCEL, MB_RETRYCANCEL, + // MB_YESNO, MB_YESNOCANCEL, MB_ICONEXCLAMATION, MB_ICONWARNING, MB_ICONERROR (+ many others). + { + assert(::IsWindow(m_hWnd)); + return ::MessageBox(m_hWnd, lpText, lpCaption, uType); + } + + inline BOOL CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint /* = TRUE*/) const + // The MoveWindow function changes the position and dimensions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint = TRUE); + } + + inline BOOL CWnd::MoveWindow(const RECT& rc, BOOL bRepaint /* = TRUE*/) const + // The MoveWindow function changes the position and dimensions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, bRepaint); + } + + inline BOOL CWnd::PostMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const + // The PostMessage function places (posts) a message in the message queue + // associated with the thread that created the window and returns without + // waiting for the thread to process the message. + { + assert(::IsWindow(m_hWnd)); + return ::PostMessage(m_hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const + // Required by by some macros + { + assert(::IsWindow(m_hWnd)); + return ::PostMessage(hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::RedrawWindow(LPCRECT lpRectUpdate, CRgn* pRgn, UINT flags) const + // The RedrawWindow function updates the specified rectangle or region in a window's client area. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgn, flags); + } + + inline int CWnd::ReleaseDC(CDC* pDC) const + // The ReleaseDC function releases a device context (DC), freeing it for use + // by other applications. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + return ::ReleaseDC(m_hWnd, pDC->GetHDC()); + } + + inline BOOL CWnd::ScreenToClient(POINT& Point) const + // The ScreenToClient function converts the screen coordinates of a specified point on the screen to client-area coordinates. + { + assert(::IsWindow(m_hWnd)); + return ::ScreenToClient(m_hWnd, &Point); + } + + inline BOOL CWnd::ScreenToClient(RECT& rc) const + // The ScreenToClient function converts the screen coordinates of a specified RECT on the screen to client-area coordinates. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rc, 2); + } + + inline LRESULT CWnd::SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const + // The SendDlgItemMessage function sends a message to the specified control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + return ::SendDlgItemMessage(m_hWnd, nIDDlgItem, Msg, wParam, lParam); + } + + inline LRESULT CWnd::SendMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const + // The SendMessage function sends the specified message to a window or windows. + // It calls the window procedure for the window and does not return until the + // window procedure has processed the message. + { + assert(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, uMsg, wParam, lParam); + } + + inline LRESULT CWnd::SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const + // Required by by some macros + { + assert(::IsWindow(m_hWnd)); + return ::SendMessage(hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const + // The SendNotifyMessage function sends the specified message to a window or windows. If the window was created by the + // calling thread, SendNotifyMessage calls the window procedure for the window and does not return until the window procedure + // has processed the message. If the window was created by a different thread, SendNotifyMessage passes the message to the + // window procedure and returns immediately; it does not wait for the window procedure to finish processing the message. + { + assert(::IsWindow(m_hWnd)); + return ::SendNotifyMessage(m_hWnd, Msg, wParam, lParam); + } + + inline CWnd* CWnd::SetActiveWindow() const + // The SetActiveWindow function activates the window, but + // not if the application is in the background. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetActiveWindow(m_hWnd) ); + } + + inline CWnd* CWnd::SetCapture() const + // The SetCapture function sets the mouse capture to the window. + // SetCapture captures mouse input either when the mouse is over the capturing + // window, or when the mouse button was pressed while the mouse was over the + // capturing window and the button is still down. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetCapture(m_hWnd) ); + } + + inline ULONG_PTR CWnd::SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const + // The SetClassLongPtr function replaces the specified value at the specified offset in the + // extra class memory or the WNDCLASSEX structure for the class to which the window belongs. + { + assert(::IsWindow(m_hWnd)); + return ::SetClassLongPtr(m_hWnd, nIndex, dwNewLong); + } + + inline CWnd* CWnd::SetFocus() const + // The SetFocus function sets the keyboard focus to the window. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetFocus(m_hWnd) ); + } + + inline void CWnd::SetFont(CFont* pFont, BOOL bRedraw /* = TRUE*/) const + // Specifies the font that the window will use when drawing text. + { + assert(::IsWindow(m_hWnd)); + assert(pFont); + SendMessage(WM_SETFONT, (WPARAM)pFont->GetHandle(), (LPARAM)bRedraw); + } + + inline HICON CWnd::SetIcon(HICON hIcon, BOOL bBigIcon) const + // Associates a new large or small icon with a window. + { + assert(::IsWindow(m_hWnd)); + return (HICON)SendMessage(WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon); + } + + inline BOOL CWnd::SetForegroundWindow() const + // The SetForegroundWindow function puts the thread that created the window into the + // foreground and activates the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetForegroundWindow(m_hWnd); + } + + inline CWnd* CWnd::SetParent(CWnd* pWndParent) const + // The SetParent function changes the parent window of the child window. + { + assert(::IsWindow(m_hWnd)); + if (pWndParent) + { + HWND hParent = pWndParent->GetHwnd(); + return FromHandle(::SetParent(m_hWnd, hParent)); + } + else + return FromHandle(::SetParent(m_hWnd, 0)); + } + + inline BOOL CWnd::SetRedraw(BOOL bRedraw /*= TRUE*/) const + // This function allows changes in that window to be redrawn or prevents changes + // in that window from being redrawn. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0L); + } + + inline LONG_PTR CWnd::SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const + // The SetWindowLongPtr function changes an attribute of the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong); + } + + inline BOOL CWnd::SetWindowPos(const CWnd* pInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The pInsertAfter can one of: &wndTop, &wndTopMost, &wndBottom, or &wndNoTopMost + { + assert(::IsWindow(m_hWnd)); + HWND hWndInsertAfter = pInsertAfter? pInsertAfter->GetHwnd() : (HWND)0; + return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + inline BOOL CWnd::SetWindowPos(const CWnd* pInsertAfter, const RECT& rc, UINT uFlags) const + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The pInsertAfter can one of: &wndTop, &wndTopMost, &wndBottom, or &wndNoTopMost + { + assert(::IsWindow(m_hWnd)); + HWND hWndInsertAfter = pInsertAfter? pInsertAfter->GetHwnd() : (HWND)0; + return ::SetWindowPos(m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags); + } + + inline int CWnd::SetWindowRgn(CRgn* pRgn, BOOL bRedraw /*= TRUE*/) const + // The SetWindowRgn function sets the window region of the window. + // The window region determines the area within the window where the system permits drawing. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + int iResult = ::SetWindowRgn(m_hWnd, hRgn, bRedraw); + if (iResult && pRgn) + pRgn->Detach(); // The system owns the region now + return iResult; + } + + inline BOOL CWnd::SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const + // The SetDlgItemInt function sets the text of a control in a dialog box to the string representation of a specified integer value. + { + assert(::IsWindow(m_hWnd)); + return ::SetDlgItemInt(m_hWnd, nIDDlgItem, uValue, bSigned); + } + + inline BOOL CWnd::SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const + // The SetDlgItemText function sets the title or text of a control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + return ::SetDlgItemText(m_hWnd, nIDDlgItem, lpString); + } + + inline UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const + // Creates a timer with the specified time-out value. + { + assert(::IsWindow(m_hWnd)); + return ::SetTimer(m_hWnd, nIDEvent, uElapse, lpTimerFunc); + } + + inline BOOL CWnd::SetWindowText(LPCTSTR lpString) const + // The SetWindowText function changes the text of the window's title bar (if it has one). + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowText(m_hWnd, lpString); + } + + inline HRESULT CWnd::SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const + // Set the XP Theme for a window. + // Exampes: + // SetWindowTheme(NULL, NULL); // Reverts the window's XP theme back to default + // SetWindowTheme(L" ", L" "); // Disables XP theme for the window + { + HRESULT hr = E_NOTIMPL; + +#ifndef _WIN32_WCE + + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + typedef HRESULT (__stdcall *PFNSETWINDOWTHEME)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + PFNSETWINDOWTHEME pfn = (PFNSETWINDOWTHEME)GetProcAddress(hMod, "SetWindowTheme"); + + hr = (*pfn)(m_hWnd, pszSubAppName, pszSubIdList); + + ::FreeLibrary(hMod); + } + +#endif + + return hr; + } + + inline BOOL CWnd::ShowWindow(int nCmdShow /*= SW_SHOWNORMAL*/) const + // The ShowWindow function sets the window's show state. + { + assert(::IsWindow(m_hWnd)); + return ::ShowWindow(m_hWnd, nCmdShow); + } + + inline BOOL CWnd::UpdateWindow() const + // The UpdateWindow function updates the client area of the window by sending a + // WM_PAINT message to the window if the window's update region is not empty. + // If the update region is empty, no message is sent. + { + assert(::IsWindow(m_hWnd)); + return ::UpdateWindow(m_hWnd); + } + + inline BOOL CWnd::ValidateRect(LPCRECT prc) const + // The ValidateRect function validates the client area within a rectangle by + // removing the rectangle from the update region of the window. + { + assert(::IsWindow(m_hWnd)); + return ::ValidateRect(m_hWnd, prc); + } + + inline BOOL CWnd::ValidateRgn(CRgn* pRgn) const + // The ValidateRgn function validates the client area within a region by + // removing the region from the current update region of the window. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::ValidateRgn(m_hWnd, hRgn); + } + + inline CWnd* CWnd::WindowFromPoint(POINT pt) + // Retrieves the window that contains the specified point (in screen coodinates). + { + return FromHandle(::WindowFromPoint(pt)); + } + + // + // These functions aren't supported on WinCE + // + #ifndef _WIN32_WCE + inline BOOL CWnd::CloseWindow() const + // The CloseWindow function minimizes (but does not destroy) the window. + // To destroy a window, an application can use the Destroy function. + { + assert(::IsWindow(m_hWnd)); + return ::CloseWindow(m_hWnd); + } + + inline int CWnd::DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const + // The DlgDirList function replaces the contents of a list box with the names of the subdirectories and files + // in a specified directory. You can filter the list of names by specifying a set of file attributes. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, uFileType); + } + + inline int CWnd::DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const + // The DlgDirListComboBox function replaces the contents of a combo box with the names of the subdirectories + // and files in a specified directory. You can filter the list of names by specifying a set of file attributes. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); + } + + inline BOOL CWnd::DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const + // The DlgDirSelectEx function retrieves the current selection from a single-selection list box. It assumes that the list box + // has been filled by the DlgDirList function and that the selection is a drive letter, filename, or directory name. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); + } + + inline BOOL CWnd::DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const + // The DlgDirSelectComboBoxEx function retrieves the current selection from a combo box filled by using the + // DlgDirListComboBox function. The selection is interpreted as a drive letter, a file, or a directory name. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); + } + + #ifndef WIN32_LEAN_AND_MEAN + inline void CWnd::DragAcceptFiles(BOOL fAccept) const + // Registers whether a window accepts dropped files. + { + assert(::IsWindow(m_hWnd)); + ::DragAcceptFiles(m_hWnd, fAccept); + } + #endif + + inline BOOL CWnd::DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const + // The DrawAnimatedRects function draws a wire-frame rectangle and animates it to indicate the opening of + // an icon or the minimizing or maximizing of a window. + { + assert(::IsWindow(m_hWnd)); + return ::DrawAnimatedRects(m_hWnd, idAni, &rcFrom, &rcTo); + } + + inline BOOL CWnd::DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const + // The DrawCaption function draws a window caption. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + return ::DrawCaption(m_hWnd, pDC->GetHDC(), &rc, uFlags); + } + + inline BOOL CWnd::EnableScrollBar(UINT uSBflags, UINT uArrows) const + // The EnableScrollBar function enables or disables one or both scroll bar arrows. + { + assert(::IsWindow(m_hWnd)); + return ::EnableScrollBar(m_hWnd, uSBflags, uArrows); + } + + inline CWnd* CWnd::GetLastActivePopup() const + // The GetLastActivePopup function determines which pop-up window owned by the specified window was most recently active. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetLastActivePopup(m_hWnd) ); + } + + inline CMenu* CWnd::GetMenu() const + // The GetMenu function retrieves a handle to the menu assigned to the window. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::GetMenu(m_hWnd)); + } + + inline int CWnd::GetScrollPos(int nBar) const + // The GetScrollPos function retrieves the current position of the scroll box + // (thumb) in the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::GetScrollPos(m_hWnd, nBar); + } + + inline BOOL CWnd::GetScrollRange(int nBar, int& MinPos, int& MaxPos) const + // The GetScrollRange function retrieves the current minimum and maximum scroll box + // (thumb) positions for the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::GetScrollRange(m_hWnd, nBar, &MinPos, &MaxPos ); + } + + inline CMenu* CWnd::GetSystemMenu(BOOL bRevert) const + // The GetSystemMenu function allows the application to access the window menu (also known as the system menu + // or the control menu) for copying and modifying. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::GetSystemMenu(m_hWnd, bRevert)); + } + + inline CWnd* CWnd::GetTopWindow() const + // The GetTopWindow function examines the Z order of the child windows associated with the parent window and + // retrieves a handle to the child window at the top of the Z order. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetTopWindow(m_hWnd) ); + } + + inline BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT& wndpl) const + // The GetWindowPlacement function retrieves the show state and the restored, + // minimized, and maximized positions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowPlacement(m_hWnd, &wndpl); + } + + inline BOOL CWnd::HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const + // The HiliteMenuItem function highlights or removes the highlighting from an item in a menu bar. + { + assert(::IsWindow(m_hWnd)); + assert(pMenu); + return ::HiliteMenuItem(m_hWnd, pMenu->GetHandle(), uItemHilite, uHilite); + } + + inline BOOL CWnd::IsIconic() const + // The IsIconic function determines whether the window is minimized (iconic). + { + assert(::IsWindow(m_hWnd)); + return ::IsIconic(m_hWnd); + } + + inline BOOL CWnd::IsZoomed() const + // The IsZoomed function determines whether the window is maximized. + { + assert(::IsWindow(m_hWnd)); + return ::IsZoomed(m_hWnd); + } + + inline BOOL CWnd::KillTimer(UINT_PTR uIDEvent) const + // Destroys the specified timer. + { + assert(::IsWindow(m_hWnd)); + return ::KillTimer(m_hWnd, uIDEvent); + } + + inline BOOL CWnd::LockWindowUpdate() const + // Disables drawing in the window. Only one window can be locked at a time. + // Use UnLockWindowUpdate to re-enable drawing in the window + { + assert(::IsWindow(m_hWnd)); + return ::LockWindowUpdate(m_hWnd); + } + + inline BOOL CWnd::OpenIcon() const + // The OpenIcon function restores a minimized (iconic) window to its previous size and position. + { + assert(::IsWindow(m_hWnd)); + return ::OpenIcon(m_hWnd); + } + + inline void CWnd::Print(CDC* pDC, DWORD dwFlags) const + // Requests that the window draw itself in the specified device context, most commonly in a printer device context. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + SendMessage(m_hWnd, WM_PRINT, (WPARAM)pDC, (LPARAM)dwFlags); + } + + inline BOOL CWnd::ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const + // The ScrollWindow function scrolls the contents of the specified window's client area. + { + assert(::IsWindow(m_hWnd)); + return ::ScrollWindow(m_hWnd, XAmount, YAmount, lprcScroll, lprcClip); + } + + inline int CWnd::ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const + // The ScrollWindow function scrolls the contents of the window's client area. + { + assert(::IsWindow(m_hWnd)); + HRGN hrgnUpdate = prgnUpdate? (HRGN)prgnUpdate->GetHandle() : NULL; + return ::ScrollWindowEx(m_hWnd, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate, flags); + } + + inline BOOL CWnd::SetMenu(CMenu* pMenu) const + // The SetMenu function assigns a menu to the specified window. + // A hMenu of NULL removes the menu. + { + assert(::IsWindow(m_hWnd)); + return ::SetMenu(m_hWnd, pMenu? pMenu->GetHandle() : NULL); + } + + inline int CWnd::SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const + // The SetScrollInfo function sets 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(m_hWnd)); + return ::SetScrollInfo(m_hWnd, fnBar, &si, fRedraw); + } + + inline int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw) const + // The SetScrollPos function sets the position of the scroll box (thumb) in + // the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); + } + + inline BOOL CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const + // The SetScrollRange function sets the minimum and maximum scroll box positions for the scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); + } + + inline BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const + // The SetWindowPlacement function sets the show state and the restored, minimized, + // and maximized positions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowPlacement(m_hWnd, &wndpl); + } + + inline BOOL CWnd::ShowOwnedPopups(BOOL fShow) const + // The ShowOwnedPopups function shows or hides all pop-up windows owned by the specified window. + { + assert(::IsWindow(m_hWnd)); + return ::ShowOwnedPopups(m_hWnd, fShow); + } + + inline BOOL CWnd::ShowScrollBar(int nBar, BOOL bShow) const + // The ShowScrollBar function shows or hides the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::ShowScrollBar(m_hWnd, nBar, bShow); + } + + inline BOOL CWnd::ShowWindowAsync(int nCmdShow) const + // The ShowWindowAsync function sets the show state of a window created by a different thread. + { + assert(::IsWindow(m_hWnd)); + return ::ShowWindowAsync(m_hWnd, nCmdShow); + } + + inline BOOL CWnd::UnLockWindowUpdate() const + // Enables drawing in the window. Only one window can be locked at a time. + // Use LockWindowUpdate to disable drawing in the window + { + assert(::IsWindow(m_hWnd)); + return ::LockWindowUpdate(0); + } + + inline CWnd* CWnd::WindowFromDC(CDC* pDC) const + // The WindowFromDC function returns a handle to the window associated with the specified display device context (DC). + { + assert(pDC); + return FromHandle( ::WindowFromDC(pDC->GetHDC()) ); + } + + + #endif + +}; // namespace Win32xx + + +#endif // _WIN32XX_WINCORE_H_ + Index: include/reactos/libs/win32++/winutils.h =================================================================== --- include/reactos/libs/win32++/winutils.h (revision 0) +++ include/reactos/libs/win32++/winutils.h (working copy) @@ -0,0 +1,658 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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_WINUTILS_H_ +#define _WIN32XX_WINUTILS_H_ + + +// define useful macros from WindowsX.h +#ifndef GET_X_LPARAM + #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#endif +#ifndef GET_Y_LPARAM + #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) +#endif + +// Define our own MIN and MAX macros +// this avoids inconsistencies with Dev-C++ and other compilers, and +// avoids conflicts between typical min/max macros and std::min/std::max +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + + +namespace Win32xx +{ + // Forward declarations + class CPoint; + class CRect; + CWinApp* GetApp(); + + + ///////////////////////////////////////// + // Definition of the CSize class + // This class can be used to replace the SIZE structure + class CSize : public SIZE + { + public: + CSize() { cx = 0; cy = 0; } + CSize(int CX, int CY) { cx = CX; cy = CY; } + CSize(SIZE sz) { cx = sz.cx; cy = sz.cy; } + CSize(POINT pt) { cx = pt.x; cy = pt.y; } + CSize(DWORD dw) { cx = (short)LOWORD(dw); cy = (short)HIWORD(dw); } + void SetSize(int CX, int CY) { cx = CX; cy = CY; } + + // Operators + operator LPSIZE() { return this; } + BOOL operator == (SIZE sz) const { return (cx == sz.cx && cy == sz.cy); } + BOOL operator != (SIZE sz) const { return (cx != sz.cx || cy != sz.cy); } + void operator += (SIZE sz) { cx += sz.cx; cy += sz.cy; } + void operator -= (SIZE sz) { cx -= sz.cx; cy -= sz.cy; } + + // Operators returning CSize + CSize operator - () const { return CSize (-cx, -cy); } + CSize operator + (SIZE sz) const { return CSize (cx + sz.cx, cy + sz.cy); } + CSize operator - (SIZE sz) const { return CSize (cx - sz.cx, cy - sz.cy); } + + // Operators returning CPoint + CPoint operator + (POINT point) const; + CPoint operator - (POINT point) const; + + // Operators returning CRect + CRect operator + (RECT rc) const; + CRect operator - (RECT rc) const; + }; + + + ///////////////////////////////////////// + // Definition of the CPoint class + // This class can be used to replace the POINT structure + class CPoint : public POINT + { + public: + CPoint() { x = 0; y = 0; } + CPoint(int X, int Y) { x = X; y = Y; } + CPoint(POINT pt) { x = pt.x ; y = pt.y; } + CPoint(POINTS pts) { x = pts.x; y = pts.y; } + CPoint(SIZE sz) { x = sz.cx; y = sz.cy; } + CPoint(DWORD dw) { x = (short) LOWORD(dw); y = (short) HIWORD(dw); } + + void Offset(int dx, int dy) { x += dx; y += dy; } + void Offset(POINT pt) { x += pt.x; y += pt.y; } + void Offset(SIZE sz) { x += sz.cx; y += sz.cy; } + void SetPoint(int X, int Y) { x = X; y = Y; } + + // Operators + operator LPPOINT() { return this; } + BOOL operator == (POINT pt) const { return ((x == pt.x) && (y == pt.y)); } + BOOL operator != (POINT pt) const { return ((x != pt.x) || (y != pt.y)); } + void operator += (SIZE sz) { x += sz.cx; y += sz.cy; } + void operator -= (SIZE sz) { x -= sz.cx; y -= sz.cy; } + void operator += (POINT pt) { x += pt.x; y += pt.y; } + void operator -= (POINT pt) { x -= pt.x; y -= pt.y; } + + // Operators returning CPoint + CPoint operator - () const { return CPoint(-x, -y); } + CPoint operator + (SIZE sz) const { return CPoint(x + sz.cx, y + sz.cy); } + CPoint operator - (SIZE sz) const { return CPoint(x - sz.cx, y - sz.cy); } + CPoint operator + (POINT pt) const { return CPoint(x + pt.x, y + pt.y); } + CPoint operator - (POINT pt) const { return CPoint(x - pt.x, y - pt.y); } + + // Operators returning CRect + CRect operator + (RECT rc) const; + CRect operator - (RECT rc) const; + }; + + + ///////////////////////////////////////// + // Definition of the CRect class + // This class can be used to replace the RECT structure. + class CRect : public RECT + { + public: + CRect() { left = top = right = bottom = 0; } + CRect(int l, int t, int r, int b) { left = l; top = t; right = r; bottom = b; } + CRect(RECT rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; } + CRect(POINT pt, SIZE sz) { right = (left = pt.x) + sz.cx; bottom = (top = pt.y) + sz.cy; } + CRect(POINT topLeft, POINT bottomRight) { left = topLeft.x; top = topLeft.y; right = bottomRight.x; bottom = bottomRight.y; } + + BOOL CopyRect(RECT rc) { return ::CopyRect(this, &rc); } + BOOL DeflateRect(int x, int y) { return ::InflateRect(this, -x, -y); } + BOOL DeflateRect(SIZE size) { return ::InflateRect(this, -size.cx, -size.cy); } + BOOL DeflateRect(RECT rc) { return ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); } + BOOL DeflateRect(int l, int t, int r, int b){ return ::InflateRect(this, l - r, t - b); } + BOOL EqualRect(RECT rc) const { return ::EqualRect(&rc, this); } + BOOL InflateRect(int dx, int dy) { return ::InflateRect(this, dx, dy); } + BOOL InflateRect(SIZE sz) { return ::InflateRect(this, sz.cx, sz.cy); } + BOOL InflateRect(RECT rc) { return ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); } + BOOL InflateRect(int l, int t, int r, int b){ return ::InflateRect(this, r - l, b - t); } + BOOL IntersectRect(RECT rc1, RECT rc2) { return ::IntersectRect(this, &rc1, &rc2); } + BOOL IsRectEmpty() const { return ::IsRectEmpty(this);} + BOOL IsRectNull() const { return (left == 0 && right == 0 && top == 0 && bottom == 0); } + CRect MulDiv(int nMult, int nDiv) const { return CRect ((left * nMult) / nDiv, (top * nMult) / nDiv, + (right * nMult) / nDiv, (bottom * nMult) / nDiv); } + void NormalizeRect() { int nTemp; if (left > right) { nTemp = left; left = right; right = nTemp; } + if (top > bottom) { nTemp = top; top = bottom; bottom = nTemp; } } + BOOL OffsetRect(int dx, int dy) { return ::OffsetRect(this, dx, dy); } + BOOL OffsetRect(POINT pt) { return ::OffsetRect(this, pt.x, pt.y); } + BOOL OffsetRect(SIZE size) { return ::OffsetRect(this, size.cx, size.cy); } + BOOL PtInRect(POINT pt) const { return ::PtInRect(this, pt); } + BOOL SetRect(int l, int t, int r, int b) { return ::SetRect(this, l, t, r, b); } + BOOL SetRect(POINT TopLeft, POINT BtmRight) { return ::SetRect(this, TopLeft.x, TopLeft.y, BtmRight.x, BtmRight.y); } + BOOL SetRectEmpty() { return ::SetRectEmpty(this); } + BOOL SubtractRect(RECT rc1, RECT rc2) { return ::SubtractRect(this, &rc1, &rc2); } + BOOL UnionRect(RECT rc1, RECT rc2) { return ::UnionRect(this, &rc1, &rc2); } + + // Reposition rectangle + void MoveToX (int x) { right = Width() + x; left = x; } + void MoveToY (int y) { bottom = Height() + y; top = y; } + void MoveToXY (int x, int y) { MoveToX(x); MoveToY(y); } + void MoveToXY (POINT pt) { MoveToX (pt.x); MoveToY (pt.y); } + + // Attributes + int Height() const { return bottom - top; } + int Width() const { return right - left; } + CSize Size() const { return CSize(Width(), Height()); } + CPoint CenterPoint() const { return CPoint((left + right) / 2, (top + bottom) / 2); } + CPoint TopLeft() const { return CPoint(left, top); } + CPoint BottomRight() const { return CPoint(right, bottom); } + + // operators + operator LPRECT() { return this; } + BOOL operator == (RECT rc) const { return ::EqualRect(this, &rc); } + BOOL operator != (RECT rc) const { return !::EqualRect(this, &rc); } + void operator += (POINT pt) { ::OffsetRect(this, pt.x, pt.y); } + void operator += (SIZE size) { ::OffsetRect(this, size.cx, size.cy); } + void operator += (RECT rc) { ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); } + void operator -= (RECT rc) { ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); } + void operator -= (POINT pt) { ::OffsetRect(this, -pt.x, -pt.y); } + void operator -= (SIZE sz) { ::OffsetRect(this, -sz.cx, -sz.cy); } + void operator &= (RECT rc) { ::IntersectRect(this, this, &rc); } + void operator |= (RECT rc) { ::UnionRect(this, this, &rc); } + + // Operators returning CRect + CRect operator + (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, pt.x, pt.y); return rc; } + CRect operator - (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, -pt.x, -pt.y); return rc; } + CRect operator + (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, sz.cx, sz.cy); return rc; } + CRect operator - (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, -sz.cx, -sz.cy); return rc; } + CRect operator + (RECT rc) const { CRect rc1(*this); rc1.InflateRect(rc); return rc1; } + CRect operator - (RECT rc) const { CRect rc1(*this); rc1.DeflateRect(rc); return rc1; } + CRect operator & (RECT rc) const { CRect rc1; ::IntersectRect(&rc1, this, &rc); return rc1; } + CRect operator | (RECT rc) const { CRect rc1; ::UnionRect(&rc1, this, &rc); return rc1; } + }; + + // CSize member function definitions + inline CPoint CSize::operator + (POINT pt) const { return CPoint(pt) + *this; } + inline CPoint CSize::operator - (POINT pt) const { return CPoint(pt) - *this; } + inline CRect CSize::operator + (RECT rc) const { return CRect(rc) + *this; } + inline CRect CSize::operator - (RECT rc) const { return CRect(rc) - *this; } + + // CPoint member function definitions + inline CRect CPoint::operator + (RECT rc) const { return CRect(rc) + *this; } + inline CRect CPoint::operator - (RECT rc) const { return CRect(rc) - *this; } + + + //////////////////////////////////////////////////////// + // Classes and functions (typedefs) for text conversions + // + // This section defines the following text conversions: + // 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 WCHAR + // W2A WCHAR to ANSI + // W2BSTR WCHAR to BSTR + // W2OLE WCHAR to OLE + // W2T WCHAR to TCHAR + + // About different character and string types: + // ------------------------------------------ + // char (or CHAR) character types are ANSI (8 bits). + // wchar_t (or WCHAR) character types are Unicode (16 bits). + // TCHAR characters are Unicode if the _UNICODE macro is defined, otherwise they are ANSI. + // BSTR (Basic String) is a type of string used in Visual Basic and COM programming. + // OLE is the same as WCHAR. It is used in Visual Basic and COM programming. + + + // Forward declarations of our classes. They are defined later. + class CA2A; + class CA2W; + class CW2A; + class CW2W; + class CA2BSTR; + class CW2BSTR; + + // typedefs for the well known text conversions + typedef CA2W A2W; + typedef CW2A W2A; + typedef CW2BSTR W2BSTR; + typedef CA2BSTR A2BSTR; + typedef CW2A BSTR2A; + typedef CW2W BSTR2W; + +#ifdef _UNICODE + typedef CA2W A2T; + typedef CW2A T2A; + typedef CW2W T2W; + typedef CW2W W2T; + typedef CW2BSTR T2BSTR; + typedef BSTR2W BSTR2T; +#else + typedef CA2A A2T; + typedef CA2A T2A; + typedef CA2W T2W; + typedef CW2A W2T; + typedef CA2BSTR T2BSTR; + typedef BSTR2A BSTR2T; +#endif + + typedef A2W A2OLE; + typedef T2W T2OLE; + typedef CW2W W2OLE; + typedef W2A OLE2A; + typedef W2T OLE2T; + typedef CW2W OLE2W; + + class CA2W + { + public: + CA2W(LPCSTR pStr) : m_pStr(pStr) + { + if (pStr) + { + // Resize the vector and assign null WCHAR to each element + int length = (int)strlen(pStr)+1; + m_vWideArray.assign(length, L'\0'); + + // Fill our vector with the converted WCHAR array + MultiByteToWideChar(CP_ACP, 0, pStr, -1, &m_vWideArray[0], length); + } + } + ~CA2W() {} + operator LPCWSTR() { return m_pStr? &m_vWideArray[0] : NULL; } + operator LPOLESTR() { return m_pStr? (LPOLESTR)&m_vWideArray[0] : (LPOLESTR)NULL; } + + private: + CA2W(const CA2W&); + CA2W& operator= (const CA2W&); + std::vector m_vWideArray; + LPCSTR m_pStr; + }; + + class CW2A + { + public: + CW2A(LPCWSTR pWStr) : m_pWStr(pWStr) + { + // Resize the vector and assign null char to each element + int length = (int)wcslen(pWStr)+1; + m_vAnsiArray.assign(length, '\0'); + + // Fill our vector with the converted char array + WideCharToMultiByte(CP_ACP, 0, pWStr, -1, &m_vAnsiArray[0], length, NULL,NULL); + } + + ~CW2A() {} + operator LPCSTR() { return m_pWStr? &m_vAnsiArray[0] : NULL; } + + private: + CW2A(const CW2A&); + CW2A& operator= (const CW2A&); + std::vector m_vAnsiArray; + LPCWSTR m_pWStr; + }; + + class CW2W + { + public: + CW2W(LPCWSTR pWStr) : m_pWStr(pWStr) {} + operator LPCWSTR() { return (LPWSTR)m_pWStr; } + operator LPOLESTR() { return (LPOLESTR)m_pWStr; } + + private: + CW2W(const CW2W&); + CW2W& operator= (const CW2W&); + + LPCWSTR m_pWStr; + }; + + class CA2A + { + public: + CA2A(LPCSTR pStr) : m_pStr(pStr) {} + operator LPCSTR() { return (LPSTR)m_pStr; } + + private: + CA2A(const CA2A&); + CA2A& operator= (const CA2A&); + + LPCSTR m_pStr; + }; + + class CW2BSTR + { + public: + CW2BSTR(LPCWSTR pWStr) { m_bstrString = ::SysAllocString(pWStr); } + ~CW2BSTR() { ::SysFreeString(m_bstrString); } + operator BSTR() { return m_bstrString;} + + private: + CW2BSTR(const CW2BSTR&); + CW2BSTR& operator= (const CW2BSTR&); + BSTR m_bstrString; + }; + + class CA2BSTR + { + public: + CA2BSTR(LPCSTR pStr) { m_bstrString = ::SysAllocString(A2W(pStr)); } + ~CA2BSTR() { ::SysFreeString(m_bstrString); } + operator BSTR() { return m_bstrString;} + + private: + CA2BSTR(const CA2BSTR&); + CA2BSTR& operator= (const CA2BSTR&); + BSTR m_bstrString; + }; + + + //////////////////////////////////////// + // Global Functions + // + + inline CWnd* FromHandle(HWND hWnd) + // Returns the CWnd object associated with the window handle + { + assert( GetApp() ); + CWnd* pWnd = hWnd? GetApp()->GetCWndFromMap(hWnd) : 0; + if ( hWnd != NULL && pWnd == 0 ) + { + GetApp()->AddTmpWnd(hWnd); + pWnd = GetApp()->GetCWndFromMap(hWnd); + ::PostMessage(hWnd, UWM_CLEANUPTEMPS, 0, 0); + } + + return pWnd; + } + + + inline CWinApp* GetApp() + // Returns a pointer to the CWinApp derrived class + { + return CWinApp::SetnGetThis(); + } + + inline CPoint GetCursorPos() + { + CPoint pt; + ::GetCursorPos(&pt); + return pt; + } + + inline HBITMAP LoadBitmap (LPCTSTR lpszName) + { + assert(GetApp()); + + HBITMAP hBitmap = (HBITMAP)::LoadImage (GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + return hBitmap; + } + + inline HBITMAP LoadBitmap (int nID) + { + return LoadBitmap(MAKEINTRESOURCE(nID)); + } + + + inline void TRACE(LPCSTR str) + // TRACE sends a string to the debug/output pane, or an external debugger + { + #ifdef _DEBUG + OutputDebugString(A2T(str)); + #else + UNREFERENCED_PARAMETER(str); // no-op + #endif + } + + inline void TRACE(LPCWSTR str) + // TRACE sends a string to the debug/output pane, or an external debugger + { + #ifdef _DEBUG + OutputDebugString(W2T(str)); + #else + UNREFERENCED_PARAMETER(str); // no-op + #endif + } + + + #ifndef _WIN32_WCE // for Win32/64 operating systems, not WinCE + + inline int GetWinVersion() + { + DWORD dwVersion = GetVersion(); + int Platform = (dwVersion < 0x80000000)? 2:1; + int MajorVer = LOBYTE(LOWORD(dwVersion)); + int MinorVer = HIBYTE(LOWORD(dwVersion)); + + int nVersion = 1000*Platform + 100*MajorVer + MinorVer; + + // Return values and window versions: + // 1400 Windows 95 + // 1410 Windows 98 + // 1490 Windows ME + // 2400 Windows NT + // 2500 Windows 2000 + // 2501 Windows XP + // 2502 Windows Server 2003 + // 2600 Windows Vista and Windows Server 2008 + // 2601 Windows 7 + + return nVersion; + } + + inline int GetComCtlVersion() + { + // Load the Common Controls DLL + HMODULE hComCtl = ::LoadLibraryA("COMCTL32.DLL"); + if (!hComCtl) + return 0; + + int ComCtlVer = 400; + + if (::GetProcAddress(hComCtl, "InitCommonControlsEx")) + { + // InitCommonControlsEx is unique to 4.7 and later + ComCtlVer = 470; + + if (::GetProcAddress(hComCtl, "DllGetVersion")) + { + typedef HRESULT CALLBACK DLLGETVERSION(DLLVERSIONINFO*); + DLLGETVERSION* pfnDLLGetVersion = NULL; + + pfnDLLGetVersion = (DLLGETVERSION*)::GetProcAddress(hComCtl, "DllGetVersion"); + if(pfnDLLGetVersion) + { + DLLVERSIONINFO dvi; + dvi.cbSize = sizeof dvi; + if(NOERROR == pfnDLLGetVersion(&dvi)) + { + DWORD dwVerMajor = dvi.dwMajorVersion; + DWORD dwVerMinor = dvi.dwMinorVersion; + ComCtlVer = 100 * dwVerMajor + dwVerMinor; + } + } + } + else if (::GetProcAddress(hComCtl, "InitializeFlatSB")) + ComCtlVer = 471; // InitializeFlatSB is unique to version 4.71 + } + + ::FreeLibrary(hComCtl); + + // return values and DLL versions + // 400 dll ver 4.00 Windows 95/Windows NT 4.0 + // 470 dll ver 4.70 Internet Explorer 3.x + // 471 dll ver 4.71 Internet Explorer 4.0 + // 472 dll ver 4.72 Internet Explorer 4.01 and Windows 98 + // 580 dll ver 5.80 Internet Explorer 5 + // 581 dll ver 5.81 Windows 2000 and Windows ME + // 582 dll ver 5.82 Windows XP or Vista without XP themes + // 600 dll ver 6.00 Windows XP with XP themes + // 610 dll ver 6.10 Windows Vista with XP themes + // 616 dll ver 6.16 Windows Vista SP1 or Windows 7 with XP themes + + return ComCtlVer; + } + + inline UINT GetSizeofMenuItemInfo() + { + UINT uSize = sizeof(MENUITEMINFO); + // For Win95 and NT, cbSize needs to be 44 + if (1400 == (GetWinVersion()) || (2400 == GetWinVersion())) + uSize = 44; + + return uSize; + } + + inline UINT GetSizeofNonClientMetrics() + { + // This function correctly determines the sizeof NONCLIENTMETRICS + UINT uSize = sizeof (NONCLIENTMETRICS); + + #if (WINVER >= 0x0600) + if (GetWinVersion() < 2600 && (uSize > 500)) // Is OS version less than Vista + uSize -= sizeof(int); // Adjust size back to correct value + #endif + + return uSize; + } + + + + // A global function to report the state of the left mouse button + inline BOOL IsLeftButtonDown() + { + SHORT state; + if (GetSystemMetrics(SM_SWAPBUTTON)) + // Mouse buttons are swapped + state = GetAsyncKeyState(VK_RBUTTON); + else + // Mouse buttons are not swapped + state = GetAsyncKeyState(VK_LBUTTON); + + // returns true if the left mouse button is down + return (state & 0x8000); + } + + inline BOOL IsAeroThemed() + { + BOOL bIsAeroThemed = FALSE; + + // Test if Windows version is XP or greater + if (GetWinVersion() >= 2501) + { + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + // Declare pointers to IsCompositionActive function + FARPROC pIsCompositionActive = ::GetProcAddress(hMod, "IsCompositionActive"); + + if(pIsCompositionActive) + { + if(pIsCompositionActive()) + { + bIsAeroThemed = TRUE; + } + } + ::FreeLibrary(hMod); + } + } + + return bIsAeroThemed; + } + + inline BOOL IsXPThemed() + { + BOOL bIsXPThemed = FALSE; + + // Test if Windows version is XP or greater + if (GetWinVersion() >= 2501) + { + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + // Declare pointers to functions + FARPROC pIsAppThemed = ::GetProcAddress(hMod, "IsAppThemed"); + FARPROC pIsThemeActive = ::GetProcAddress(hMod, "IsThemeActive"); + + if(pIsAppThemed && pIsThemeActive) + { + if(pIsAppThemed() && pIsThemeActive()) + { + // Test if ComCtl32 dll used is version 6 or later + bIsXPThemed = (GetComCtlVersion() >= 600); + } + } + ::FreeLibrary(hMod); + } + } + + return bIsXPThemed; + } + + #endif // #ifndef _WIN32_WCE + + // Required for WinCE + #ifndef lstrcpyn + inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength) + { + if(NULL == lpstrDest || NULL == lpstrSrc || nLength <= 0) + return NULL; + int nLen = MIN((int)lstrlen(lpstrSrc), nLength - 1); + LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR)); + lpstrDest[nLen] = _T('\0'); + return lpstrRet; + } + #endif // !lstrcpyn + +} + + +#endif // _WIN32XX_WINUTILS_H_ Index: include/reactos/libs/win32++/changes.txt =================================================================== --- include/reactos/libs/win32++/changes.txt (revision 0) +++ include/reactos/libs/win32++/changes.txt (working copy) @@ -0,0 +1,1430 @@ +Version 7.4 +=========== +Bug Fixes +* The dockbar's parent for dock containers was set incorrectly. The wrong + dockbar could be destroyed when a dock container was destroyed. +* Corrected variable initialisation in CMenuMetrics + +New Features and Enhancements +* TRACE now accepts both ANSI and Unicode strings. + + +Version 7.3 +=========== + +New Features and Enhancements +----------------------------- +* Adjusted the frame's appearance + - Updated the visual appearance of popup menus on systems using Windows Aero. On + systems with Aero, popup menus are rendered with Windows Visual Styles. Systems + without Areo continue to use the Win32++ theme for popup menus. + - Frames now honour the current window theme's menu and status fonts. + - the frame's appearence changes dynamically to reflect changes to the window theme. + - minor adjustment to the rebar theme colours for the "Modern" theme. + +* Extended CWebBrowser + The CWebBrower class has been extended to wrap the member functions of + iWebBrowser2. The Browser sample has been updated and now supports + Copy/Paste. + +* Added the following controls + - CDateTime + - CHeader + - CHotKey + - CIPAddress + - CMonthCalendar + - CTooltip + +* CString constructors now accept either ANSI or Unicode characters and converts + these to TCHAR as required. + +* Extended CDC + The CDC::DetachBitmap function has been added. This provides a convenient + way of detaching a bitmap from a memory DC created by CreateCompatibleBitmap. + The various CDC::CreateXXX functions now return void instead of a pointer + to the old GDI object. + + +Changes in detail +----------------- +- Added CDateTime +- Added CHeader +- Added CHotKey +- Added CIPAddress +- Added CMonthCalendar +- Added CTooltip + +- Added wndTop a special CWnd for use with SetWindowPos +- Added wndTopMost a special CWnd for use with SetWindowPos +- Added wndNoTopMost a special CWnd for use with SetWindowPos +- Added wndBottom a special CWnd for use with SetWindowPos + +- Added CDC::DetachBitmap +- Added CFrame::DrawMenuItem +- Added CFrame::DrawMenuItemBkgnd +- Added CFrame::MeasureMenuItem +- Added CGDIObject::DeleteObject +- Added CString::CString(LPCSTR pszText); +- Added CString::CString(LPCWSTR pszText); +- Added CString::operator += (LPCSTR szText) +- Added CString::operator += (LPCWSTR szText) +- Added CReBar::SetToolTips +- Added CWebBrowser::ExecWB +- Added CWebBrowser::GetApplication +- Added CWebBrowser::GetBusy +- Added CWebBrowser::GetContainer +- Added CWebBrowser::GetFullScreen +- Added CWebBrowser::GetHeight +- Added CWebBrowser::GetLeft +- Added CWebBrowser::GetLocationName +- Added CWebBrowser::GetLocationURL +- Added CWebBrowser::GetOffline +- Added CWebBrowser::GetProperty +- Added CWebBrowser::GetReadyState +- Added CWebBrowser::GetRegisterAsBrowser +- Added CWebBrowser::GetTheaterMode +- Added CWebBrowser::GetTop +- Added CWebBrowser::GetTopLevelContainer +- Added CWebBrowser::GetType +- Added CWebBrowser::GetVisible +- Added CWebBrowser::GetWidth +- Added CWebBrowser::GoBack +- Added CWebBrowser::GoForward +- Added CWebBrowser::GoHome +- Added CWebBrowser::GoSearch +- Added CWebBrowser::Navigate2 +- Added CWebBrowser::PutProperty +- Added CWebBrowser::Refresh +- Added CWebBrowser::Refresh2 +- Added CWebBrowser::SetFullScreen +- Added CWebBrowser::SetHeight +- Added CWebBrowser::SetLeft +- Added CWebBrowser::SetOffline +- Added CWebBrowser::SetRegisterAsBrowser +- Added CWebBrowser::SetTheaterMode +- Added CWebBrowser::SetTop +- Added CWebBrowser::SetVisible +- Added CWebBrowser::SetWidth +- Added CWebBrowser::Stop +- Modified CComboBoxEx::GetComboBoxControl now returns CWnd* +- Modified CComboBoxEx::GetEditCtrl now returns CEdit* +- Modified CDC::CreateBitmap now returns void +- Modified CDC::CreateCompatibleBitmap now returns void +- Modified CDC::CreateDIBSection now returns void +- Modified CDC::CreateBitmapIndirect now returns void +- Modified CDC::CreateDIBitmap now returns void +- Modified CDC::CreateMappedBitmap now returns void +- Modified CDC::CreatePatternBrush now returns void +- Modified CDC::CreateSolidBrush now returns void +- Modified CDC::CreateBrushIndirect now returns void +- Modified CDC::CreateHatchBrush now returns void +- Modified CDC::CreateDIBPatternBrush now returns void +- Modified CDC::CreateDIBPatternBrushPt now returns void +- Modified CDC::CreateFontIndirect now returns void +- Modified CDC::CreateFont now returns void +- Modified CDC::CreatePen now returns void +- Modified CDC::CreatePenIndirect now returns void +- Modified CDC::LoadBitmap now returns BOOL +- Modified CDC::LoadImage now returns BOOL +- Modified CDC::LoadOEMBitmap now returns BOOL +- Modified CDocker::GetCaption now returns CString +- Modified CDocker::LoadRegistrySettings now accepts CString +- Modified CDocker::SaveRegistrySettings now accepts CString +- Modified CFrame::GetMRUEntry now returns CString +- Modified CFrame::GetRegistryKeyName now returns CString +- Modified CListView::GetEditCtrl now returns CEdit* +- Modified CListView::GetItemText now returns CString +- Modified CListView::GetHeader now returns CHeader* +- Modified CListView::GetToolTips now returns CToolTip* +- Modified CListView::SetToolTips now accepts CToolTip* +- Modified CListView::EditLabel now returns CEdit* +- Modified CRebar::GetToolTips now returns CToolTip* +- Modified CStatusBar::GetPartText now returns CString +- Modified CToolBar::GetToolTips now returns CToolTip* +- Modified CToolBar::SetToolTips now accepts CToolTip* +- Modified CTreeView::GetEditCtrl now returns CEdit* +- Modified CTreeView::GetToolTips now returns CToolTip* +- Modified CTreeView::SetToolTips now accepts CToolTip* +- Modified CWnd::SetWindowPos now uses CWnd* for first argument +- Removed CString::b_str +- Removed CString(LPCTSTR pszText); +- Removed CString::operator += (LPCTSTR szText); +- Renamed CFrame::DrawCheckmark to DrawMenuCheckmark + + +Incompatibilities with previous versions +---------------------------------------- + + +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 OnDraw. Code that previously + overrode OnPaint will now need to override OnDraw instead. OnDraw 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. + + +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 +=========== +Bug Fixes: +- Fixed TCharToString +- Dockers can now be used as the view for CMDIChild + +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. + + +Other Changes +------------- +Removed CSplitter class + +Added RibbonFrame sample +Added RibbonSimple sample + +Added 'Compile VS2005 Express' tool +Added 'Compile VS2008 Express' tool +Added 'Compile VS2010 Express' tool + + +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. + + +Version 6.3 +=========== + +Major Changes +------------- +* Added support for docking. 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. + + +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. + +* 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. +* 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 Index: include/reactos/libs/win32++/controls.h =================================================================== --- include/reactos/libs/win32++/controls.h (revision 0) +++ include/reactos/libs/win32++/controls.h (working copy) @@ -0,0 +1,2067 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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, CDateTime, CIPAddress, +// CHeader, CHotKey, CMonthCalendar, CProgressBar, CScrollBar, +// CSlider, CSpinButton, and CToolTip. + + +#ifndef _WIN32XX_CONTROLS_H_ +#define _WIN32XX_CONTROLS_H_ + +#include "wincore.h" +#include "stdcontrols.h" + +namespace Win32xx +{ + + // Forward declarations + class CMonthCalendar; + class CToolTip; + + 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() { ::InitCommonControls(); } + + 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 CComboBox + { + public: + CComboBoxEx() + { + INITCOMMONCONTROLSEX icce; + icce.dwSize = sizeof(INITCOMMONCONTROLSEX); + icce.dwICC = ICC_USEREX_CLASSES; + ::InitCommonControlsEx(&icce); + } + virtual ~CComboBoxEx() {} + + int DeleteItem(int nIndex ) const; + CWnd* GetComboBoxCtrl() const; + CEdit* 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 CDateTime : public CWnd + { + public: + CDateTime() + { + INITCOMMONCONTROLSEX icce; + icce.dwSize = sizeof(INITCOMMONCONTROLSEX); + icce.dwICC = ICC_DATE_CLASSES; + ::InitCommonControlsEx(&icce); + } + virtual ~CDateTime() {} + + COLORREF GetMonthCalColor(int iColor) const; + COLORREF SetMonthCalColor(int iColor, COLORREF ref); + BOOL SetFormat(LPCTSTR pstrFormat); + CMonthCalendar* GetMonthCalCtrl() const; + CFont* GetMonthCalFont() const; + void SetMonthCalFont(HFONT hFont, BOOL bRedraw = TRUE); + DWORD GetRange(LPSYSTEMTIME lpSysTimeArray) const; + BOOL SetRange(DWORD flags, LPSYSTEMTIME lpSysTimeArray); + DWORD GetTime(LPSYSTEMTIME pTimeDest) const; + BOOL SetTime(DWORD flag, LPSYSTEMTIME pTimeNew = NULL); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = DATETIMEPICK_CLASS; } + }; + + class CHeader : public CWnd + { + public: + CHeader() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_WIN95_CLASSES; + ::InitCommonControlsEx(&icex); + } + virtual ~CHeader() {} + + // Attributes + HIMAGELIST GetImageList() const; + BOOL GetItem(int nPos, HDITEM* pHeaderItem) const; + int GetItemCount() const; + CRect GetItemRect(int nIndex) const; + BOOL GetOrderArray(LPINT piArray, int iCount); + int OrderToIndex(int nOrder) const; + HIMAGELIST SetImageList(HIMAGELIST himl); + BOOL SetItem(int nPos, HDITEM* pHeaderItem); + BOOL SetOrderArray(int iCount, LPINT piArray); + int GetBitmapMargin() const; + int SetBitmapMargin(int nWidth); + + // Operations + HIMAGELIST CreateDragImage(int nIndex); + BOOL DeleteItem(int nPos); + int InsertItem(int nPos, HDITEM* phdi); + BOOL Layout(HDLAYOUT* pHeaderLayout); +#ifdef Header_SetHotDivider + int SetHotDivider(CPoint pt); + int SetHotDivider(int nIndex); +#endif +#ifdef Header_ClearFilter + int ClearAllFilters(); + int ClearFilter(int nColumn); + int EditFilter(int nColumn, BOOL bDiscardChanges); + int SetFilterChangeTimeout(DWORD dwTimeOut); +#endif + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_HEADER ; } + }; + + class CHotKey : public CWnd + { + public: + CHotKey() { ::InitCommonControls(); } + virtual ~CHotKey() {} + + DWORD GetHotKey() const; + CString GetKeyName(UINT vk, BOOL fExtended) const; + void SetHotKey(DWORD dwKey); + void SetRules(WORD wInvalidComb, WORD wModifiers); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = HOTKEY_CLASS; } + }; + + class CIPAddress : public CWnd + { + public: + CIPAddress() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_INTERNET_CLASSES; + ::InitCommonControlsEx(&icex); + } + virtual ~CIPAddress() {} + + void ClearAddress(); + int GetAddress(BYTE& nField0, BYTE& nField1, BYTE& nField2, BYTE& nField3); + int GetAddress(DWORD* dwAddress); + BOOL IsBlank() const; + void SetAddress(BYTE nField0, BYTE nField1, BYTE nField2, BYTE nField3); + void SetAddress(DWORD dwAddress); + void SetFieldFocus(WORD nField); + void SetFieldRange(int nField, BYTE nLower, BYTE nUpper); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = WC_IPADDRESS; } + + }; + + class CMonthCalendar : public CWnd + { + public: + CMonthCalendar() + { + INITCOMMONCONTROLSEX icex; + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_DATE_CLASSES; + InitCommonControlsEx(&icex); + } + virtual ~CMonthCalendar() {} + + // Attributes + COLORREF GetColor(int nRegion) const; + int GetFirstDayOfWeek(BOOL* pbLocal = NULL) const; + CRect GetMinReqRect() const; + int GetMonthDelta() const; + COLORREF SetColor(int nRegion, COLORREF ref); + BOOL SetFirstDayOfWeek(int iDay, int* lpnOld = NULL); + int SetMonthDelta(int iDelta); + + // Operations + BOOL GetCurSel(LPSYSTEMTIME pDateTime) const; + int GetMaxSelCount() const; + int GetMonthRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange, DWORD dwFlags) const; + DWORD GetRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const; + BOOL GetSelRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const; + BOOL GetToday(LPSYSTEMTIME pDateTime) const; + DWORD HitTest(PMCHITTESTINFO pMCHitTest); + BOOL SetCurSel(const LPSYSTEMTIME pDateTime); + BOOL SetDayState(int nMonths, LPMONTHDAYSTATE pStates); + BOOL SetMaxSelCount(int nMax); + BOOL SetRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange); + BOOL SetSelRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange); + void SetToday(const LPSYSTEMTIME pDateTime); + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = MONTHCAL_CLASS; } + }; + + class CProgressBar : public CWnd + { + public: + CProgressBar() { ::InitCommonControls(); } + 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() { ::InitCommonControls(); } + 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; + CToolTip* 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(CToolTip* 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() { ::InitCommonControls(); } + 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); + }; + + class CToolTip : public CWnd + { + public: + CToolTip(); + virtual ~CToolTip(); + + //Attributes + int GetDelayTime(DWORD dwDuration) const; + void GetMargin(LPRECT lprc) const; + int GetMaxTipWidth() const; + void GetText(CString& str, CWnd* pWnd, UINT_PTR nIDTool = 0) const; + COLORREF GetTipBkColor() const; + COLORREF GetTipTextColor() const; + int GetToolCount() const; + BOOL GetToolInfo(TOOLINFO& ToolInfo, CWnd* pWnd, UINT_PTR nIDTool = 0) const; + void SetDelayTime(UINT nDelay); + void SetDelayTime(DWORD dwDuration, int iTime); + void SetMargin(LPRECT lprc); + int SetMaxTipWidth(int iWidth); + void SetTipBkColor(COLORREF clr); + void SetTipTextColor(COLORREF clr); + void SetToolInfo(LPTOOLINFO lpToolInfo); +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + CSize GetBubbleSize(LPTOOLINFO lpToolInfo) const; +#endif + + //Operations + void Activate(BOOL bActivate); + BOOL AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0); + BOOL AddTool(CWnd* pWnd, LPCTSTR lpszText = LPSTR_TEXTCALLBACK, LPCRECT lpRectTool = NULL, UINT_PTR nIDTool = 0); + void DelTool(CWnd* pWnd, UINT_PTR nIDTool = 0); + BOOL HitTest(CWnd* pWnd, CPoint pt, LPTOOLINFO lpToolInfo) const; + void Pop(); + void RelayEvent(LPMSG lpMsg); + + void SetToolRect(CWnd* pWnd, UINT_PTR nIDTool, LPCRECT lpRect); + void Update(); + void UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT_PTR nIDTool = 0); + void UpdateTipText(UINT nIDText, CWnd* pWnd, UINT_PTR nIDTool = 0); + +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + BOOL AdjustRect(LPRECT lprc, BOOL bLarger = TRUE); + BOOL SetTitle(UINT uIcon, LPCTSTR lpstrTitle); +#endif +#if (defined TTM_SETWINDOWTHEME) && (WINVER >= 0x0501) + HRESULT SetWindowTheme(LPCWSTR lpstrTheme); +#endif + + protected: + // Overridables + virtual void PreRegisterClass(WNDCLASS &wc) { wc.lpszClassName = TOOLTIPS_CLASS; ; } + virtual void PreCreate(CREATESTRUCT &cs) + { + cs.dwExStyle = WS_EX_TOOLWINDOW; + cs.style = WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP; + } + + private: + void LoadToolInfo(TOOLINFO& ti, CWnd* pWnd, UINT_PTR nIDTool) const; + }; + + +} // 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 CEdit* CComboBoxEx::GetEditCtrl() const + // Retrieves the handle to the edit control portion of the ComboBoxEx control. + { + assert(IsWindow()); + return (CEdit*)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 CDateTime class + // + inline COLORREF CDateTime::GetMonthCalColor(int iColor) const + { + assert(IsWindow()); + return (COLORREF)DateTime_GetMonthCalColor(m_hWnd, iColor); + } + + inline COLORREF CDateTime::SetMonthCalColor(int iColor, COLORREF clr) + { + assert(IsWindow()); + return (COLORREF)DateTime_SetMonthCalColor(m_hWnd, iColor, clr); + } + + inline BOOL CDateTime::SetFormat(LPCTSTR pszFormat) + { + assert(IsWindow()); + return DateTime_SetFormat(m_hWnd, pszFormat); + } + + inline CMonthCalendar* CDateTime::GetMonthCalCtrl() const + { + assert(IsWindow()); + return (CMonthCalendar*)FromHandle((HWND)DateTime_GetMonthCal(m_hWnd)); + } + + inline CFont* CDateTime::GetMonthCalFont() const + { + assert(IsWindow()); + return FromHandle((HFONT)DateTime_GetMonthCalFont(m_hWnd)); + } + + inline void CDateTime::SetMonthCalFont(HFONT hFont, BOOL bRedraw /*= TRUE*/) + { + assert(IsWindow()); + DateTime_SetMonthCalFont(m_hWnd, hFont, MAKELONG(bRedraw, 0)); + } + + inline DWORD CDateTime::GetRange(LPSYSTEMTIME lpSysTimeArray) const + { + assert(IsWindow()); + return DateTime_GetRange(m_hWnd, lpSysTimeArray); + } + + inline BOOL CDateTime::SetRange(DWORD flags, LPSYSTEMTIME lpSysTimeArray) + { + assert(IsWindow()); + return DateTime_SetRange(m_hWnd, flags, lpSysTimeArray); + } + + inline DWORD CDateTime::GetTime(LPSYSTEMTIME pTimeDest) const + { + assert(IsWindow()); + return DateTime_GetSystemtime(m_hWnd, pTimeDest); + } + + inline BOOL CDateTime::SetTime(DWORD flag, LPSYSTEMTIME pTimeNew /*= NULL*/) + { + assert(IsWindow()); + return DateTime_SetSystemtime(m_hWnd, flag, pTimeNew); + } + + + //////////////////////////////////////// + // Definitions for the CHotKey class + // + inline DWORD CHotKey::GetHotKey() const + { + assert(IsWindow()); + return (DWORD)SendMessage(HKM_GETHOTKEY, 0, 0); + } + + inline CString CHotKey::GetKeyName(UINT vk, BOOL fExtended) const + { + // Translate the virtual-key code to a scan code + LONG lScan = MapVirtualKey(vk, 0); + + // Construct an LPARAM with the scan code in Bits 16-23, and an extended flag in bit 24 + LPARAM lParam = lScan << 16; + if (fExtended) + lParam |= 0x01000000L; + + CString str; + int nBufferLen = 64; + int nStrLen = nBufferLen; + + // Loop until we have retrieved the entire string + while(nStrLen == nBufferLen) + { + nBufferLen *= 4; + LPTSTR pszStr = str.GetBuffer(nBufferLen); + nStrLen = ::GetKeyNameText((LONG)lParam, pszStr, nBufferLen + 1); + str.ReleaseBuffer(); + } + + return str; + } + + inline void CHotKey::SetHotKey(DWORD dwKey) + { + assert(IsWindow()); + SendMessage(HKM_SETHOTKEY, (WPARAM)dwKey, 0); + } + + inline void CHotKey::SetRules(WORD wInvalidComb, WORD wModifiers) + { + assert(IsWindow()); + SendMessage(HKM_SETRULES, wInvalidComb, wModifiers); + } + + + //////////////////////////////////////// + // Definitions for the CHeader class + // + inline HIMAGELIST CHeader::CreateDragImage(int nIndex) + { + assert(IsWindow()); + return Header_CreateDragImage(m_hWnd, nIndex); + } + + inline BOOL CHeader::DeleteItem(int nPos) + { + assert(IsWindow()); + return Header_DeleteItem(m_hWnd, nPos); + } + + inline HIMAGELIST CHeader::GetImageList() const + { + assert(IsWindow()); + return Header_GetImageList(m_hWnd); + } + + inline BOOL CHeader::GetItem(int nPos, HDITEM* pHeaderItem) const + { + assert(IsWindow()); + return Header_GetItem(m_hWnd, nPos, pHeaderItem); + } + + inline int CHeader::GetItemCount() const + { + assert(IsWindow()); + return Header_GetItemCount(m_hWnd); + } + + inline CRect CHeader::GetItemRect(int nIndex) const + { + assert(IsWindow()); + RECT rc; + Header_GetItemRect(m_hWnd, nIndex, &rc); + return rc; + } + + inline BOOL CHeader::GetOrderArray(LPINT piArray, int iCount) + { + assert(IsWindow()); + return Header_GetOrderArray(m_hWnd, piArray, iCount); + } + + inline int CHeader::InsertItem(int nPos, HDITEM* phdi) + { + assert(IsWindow()); + return Header_InsertItem(m_hWnd, nPos, phdi); + } + + inline BOOL CHeader::Layout(HDLAYOUT* pHeaderLayout) + { + assert(IsWindow()); + return Header_Layout(m_hWnd, pHeaderLayout); + } + + inline int CHeader::OrderToIndex(int nOrder) const + { + assert(IsWindow()); + return Header_OrderToIndex( m_hWnd, nOrder); + } + +#ifdef Header_SetHotDivider + inline int CHeader::SetHotDivider(CPoint pt) + { + assert(IsWindow()); + return Header_SetHotDivider(m_hWnd, TRUE, MAKELPARAM(pt.x, pt.y)); + } + + inline int CHeader::SetHotDivider(int nIndex) + { + assert(IsWindow()); + return Header_SetHotDivider(m_hWnd, FALSE, nIndex); + } +#endif + + inline HIMAGELIST CHeader::SetImageList(HIMAGELIST himl) + { + assert(IsWindow()); + return Header_SetImageList(m_hWnd, himl); + } + + inline BOOL CHeader::SetItem(int nPos, HDITEM* pHeaderItem) + { + assert(IsWindow()); + return Header_SetItem(m_hWnd, nPos, pHeaderItem); + } + + inline BOOL CHeader::SetOrderArray(int iCount, LPINT piArray) + { + assert(IsWindow()); + return Header_SetOrderArray(m_hWnd, iCount, piArray); + } + +#ifdef Header_ClearFilter + inline int CHeader::ClearFilter(int nColumn) + { + assert(IsWindow()); + return Header_ClearFilter(m_hWnd, nColumn); + } + + inline int CHeader::ClearAllFilters() + { + assert(IsWindow()); + return Header_ClearAllFilters(m_hWnd); + } + + inline int CHeader::EditFilter(int nColumn, BOOL bDiscardChanges) + { + assert(IsWindow()); + return Header_EditFilter(m_hWnd, nColumn, LPARAM MAKELPARAM(bDiscardChanges, 0)); + } + + inline int CHeader::GetBitmapMargin() const + { + assert(IsWindow()); + return Header_GetBitmapMargin(m_hWnd); + } + + inline int CHeader::SetBitmapMargin(int nWidth) + { + assert(IsWindow()); + return Header_SetBitmapMargin(m_hWnd, nWidth); + } + + inline int CHeader::SetFilterChangeTimeout(DWORD dwTimeOut) + { + assert(IsWindow()); + return Header_SetFilterChangeTimeout(m_hWnd, dwTimeOut); + } +#endif + + //////////////////////////////////////// + // Definitions for the CIPAddress class + // + inline void CIPAddress::ClearAddress() + { + assert(IsWindow()); + SendMessage(IPM_CLEARADDRESS, 0, 0); + } + + inline int CIPAddress::GetAddress(BYTE& nField0, BYTE& nField1, BYTE& nField2, BYTE& nField3) + { + DWORD dwAddr; + int iValue = GetAddress(&dwAddr); + nField0 = (BYTE)FIRST_IPADDRESS(dwAddr); + nField1 = (BYTE)SECOND_IPADDRESS(dwAddr); + nField2 = (BYTE)THIRD_IPADDRESS(dwAddr); + nField3 = (BYTE)FOURTH_IPADDRESS(dwAddr); + return iValue; + } + + inline int CIPAddress::GetAddress(DWORD* dwAddress) + { + assert(IsWindow()); + return (int)SendMessage(IPM_GETADDRESS, 0, (LPARAM)&dwAddress); + } + + inline BOOL CIPAddress::IsBlank() const + { + assert(IsWindow()); + return (BOOL)SendMessage(IPM_ISBLANK, 0, 0); + } + + inline void CIPAddress::SetAddress(BYTE nField0, BYTE nField1, BYTE nField2, BYTE nField3) + { + assert(IsWindow()); + SendMessage(IPM_SETADDRESS, 0, (LPARAM)MAKEIPADDRESS(nField0, nField1, nField2, nField3)); + } + + inline void CIPAddress::SetAddress(DWORD dwAddress) + { + assert(IsWindow()); + SendMessage(IPM_SETADDRESS, 0, (LPARAM)dwAddress); + } + + inline void CIPAddress::SetFieldFocus(WORD nField) + { + assert(IsWindow()); + SendMessage(IPM_SETFOCUS, nField, 0); + } + + inline void CIPAddress::SetFieldRange(int nField, BYTE nLower, BYTE nUpper) + { + assert(IsWindow()); + SendMessage(IPM_SETRANGE, MAKEIPRANGE(nLower, nUpper), nField); + } + + + /////////////////////////////////////////// + // Definitions for the CMonthCalendar class + // + inline COLORREF CMonthCalendar::GetColor(int nRegion) const + { + assert(IsWindow()); + return (COLORREF)MonthCal_GetColor(m_hWnd, nRegion); + } + + inline BOOL CMonthCalendar::GetCurSel(LPSYSTEMTIME pDateTime) const + { + assert(IsWindow()); + return MonthCal_GetCurSel(m_hWnd, pDateTime); + } + + inline int CMonthCalendar::GetFirstDayOfWeek(BOOL* pbLocal /*= NULL*/) const + { + assert(IsWindow()); + DWORD dwValue = MonthCal_GetFirstDayOfWeek(m_hWnd); + + if (pbLocal) + *pbLocal = HIWORD(dwValue); + + return LOWORD(dwValue); + } + + inline int CMonthCalendar::GetMaxSelCount() const + { + assert(IsWindow()); + return MonthCal_GetMaxSelCount(m_hWnd); + } + + inline CRect CMonthCalendar::GetMinReqRect() const + { + assert(IsWindow()); + RECT rc; + MonthCal_GetMinReqRect(m_hWnd, &rc); + return rc; + } + + inline int CMonthCalendar::GetMonthDelta() const + { + assert(IsWindow()); + return MonthCal_GetMonthDelta(m_hWnd); + } + + inline int CMonthCalendar::GetMonthRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange, DWORD dwFlags) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + int nCount = MonthCal_GetMonthRange(m_hWnd, dwFlags, MinMax); + return nCount; + } + + inline DWORD CMonthCalendar::GetRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + DWORD dwValue = MonthCal_GetRange(m_hWnd, &MinMax); + memcpy(pMinRange, &MinMax[0], sizeof(SYSTEMTIME)); + memcpy(pMaxRange, &MinMax[1], sizeof(SYSTEMTIME)); + return dwValue; + } + + inline BOOL CMonthCalendar::GetSelRange(LPSYSTEMTIME pMinRange, LPSYSTEMTIME pMaxRange) const + { + assert(IsWindow()); + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + return (BOOL)MonthCal_GetSelRange(m_hWnd, &MinMax); + } + + inline BOOL CMonthCalendar::GetToday(LPSYSTEMTIME pDateTime) const + { + assert(IsWindow()); + return MonthCal_GetToday(m_hWnd, pDateTime); + } + + inline DWORD CMonthCalendar::HitTest(PMCHITTESTINFO pMCHitTest) + { + assert(IsWindow()); + return (DWORD)MonthCal_HitTest(m_hWnd, pMCHitTest); + } + + inline COLORREF CMonthCalendar::SetColor(int nRegion, COLORREF clr) + { + assert(IsWindow()); + return (COLORREF)MonthCal_SetColor(m_hWnd, nRegion, clr); + } + + inline BOOL CMonthCalendar::SetCurSel(const LPSYSTEMTIME pDateTime) + { + assert(IsWindow()); + return MonthCal_SetCurSel(m_hWnd, pDateTime); + } + + inline BOOL CMonthCalendar::SetDayState(int nMonths, LPMONTHDAYSTATE pStates) + { + assert(IsWindow()); + return (BOOL)MonthCal_SetDayState(m_hWnd, nMonths, pStates); + } + + inline BOOL CMonthCalendar::SetFirstDayOfWeek(int iDay, int* pnOld/* = NULL*/) + { + assert(IsWindow()); + DWORD dwValue = (DWORD)MonthCal_SetFirstDayOfWeek(m_hWnd, iDay); + + if(pnOld) + *pnOld = LOWORD(dwValue); + + return (BOOL)HIWORD(dwValue); + } + + inline BOOL CMonthCalendar::SetMaxSelCount(int nMax) + { + assert(IsWindow()); + return MonthCal_SetMaxSelCount(m_hWnd, nMax); + } + + inline int CMonthCalendar::SetMonthDelta(int iDelta) + { + assert(IsWindow()); + return MonthCal_SetMonthDelta(m_hWnd, iDelta); + } + + inline BOOL CMonthCalendar::SetRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange) + { + + SYSTEMTIME MinMax[2]; + DWORD dwLimit; + + if (pMinRange != NULL) + { + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + dwLimit = GDTR_MIN; + } + + if (pMaxRange) + { + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + dwLimit |= GDTR_MAX; + } + + return (BOOL)MonthCal_SetRange(m_hWnd, dwLimit, &MinMax); + } + + inline BOOL CMonthCalendar::SetSelRange(const LPSYSTEMTIME pMinRange, const LPSYSTEMTIME pMaxRange) + { + SYSTEMTIME MinMax[2]; + memcpy(&MinMax[0], pMinRange, sizeof(SYSTEMTIME)); + memcpy(&MinMax[1], pMaxRange, sizeof(SYSTEMTIME)); + return (BOOL)MonthCal_SetSelRange(m_hWnd, &MinMax); + } + + inline void CMonthCalendar::SetToday(const LPSYSTEMTIME pDateTime) + { + assert(IsWindow()); + MonthCal_SetToday(m_hWnd, pDateTime); + } + + + //////////////////////////////////////// + // 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 CToolTip* CSlider::GetToolTips() const + // Retrieves the handle to the ToolTip control assigned to the trackbar, if any. + { + assert(IsWindow()); + return (CToolTip*)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(CToolTip* pToolTip) const + // Assigns a ToolTip control to the trackbar control. + { + assert(IsWindow()); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + SendMessage(TBM_SETTOOLTIPS, (WPARAM)hToolTip, 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)); + } + + //////////////////////////////////////// + // Definitions for the CToolTip class + // + + inline CToolTip::CToolTip() + {} + + inline CToolTip::~CToolTip() + {} + + inline void CToolTip::Activate(BOOL bActivate) + // Activates or deactivates a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_ACTIVATE, bActivate, 0); + } + + inline BOOL CToolTip::AddTool(CWnd* pWnd, UINT nIDText, LPCRECT lpRectTool /*= NULL*/, UINT_PTR nIDTool /*= 0*/) + // Registers a tool with a ToolTip control. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.hinst = GetApp()->GetResourceHandle(); + ti.lpszText = (LPTSTR)MAKEINTRESOURCE(nIDText); + if (lpRectTool) + ti.rect = *lpRectTool; + return (BOOL)SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti); + } + + inline BOOL CToolTip::AddTool(CWnd* pWnd, LPCTSTR lpszText /*= LPSTR_TEXTCALLBACK*/, LPCRECT lpRectTool /*= NULL*/, UINT_PTR nIDTool /*= 0*/) + // Registers a tool with a ToolTip control. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = (LPTSTR)lpszText; + if (lpRectTool) + ti.rect = *lpRectTool; + return (BOOL)SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti); + } + + inline void CToolTip::DelTool(CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Removes a tool from a ToolTip control. + { + assert(IsWindow()); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + SendMessage(TTM_DELTOOL, 0, (LPARAM)&ti); + } + + inline int CToolTip::GetDelayTime(DWORD dwDuration) const + // Retrieves the initial, pop-up, and reshow durations currently set for a ToolTip control. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETDELAYTIME, dwDuration, 0); + } + + inline void CToolTip::GetMargin(LPRECT lprc) const + // Retrieves the top, left, bottom, and right margins set for a ToolTip window. + { + assert(IsWindow()); + SendMessage(TTM_GETMARGIN, 0, (LPARAM)lprc); + } + + inline int CToolTip::GetMaxTipWidth() const + // Retrieves the maximum width for a ToolTip window. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETMAXTIPWIDTH, 0, 0); + } + + inline void CToolTip::GetText(CString& str, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) const + // Retrieves the information a ToolTip control maintains about a tool. + { + assert(IsWindow()); + assert(pWnd); + LPTSTR pszText = str.GetBuffer(80); // Maximum allowed Tooltip is 80 characters for Windows XP and below + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = pszText; + SendMessage(TTM_GETTEXT, 0, (LPARAM)&ti); + str.ReleaseBuffer(); + } + + inline COLORREF CToolTip::GetTipBkColor() const + // Retrieves the background color in a ToolTip window. + { + assert(IsWindow()); + return (COLORREF)SendMessage(TTM_GETTIPBKCOLOR, 0,0); + } + + inline COLORREF CToolTip::GetTipTextColor() const + // Retrieves the text color in a ToolTip window. + { + assert(IsWindow()); + return (COLORREF)SendMessage(TTM_GETTIPTEXTCOLOR, 0, 0); + } + + inline int CToolTip::GetToolCount() const + // Retrieves a count of the tools maintained by a ToolTip control. + { + assert(IsWindow()); + return (int)SendMessage(TTM_GETTOOLCOUNT, 0, 0); + } + + inline BOOL CToolTip::GetToolInfo(TOOLINFO& ToolInfo, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) const + // Retrieves the information that a ToolTip control maintains about a tool. + { + assert(IsWindow()); + assert(pWnd); + LoadToolInfo(ToolInfo, pWnd, nIDTool); + return (BOOL)SendMessage(TTM_GETTOOLINFO, 0, (LPARAM)&ToolInfo); + } + + inline BOOL CToolTip::HitTest(CWnd* pWnd, CPoint pt, LPTOOLINFO lpToolInfo) const + // Tests a point to determine whether it is within the bounding rectangle of the + // specified tool and, if it is, retrieves information about the tool. + { + assert(IsWindow()); + assert(pWnd); + assert(lpToolInfo); + TTHITTESTINFO hti = {0}; + hti.hwnd = pWnd->GetHwnd(); + hti.pt = pt; + hti.ti = *lpToolInfo; + return (BOOL)SendMessage(TTM_HITTEST, 0, (LPARAM)&hti); + } + + inline void CToolTip::LoadToolInfo(TOOLINFO& ti, CWnd* pWnd, UINT_PTR nIDTool) const + { + ZeroMemory(&ti, sizeof(TOOLINFO)); + ti.cbSize = sizeof(TOOLINFO); + HWND hWnd = pWnd->GetHwnd(); + if (nIDTool == 0) + { + ti.hwnd = ::GetParent(hWnd); + ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS; + ti.uId = (UINT)hWnd; + } + else + { + ti.hwnd = hWnd; + ti.uId = nIDTool; + } + } + + inline void CToolTip::Pop() + // Removes a displayed ToolTip window from view. + { + assert(IsWindow()); + SendMessage(TTM_POP, 0, 0); + } + + inline void CToolTip::RelayEvent(LPMSG lpMsg) + // Passes a mouse message to a ToolTip control for processing. + { + assert(IsWindow()); + SendMessage(TTM_RELAYEVENT, 0, (LPARAM)lpMsg); + } + + inline void CToolTip::SetDelayTime(UINT nDelay) + // Sets the initial delay for a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETDELAYTIME, TTDT_INITIAL, nDelay); + } + + inline void CToolTip::SetDelayTime(DWORD dwDuration, int iTime) + // Sets the initial, pop-up, and reshow durations for a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETDELAYTIME, dwDuration, iTime); + } + + inline void CToolTip::SetMargin(LPRECT lprc) + // Sets the top, left, bottom, and right margins for a ToolTip window. + { + assert(IsWindow()); + assert(lprc); + SendMessage(TTM_SETMARGIN, 0, (LPARAM)lprc); + } + + inline int CToolTip::SetMaxTipWidth(int iWidth) + // Sets the maximum width for a ToolTip window. + { + assert(IsWindow()); + return (int)SendMessage(TTM_SETMAXTIPWIDTH, 0, iWidth); + } + + inline void CToolTip::SetTipBkColor(COLORREF clr) + // Sets the background color in a ToolTip window. + // Ignored when XP themes are active. + { + assert(IsWindow()); + SendMessage(TTM_SETTIPBKCOLOR, clr, 0); + } + + inline void CToolTip::SetTipTextColor(COLORREF clr) + // Sets the text color in a ToolTip window. + // Ignored when XP themes are active. + { + assert(IsWindow()); + SendMessage(TTM_SETTIPTEXTCOLOR, clr, 0); + } + + inline void CToolTip::SetToolInfo(LPTOOLINFO lpToolInfo) + // Sets the information that a ToolTip control maintains for a tool. + { + assert(IsWindow()); + SendMessage(TTM_SETTOOLINFO, 0, (LPARAM)lpToolInfo); + } + + inline void CToolTip::SetToolRect(CWnd* pWnd, UINT_PTR nIDTool, LPCRECT lpRect) + // Sets a new bounding rectangle for a tool. + { + assert(IsWindow()); + assert(pWnd); + assert(lpRect); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.rect = *lpRect; + SendMessage(TTM_NEWTOOLRECT, 0, (LPARAM)&ti); + } + + inline void CToolTip::Update() + // Forces the current tool to be redrawn. + { + assert(IsWindow()); + SendMessage(TTM_UPDATE, 0, 0); + } + + inline void CToolTip::UpdateTipText(LPCTSTR lpszText, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Sets the ToolTip text for a tool. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.lpszText = (LPTSTR)lpszText; + SendMessage(TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + } + + inline void CToolTip::UpdateTipText(UINT nIDText, CWnd* pWnd, UINT_PTR nIDTool /*= 0*/) + // Sets the ToolTip text for a tool. + { + assert(IsWindow()); + assert(pWnd); + TOOLINFO ti; + LoadToolInfo(ti, pWnd, nIDTool); + ti.hinst = GetApp()->GetResourceHandle(); + ti.lpszText = (LPTSTR)MAKEINTRESOURCE(nIDText); + SendMessage(TTM_UPDATETIPTEXT, 0, (LPARAM)&ti); + } + +#if (defined TTM_SETTITLE) && (_WIN32_IE >=0x0500) + inline BOOL CToolTip::AdjustRect(LPRECT lprc, BOOL bLarger /*= TRUE*/) + // Calculates a ToolTip control's text display rectangle from its window rectangle, or the + // ToolTip window rectangle needed to display a specified text display rectangle. + { + assert(IsWindow()); + return (BOOL)SendMessage(TTM_ADJUSTRECT, bLarger, (LPARAM)lprc); + } + + inline CSize CToolTip::GetBubbleSize(LPTOOLINFO lpToolInfo) const + // Returns the width and height of a ToolTip control. + { + assert(IsWindow()); + LRESULT lr = SendMessage(TTM_GETBUBBLESIZE, (LPARAM)lpToolInfo); + CSize sz(LOWORD(lr), HIWORD(lr)); + return sz; + } + + inline BOOL CToolTip::SetTitle(UINT uIcon, LPCTSTR lpstrTitle) + // Adds a standard icon and title string to a ToolTip. + { + assert(IsWindow()); + return (BOOL)SendMessage(TTM_SETTITLE, uIcon, (LPARAM)lpstrTitle); + } +#endif + +#if (defined TTM_SETWINDOWTHEME) && (WINVER >= 0x0501) + inline HRESULT CToolTip::SetWindowTheme(LPCWSTR lpstrTheme) + // Sets the visual style of a ToolTip control. + { + assert(IsWindow()); + SendMessage(TTM_SETWINDOWTHEME, 0, (LPARAM)lpstrTheme); + return NULL; + } +#endif + + +} // namespace Win32xx + +#endif // define _WIN32XX_CONTROLS_H_ + Index: include/reactos/libs/win32++/copyright.txt =================================================================== --- include/reactos/libs/win32++/copyright.txt (revision 0) +++ include/reactos/libs/win32++/copyright.txt (working copy) @@ -0,0 +1,33 @@ +Win32++ Version 7.3 +Released: 30th November 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. Index: include/reactos/libs/win32++/cstring.h =================================================================== --- include/reactos/libs/win32++/cstring.h (revision 0) +++ include/reactos/libs/win32++/cstring.h (working copy) @@ -0,0 +1,965 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 both ANSI and Unicode characters and +// automatically converts these to TCHAR as required. +// +// 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: +// 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); + friend bool operator < (const CString& string1, const CString& string2); + friend bool operator > (const CString& string1, const CString& string2); + friend bool operator < (const CString& string1, LPCTSTR pszText); + friend bool operator > (const CString& string1, LPCTSTR pszText); + friend bool operator <= (const CString& string1, const CString& string2); + friend bool operator >= (const CString& string1, const CString& string2); + friend bool operator <= (const CString& string1, LPCTSTR pszText); + friend bool operator >= (const CString& string1, LPCTSTR pszText); + + public: + CString(); + ~CString(); + CString(const CString& str); + CString(LPCSTR pszText); + CString(LPCWSTR pszText); + CString(TCHAR ch, int nLength = 1); + CString(LPCTSTR pszText, int nLength); + + CString& operator = (const CString& str); + CString& operator = (const TCHAR ch); + CString& operator = (LPCSTR pszText); + CString& operator = (LPCWSTR pszText); + bool operator == (LPCTSTR pszText) const; + bool operator != (LPCTSTR pszText) const; + operator LPCTSTR() const; + TCHAR operator [] (int nIndex) const; + CString& operator += (const CString& str); + CString& operator += (LPCSTR szText); + CString& operator += (LPCWSTR szText); + + // Attributes + 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(LPCSTR pszText) + { + m_str.assign(A2T(pszText)); + } + + inline CString::CString(LPCWSTR pszText) + { + m_str.assign(W2T(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 = (LPCSTR pszText) + { + m_str.assign(A2T(pszText)); + return *this; + } + + inline CString& CString::operator = (LPCWSTR pszText) + { + m_str.assign(W2T(pszText)); + return *this; + } + + inline bool CString::operator == (LPCTSTR pszText) const + // Returns TRUE if the strings have the same content + { + assert(pszText); + return (0 == Compare(pszText)); + } + + inline bool CString::operator != (LPCTSTR pszText) const + // Returns TRUE if the strings have a different content + { + assert(pszText); + return Compare(pszText) != 0; + } + + inline CString::operator LPCTSTR() const + { + return m_str.c_str(); + } + + inline TCHAR CString::operator [] (int nIndex) const + { + assert(nIndex >= 0); + assert(nIndex < GetLength()); + return m_str[nIndex]; + } + + inline CString& CString::operator += (const CString& str) + { + m_str.append(str); + return *this; + } + + inline CString& CString::operator += (LPCSTR szText) + { + m_str.append(A2T(szText)); + return *this; + } + + inline CString& CString::operator += (LPCWSTR szText) + { + m_str.append(W2T(szText)); + 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; + + va_list args; + va_start(args, pszFormat); + str.FormatV(pszFormat, args); + va_end(args); + + 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)) + { + va_list args; + va_start(args, nFormatID); + str2.FormatV(str1.c_str(), args); + va_end(args); + + 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 _tcscmp(m_str.data(), 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. + { + CString str; + if (str.LoadString(nID)) + { + va_list args; + va_start(args, nID); + FormatV(str.c_str(), args); + va_end(args); + } + } + + 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; + + 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 (nLength != 0); + } +#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. + { + // Error 2285 with Borland 5.5 occurs here unless option -tWM is used instead of -tW + std::reverse(m_str.begin(), m_str.end()); + } + + inline void CString::MakeUpper() + // Converts all the characters in this string to uppercase characters. + { + // Error 2285 with Borland 5.5 occurs here unless option -tWM is used instead of -tW + 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, 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; + } + + inline bool operator < (const CString& string1, const CString& string2) + { + return string1.Compare(string2) < 0; + } + + inline bool operator > (const CString& string1, const CString& string2) + { + return string1.Compare(string2) > 0; + } + + inline bool operator <= (const CString& string1, const CString& string2) + { + return string1.Compare(string2) <= 0; + } + + inline bool operator >= (const CString& string1, const CString& string2) + { + return string1.Compare(string2) >= 0; + } + + inline bool operator < (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) < 0; + } + + inline bool operator > (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) > 0; + } + + inline bool operator <= (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) <= 0; + } + + inline bool operator >= (const CString& string1, LPCTSTR pszText) + { + return string1.Compare(pszText) >= 0; + } + + // Global LoadString + inline CString LoadString(UINT nID) + { + CString str; + str.LoadString(nID); + return str; + } + + +} // namespace Win32xx + +#endif//_WIN32XX_CSTRING_H_ Index: include/reactos/libs/win32++/default_resource.h =================================================================== --- include/reactos/libs/win32++/default_resource.h (revision 0) +++ include/reactos/libs/win32++/default_resource.h (working copy) @@ -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++. + + Index: include/reactos/libs/win32++/default_resource.rc =================================================================== --- include/reactos/libs/win32++/default_resource.rc (revision 0) +++ include/reactos/libs/win32++/default_resource.rc (working copy) @@ -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 + + Index: include/reactos/libs/win32++/dialog.h =================================================================== --- include/reactos/libs/win32++/dialog.h (revision 0) +++ include/reactos/libs/win32++/dialog.h (working copy) @@ -0,0 +1,887 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + +#define IDLE_TIMER_ID 300 + +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 WM_TIMER: + if (wParam == IDLE_TIMER_ID) + GetApp()->CleanupTemps(); + return 0L; + case UWM_CLEANUPTEMPS: + { + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + pTLSData->vTmpWnds.clear(); + } + break; + case WM_INITDIALOG: + { + // Center the dialog + CenterWindow(); + if (IsModal()) + SetTimer(IDLE_TIMER_ID, 1000, 0); + } + 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("\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("\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 + if ( IsWindow() ) + 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. + // If you need the dialog to create another window, put it in a + // different thread. + } + } + } + + 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(pWndPrev, rc, SWP_NOCOPYBITS); + (*iter).rcOld = rc; + } + } + } + +#endif // #ifndef _WIN32_WCE + +} // namespace Win32xx + + + +#endif // _WIN32XX_DIALOG_H_ + Index: include/reactos/libs/win32++/docking.h =================================================================== --- include/reactos/libs/win32++/docking.h (revision 0) +++ include/reactos/libs/win32++/docking.h (working copy) @@ -0,0 +1,4237 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CString m_strTooltip; + 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_strTabText; } + 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_strTabText = 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; + CString m_strTabText; + 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(LPCTSTR szRegistryKeyName); + virtual void RecalcDockLayout(); + virtual BOOL SaveRegistrySettings(LPCTSTR szRegistryKeyName); + 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(); + ::SelectObject(*pDC, 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("**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_NCLBUTTONDBLCLK: + 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("Missing docking resource: Target Centre\n"); + + if (bmLeft.GetHandle()) pDC->DrawBitmap(0, 29, 31, 29, bmLeft, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Left\n"); + + if (bmTop.GetHandle()) pDC->DrawBitmap(29, 0, 29, 31, bmTop, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Top\n"); + + if (bmRight.GetHandle()) pDC->DrawBitmap(55, 29, 31, 29, bmRight, RGB(255,0,255)); + else TRACE("Missing docking resource: Target Right\n"); + + if (bmBottom.GetHandle()) pDC->DrawBitmap(29, 55, 29, 31, bmBottom, RGB(255,0,255)); + else TRACE("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(&wndTopMost, 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("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(&wndTopMost, 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(&wndTopMost, 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(&wndTopMost, 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(&wndTopMost, 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("**WARNING** Horizontal cursor resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SPLITV), RT_GROUP_CURSOR)) + TRACE("**WARNING** Vertical cursor resource missing\n"); + } + + if (!(dwDockStyle & DS_NO_UNDOCK)) + { + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDCENTER), RT_BITMAP)) + TRACE("**WARNING** Docking center bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDLEFT), RT_BITMAP)) + TRACE("**WARNING** Docking left bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDRIGHT), RT_BITMAP)) + TRACE("**WARNING** Docking right bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDTOP), RT_BITMAP)) + TRACE("**WARNING** Docking top bitmap resource missing\n"); + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDBOTTOM), RT_BITMAP)) + TRACE("**WARNING** Docking center bottom resource missing\n"); + } + + if (dwDockStyle & DS_DOCKED_CONTAINER) + { + if (!FindResource(hMod, MAKEINTRESOURCE(IDW_SDMIDDLE), RT_BITMAP)) + TRACE("**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(0, 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("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("Error: Undocked dockers should not have a dock parent\n"); + bResult = FALSE; + } + + if ((*iter)->IsDocked() && (*iter)->m_pDockParent == 0) + { + TRACE("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("Error: Docking parent/Child information mismatch\n"); + bResult = FALSE; + } + if ((*iterChild)->GetParent() != (*iter).get()) + { + TRACE("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("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); + + // Delete any child containers this container might have + if (GetContainer()) + { + std::vector AllContainers = GetContainer()->GetAllContainers(); + std::vector::iterator iter; + for (iter = AllContainers.begin(); iter < AllContainers.end(); ++iter) + { + if (GetContainer() != (*iter).pContainer) + GetContainer()->RemoveContainer((*iter).pContainer); + } + } + + 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); + pDock->GetDockBar().SetParent(GetDockAncestor()); + } + } + + 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(); + } + + if (GetDockAncestor()->GetView() == pView) + pDock = GetDockAncestor(); + + 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(LPCTSTR szRegistryKeyName) + // Recreates the docker layout based on information stored in the registry. + // Assumes the DockAncestor window is already created. + { + BOOL bResult = FALSE; + + if (szRegistryKeyName) + { + std::vector vDockList; + std::vector vActiveContainers; + + CString strKey = _T("Software\\") + CString(szRegistryKeyName) + _T("\\Dock Windows"); + HKEY hKey = 0; + RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey); + if (hKey) + { + DWORD dwType = REG_BINARY; + DWORD BufferSize = sizeof(DockInfo); + DockInfo di; + int i = 0; + TCHAR szNumber[20]; + CString strSubKey = _T("DockChild"); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&di, &BufferSize)) + { + vDockList.push_back(di); + i++; + strSubKey = _T("DockChild"); + strSubKey += _itot(i, szNumber, 10); + } + + dwType = REG_DWORD; + BufferSize = sizeof(int); + int nID; + i = 0; + strSubKey = _T("ActiveContainer"); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&nID, &BufferSize)) + { + vActiveContainers.push_back(nID); + i++; + strSubKey = _T("ActiveContainer"); + strSubKey += _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("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("Failed to add dockers with parents from registry"); + bResult = FALSE; + } + + vDockList.erase(iter); + break; + } + } + + if (!bFound) + { + TRACE("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("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 = (DWORD)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 the docker'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(GetDockAncestor()); + + // 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(LPCTSTR szRegistryKeyName) + // 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 (szRegistryKeyName) + { + // 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); + } + + CString strKeyName = _T("Software\\") + CString(szRegistryKeyName); + HKEY hKey = NULL; + HKEY hKeyDock = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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]; + CString strSubKey = _T("DockChild"); + strSubKey += _itot((int)u, szNumber, 10); + if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 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]; + CString strSubKey = _T("ActiveContainer"); + strSubKey += _itot(i++, szNumber, 10); + int nID = GetDockFromView(pContainer)->GetDockID(); + if(ERROR_SUCCESS != RegSetValueEx(hKeyDock, strSubKey, 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, strKeyName); + 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; + + if (GetDockFromView(pContainer) == GetDockAncestor()) 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); + pDock->GetDockBar().SetParent(GetDockAncestor()); + 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(0, 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(0, 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_strTooltip = LoadString(nID); + lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str(); + } + else + m_strTooltip = _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_ + Index: include/reactos/libs/win32++/file.h =================================================================== --- include/reactos/libs/win32++/file.h (revision 0) +++ include/reactos/libs/win32++/file.h (working copy) @@ -0,0 +1,396 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 HighPosCur = 0; + LONG HighPosEnd = 0; + + DWORD LowPosCur = SetFilePointer(m_hFile, 0, &HighPosCur, FILE_CURRENT); + DWORD LowPosEnd = SetFilePointer(m_hFile, 0, &HighPosEnd, FILE_END); + SetFilePointer(m_hFile, LowPosCur, &HighPosCur, FILE_BEGIN); + + ULONGLONG Result = ((ULONGLONG)HighPosEnd << 32) + LowPosEnd; + 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("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 Index: include/reactos/libs/win32++/frame.h =================================================================== --- include/reactos/libs/win32++/frame.h (revision 0) +++ include/reactos/libs/win32++/frame.h (working copy) @@ -0,0 +1,3863 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 +#ifndef TMT_BORDERSIZE + #define TMT_BORDERSIZE 2403 +#endif +#ifndef TMT_CONTENTMARGINS + #define TMT_CONTENTMARGINS 3602 +#endif +#ifndef VSCLASS_MENU + #define VSCLASS_MENU L"MENU" +#endif +#ifndef ODS_NOACCEL + #define ODS_NOACCEL 0x0100 +#endif +#ifndef ODS_HOTLIGHT + #define ODS_HOTLIGHT 0x0040 +#endif +#ifndef ODS_INACTIVE + #define ODS_INACTIVE 0x0080 +#endif +#ifndef DT_HIDEPREFIX + #define DT_HIDEPREFIX 0x00100000 +#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 + }; + + // define some structs and enums from uxtheme.h and vssym32.h + typedef struct _MARGINS + { + int cxLeftWidth; // width of left border that retains its size + int cxRightWidth; // width of right border that retains its size + int cyTopHeight; // height of top border that retains its size + int cyBottomHeight; // height of bottom border that retains its size + } MARGINS, *PMARGINS; + + class CMargins : public MARGINS + { + public: + CMargins(int cxLeft, int cxRight, int cyTop, int cyBottom) + { + cxLeftWidth = cxLeft; cxRightWidth = cxRight; + cyTopHeight = cyTop; cyBottomHeight = cyBottom; + } + CMargins() + { + cxLeftWidth = 0; cxRightWidth = 0; + cyTopHeight = 0; cyBottomHeight = 0; + } + int Width() const { return cxLeftWidth + cxRightWidth; } + int Height() const { return cyTopHeight + cyBottomHeight; } + void SetMargins(int cxLeft, int cxRight, int cyTop, int cyBottom) + { + cxLeftWidth = cxLeft; cxRightWidth = cxRight; + cyTopHeight = cyTop; cyBottomHeight = cyBottom; + } + }; + + enum THEMESIZE + { + TS_MIN, // minimum size + TS_TRUE, // size without stretching + TS_DRAW // size that theme mgr will use to draw part + }; + + enum POPUPCHECKSTATES + { + MC_CHECKMARKNORMAL = 1, + MC_CHECKMARKDISABLED = 2, + MC_BULLETNORMAL = 3, + MC_BULLETDISABLED = 4, + }; + + enum POPUPCHECKBACKGROUNDSTATES + { + MCB_DISABLED = 1, + MCB_NORMAL = 2, + MCB_BITMAP = 3, + }; + + enum POPUPITEMSTATES + { + MPI_NORMAL = 1, + MPI_HOT = 2, + MPI_DISABLED = 3, + MPI_DISABLEDHOT = 4, + }; + + enum POPUPSUBMENUSTATES + { + MSM_NORMAL = 1, + MSM_DISABLED = 2, + }; + + enum MENUPARTS + { + MENU_MENUITEM_TMSCHEMA = 1, + MENU_MENUDROPDOWN_TMSCHEMA = 2, + MENU_MENUBARITEM_TMSCHEMA = 3, + MENU_MENUBARDROPDOWN_TMSCHEMA = 4, + MENU_CHEVRON_TMSCHEMA = 5, + MENU_SEPARATOR_TMSCHEMA = 6, + MENU_BARBACKGROUND = 7, + MENU_BARITEM = 8, + MENU_POPUPBACKGROUND = 9, + MENU_POPUPBORDERS = 10, + MENU_POPUPCHECK = 11, + MENU_POPUPCHECKBACKGROUND = 12, + MENU_POPUPGUTTER = 13, + MENU_POPUPITEM = 14, + MENU_POPUPSEPARATOR = 15, + MENU_POPUPSUBMENU = 16, + MENU_SYSTEMCLOSE = 17, + MENU_SYSTEMMAXIMIZE = 18, + MENU_SYSTEMMINIMIZE = 19, + MENU_SYSTEMRESTORE = 20, + }; + + + // Forward declaration of CFrame. Its defined later. + class CFrame; + + struct MenuItemData + // Each Dropdown menu item has this data + { + HMENU hMenu; + MENUITEMINFO mii; + UINT nPos; + std::vector vItemText; + + MenuItemData() : hMenu(0), nPos(0) { vItemText.assign(MAX_MENU_STRING, _T('\0')); } + LPTSTR GetItemText() {return &vItemText[0];} + }; + + + //////////////////////////////////// + // 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 CMenuMetrics class + // This class is used by CFrame to retrieve the size of the components + // used to perform owner-drawing of menu items. Windows Visual Styles + // are used to render menu items for systems running Aero (Vista and above). + // Win32++ custom themes are used to render menu items for systems without Aero. + class CMenuMetrics + { + public: + CMenuMetrics(CFrame* pFrame); + ~CMenuMetrics(); + + CRect GetCheckBackgroundRect(CRect rcItem); + CRect GetCheckRect(CRect rcItem); + CRect GetGutterRect(CRect rcItem); + CRect GetSelectionRect(CRect rcItem); + CRect GetSeperatorRect(CRect rcItem); + CRect GetTextRect(CRect rcItem); + CSize GetTextSize(MenuItemData* pmd); + void Initialize(); + int ToItemStateId(UINT uItemState); + int ToCheckBackgroundStateId(int iStateId); + int ToCheckStateId(UINT fType, int iStateId); + + // Wrappers for Windows API functions + HRESULT CloseThemeData(); + HRESULT DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect); + HRESULT DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect); + HRESULT GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz); + HRESULT GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal); + HRESULT GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins); + HRESULT GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect); + BOOL IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId); + HANDLE OpenThemeData(HWND hwnd, LPCWSTR pszClassList); + + HANDLE m_hTheme; // Theme handle + CFrame* m_pFrame; // Pointer to the frame window + HMODULE m_hmodUXTheme; // Module handle to the UXTheme dll + + CMargins m_marCheck; // Check margins + CMargins m_marCheckBackground; // Check background margins + CMargins m_marItem; // Item margins + CMargins m_marText; // Text margins + + CSize m_sizeCheck; // Check size metric + CSize m_sizeSeparator; // Separator size metric + + private: + typedef HRESULT WINAPI CLOSETHEMEDATA(HANDLE); + typedef HRESULT WINAPI DRAWTHEMEBACKGROUND(HANDLE, HDC, int, int, const RECT*, const RECT*); + typedef HRESULT WINAPI DRAWTHEMETEXT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, DWORD, LPCRECT); + typedef HRESULT WINAPI GETTHEMEPARTSIZE(HANDLE, HDC, int, int, LPCRECT, THEMESIZE, SIZE*); + typedef HRESULT WINAPI GETTHEMEINT(HANDLE, int, int, int, int*); + typedef HRESULT WINAPI GETTHEMEMARGINS(HANDLE, HDC, int, int, int, LPRECT, MARGINS*); + typedef HRESULT WINAPI GETTHEMETEXTEXTENT(HANDLE, HDC, int, int, LPCWSTR, int, DWORD, LPCRECT, LPCRECT); + typedef HRESULT WINAPI ISTHEMEBGPARTTRANSPARENT(HANDLE, int, int); + typedef HANDLE WINAPI OPENTHEMEDATA(HWND, LPCWSTR); + + // Pointers to functions defined in uxTheme.dll + CLOSETHEMEDATA* m_pfnCloseThemeData; + DRAWTHEMEBACKGROUND* m_pfnDrawThemeBackground; + DRAWTHEMETEXT* m_pfnDrawThemeText; + GETTHEMEPARTSIZE* m_pfnGetThemePartSize; + GETTHEMEINT* m_pfnGetThemeInt; + GETTHEMEMARGINS* m_pfnGetThemeMargins; + GETTHEMETEXTEXTENT* m_pfnGetThemeTextExtent; + ISTHEMEBGPARTTRANSPARENT* m_pfnIsThemeBGPartTransparent; + OPENTHEMEDATA* m_pfnOpenThemeData; + }; + + + ////////////////////////////////// + // Declaration of the CFrame class + // + class CFrame : public CWnd + { + friend class CMenuBar; + typedef Shared_Ptr ItemDataPtr; + + public: + CFrame(); + virtual ~CFrame(); + + // Override these functions as required + virtual void AdjustFrameRect(RECT rcView) const; + virtual CString GetThemeName() 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; } + CString GetRegistryKeyName() const { return m_strKeyName; } + CWnd* GetView() const { return m_pView; } + CString 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); + 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 DrawMenuItem(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis); + virtual void DrawMenuItemText(LPDRAWITEMSTRUCT pdis); + virtual int GetMenuItemPos(HMENU hMenu, LPCTSTR szItem); + virtual BOOL LoadRegistrySettings(LPCTSTR szKeyName); + virtual BOOL LoadRegistryMRUSettings(UINT nMaxMRU = 0); + virtual void MeasureMenuItem(MEASUREITEMSTRUCT *pmis); + 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, + }; + + Shared_Ptr m_pMenuMetrics; // Smart pointer for CMenuMetrics + CString m_strStatusText; // CString 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_bUseToolBar; // set to TRUE if the toolbar is used + 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 MenuItemData pointers + std::vector m_vMRUEntries; // Vector of CStrings for MRU entires + std::vector m_vMenuIcons; // vector of menu icon resource IDs + 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 + CFont m_fntMenuBar; // MenuBar font + CFont m_fntStatusBar; // StatusBar font + 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; + CString m_strKeyName; // CString for Registry key name + CString m_strTooltip; // CString for tool tips + CString m_XPThemeName; // CString for Windows Theme Name + 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 DrawDC(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; + DrawDC.DrawIconEx(x, y, hIcon, cx, cy, 0, NULL, DI_NORMAL); + + DrawDC.Detach(); + return CDRF_SKIPDEFAULT; // No further drawing + } + + else if (nState & (CDIS_HOT | CDIS_SELECTED)) + { + if ((nState & CDIS_SELECTED) || (GetButtonState(dwItem) & TBSTATE_PRESSED)) + { + DrawDC.GradientFill(m_ThemeMenu.clrPressed1, m_ThemeMenu.clrPressed2, rcRect, FALSE); + } + else if (nState & CDIS_HOT) + { + DrawDC.GradientFill(m_ThemeMenu.clrHot1, m_ThemeMenu.clrHot2, rcRect, FALSE); + } + + // Draw border + DrawDC.CreatePen(PS_SOLID, 1, m_ThemeMenu.clrOutline); + DrawDC.MoveTo(rcRect.left, rcRect.bottom); + DrawDC.LineTo(rcRect.left, rcRect.top); + DrawDC.LineTo(rcRect.right-1, rcRect.top); + DrawDC.LineTo(rcRect.right-1, rcRect.bottom); + DrawDC.MoveTo(rcRect.right-1, rcRect.bottom); + DrawDC.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 + CFont* pFont = GetFont(); + ::SelectObject(DrawDC, pFont->GetHandle()); + + rcRect.bottom += 1; + int iMode = DrawDC.SetBkMode(TRANSPARENT); + DrawDC.DrawText(str, lstrlen(str), rcRect, DT_VCENTER | DT_CENTER | DT_SINGLELINE); + + DrawDC.SetBkMode(iMode); + DrawDC.Detach(); + return CDRF_SKIPDEFAULT; // No further drawing + } + DrawDC.Detach(); + } + return CDRF_DODEFAULT ; // Do default drawing + + // Painting cycle has completed + case CDDS_POSTPAINT: + // Draw MDI Minimise, Restore and Close buttons + { + CDC DrawDC(lpNMCustomDraw->nmcd.hdc); + DrawAllMDIButtons(DrawDC); + DrawDC.Detach(); + } + 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(...) + + + inline CMenuMetrics::CMenuMetrics(CFrame* pFrame) : m_hTheme(0), m_hmodUXTheme(0), m_pfnCloseThemeData(0), m_pfnDrawThemeBackground(0), + m_pfnDrawThemeText(0), m_pfnGetThemePartSize(0), m_pfnGetThemeInt(0), m_pfnGetThemeMargins(0), + m_pfnGetThemeTextExtent(0), m_pfnIsThemeBGPartTransparent(0), m_pfnOpenThemeData(0) + { + assert(pFrame); + m_pFrame = pFrame; + + Initialize(); + } + + inline void CMenuMetrics::Initialize() + { + assert(m_pFrame); + + if (!m_hmodUXTheme) + m_hmodUXTheme = ::LoadLibrary(_T("UXTHEME.DLL")); + + if (m_hmodUXTheme) + { + m_pfnCloseThemeData = (CLOSETHEMEDATA*)::GetProcAddress(m_hmodUXTheme, "CloseThemeData"); + m_pfnDrawThemeBackground = (DRAWTHEMEBACKGROUND*)::GetProcAddress(m_hmodUXTheme, "DrawThemeBackground"); + m_pfnDrawThemeText = (DRAWTHEMETEXT*)::GetProcAddress(m_hmodUXTheme, "DrawThemeText"); + m_pfnGetThemePartSize = (GETTHEMEPARTSIZE*)::GetProcAddress(m_hmodUXTheme, "GetThemePartSize"); + m_pfnGetThemeInt = (GETTHEMEINT*)::GetProcAddress(m_hmodUXTheme, "GetThemeInt"); + m_pfnGetThemeMargins = (GETTHEMEMARGINS*)::GetProcAddress(m_hmodUXTheme, "GetThemeMargins"); + m_pfnGetThemeTextExtent = (GETTHEMETEXTEXTENT*)::GetProcAddress(m_hmodUXTheme, "GetThemeTextExtent"); + m_pfnIsThemeBGPartTransparent = (ISTHEMEBGPARTTRANSPARENT*)::GetProcAddress(m_hmodUXTheme, "IsThemeBackgroundPartiallyTransparent"); + m_pfnOpenThemeData = (OPENTHEMEDATA*)::GetProcAddress(m_hmodUXTheme, "OpenThemeData"); + } + + if (m_hTheme) + { + CloseThemeData(); + m_hTheme = 0; + } + + m_hTheme = OpenThemeData(*m_pFrame, VSCLASS_MENU); + + if (m_hTheme) + { + int iBorderSize = 0; // Border space between item text and accelerator + int iBgBorderSize = 0; // Border space between item text and gutter + GetThemePartSize(NULL, MENU_POPUPCHECK, 0, NULL, TS_TRUE, &m_sizeCheck); + GetThemePartSize(NULL, MENU_POPUPSEPARATOR, 0, NULL, TS_TRUE, &m_sizeSeparator); + GetThemeInt(MENU_POPUPITEM, 0, TMT_BORDERSIZE, &iBorderSize); + GetThemeInt(MENU_POPUPBACKGROUND, 0, TMT_BORDERSIZE, &iBgBorderSize); + GetThemeMargins(NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &m_marCheck); + GetThemeMargins(NULL, MENU_POPUPCHECKBACKGROUND, 0, TMT_CONTENTMARGINS, NULL, &m_marCheckBackground); + GetThemeMargins(NULL, MENU_POPUPITEM, 0, TMT_CONTENTMARGINS, NULL, &m_marItem); + + // Popup text margins + m_marText = m_marItem; + m_marText.cxRightWidth = iBorderSize; + m_marText.cxLeftWidth = iBgBorderSize; + } + else + { + m_sizeCheck.SetSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + m_sizeSeparator.SetSize(1, 7); + m_marCheck.SetMargins(4, 4, 2, 2); + m_marCheckBackground.SetMargins(0, 0, 0, 0); + m_marItem.SetMargins(0, 0, 0, 0); + m_marText.SetMargins(8, 16, 0, 0); + } + } + + inline CMenuMetrics::~CMenuMetrics() + { + if (m_hTheme) + CloseThemeData(); + + if (m_hmodUXTheme) + ::FreeLibrary(m_hmodUXTheme); + } + + inline HRESULT CMenuMetrics::CloseThemeData() + { + if (m_pfnCloseThemeData) + return (*m_pfnCloseThemeData)(m_hTheme); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::DrawThemeBackground(HDC hdc, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect) + { + if (m_pfnDrawThemeBackground) + return (*m_pfnDrawThemeBackground)(m_hTheme, hdc, iPartId, iStateId, pRect, pClipRect); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::DrawThemeText(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, DWORD dwTextFlags2, LPCRECT pRect) + { + if (m_pfnDrawThemeText) + return (*m_pfnDrawThemeText)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, pRect); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemePartSize(HDC hdc, int iPartId, int iStateId, LPCRECT prc, THEMESIZE eSize, SIZE* psz) + { + if (m_pfnGetThemePartSize) + return (*m_pfnGetThemePartSize)(m_hTheme, hdc, iPartId, iStateId, prc, eSize, psz); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeInt(int iPartId, int iStateId, int iPropId, int* piVal) + { + if (m_pfnGetThemeInt) + return (*m_pfnGetThemeInt)(m_hTheme, iPartId, iStateId, iPropId, piVal); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeMargins(HDC hdc, int iPartId, int iStateId, int iPropId, LPRECT prc, MARGINS* pMargins) + { + if (m_pfnGetThemeMargins) + return (*m_pfnGetThemeMargins)(m_hTheme, hdc, iPartId, iStateId, iPropId, prc, pMargins); + + return E_NOTIMPL; + } + + inline HRESULT CMenuMetrics::GetThemeTextExtent(HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int iCharCount, DWORD dwTextFlags, LPCRECT pBoundingRect, LPRECT pExtentRect) + { + if (m_pfnGetThemeTextExtent) + return (*m_pfnGetThemeTextExtent)(m_hTheme, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, pBoundingRect, pExtentRect); + + return E_NOTIMPL; + } + + inline BOOL CMenuMetrics::IsThemeBackgroundPartiallyTransparent(int iPartId, int iStateId) + { + if (m_pfnIsThemeBGPartTransparent) + return (*m_pfnIsThemeBGPartTransparent)(m_hTheme, iPartId, iStateId); + + return E_NOTIMPL; + } + + inline HANDLE CMenuMetrics::OpenThemeData(HWND hwnd, LPCWSTR pszClassList) + { + if (m_pfnOpenThemeData) + return (*m_pfnOpenThemeData)(hwnd, pszClassList); + + return NULL; + } + + inline CRect CMenuMetrics::GetCheckBackgroundRect(CRect rcItem) + { + int x = rcItem.left + m_marCheckBackground.cxLeftWidth; + int y = rcItem.top + m_marCheckBackground.cyTopHeight; + int cx = m_sizeCheck.cx + m_marCheck.Width(); + int cy = m_sizeCheck.cy + m_marCheck.Height(); + + return CRect(x, y, x + cx, y + cy); + } + + inline CRect CMenuMetrics::GetGutterRect(CRect rcItem) + { + int x = rcItem.left; + int y = rcItem.top; + int cx = m_marItem.cxLeftWidth + m_marCheckBackground.Width() + m_marCheck.Width() + m_sizeCheck.cx; + int cy = rcItem.Height(); + + return CRect(x, y, x + cx, y + cy); + } + + inline CRect CMenuMetrics::GetCheckRect(CRect rcItem) + { + int x = rcItem.left + m_marCheckBackground.cxLeftWidth + m_marCheck.cxLeftWidth; + int y = rcItem.top + m_marCheckBackground.cyTopHeight + m_marCheck.cyTopHeight; + + return CRect(x, y, x + m_sizeCheck.cx, y + m_sizeCheck.cy); + } + + inline CRect CMenuMetrics::GetSelectionRect(CRect rcItem) + { + int x = rcItem.left + m_marItem.cxLeftWidth; + int y = rcItem.top; + + return CRect(x, y, rcItem.right - m_marItem.cxRightWidth, y + rcItem.Height()); + } + + inline CRect CMenuMetrics::GetSeperatorRect(CRect rcItem) + { + int left = GetGutterRect(rcItem).right; + int top = rcItem.top; + int right = rcItem.right - m_marItem.cxRightWidth; + int bottom = rcItem.top + m_sizeSeparator.cy; + + return CRect(left, top, right, bottom); + } + + inline CSize CMenuMetrics::GetTextSize(MenuItemData* pmd) + { + CSize sizeText; + assert(m_pFrame); + CClientDC DesktopDC(NULL); + LPCTSTR szItemText = pmd->GetItemText(); + + if (IsAeroThemed()) + { + CRect rcText; + GetThemeTextExtent(DesktopDC, MENU_POPUPITEM, 0, T2W(szItemText), lstrlen(szItemText), + DT_LEFT | DT_SINGLELINE, NULL, &rcText); + + sizeText.SetSize(rcText.right + m_marText.Width(), rcText.bottom + m_marText.Height()); + } + else + { + // 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; + + // Calculate the size of the text + DesktopDC.CreateFontIndirect(&nm.lfMenuFont); + sizeText = DesktopDC.GetTextExtentPoint32(szItemText, lstrlen(szItemText)); + // sizeText.cx += m_marText.Width(); + sizeText.cx += m_marText.cxRightWidth; + sizeText.cy += m_marText.Height(); + } + + if (_tcschr(szItemText, _T('\t'))) + sizeText.cx += 8; // Add POST_TEXT_GAP if the text includes a tab + + return sizeText; + } + + inline CRect CMenuMetrics::GetTextRect(CRect rcItem) + { + int left = GetGutterRect(rcItem).Width() + m_marText.cxLeftWidth; + int top = rcItem.top + m_marText.cyTopHeight; + int right = rcItem.right - m_marItem.cxRightWidth - m_marText.cxRightWidth; + int bottom = rcItem.bottom - m_marText.cyBottomHeight; + + return CRect(left, top, right, bottom); + } + + inline int CMenuMetrics::ToItemStateId(UINT uItemState) + { + const bool fDisabled = ((uItemState & (ODS_INACTIVE | ODS_DISABLED)) != 0); + const bool fHot = ((uItemState & (ODS_HOTLIGHT | ODS_SELECTED)) != 0); + POPUPITEMSTATES iState; + + if (fDisabled) + iState = (fHot ? MPI_DISABLEDHOT : MPI_DISABLED); + else if (fHot) + iState = MPI_HOT; + else + iState= MPI_NORMAL; + + return iState; + } + + inline int CMenuMetrics::ToCheckBackgroundStateId(int iStateId) + { + POPUPCHECKBACKGROUNDSTATES iStateIdCheckBackground; + + // Determine the check background state. + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheckBackground = MCB_DISABLED; + else + iStateIdCheckBackground = MCB_NORMAL; + + return iStateIdCheckBackground; + } + + inline int CMenuMetrics::ToCheckStateId(UINT fType, int iStateId) + { + POPUPCHECKSTATES iStateIdCheck; + + if (fType & MFT_RADIOCHECK) + { + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheck = MC_BULLETDISABLED; + else + iStateIdCheck = MC_BULLETNORMAL; + } + else + { + if (iStateId == MPI_DISABLED || iStateId == MPI_DISABLEDHOT) + iStateIdCheck = MC_CHECKMARKDISABLED; + else + iStateIdCheck = MC_CHECKMARKNORMAL; + } + + return iStateIdCheck; + } + + + /////////////////////////////////// + // Definitions for the CFrame class + // + inline CFrame::CFrame() : m_pMenuMetrics(0), m_strStatusText(_T("Ready")), m_bShowIndicatorStatus(TRUE), m_bShowMenuStatus(TRUE), + m_bUseReBar(FALSE), m_bUseThemes(TRUE), m_bUseToolBar(TRUE), m_bShowStatusBar(TRUE), m_bShowToolBar(TRUE), + m_himlMenu(0), m_himlMenuDis(0), 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'); + + NONCLIENTMETRICS nm = {0}; + nm.cbSize = GetSizeofNonClientMetrics(); + SystemParametersInfo (SPI_GETNONCLIENTMETRICS, 0, &nm, 0); + m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont); + m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont); + } + + 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) + { + // Create a new ImageList if required + if (NULL == m_himlMenu) + { + if (m_himlMenu) ImageList_Destroy(m_himlMenu); + m_himlMenu = ImageList_Create(16, 16, 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("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("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("Warning ... No resource IDs assigned to the toolbar\n"); + } + } + + inline void CFrame::DrawMenuItem(LPDRAWITEMSTRUCT pdis) + { + MenuItemData* pmid = (MenuItemData*)pdis->itemData; + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + MenuTheme tm = GetMenuTheme(); + CDC DrawDC(pdis->hDC); + + if (IsAeroThemed() && m_pMenuMetrics->IsThemeBackgroundPartiallyTransparent(MENU_POPUPITEM, iStateId)) + { + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPBACKGROUND, 0, &pdis->rcItem, NULL); + } + + // Draw the gutter + CRect rcGutter = m_pMenuMetrics->GetGutterRect(pdis->rcItem); + if (IsAeroThemed()) + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPGUTTER, 0, &rcGutter, NULL); + else + DrawDC.GradientFill(tm.clrPressed1, tm.clrPressed2, rcGutter, TRUE); + + if (pmid->mii.fType & MFT_SEPARATOR) + { + // Draw the separator + if (IsAeroThemed()) + { + CRect rcSeparator = m_pMenuMetrics->GetSeperatorRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSEPARATOR, 0, &rcSeparator, NULL); + } + else + { + CRect rc = pdis->rcItem; + CRect rcSep = pdis->rcItem; + rcSep.left = m_pMenuMetrics->GetGutterRect(rc).Width() + 2; + DrawDC.SolidFill(RGB(255,255,255), rcSep); + rcSep.top += (rc.bottom - rc.top)/2; + DrawDC.DrawEdge(rcSep, EDGE_ETCHED, BF_TOP); + } + } + else + { + // Draw the item background + DrawMenuItemBkgnd(pdis); + + // Draw Checkmark or icon + if (pmid->mii.fState & MFS_CHECKED) + DrawMenuItemCheckmark(pdis); + else + DrawMenuItemIcon(pdis); + + // Draw the text. + DrawMenuItemText(pdis); + } + + if (IsAeroThemed()) + { + // Draw the Submenu arrow + if (pmid->mii.hSubMenu) + { + CRect rcSubMenu = pdis->rcItem; + rcSubMenu.left = pdis->rcItem.right - m_pMenuMetrics->m_marItem.cxRightWidth - m_pMenuMetrics->m_marText.cxRightWidth;; + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPSUBMENU, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcSubMenu, NULL); + } + + // Suppress further drawing to prevent an incorrect Submenu arrow being drawn + CRect rc = pdis->rcItem; + ::ExcludeClipRect(pdis->hDC, rc.left, rc.top, rc.right, rc.bottom); + } + + DrawDC.Detach(); + } + + inline void CFrame::DrawMenuItemBkgnd(LPDRAWITEMSTRUCT pdis) + { + // Draw the item background + CRect rcSelection = m_pMenuMetrics->GetSelectionRect(pdis->rcItem); + if (IsAeroThemed()) + { + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPITEM, iStateId, &rcSelection, NULL); + } + else + { + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + BOOL bSelected = pdis->itemState & ODS_SELECTED; + CRect rcDraw = pdis->rcItem; + CDC* pDrawDC = FromHandle(pdis->hDC); + MenuTheme tm = GetMenuTheme(); + + if ((bSelected) && (!bDisabled)) + { + // draw selected item background + pDrawDC->CreateSolidBrush(tm.clrHot1); + pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline); + pDrawDC->Rectangle(rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom); + } + else + { + // draw non-selected item background + rcDraw.left = m_pMenuMetrics->GetGutterRect(pdis->rcItem).Width(); + pDrawDC->SolidFill(RGB(255,255,255), rcDraw); + } + } + } + + inline void CFrame::DrawMenuItemCheckmark(LPDRAWITEMSTRUCT pdis) + // Draws the checkmark or radiocheck transparently + { + CRect rc = pdis->rcItem; + UINT fType = ((MenuItemData*)pdis->itemData)->mii.fType; + MenuTheme tm = GetMenuTheme(); + CRect rcBk; + CDC* pDrawDC = FromHandle(pdis->hDC); + + if (IsAeroThemed()) + { + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + MenuItemData* pmid = (MenuItemData*)pdis->itemData; + CRect rcCheckBackground = m_pMenuMetrics->GetCheckBackgroundRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECKBACKGROUND, m_pMenuMetrics->ToCheckBackgroundStateId(iStateId), &rcCheckBackground, NULL); + CRect rcCheck = m_pMenuMetrics->GetCheckRect(pdis->rcItem); + m_pMenuMetrics->DrawThemeBackground(pdis->hDC, MENU_POPUPCHECK, m_pMenuMetrics->ToCheckStateId(pmid->mii.fType, iStateId), &rcCheck, NULL); + } + else + { + // Draw the checkmark's background rectangle first + int Iconx = m_pMenuMetrics->m_sizeCheck.cx; + int Icony = m_pMenuMetrics->m_sizeCheck.cy; + int left = m_pMenuMetrics->m_marCheck.cxLeftWidth; + int top = rc.top + (rc.Height() - Icony)/2; + rcBk.SetRect(left, top, left + Iconx, top + Icony); + + pDrawDC->CreateSolidBrush(tm.clrHot2); + pDrawDC->CreatePen(PS_SOLID, 1, tm.clrOutline); + + // Draw the checkmark's background rectangle + pDrawDC->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; + + 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); + pDrawDC->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); + pDrawDC->BitBlt(rcBk.left + xoffset, rcBk.top + yoffset, cxCheck, cyCheck, &MaskDC, 0, 0, SRCAND); + } + } + } + + inline void CFrame::DrawMenuItemIcon(LPDRAWITEMSTRUCT pdis) + { + if (!m_himlMenu) + return; + + // Get icon size + int Iconx = m_pMenuMetrics->m_sizeCheck.cx; + int Icony = m_pMenuMetrics->m_sizeCheck.cy; + + // get the drawing rectangle + CRect rc = pdis->rcItem; + int left = m_pMenuMetrics->m_marCheck.cxLeftWidth; + 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 ) + { + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + if ((bDisabled) && (m_himlMenuDis)) + ImageList_Draw(m_himlMenuDis, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT); + else + ImageList_Draw(m_himlMenu, iImage, pdis->hDC, rc.left, rc.top, ILD_TRANSPARENT); + } + } + + inline void CFrame::DrawMenuItemText(LPDRAWITEMSTRUCT pdis) + { + LPCTSTR ItemText = ((MenuItemData*)pdis->itemData)->GetItemText(); + BOOL bDisabled = pdis->itemState & ODS_GRAYED; + COLORREF colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT : COLOR_MENUTEXT); + + // Calculate the text rect size + CRect rcText = m_pMenuMetrics->GetTextRect(pdis->rcItem); + + // 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 + if (IsAeroThemed()) + { + ULONG uAccel = ((pdis->itemState & ODS_NOACCEL) ? DT_HIDEPREFIX : 0); + int iStateId = m_pMenuMetrics->ToItemStateId(pdis->itemState); + + // Draw the item text before the tab + m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(ItemText), nTab, DT_SINGLELINE | DT_LEFT | DT_TOP | uAccel, 0, &rcText); + + // Draw text after tab, right aligned + if(nTab != -1) + m_pMenuMetrics->DrawThemeText(pdis->hDC, MENU_POPUPITEM, iStateId, T2W(&ItemText[nTab + 1]), -1, DT_SINGLELINE | DT_RIGHT | DT_TOP | uAccel, 0, &rcText); + } + else + { + SetTextColor(pdis->hDC, colorText); + int iMode = SetBkMode(pdis->hDC, TRANSPARENT); + DrawText(pdis->hDC, ItemText, nTab, rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER); + + // Draw text after tab, right aligned + if(nTab != -1) + DrawText(pdis->hDC, &ItemText[nTab + 1], -1, rcText, DT_SINGLELINE | DT_RIGHT | DT_VCENTER); + + SetBkMode(pdis->hDC, iMode); + } + } + + 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 CString CFrame::GetMRUEntry(UINT nIndex) + { + CString strPathName; + if (nIndex < m_vMRUEntries.size()) + { + strPathName = m_vMRUEntries[nIndex]; + + // Now put the selected entry at Index 0 + AddMRUEntry(strPathName); + } + return strPathName; + } + + 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 CString CFrame::GetThemeName() const + { + // Returns the XP theme name + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + WCHAR ThemeName[31] = L""; + 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, ThemeName, 30, 0, 0); + + ::FreeLibrary(hMod); + } + + return CString(ThemeName); + } + + 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_strKeyName.IsEmpty()); // KeyName must be set before calling LoadRegistryMRUSettings + HKEY hKey = NULL; + BOOL bRet = FALSE; + + try + { + m_nMaxMRU = MIN(nMaxMRU, 16); + std::vector vMRUEntries; + CString strKey = _T("Software\\") + m_strKeyName + _T("\\Recent Files"); + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 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("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_strKeyName = szKeyName; + + CString strKey = _T("Software\\") + m_strKeyName + _T("\\Frame Settings"); + HKEY hKey = 0; + BOOL bRet = FALSE; + + try + { + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 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("Failed to load values from registry, using defaults!\n"); + e.what(); + + if (hKey) + RegCloseKey(hKey); + } + + return bRet; + } + + inline void CFrame::MeasureMenuItem(MEASUREITEMSTRUCT *pmis) + { + int cxTotal = 0; + int cyMax = 0; + + MenuItemData* pmid = (MenuItemData*)pmis->itemData; + assert(::IsMenu(pmid->hMenu)); // Does itemData contain a valid MenuItemData struct? + + // Add icon/check width + cxTotal += m_pMenuMetrics->m_sizeCheck.cx + m_pMenuMetrics->m_marCheckBackground.Width() + m_pMenuMetrics->m_marCheck.Width(); + + if (pmid->mii.fType & MFT_SEPARATOR) + { + // separator height + cyMax = m_pMenuMetrics->m_sizeSeparator.cy + m_pMenuMetrics->m_marItem.Height(); + } + else + { + // Add check background horizontal padding. + cxTotal += m_pMenuMetrics->m_marCheckBackground.cxLeftWidth + m_pMenuMetrics->m_marCheckBackground.cxRightWidth; + + // Add selection margin padding. + cxTotal += m_pMenuMetrics->m_marItem.cxLeftWidth + m_pMenuMetrics->m_marItem.cxRightWidth; + + // Account for text size + CSize sizeText = m_pMenuMetrics->GetTextSize(pmid); + cxTotal += sizeText.cx; + cyMax = MAX(cyMax, sizeText.cy); + + // Account for icon or check height + cyMax = MAX(cyMax, m_pMenuMetrics->m_sizeCheck.cy + m_pMenuMetrics->m_marCheckBackground.Height() + m_pMenuMetrics->m_marCheck.Height()); + } + + // Return the composite sizes. + pmis->itemWidth = cxTotal; + pmis->itemHeight = cyMax; + } + + 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); + m_pMenuMetrics = new CMenuMetrics(this); + + UpdateMRUMenu(); + + // Create the ToolBar + if (m_bUseToolBar) + { + CreateToolBar(); + ShowToolBar(m_bShowToolBar); + } + else + { + GetFrameMenu().CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED); + GetFrameMenu().EnableMenuItem(IDW_VIEW_TOOLBAR, MF_GRAYED); + } + + // Create the status bar + GetStatusBar().Create(this); + GetStatusBar().SetFont(&m_fntStatusBar, FALSE); + 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 + OnSysColorChange(); + 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); + + if (!IsRectEmpty(&pdis->rcItem)) + DrawMenuItem(pdis); + + return TRUE; + } + + inline void CFrame::OnExitMenuLoop() + { + if (m_bUseThemes) + { + 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]->mii.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_bUseThemes) + { + CMenu* pMenu = FromHandle((HMENU)wParam); + + for (UINT i = 0; i < pMenu->GetMenuItemCount(); ++i) + { + MenuItemData* pItem = new MenuItemData; // deleted in OnExitMenuLoop + m_vMenuItemData.push_back(ItemDataPtr(pItem)); // Store pItem in smart pointer for later automatic deletion + + MENUITEMINFO mii = {0}; + mii.cbSize = GetSizeofMenuItemInfo(); + + // Use old fashioned MIIM_TYPE instead of MIIM_FTYPE for MS VC6 compatibility + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU |MIIM_CHECKMARKS | MIIM_TYPE | MIIM_DATA; + mii.dwTypeData = pItem->GetItemText(); // assign TCHAR pointer, text is assigned by GetMenuItemInfo + 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) + { + pItem->hMenu = *pMenu; + pItem->nPos = i; + pItem->mii = mii; + mii.dwItemData = (DWORD_PTR)pItem; + mii.fType |= MFT_OWNERDRAW; + 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); + + MeasureMenuItem(pmis); + 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_strStatusText = LoadString(nID); + else + m_strStatusText = _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_strTooltip = LoadString(nID); + lpDispInfo->lpszText = (LPTSTR)m_strTooltip.c_str(); + } + else + m_strTooltip = _T(""); + } + } + } + break; + } // switch LPNMHDR + + return 0L; + + } // CFrame::Onotify(...) + + inline void CFrame::OnSetFocus() + { + SetStatusText(); + } + + inline void CFrame::OnSysColorChange() + { + // Honour theme color changes + if (GetReBar().IsWindow()) + { + 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); + m_fntStatusBar.CreateFontIndirect(&nm.lfStatusFont); + GetStatusBar().SetFont(&m_fntStatusBar, TRUE); + SetStatusText(); + + + if (GetMenuBar().IsWindow()) + { + // Update the MenuBar font and button size + m_fntMenuBar.CreateFontIndirect(&nm.lfMenuFont); + GetMenuBar().SetFont(&m_fntMenuBar, TRUE); + GetMenuBar().SetMenu(GetFrameMenu()); + + // Update the MenuBar band size + int nBand = GetReBar().GetBand(GetMenuBar()); + REBARBANDINFO rbbi = {0}; + CClientDC dcMenuBar(&GetMenuBar()); + dcMenuBar.SelectObject(GetMenuBar().GetFont()); + CSize sizeMenuBar = dcMenuBar.GetTextExtentPoint32(_T("\tSomeText"), lstrlen(_T("\tSomeText"))); + int MenuBar_Height = sizeMenuBar.cy + 6; + rbbi.fMask = RBBIM_CHILDSIZE; + rbbi.cyMinChild = MenuBar_Height; + rbbi.cyMaxChild = MenuBar_Height; + GetReBar().SetBandInfo(nBand, rbbi); + } + + if (m_XPThemeName != GetThemeName()) + SetTheme(); + m_pMenuMetrics->Initialize(); + + // 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_strStatusText = LoadString(nID); + else + m_strStatusText = _T("Ready"); + + if (GetStatusBar().IsWindow()) + SetStatusText(); + } + m_nOldID = nID; + } + } + else + { + if (m_nOldID != -1) + { + m_strStatusText = _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_strKeyName.IsEmpty()) + { + CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Frame Settings"); + HKEY hKey = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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("Failed to save registry settings\n"); + + if (hKey) + { + // Roll back the registry changes by deleting this subkey + RegDeleteKey(HKEY_CURRENT_USER ,strKeyName); + RegCloseKey(hKey); + } + + e.what(); + return FALSE; + } + + // Store the MRU entries in the registry + if (m_nMaxMRU > 0) + { + CString strKeyName = _T("Software\\") + m_strKeyName + _T("\\Recent Files"); + HKEY hKey = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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); + CString strPathName; + if (i < m_vMRUEntries.size()) + strPathName = m_vMRUEntries[i]; + + if (ERROR_SUCCESS != RegSetValueEx(hKey, szSubKey, 0, REG_SZ, (LPBYTE)strPathName.c_str(), (1 + strPathName.GetLength() )*sizeof(TCHAR))) + throw CWinException(_T("RegSetValueEx failed")); + } + + RegCloseKey(hKey); + } + + catch (const CWinException& e) + { + TRACE("Failed to save registry MRU settings\n"); + + if (hKey) + { + // Roll back the registry changes by deleting this subkey + RegDeleteKey(HKEY_CURRENT_USER ,strKeyName); + 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_strStatusText); + } + } + + 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) + { + // Retrieve the XP theme name + m_XPThemeName = GetThemeName(); + + enum Themetype{ Modern, Grey, Blue, Silver, Olive }; + + int Theme = Grey; + if (GetWinVersion() < 2600) // Not for Vista and above + { + if (m_XPThemeName == _T("NormalColor")) + Theme = Blue; + if (m_XPThemeName == _T("Metallic")) + Theme = Silver; + if (m_XPThemeName == _T("HomeStead")) + 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(225, 230, 255), RGB(240, 242, 250), RGB(248, 248, 248), 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); + m_bShowStatusBar = TRUE; + } + else + { + m_Menu.CheckMenuItem(IDW_VIEW_STATUSBAR, MF_UNCHECKED); + GetStatusBar().ShowWindow(SW_HIDE); + m_bShowStatusBar = FALSE; + } + + // 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); + m_bShowToolBar = TRUE; + } + else + { + m_Menu.CheckMenuItem(IDW_VIEW_TOOLBAR, MF_UNCHECKED); + if (IsReBarUsed()) + GetReBar().SendMessage(RB_SHOWBAND, GetReBar().GetBand(GetToolBar()), FALSE); + else + GetToolBar().ShowWindow(SW_HIDE); + m_bShowToolBar = FALSE; + } + + 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 + CString strMRUArray[16]; + UINT MaxMRUArrayIndex = 0; + if (m_vMRUEntries.size() > 0) + { + for (UINT n = 0; ((n < m_vMRUEntries.size()) && (n <= m_nMaxMRU)); ++n) + { + strMRUArray[n] = m_vMRUEntries[n]; + if (strMRUArray[n].GetLength() > MAX_MENU_STRING - 10) + { + // Truncate the string if its too long + strMRUArray[n].Delete(0, strMRUArray[n].GetLength() - MAX_MENU_STRING +10); + strMRUArray[n] = _T("... ") + strMRUArray[n]; + } + + // Prefix the string with its number + TCHAR tVal[5]; + wsprintf(tVal, _T("%d "), n+1); + strMRUArray[n] = tVal + strMRUArray[n]; + MaxMRUArrayIndex = n; + } + } + else + { + strMRUArray[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)strMRUArray[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("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_ Index: include/reactos/libs/win32++/gdi.h =================================================================== --- include/reactos/libs/win32++/gdi.h (revision 0) +++ include/reactos/libs/win32++/gdi.h (working copy) @@ -0,0 +1,3992 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); +// 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); +// 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); + void DeleteObject(); + 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 + void CreateBitmap(int cx, int cy, UINT Planes, UINT BitsPerPixel, LPCVOID pvColors); + void CreateCompatibleBitmap(CDC* pDC, int cx, int cy); + void CreateDIBSection(CDC* pDC, const BITMAPINFO& bmi, UINT iUsage, LPVOID *ppvBits, + HANDLE hSection, DWORD dwOffset); + + CBitmap DetachBitmap(); + BITMAP GetBitmapData() const; + BOOL LoadBitmap(UINT nID); + BOOL LoadBitmap(LPCTSTR lpszName); + BOOL LoadImage(UINT nID, int cxDesired, int cyDesired, UINT fuLoad); + BOOL LoadImage(LPCTSTR lpszName, int cxDesired, int cyDesired, UINT fuLoad); + BOOL LoadOEMBitmap(UINT nIDBitmap); // for OBM_/OCR_/OIC + +#ifndef _WIN32_WCE + void CreateBitmapIndirect(LPBITMAP pBitmap); + void CreateDIBitmap(CDC* pDC, const BITMAPINFOHEADER& bmih, DWORD fdwInit, LPCVOID lpbInit, + BITMAPINFO& bmi, UINT fuUsage); + void CreateMappedBitmap(UINT nIDBitmap, UINT nFlags /*= 0*/, LPCOLORMAP lpColorMap /*= NULL*/, int nMapSize /*= 0*/); +#endif + + // Create and Select Brushes + void CreatePatternBrush(CBitmap* pBitmap); + void CreateSolidBrush(COLORREF rbg); + LOGBRUSH GetLogBrush() const; + +#ifndef _WIN32_WCE + void CreateBrushIndirect(LPLOGBRUSH pLogBrush); + void CreateHatchBrush(int fnStyle, COLORREF rgb); + void CreateDIBPatternBrush(HGLOBAL hglbDIBPacked, UINT fuColorSpec); + void CreateDIBPatternBrushPt(LPCVOID lpPackedDIB, UINT iUsage); +#endif + + // Create and Select Fonts + void CreateFontIndirect(LPLOGFONT plf); + LOGFONT GetLogFont() const; + +#ifndef _WIN32_WCE + void 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 + void CreatePen(int nStyle, int nWidth, COLORREF rgb); + void 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 void CGDIObject::DeleteObject() + { + assert(m_pData); + + if (m_pData->hGDIObject) + { + ::DeleteObject(Detach()); + } + } + + 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 == 0) + 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 void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap); + } + + inline CBitmap CDC::DetachBitmap() + // Provides a convenient method of detaching a bitmap from a memory device context. + // Returns the CBitmap detached from the DC. + // Useage: CBitmap MyBitmap = MyMemDC.DetachBitmap(); + { + // Create a stock bitmap to replace the current one. + CBitmap* pBitmap = new CBitmap; + pBitmap->CreateBitmap(1, 1, 1, 1, 0); + m_pData->m_vGDIObjects.push_back(pBitmap); + + // Select our new stock bitmap into the device context + HBITMAP hBitmap = (HBITMAP)::SelectObject(*this, *pBitmap); + + // Detach the bitmap from our internally managed GDIObjects + std::vector::iterator it; + for (it = m_pData->m_vGDIObjects.begin(); it < m_pData->m_vGDIObjects.end(); ++it) + { + if((*it)->GetHandle() == hBitmap) + (*it)->Detach(); + } + + // Create a local CBitmap. We can return this by value because it is reference counted + CBitmap Bitmap(hBitmap); + return Bitmap; + } + + 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; + } + } + } + + 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 BOOL CDC::LoadBitmap(UINT nID) + // Loads a bitmap from the resource and selects it into the device context + { + return LoadBitmap(MAKEINTRESOURCE(nID)); + } + + inline BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + + inline BOOL 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 BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + + inline BOOL 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); + + if (bResult) + ::SelectObject(*this, *pBitmap); + + return bResult; + } + +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBitmap);; + } +#endif // !_WIN32_WCE + + + // Brush functions +#ifndef _WIN32_WCE + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *pBrush); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *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 void 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); + ::SelectObject(m_pData->hDC, *pFont); + } +#endif + + inline void 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); + ::SelectObject(m_pData->hDC, *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 void 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); + ::SelectObject(m_pData->hDC, *pPen); + } + + inline void 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); + ::SelectObject(m_pData->hDC, *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); + 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 Bitmap = MemDC.DetachBitmap(); + ImageList_AddMasked(himlDisabled, Bitmap, 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_ + Index: include/reactos/libs/win32++/info.txt =================================================================== --- include/reactos/libs/win32++/info.txt (revision 0) +++ include/reactos/libs/win32++/info.txt (working copy) @@ -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 Index: include/reactos/libs/win32++/listview.h =================================================================== --- include/reactos/libs/win32++/listview.h (revision 0) +++ include/reactos/libs/win32++/listview.h (working copy) @@ -0,0 +1,870 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CEdit* GetEditControl( ) const; + DWORD GetExtendedStyle( ) const; + CHeader* 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; + CString 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; + CToolTip* 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; + CToolTip* SetToolTips ( CToolTip* pToolTip ) 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; + CEdit* 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 CEdit* 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 (CEdit*)FromHandle(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 CHeader* CListView::GetHeader( ) const + // Retrieves the handle to the header control used by a list-view control. + { + assert(::IsWindow(m_hWnd)); + return (CHeader*)FromHandle(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 CString 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)); + + CString 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 CToolTip* CListView::GetToolTips( ) const + // Retrieves the ToolTip control that the list-view control uses to display ToolTips. + { + assert(::IsWindow(m_hWnd)); + return(CToolTip*)FromHandle(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 CToolTip* CListView::SetToolTips( CToolTip* pToolTip ) const + // Sets the ToolTip control that the list-view control will use to display ToolTips. + { + assert(::IsWindow(m_hWnd)); + assert(pToolTip); + + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + return (CToolTip*) FromHandle( (HWND)::SendMessage(m_hWnd, LVM_SETTOOLTIPS, (WPARAM)hToolTip, 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 CEdit* CListView::EditLabel( int iItem ) const + // Begins in-place editing of the specified list-view item's text. + { + assert(::IsWindow(m_hWnd)); + return (CEdit*)FromHandle( 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_ + Index: include/reactos/libs/win32++/mdi.h =================================================================== --- include/reactos/libs/win32++/mdi.h (revision 0) +++ include/reactos/libs/win32++/mdi.h (working copy) @@ -0,0 +1,784 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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) + { + CString strMenuItem ( (*v)->GetWindowText() ); + + if (strMenuItem.GetLength() > MAX_MENU_STRING -10) + { + // Truncate the string if its too long + strMenuItem.Delete(strMenuItem.GetLength() - MAX_MENU_STRING +10); + strMenuItem += _T(" ..."); + } + + TCHAR szMenuString[MAX_MENU_STRING+1]; + wsprintf(szMenuString, _T("&%d %s"), nWindow+1, strMenuItem.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_ + Index: include/reactos/libs/win32++/menu.h =================================================================== --- include/reactos/libs/win32++/menu.h (revision 0) +++ include/reactos/libs/win32++/menu.h (working copy) @@ -0,0 +1,600 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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_ + Index: include/reactos/libs/win32++/propertysheet.h =================================================================== --- include/reactos/libs/win32++/propertysheet.h (revision 0) +++ include/reactos/libs/win32++/propertysheet.h (working copy) @@ -0,0 +1,960 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + + CString 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); + + CString 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; + 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.Empty(); + m_PSP.dwFlags &= ~PSP_USETITLE; + } + + m_PSP.pszTitle = m_Title; + } + + 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.Empty(); + + m_PSH.pszCaption = m_Title; + } + + 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_ Index: include/reactos/libs/win32++/rebar.h =================================================================== --- include/reactos/libs/win32++/rebar.h (revision 0) +++ include/reactos/libs/win32++/rebar.h (working copy) @@ -0,0 +1,718 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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" +#include "controls.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; + CToolTip* 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); + void SetToolTips(CToolTip* pToolTip) const; + + 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 CToolTip* CReBar::GetToolTips() const + // Retrieves the handle to any ToolTip control associated with the rebar control. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*)FromHandle( (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 void CReBar::SetToolTips(CToolTip* pToolTip) const + // Associates a ToolTip control with the rebar control. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : (HWND)0; + SendMessage(RB_SETTOOLTIPS, WPARAM(hToolTip), 0); + } + + 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_ Index: include/reactos/libs/win32++/release notes.txt =================================================================== --- include/reactos/libs/win32++/release notes.txt (revision 0) +++ include/reactos/libs/win32++/release notes.txt (working copy) @@ -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 Index: include/reactos/libs/win32++/ribbon.h =================================================================== --- include/reactos/libs/win32++/ribbon.h (revision 0) +++ include/reactos/libs/win32++/ribbon.h (working copy) @@ -0,0 +1,527 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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("Ribbon Created Succesfully\n"); + else + throw CWinException("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) + { + CString strCurrentFile = (*iter); + WCHAR wszCurrentFile[MAX_PATH] = {0L}; + lstrcpynW(wszCurrentFile, T2W(strCurrentFile), 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_ + Index: include/reactos/libs/win32++/shared_ptr.h =================================================================== --- include/reactos/libs/win32++/shared_ptr.h (revision 0) +++ include/reactos/libs/win32++/shared_ptr.h (working copy) @@ -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_ Index: include/reactos/libs/win32++/socket.h =================================================================== --- include/reactos/libs/win32++/socket.h (revision 0) +++ include/reactos/libs/win32++/socket.h (working copy) @@ -0,0 +1,778 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); + + CString m_ErrorMessage; + 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("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("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("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("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("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("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("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("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("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("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("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("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("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("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("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_ErrorMessage = _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_ErrorMessage = Message; + ::LocalFree(Message); + } + + return m_ErrorMessage; + } + + inline int CSocket::GetPeerName(struct sockaddr* name, int* namelen) + { + int Result = ::getpeername(m_Socket, name, namelen); + if (0 != Result) + TRACE("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("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("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("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("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("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("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("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("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("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("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("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("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("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("*** 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_ + Index: include/reactos/libs/win32++/statusbar.h =================================================================== --- include/reactos/libs/win32++/statusbar.h (revision 0) +++ include/reactos/libs/win32++/statusbar.h (working copy) @@ -0,0 +1,226 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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); + CString 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 CString CStatusBar::GetPartText(int iPart) const + { + assert(::IsWindow(m_hWnd)); + CString 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_ Index: include/reactos/libs/win32++/stdcontrols.h =================================================================== --- include/reactos/libs/win32++/stdcontrols.h (revision 0) +++ include/reactos/libs/win32++/stdcontrols.h (working copy) @@ -0,0 +1,1001 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 PreRegisterClass(WNDCLASS &wc); + }; + + 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::PreRegisterClass(WNDCLASS &wc) + { + // Set the Window Class + wc.lpszClassName = _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_ + Index: include/reactos/libs/win32++/tab.h =================================================================== --- include/reactos/libs/win32++/tab.h (revision 0) +++ include/reactos/libs/win32++/tab.h (working copy) @@ -0,0 +1,1682 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 SetFont(CFont* pFont, BOOL bRedraw = 1); + 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(CString strRegistryKeyName); + virtual void RecalcLayout(); + virtual BOOL SaveRegistrySettings(CString strRegistryKeyName); + 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 + ::SelectObject(dcMem, 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); + ::SelectObject(dcClient, 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); + ::SelectObject(dcClient, 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); + ::SelectObject(dcMem, 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::SetFont(CFont* pFont, BOOL bRedraw /* = 1 */) + { + assert(pFont); + m_Font = *pFont; + int HeightGap = 5; + SetTabHeight( MAX(20, GetTextHeight() + HeightGap) ); + CWnd::SetFont(pFont, bRedraw); + } + + 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(0, 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); + int nLength = 30; + std::vector vTChar1( nLength+1, _T('\0') ); // vector for TCHAR array + std::vector vTChar2( nLength+1, _T('\0') ); // vector for TCHAR array + + TCITEM Item1 = {0}; + Item1.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT; + Item1.cchTextMax = nLength; + Item1.pszText = &vTChar1.front(); + GetItem(nTab1, &Item1); + + TCITEM Item2 = {0}; + Item2.mask = TCIF_IMAGE | TCIF_PARAM | TCIF_RTLREADING | TCIF_STATE | TCIF_TEXT; + Item2.cchTextMax = nLength; + Item2.pszText = &vTChar2.front(); + 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_DESTROY: + // Required for Windows NT + { + for (int i = GetItemCount()-1; i >= 0; --i) + { + RemoveTabPage(i); + } + } + break; + case WM_PAINT: + if (GetWindowLongPtr(GWL_STYLE) & TCS_OWNERDRAWFIXED) + { + // Remove all pending paint requests + PAINTSTRUCT ps; + ::BeginPaint(m_hWnd, &ps); + ::EndPaint(m_hWnd, &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; + } + + 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(CString strRegistryKeyName) + { + BOOL bResult = FALSE; + + if (!strRegistryKeyName.IsEmpty()) + { + CString strKey = _T("Software\\") + strRegistryKeyName + _T("\\MDI Children"); + HKEY hKey = 0; + RegOpenKeyEx(HKEY_CURRENT_USER, strKey, 0, KEY_READ, &hKey); + if (hKey) + { + DWORD dwType = REG_BINARY; + DWORD BufferSize = sizeof(TabPageInfo); + TabPageInfo tbi = {0}; + int i = 0; + TCHAR szNumber[16]; + CString strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + + // Fill the DockList vector from the registry + while (0 == RegQueryValueEx(hKey, strSubKey, NULL, &dwType, (LPBYTE)&tbi, &BufferSize)) + { + CWnd* pWnd = NewMDIChildFromID(tbi.idTab); + if (pWnd) + { + AddMDIChild(pWnd, tbi.szTabText, tbi.idTab); + i++; + strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + bResult = TRUE; + } + else + { + TRACE("Failed to get TabbedMDI info from registry"); + bResult = FALSE; + break; + } + } + + // Load Active MDI Tab from the registry + strSubKey = _T("Active MDI Tab"); + int nTab; + dwType = REG_DWORD; + BufferSize = sizeof(int); + if(ERROR_SUCCESS == RegQueryValueEx(hKey, strSubKey, 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("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(CString strRegistryKeyName) + { + if (!strRegistryKeyName.IsEmpty()) + { + CString strKeyName = _T("Software\\") + strRegistryKeyName; + HKEY hKey = NULL; + HKEY hKeyMDIChild = NULL; + + try + { + if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, strKeyName, 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]; + CString strSubKey = _T("MDI Child "); + strSubKey += _itot(i, szNumber, 10); + TabPageInfo pdi = GetTab().GetTabPageInfo(i); + if (ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 0, REG_BINARY, (LPBYTE)&pdi, sizeof(TabPageInfo))) + throw (CWinException(_T("RegSetValueEx Failed"))); + } + + // Add Active Tab to the registry + CString strSubKey = _T("Active MDI Tab"); + int nTab = GetActiveMDITab(); + if(ERROR_SUCCESS != RegSetValueEx(hKeyMDIChild, strSubKey, 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, strKeyName); + 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_ Index: include/reactos/libs/win32++/taskdialog.h =================================================================== --- include/reactos/libs/win32++/taskdialog.h (revision 0) +++ include/reactos/libs/win32++/taskdialog.h (working copy) @@ -0,0 +1,810 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + { + CString cs = LoadString((UINT)pFromTChar); + int len = pFromTChar? cs.GetLength() + 1 : 1; + vTChar.assign(len, _T('\0')); + vWChar.assign(len, _T('\0')); + if (pFromTChar) + lstrcpy( &vTChar.front(), cs); + } + 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 Index: include/reactos/libs/win32++/thread.h =================================================================== --- include/reactos/libs/win32++/thread.h (revision 0) +++ include/reactos/libs/win32++/thread.h (working copy) @@ -0,0 +1,241 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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("*** 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_ + Index: include/reactos/libs/win32++/toolbar.h =================================================================== --- include/reactos/libs/win32++/toolbar.h (revision 0) +++ include/reactos/libs/win32++/toolbar.h (working copy) @@ -0,0 +1,1367 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CToolTip* 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(CToolTip* pToolTip) 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 CToolTip* CToolBar::GetToolTips() const + // Retrieves the handle to the ToolTip control, if any, associated with the toolbar. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*)FromHandle( (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 DrawDC(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? + { + DrawDC.SelectObject(GetFont()); + if (SendMessage(TB_GETBUTTONTEXT, dwItem, (LPARAM)pszText)> 0) + { + TextSize = DrawDC.GetTextExtentPoint32(pszText, lstrlen(pszText)); + } + } + + // Draw outline rectangle + if (nState & (CDIS_HOT | CDIS_SELECTED | CDIS_CHECKED)) + { + DrawDC.CreatePen(PS_SOLID, 1, m_Theme.clrOutline); + DrawDC.MoveTo(rcRect.left, rcRect.top); + DrawDC.LineTo(rcRect.left, rcRect.bottom-1); + DrawDC.LineTo(rcRect.right-1, rcRect.bottom-1); + DrawDC.LineTo(rcRect.right-1, rcRect.top); + DrawDC.LineTo(rcRect.left, rcRect.top); + } + + // Draw filled gradient background + rcRect.InflateRect(-1, -1); + if ((nState & (CDIS_SELECTED|CDIS_CHECKED)) || (GetButtonState(dwItem) & TBSTATE_PRESSED)) + { + DrawDC.GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcRect, FALSE); + } + else if (nState & CDIS_HOT) + { + DrawDC.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; + DrawDC.GradientFill(m_Theme.clrPressed1, m_Theme.clrPressed2, rcArrowBkgnd, FALSE); + } + + m_bDrawArrowBkgrnd = FALSE; + + // Manually draw the dropdown arrow + DrawDC.CreatePen(PS_SOLID, 1, RGB(0,0,0)); + for (int i = 2; i >= 0; --i) + { + DrawDC.MoveTo(xAPos -i-1, yAPos - i+1); + DrawDC.LineTo(xAPos +i, yAPos - i+1); + } + + // Draw line between icon and dropdown arrow + if ((nStyle & TBSTYLE_DROPDOWN) && ((nState & CDIS_SELECTED) || nState & CDIS_HOT)) + { + DrawDC.CreatePen(PS_SOLID, 1, m_Theme.clrOutline); + DrawDC.MoveTo(rcRect.right - 13, rcRect.top); + DrawDC.LineTo(rcRect.right - 13, rcRect.bottom); + } + } + + // Draw the button image + if (xImage > 0) + { + ImageList_Draw(himlToolBar, iImage, DrawDC, 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 = DrawDC.SetBkMode(TRANSPARENT); + DrawDC.SelectObject(GetFont()); + + if (nState & (CDIS_DISABLED)) + { + // Draw text twice for embossed look + rcText.OffsetRect(1, 1); + DrawDC.SetTextColor(RGB(255,255,255)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT); + rcText.OffsetRect(-1, -1); + DrawDC.SetTextColor(GetSysColor(COLOR_GRAYTEXT)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT); + } + else + { + DrawDC.SetTextColor(GetSysColor(COLOR_BTNTEXT)); + DrawDC.DrawText(pszText, lstrlen(pszText), rcText, DT_LEFT | DT_END_ELLIPSIS); + } + DrawDC.SetBkMode(iMode); + + } + DrawDC.Detach(); + } + 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) && (GetComCtlVersion() > 470)) + 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; + CString 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 (GetComCtlVersion() < 470) + { + // 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(CToolTip* pToolTip) const + // Associates a ToolTip control with a toolbar. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : (HWND)0; + SendMessage(TB_SETTOOLTIPS, (WPARAM)hToolTip, 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_ Index: include/reactos/libs/win32++/treeview.h =================================================================== --- include/reactos/libs/win32++/treeview.h (revision 0) +++ include/reactos/libs/win32++/treeview.h (working copy) @@ -0,0 +1,625 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CEdit* 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; + CString 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; + CToolTip* 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; + CToolTip* SetToolTips(CToolTip* pToolTip) 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 CEdit* 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 (CEdit*)FromHandle(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 CString 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)); + + CString 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_GetPrevVisible(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 CToolTip* CTreeView::GetToolTips() const + // Retrieves the handle to the child ToolTip control used by a tree-view control. + { + assert(::IsWindow(m_hWnd)); + return (CToolTip*) FromHandle( 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 CToolTip* CTreeView::SetToolTips(CToolTip* pToolTip) const + // Sets a tree-view control's child ToolTip control. + { + assert(::IsWindow(m_hWnd)); + HWND hToolTip = pToolTip? pToolTip->GetHwnd() : 0; + return (CToolTip*) FromHandle( TreeView_SetToolTips( m_hWnd, hToolTip ) ); + } + + // 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_ + Index: include/reactos/libs/win32++/wceframe.h =================================================================== --- include/reactos/libs/win32++/wceframe.h (revision 0) +++ include/reactos/libs/win32++/wceframe.h (working copy) @@ -0,0 +1,409 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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; + CString m_strAppName; + +#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_strAppName = _T("Win32++ Application"); + + // Choose a unique class name for this app + if (LoadString(IDW_MAIN) != _T("")) + { + m_strAppName = LoadString(IDW_MAIN); + } + + cs.lpszClass = m_strAppName; + } + + 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_ + Index: include/reactos/libs/win32++/wcestddef.h =================================================================== --- include/reactos/libs/win32++/wcestddef.h (revision 0) +++ include/reactos/libs/win32++/wcestddef.h (working copy) @@ -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 Index: include/reactos/libs/win32++/webbrowser.h =================================================================== --- include/reactos/libs/win32++/webbrowser.h (revision 0) +++ include/reactos/libs/win32++/webbrowser.h (working copy) @@ -0,0 +1,1220 @@ +// Win32++ Version 7.3 +// Released: 30th November 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 +#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(); + + + //Attributes + LPDISPATCH GetApplication() const; + CAXWindow& GetAXWindow() const { return (CAXWindow&)m_AXContainer; } + BOOL GetBusy() const; + LPDISPATCH GetContainer() const; + BOOL GetFullScreen() const; + long GetHeight() const; + IWebBrowser2* GetIWebBrowser2() const { return m_pIWebBrowser2; } + long GetLeft() const; + CString GetLocationName() const; + CString GetLocationURL() const; + BOOL GetOffline() const; + READYSTATE GetReadyState() const; + BOOL GetRegisterAsBrowser() const; + BOOL GetTheaterMode() const; + long GetTop() const; + BOOL GetTopLevelContainer() const; + CString GetType() const; + BOOL GetVisible() const; + long GetWidth() const; + void SetFullScreen(BOOL bNewValue); + void SetHeight(long nNewValue); + void SetLeft(long nNewValue); + void SetOffline(BOOL bNewValue); + void SetRegisterAsBrowser(BOOL bNewValue); + void SetTheaterMode(BOOL bNewValue); + void SetTop(long nNewValue); + void SetVisible(BOOL bNewValue); + void SetWidth(long nNewValue); + + // Operations + void AddWebBrowserControl(void); + void ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT* pvaIn, VARIANT* pvaOut); + BOOL GetProperty(LPCTSTR pszProperty, CString& strValue); + VARIANT GetProperty( LPCTSTR pszProperty); + void GoBack(); + void GoForward(); + void GoHome(); + void GoSearch(); + void Navigate(LPCTSTR pszURL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL, + LPCTSTR pszHeaders = NULL, LPVOID pvPostData = NULL, DWORD dwPostDataLen = 0); + void Navigate2(LPITEMIDLIST pIDL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL); + void Navigate2(LPCTSTR pszURL, DWORD dwFlags = 0, LPCTSTR pszTargetFrameName = NULL, + LPCTSTR pszHeaders = NULL, LPVOID lpvPostData = NULL, DWORD dwPostDataLen = 0); + void PutProperty(LPCTSTR pszPropertyName, const VARIANT& vtValue); + void PutProperty(LPCTSTR pszPropertyName, double dValue); + void PutProperty(LPCTSTR pszPropertyName, long lValue); + void PutProperty(LPCTSTR pszPropertyName, LPCTSTR lpszValue); + void PutProperty(LPCTSTR pszPropertyName, short nValue); + void Refresh(); + void Refresh2(int nLevel); + void Stop(); + + 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 +{ + ///////////////////////////////////////// + // Global functions + // + inline UINT GetPidlLength(LPITEMIDLIST pidl) + { + assert(pidl); + UINT cbPidl = sizeof(pidl->mkid.cb); + while(pidl && pidl->mkid.cb) + { + cbPidl += pidl->mkid.cb; + + // Walk to next item + BYTE* ptr = (BYTE*)pidl; + ptr += pidl->mkid.cb; + pidl = (LPITEMIDLIST)ptr; + } + + return cbPidl; + } + + + ///////////////////////////////////////// + // Definitions for the CAXWindow class + // + inline CAXWindow::CAXWindow() : m_cRefs(1), m_hWnd(NULL), m_pUnk(NULL) + { + } + + inline CAXWindow::~CAXWindow() + { + if (m_pUnk) + m_pUnk->Release(); + + Release(); + } + + 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(); + } + + } + + 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)) + { + m_pIWebBrowser2->Navigate((OLECHAR*)L"about:blank", 0, 0, 0, 0); + } + } + } + + 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); + } + + inline LPDISPATCH CWebBrowser::GetApplication() const + // Retrieves the automation object for the application that is hosting the WebBrowser Control. + { + LPDISPATCH Value; + GetIWebBrowser2()->get_Application(&Value); + return Value; + } + + inline BOOL CWebBrowser::GetBusy() const + // Retrieves a value that indicates whether the object is engaged in a navigation or downloading operation. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Busy(&bValue); + return (BOOL)bValue; + } + + inline LPDISPATCH CWebBrowser::GetContainer() const + // Retrieves an object reference to a container. + { + LPDISPATCH Value; + GetIWebBrowser2()->get_Container(&Value); + return Value; + } + + inline BOOL CWebBrowser::GetFullScreen() const + // Retrieves a value that indicates whether Internet Explorer is in full-screen mode or normal window mode. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_FullScreen(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetHeight() const + // Retrieves the height of the object. + { + long lValue; + GetIWebBrowser2()->get_Height(&lValue); + return lValue; + } + + inline long CWebBrowser::GetLeft() const + // Retrieves the coordinate of the left edge of the object. + { + long lValue; + GetIWebBrowser2()->get_Left(&lValue); + return lValue; + } + + inline CString CWebBrowser::GetLocationName() const + // Retrieves the path or title of the resource that is currently displayed. + { + BSTR bstr; + GetIWebBrowser2()->get_LocationName(&bstr); + CString str(bstr); + SysFreeString(bstr); + return str; + } + + inline CString CWebBrowser::GetLocationURL() const + // Retrieves the URL of the resource that is currently displayed. + { + BSTR bstr; + GetIWebBrowser2()->get_LocationURL(&bstr); + CString str(bstr); + SysFreeString(bstr); + return str; + } + + inline BOOL CWebBrowser::GetOffline() const + // Retrieves a value that indicates whether the object is operating in offline mode. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Offline(&bValue); + return (BOOL)bValue; + } + + inline READYSTATE CWebBrowser::GetReadyState() const + // Retrieves the ready state of the object. + { + READYSTATE rsValue; + GetIWebBrowser2()->get_ReadyState(&rsValue); + return rsValue; + } + + inline BOOL CWebBrowser::GetRegisterAsBrowser() const + // Retrieves a value that indicates whether the object is registered as a top-level browser window. + { + VARIANT_BOOL bValue = VARIANT_FALSE; +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x600) + GetIWebBrowser2()->get_RegisterAsBrowser(&bValue); +#endif + return (BOOL)bValue; + } + + inline BOOL CWebBrowser::GetTheaterMode() const + // Retrieves the theater mode state of the object. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_TheaterMode(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetTop() const + // Retrieves the coordinate of the top edge of the object. + { + long lValue; + GetIWebBrowser2()->get_Top(&lValue); + return lValue; + } + + inline BOOL CWebBrowser::GetTopLevelContainer() const + //Retrieves a value that indicates whether the object is a top-level container. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_TopLevelContainer(&bValue); + return (BOOL)bValue; + } + + inline CString CWebBrowser::GetType() const + // Retrieves the user type name of the contained document object. + { + BSTR bString; + GetIWebBrowser2()->get_Type(&bString); + CString str(bString); + SysFreeString(bString); + return str; + } + + inline BOOL CWebBrowser::GetVisible() const + // Retrieves a value that indicates whether the object is visible or hidden. + { + VARIANT_BOOL bValue = VARIANT_FALSE; + GetIWebBrowser2()->get_Visible(&bValue); + return (BOOL)bValue; + } + + inline long CWebBrowser::GetWidth() const + // Retrieves the width of the object. + { + long lValue; + GetIWebBrowser2()->get_Width(&lValue); + return lValue; + } + + inline void CWebBrowser::SetFullScreen(BOOL bNewValue) + // Sets a value that indicates whether Internet Explorer is in full-screen mode or normal window mode. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_FullScreen(vBool); + } + + inline void CWebBrowser::SetHeight(long nNewValue) + // Sets the height of the object. + { + GetIWebBrowser2()->put_Height(nNewValue); + } + + inline void CWebBrowser::SetLeft(long nNewValue) + // Sets the coordinate of the left edge of the object. + { + GetIWebBrowser2()->put_Left(nNewValue); + } + + inline void CWebBrowser::SetOffline(BOOL bNewValue) + // Sets a value that indicates whether the object is operating in offline mode. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_Offline(vBool); + } + + inline void CWebBrowser::SetRegisterAsBrowser(BOOL bNewValue) + // Sets a value that indicates whether the object is registered as a top-level browser window. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_RegisterAsBrowser(vBool); + } + + inline void CWebBrowser::SetTheaterMode(BOOL bNewValue) + // Sets the theatre mode state of the object. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_TheaterMode(vBool); + } + + inline void CWebBrowser::SetTop(long nNewValue) + // Sets the coordinate of the top edge of the object. + { + GetIWebBrowser2()->put_Top(nNewValue); + } + + inline void CWebBrowser::SetVisible(BOOL bNewValue) + // Sets a value that indicates whether the object is visible or hidden. + { + VARIANT_BOOL vBool = bNewValue? VARIANT_TRUE : VARIANT_FALSE; + GetIWebBrowser2()->put_Visible(vBool); + } + + inline void CWebBrowser::SetWidth(long nNewValue) + // Sets the width of the object. + { + GetIWebBrowser2()->put_Width(nNewValue); + } + + inline void CWebBrowser::ExecWB(OLECMDID cmdID, OLECMDEXECOPT cmdexecopt, VARIANT* pvaIn, VARIANT* pvaOut) + // Executes a command using the IOleCommandTarget interface. + { + GetIWebBrowser2()->ExecWB(cmdID, cmdexecopt, pvaIn, pvaOut); + } + + inline BOOL CWebBrowser::GetProperty(LPCTSTR pszProperty, CString& strValue) + // Gets the value associated with the specified property name. + { + VARIANT v; + HRESULT hResult = GetIWebBrowser2()->GetProperty(T2BSTR(pszProperty), &v); + if (v.vt == VT_EMPTY) + strValue.Empty(); + else + strValue = BSTR2T(v.bstrVal); + + return (hResult == S_OK); + } + + inline VARIANT CWebBrowser::GetProperty( LPCTSTR pszProperty ) + // Gets the value associated with the specified property name. + { + VARIANT v; + GetIWebBrowser2()->GetProperty( T2BSTR(pszProperty), &v ); + return v; + } + + inline void CWebBrowser::GoBack() + // Navigates backward one item in the history list. + { + GetIWebBrowser2()->GoBack(); + } + + inline void CWebBrowser::GoForward() + // Navigates forward one item in the history list. + { + GetIWebBrowser2()->GoForward(); + } + + inline void CWebBrowser::GoHome() + // Navigates to the current home or start page. + { + GetIWebBrowser2()->GoHome(); + } + + inline void CWebBrowser::GoSearch() + // Navigates to the current search page. + { + GetIWebBrowser2()->GoSearch(); + } + + inline void CWebBrowser::Navigate(LPCTSTR pszURL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/, + LPCTSTR pszHeaders /*= NULL*/, LPVOID pvPostData /*= NULL*/, DWORD dwPostDataLen /*= 0*/) + // Navigates to a resource identified by a URL or to a file identified by a full path. + { + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + SAFEARRAY* psa = SafeArrayCreateVector(VT_UI1, 0, dwPostDataLen); + CopyMemory(psa->pvData, pvPostData, dwPostDataLen); + VARIANT PostData; + PostData.vt = VT_ARRAY|VT_UI1; + PostData.parray = psa; + + VARIANT Headers; + Headers.vt = VT_BSTR; + Headers.bstrVal = SysAllocString(T2W(pszHeaders)); + BSTR url = SysAllocString(T2W(pszURL)); + + GetIWebBrowser2()->Navigate(url, &Flags, &TargetFrameName, &PostData, &Headers); + + VariantClear(&Flags); + VariantClear(&TargetFrameName); + VariantClear(&PostData); + VariantClear(&Headers); + } + + inline void CWebBrowser::Navigate2(LPITEMIDLIST pIDL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/) + // Navigates the browser to a location specified by a pointer to an item identifier list (PIDL) for an entity in the Microsoft Windows Shell namespace. + { + UINT cb = GetPidlLength(pIDL); + LPSAFEARRAY psa = SafeArrayCreateVector(VT_UI1, 0, cb); + VARIANT PIDL; + PIDL.vt = VT_ARRAY|VT_UI1; + PIDL.parray = psa; + CopyMemory(psa->pvData, pIDL, cb); + + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + GetIWebBrowser2()->Navigate2(&PIDL, &Flags, &TargetFrameName, 0, 0); + + VariantClear(&PIDL); + VariantClear(&Flags); + VariantClear(&TargetFrameName); + } + + inline void CWebBrowser::Navigate2(LPCTSTR pszURL, DWORD dwFlags /*= 0*/, LPCTSTR pszTargetFrameName /*= NULL*/, + LPCTSTR pszHeaders /*= NULL*/, LPVOID pvPostData /*= NULL*/, DWORD dwPostDataLen /*= 0*/) + // Navigates the browser to a location that is expressed as a URL. + { + VARIANT URL; + URL.vt = VT_BSTR; + URL.bstrVal = SysAllocString(T2W(pszURL)); + + VARIANT Flags; + Flags.vt = VT_I4; + Flags.lVal = dwFlags; + + VARIANT TargetFrameName; + TargetFrameName.vt = VT_BSTR; + TargetFrameName.bstrVal = SysAllocString(T2W(pszTargetFrameName)); + + // Store the pidl in a SafeArray, and assign the SafeArray to a VARIANT + SAFEARRAY* psa = SafeArrayCreateVector(VT_UI1, 0, dwPostDataLen); + CopyMemory(psa->pvData, pvPostData, dwPostDataLen); + VARIANT PostData; + PostData.vt = VT_ARRAY|VT_UI1; + PostData.parray = psa; + + VARIANT Headers; + Headers.vt = VT_BSTR; + Headers.bstrVal = SysAllocString(T2W(pszHeaders)); + + GetIWebBrowser2()->Navigate2(&URL, &Flags, &TargetFrameName, &PostData, &Headers); + + VariantClear(&URL); + VariantClear(&Flags); + VariantClear(&TargetFrameName); + VariantClear(&PostData); + VariantClear(&Headers); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszProperty, const VARIANT& vtValue) + // Sets the value of a property associated with the object. + { + GetIWebBrowser2()->PutProperty(T2BSTR(pszProperty), vtValue); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, double dValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.dblVal = dValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, long lValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.lVal= lValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, LPCTSTR lpszValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_BSTR; + v.bstrVal= SysAllocString(T2W(lpszValue)); + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::PutProperty(LPCTSTR pszPropertyName, short nValue) + // Sets the value of a property associated with the object. + { + VARIANT v; + v.vt = VT_I4; + v.iVal = nValue; + GetIWebBrowser2()->PutProperty(T2BSTR(pszPropertyName), v); + VariantClear(&v); + } + + inline void CWebBrowser::Refresh() + // Reloads the file that is currently displayed in the object. + { + GetIWebBrowser2()->Refresh(); + } + + inline void CWebBrowser::Refresh2(int nLevel) + // Reloads the file that is currently displayed with the specified refresh level. + { + VARIANT v; + v.vt = VT_I4; + v.intVal = nLevel; + GetIWebBrowser2()->Refresh2(&v); + VariantClear(&v); + } + + inline void CWebBrowser::Stop() + // Cancels a pending navigation or download, and stops dynamic page elements, such as background sounds and animations. + { + GetIWebBrowser2()->Stop(); + } + + +} + +#endif // _WIN32XX_WEBBROWSER_H_ + Index: include/reactos/libs/win32++/wincore.h =================================================================== --- include/reactos/libs/win32++/wincore.h (revision 0) +++ include/reactos/libs/win32++/wincore.h (working copy) @@ -0,0 +1,3022 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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 + #pragma option -w-8030 // Temporary used for 'rhs' + #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 +#include +#include +#include +#include +#include +#include "shared_ptr.h" +//#include "winutils.h" // included later in this file +//#include "cstring.h" // included later in this file +//#include "gdi.h" // included later in this file +//#include "menu.h" // included later in this file + +// For compilers lacking Win64 support +#ifndef GetWindowLongPtr + #define GetWindowLongPtr GetWindowLong + #define SetWindowLongPtr SetWindowLong + #define GWLP_WNDPROC GWL_WNDPROC + #define GWLP_HINSTANCE GWL_HINSTANCE + #define GWLP_ID GWL_ID + #define GWLP_USERDATA GWL_USERDATA + #define DWLP_DLGPROC DWL_DLGPROC + #define DWLP_MSGRESULT DWL_MSGRESULT + #define DWLP_USER DWL_USER + #define DWORD_PTR DWORD + #define LONG_PTR LONG + #define ULONG_PTR LONG +#endif +#ifndef GetClassLongPtr + #define GetClassLongPtr GetClassLong + #define SetClassLongPtr SetClassLong + #define GCLP_HBRBACKGROUND GCL_HBRBACKGROUND + #define GCLP_HCURSOR GCL_HCURSOR + #define GCLP_HICON GCL_HICON + #define GCLP_HICONSM GCL_HICONSM + #define GCLP_HMODULE GCL_HMODULE + #define GCLP_MENUNAME GCL_MENUNAME + #define GCLP_WNDPROC GCL_WNDPROC +#endif + + +// Messages defined by Win32++ +#define UWM_POPUPMENU (WM_APP + 1) // Message - creates the menubar popup menu +#define UWM_DOCK_START (WM_APP + 2) // Notification - about to start undocking +#define UWM_DOCK_MOVE (WM_APP + 3) // Notification - undocked docker is being moved +#define UWM_DOCK_END (WM_APP + 4) // Notification - docker has been docked +#define UWM_BAR_START (WM_APP + 5) // Notification - docker bar selected for move +#define UWM_BAR_MOVE (WM_APP + 6) // Notification - docker bar moved +#define UWM_BAR_END (WM_APP + 7) // Notification - end of docker bar move +#define UWM_UNDOCKED (WM_APP + 8) // Notification - sent by docker when undocked +#define UWM_FRAMELOSTFOCUS (WM_APP + 9) // Notification - sent by frame to view window when focus lost +#define UWM_FRAMEGOTFOCUS (WM_APP + 10) // Notification - sent by frame to view window when focus acquired +#define UWM_DOCK_DESTROYED (WM_APP + 11) // Message - posted when docker is destroyed +#define UWM_TAB_CHANGED (WM_APP + 12) // Notification - tab layout changed +#define UWM_TOOLBAR_RESIZE (WM_APP + 13) // Message - sent by toolbar to parent. Used by the rebar +#define UWM_UPDATE_COMMAND (WM_APP + 14) // Message - sent before a menu is displayed. Used by OnUpdate +#define UWM_DOCK_ACTIVATED (WM_APP + 15) // Message - sent to dock ancestor when a docker is activated or deactivated. +#define UWM_GETMENUTHEME (WM_APP + 16) // Message - returns a pointer to MenuTheme +#define UWM_GETREBARTHEME (WM_APP + 17) // Message - returns a pointer to CToolBar +#define UWM_GETTOOLBARTHEME (WM_APP + 18) // Message - returns a pointer to ToolBarTheme +#define UWM_CLEANUPTEMPS (WM_APP + 19) // Message - posted to cleanup temporary CDCs + + +// Automatically include the Win32xx namespace +// define NO_USING_NAMESPACE to skip this step +namespace Win32xx {} +#ifndef NO_USING_NAMESPACE + using namespace Win32xx; +#endif + +// Required for WinCE +#ifndef TLS_OUT_OF_INDEXES + #define TLS_OUT_OF_INDEXES ((DWORD_PTR) -1) +#endif +#ifndef WM_PARENTNOTIFY + #define WM_PARENTNOTIFY 0x0210 +#endif + + +namespace Win32xx +{ + + //////////////////////////////////////////////// + // Forward declarations. + // These classes are defined later or elsewhere + class CDC; + class CGDIObject; + class CMenu; + class CWinApp; + class CWnd; + class CBitmap; + class CBrush; + class CFont; + class CPalette; + class CPen; + class CRgn; + + // tString is a TCHAR std::string + typedef std::basic_string tString; + + // tStringStream is a TCHAR std::stringstream + typedef std::basic_stringstream tStringStream; + + // Some useful smart pointers + typedef Shared_Ptr DCPtr; + typedef Shared_Ptr GDIPtr; + typedef Shared_Ptr MenuPtr; + typedef Shared_Ptr WndPtr; + typedef Shared_Ptr BitmapPtr; + typedef Shared_Ptr BrushPtr; + typedef Shared_Ptr FontPtr; + typedef Shared_Ptr PalettePtr; + typedef Shared_Ptr PenPtr; + typedef Shared_Ptr RgnPtr; + + enum Constants // Defines the maximum size for TCHAR strings + { + MAX_MENU_STRING = 80, + MAX_STRING_SIZE = 255, + }; + + struct CompareHDC // The comparison function object used by CWinApp::m_mapHDC + { + bool operator()(HDC const a, const HDC b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareGDI // The comparison function object used by CWinApp::m_mapGDI + { + bool operator()(HGDIOBJ const a, const HGDIOBJ b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareHMENU // The comparison function object used by CWinApp::m_mapHMENU + { + bool operator()(HMENU const a, const HMENU b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct CompareHWND // The comparison function object used by CWinApp::m_mapHWND + { + bool operator()(HWND const a, const HWND b) const + {return ((DWORD_PTR)a < (DWORD_PTR)b);} + }; + + struct TLSData // Used for Thread Local Storage (TLS) + { + CWnd* pCWnd; // pointer to CWnd object for Window creation + CWnd* pMenuBar; // pointer to CMenuBar object used for the WH_MSGFILTER hook + HHOOK hHook; // WH_MSGFILTER hook for CMenuBar and Modeless Dialogs + + std::vector vTmpDCs; // A vector of temporary CDC pointers + std::vector vTmpGDIs; // A vector of temporary CGDIObject pointers + std::vector vTmpWnds; // A vector of temporary CWnd pointers + TLSData() : pCWnd(0), pMenuBar(0), hHook(0) {} + +#ifndef _WIN32_WCE + std::vector vTmpMenus; // A vector of temporary CMenu pointers +#endif + }; + + + ///////////////////////////////////////// + // Declarations for the CCriticalSection class + // This class is used for thread synchronisation + class CCriticalSection + { + public: + CCriticalSection() { ::InitializeCriticalSection(&m_cs); } + ~CCriticalSection() { ::DeleteCriticalSection(&m_cs); } + + void Lock() { ::EnterCriticalSection(&m_cs); } + void Release() { ::LeaveCriticalSection(&m_cs); } + + private: + CCriticalSection ( const CCriticalSection& ); + CCriticalSection& operator = ( const CCriticalSection& ); + + CRITICAL_SECTION m_cs; + }; + + + //////////////////////////////////////// + // Declaration of the CWinException class + // + // Note: Each function guarantees not to throw an exception + + class CWinException : public std::exception + { + public: + CWinException(LPCTSTR pszText) throw (); + ~CWinException() throw() {} + DWORD GetError() const throw (); + LPCTSTR GetErrorString() const throw (); + const char * what () const throw (); + + private: + DWORD m_Error; + LPCTSTR m_pszText; + TCHAR m_szErrorString[MAX_STRING_SIZE]; + }; + + + /////////////////////////////////// + // Declaration of the CWinApp class + // + class CWinApp + { + // Provide these access to CWinApp's private members: + friend class CDC; + friend class CDialog; + friend class CGDIObject; + friend class CMenu; + friend class CMenuBar; + friend class CPropertyPage; + friend class CPropertySheet; + friend class CTaskDialog; + friend class CWnd; + friend CWinApp* GetApp(); + friend CGDIObject* FromHandle(HGDIOBJ hObject); + friend CBitmap* FromHandle(HBITMAP hBitmap); + friend CBrush* FromHandle(HBRUSH hBrush); + friend CFont* FromHandle(HFONT hFont); + friend CPalette* FromHandle(HPALETTE hPalette); + friend CPen* FromHandle(HPEN hPen); + friend CRgn* FromHandle(HRGN hRgn); + friend CDC* FromHandle(HDC hDC); + friend CWnd* FromHandle(HWND hWnd); +#ifndef _WIN32_WCE + friend CMenu* FromHandle(HMENU hMenu); +#endif + + typedef Shared_Ptr TLSDataPtr; + + public: + CWinApp(); + virtual ~CWinApp(); + + HACCEL GetAccelerators() const { return m_hAccel; } + HINSTANCE GetInstanceHandle() const { return m_hInstance; } + HINSTANCE GetResourceHandle() const { return (m_hResource ? m_hResource : m_hInstance); } + void SetAccelerators(HACCEL hAccel, CWnd* pWndAccel); + void SetResourceHandle(HINSTANCE hResource); + + // These are the functions you might wish to override + virtual BOOL InitInstance(); + virtual int MessageLoop(); + virtual BOOL OnIdle(LONG lCount); + virtual BOOL PreTranslateMessage(MSG Msg); + virtual int Run(); + + private: + CWinApp(const CWinApp&); // Disable copy construction + CWinApp& operator = (const CWinApp&); // Disable assignment operator + CDC* GetCDCFromMap(HDC hDC); + CGDIObject* GetCGDIObjectFromMap(HGDIOBJ hObject); + CMenu* GetCMenuFromMap(HMENU hMenu); + CWnd* GetCWndFromMap(HWND hWnd); + + void AddTmpDC(CDC* pDC); + void AddTmpGDI(CGDIObject* pObject); + CMenu* AddTmpMenu(HMENU hMenu); + CWnd* AddTmpWnd(HWND hWnd); + void CleanupTemps(); + DWORD GetTlsIndex() const {return m_dwTlsIndex;} + void SetCallback(); + TLSData* SetTlsIndex(); + static CWinApp* SetnGetThis(CWinApp* pThis = 0); + + std::map m_mapHDC; // maps device context handles to CDC objects + std::map m_mapGDI; // maps GDI handles to CGDIObjects. + std::map m_mapHMENU; // maps menu handles to CMenu objects + std::map m_mapHWND; // maps window handles to CWnd objects + std::vector m_vTLSData; // vector of TLSData smart pointers, one for each thread + CCriticalSection m_csMapLock; // thread synchronisation for m_mapHWND + CCriticalSection m_csTLSLock; // thread synchronisation for m_vTLSData + CCriticalSection m_csAppStart; // thread synchronisation for application startup + HINSTANCE m_hInstance; // handle to the applications instance + HINSTANCE m_hResource; // handle to the applications resources + DWORD m_dwTlsIndex; // Thread Local Storage index + WNDPROC m_Callback; // callback address of CWnd::StaticWndowProc + HACCEL m_hAccel; // handle to the accelerator table + CWnd* m_pWndAccel; // handle to the window for accelerator keys + + }; + +} + +#include "winutils.h" +#include "cstring.h" + + +namespace Win32xx +{ + //////////////////////////////// + // Declaration of the CWnd class + // + class CWnd + { + friend class CMDIChild; + friend class CDialog; + friend class CPropertyPage; + friend class CTaskDialog; + friend class CWinApp; + + public: + CWnd(); // Constructor + CWnd(HWND hWnd) // Constructor + { + if (hWnd == HWND_TOP || hWnd == HWND_TOPMOST || hWnd == HWND_BOTTOM || hWnd == HWND_NOTOPMOST) + { + m_hWnd = hWnd; + } + else + Attach(hWnd); + } + virtual ~CWnd(); // Destructor + + // These virtual functions can be overridden + virtual BOOL Attach(HWND hWnd); + virtual BOOL AttachDlgItem(UINT nID, CWnd* pParent); + virtual void CenterWindow() const; + virtual HWND Create(CWnd* pParent = NULL); + virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL); + virtual HWND CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam = NULL); + virtual void Destroy(); + virtual HWND Detach(); + virtual HICON SetIconLarge(int nIcon); + virtual HICON SetIconSmall(int nIcon); + + // Attributes + HWND GetHwnd() const { return m_hWnd; } + WNDPROC GetPrevWindowProc() const { return m_PrevWindowProc; } + + // Wrappers for Win32 API functions + // These functions aren't virtual, and shouldn't be overridden + CDC* BeginPaint(PAINTSTRUCT& ps) const; + BOOL BringWindowToTop() const; + LRESULT CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const; + BOOL CheckDlgButton(int nIDButton, UINT uCheck) const; + BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const; + CWnd* ChildWindowFromPoint(POINT pt) const; + BOOL ClientToScreen(POINT& pt) const; + BOOL ClientToScreen(RECT& rc) const; + LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const; + HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const; + HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const; + BOOL DrawMenuBar() const; + BOOL EnableWindow(BOOL bEnable = TRUE) const; + BOOL EndPaint(PAINTSTRUCT& ps) const; + CWnd* GetActiveWindow() const; + CWnd* GetAncestor(UINT gaFlag = 3 /*= GA_ROOTOWNER*/) const; + CWnd* GetCapture() const; + ULONG_PTR GetClassLongPtr(int nIndex) const; + CString GetClassName() const; + CRect GetClientRect() const; + CDC* GetDC() const; + CDC* GetDCEx(HRGN hrgnClip, DWORD flags) const; + CWnd* GetDesktopWindow() const; + CWnd* GetDlgItem(int nIDDlgItem) const; + UINT GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const; + CString GetDlgItemText(int nIDDlgItem) const; + CWnd* GetFocus() const; + CFont* GetFont() const; + HICON GetIcon(BOOL bBigIcon) const; + CWnd* GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const; + CWnd* GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const; + CWnd* GetParent() const; + BOOL GetScrollInfo(int fnBar, SCROLLINFO& si) const; + CRect GetUpdateRect(BOOL bErase) const; + int GetUpdateRgn(CRgn* pRgn, BOOL bErase) const; + CWnd* GetWindow(UINT uCmd) const; + CDC* GetWindowDC() const; + LONG_PTR GetWindowLongPtr(int nIndex) const; + CRect GetWindowRect() const; + CString GetWindowText() const; + int GetWindowTextLength() const; + void Invalidate(BOOL bErase = TRUE) const; + BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) const; + BOOL InvalidateRgn(CRgn* pRgn, BOOL bErase = TRUE) const; + BOOL IsChild(CWnd* pChild) const; + BOOL IsDialogMessage(LPMSG lpMsg) const; + UINT IsDlgButtonChecked(int nIDButton) const; + BOOL IsWindow() const; + BOOL IsWindowEnabled() const; + BOOL IsWindowVisible() const; + BOOL KillTimer(UINT_PTR uIDEvent) const; + int MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const; + void MapWindowPoints(CWnd* pWndTo, POINT& pt) const; + void MapWindowPoints(CWnd* pWndTo, RECT& rc) const; + void MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const; + BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) const; + BOOL MoveWindow(const RECT& rc, BOOL bRepaint = TRUE) const; + BOOL PostMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const; + BOOL PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const; + BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, CRgn* pRgn = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_ALLCHILDREN) const; + int ReleaseDC(CDC* pDC) const; + BOOL ScreenToClient(POINT& Point) const; + BOOL ScreenToClient(RECT& rc) const; + LRESULT SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const; + LRESULT SendMessage(UINT uMsg, WPARAM wParam = 0L, LPARAM lParam = 0L) const; + LRESULT SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const; + BOOL SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const; + CWnd* SetActiveWindow() const; + CWnd* SetCapture() const; + ULONG_PTR SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const; + BOOL SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const; + BOOL SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const; + CWnd* SetFocus() const; + void SetFont(CFont* pFont, BOOL bRedraw = TRUE) const; + BOOL SetForegroundWindow() const; + HICON SetIcon(HICON hIcon, BOOL bBigIcon) const; + CWnd* SetParent(CWnd* pWndParent) const; + BOOL SetRedraw(BOOL bRedraw = TRUE) const; + int SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const; + UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const; + LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const; + BOOL SetWindowPos(const CWnd* pInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const; + BOOL SetWindowPos(const CWnd* pInsertAfter, const RECT& rc, UINT uFlags) const; + int SetWindowRgn(CRgn* pRgn, BOOL bRedraw = TRUE) const; + BOOL SetWindowText(LPCTSTR lpString) const; + HRESULT SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const; + BOOL ShowWindow(int nCmdShow = SW_SHOWNORMAL) const; + BOOL UpdateWindow() const; + BOOL ValidateRect(LPCRECT prc) const; + BOOL ValidateRgn(CRgn* pRgn) const; + static CWnd* WindowFromPoint(POINT pt); + + #ifndef _WIN32_WCE + BOOL CloseWindow() const; + int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const; + int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const; + BOOL DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const; + BOOL DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const; + BOOL DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const; + BOOL DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const; + BOOL EnableScrollBar(UINT uSBflags, UINT uArrows) const; + CWnd* GetLastActivePopup() const; + CMenu* GetMenu() const; + int GetScrollPos(int nBar) const; + BOOL GetScrollRange(int nBar, int& MinPos, int& MaxPos) const; + CMenu* GetSystemMenu(BOOL bRevert) const; + CWnd* GetTopWindow() const; + BOOL GetWindowPlacement(WINDOWPLACEMENT& pWndpl) const; + BOOL HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const; + BOOL IsIconic() const; + BOOL IsZoomed() const; + BOOL LockWindowUpdate() const; + BOOL OpenIcon() const; + void Print(CDC* pDC, DWORD dwFlags) const; + BOOL SetMenu(CMenu* pMenu) const; + BOOL ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const; + int ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const; + int SetScrollPos(int nBar, int nPos, BOOL bRedraw) const; + BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const; + BOOL SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const; + BOOL ShowOwnedPopups(BOOL fShow) const; + BOOL ShowScrollBar(int nBar, BOOL bShow) const; + BOOL ShowWindowAsync(int nCmdShow) const; + BOOL UnLockWindowUpdate() const; + CWnd* WindowFromDC(CDC* pDC) const; + + #ifndef WIN32_LEAN_AND_MEAN + void DragAcceptFiles(BOOL fAccept) const; + #endif + #endif + + static LRESULT CALLBACK StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + operator HWND() const { return m_hWnd; } + + protected: + // Override these functions as required + virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void OnCreate(); + virtual void OnDraw(CDC* pDC); + virtual BOOL OnEraseBkgnd(CDC* pDC); + virtual void OnInitialUpdate(); + virtual void OnMenuUpdate(UINT nID); + virtual LRESULT OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotify(WPARAM wParam, LPARAM lParam); + virtual LRESULT OnNotifyReflect(WPARAM wParam, LPARAM lParam); + virtual void PreCreate(CREATESTRUCT& cs); + virtual void PreRegisterClass(WNDCLASS& wc); + virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam); + virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam); + + HWND m_hWnd; // handle to this object's window + + private: + CWnd(const CWnd&); // Disable copy construction + CWnd& operator = (const CWnd&); // Disable assignment operator + void AddToMap(); + void Cleanup(); + LRESULT MessageReflect(HWND hwndParent, UINT uMsg, WPARAM wParam, LPARAM lParam); + BOOL RegisterClass(WNDCLASS& wc); + BOOL RemoveFromMap(); + void Subclass(HWND hWnd); + + Shared_Ptr m_pwc; // defines initialisation parameters for PreRegisterClass + Shared_Ptr m_pcs; // defines initialisation parameters for PreCreate and Create + WNDPROC m_PrevWindowProc; // pre-subclassed Window Procedure + BOOL m_IsTmpWnd; // True if this CWnd is a TmpWnd + + }; // class CWnd + + // Special CWnd objects used by SetWindowPos + static const CWnd wndTop(HWND_TOP); + static const CWnd wndTopMost(HWND_TOPMOST); + static const CWnd wndBottom(HWND_BOTTOM); + static const CWnd wndNoTopMost(HWND_NOTOPMOST); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#include "gdi.h" +#include "menu.h" + +namespace Win32xx +{ + + ////////////////////////////////////////// + // Definitions for the CWinException class + // + inline CWinException::CWinException(LPCTSTR pszText) throw () : m_Error(::GetLastError()), m_pszText(pszText) + { + memset(m_szErrorString, 0, MAX_STRING_SIZE * sizeof(TCHAR)); + + if (m_Error != 0) + { + DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS; + ::FormatMessage(dwFlags, NULL, m_Error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), m_szErrorString, MAX_STRING_SIZE-1, NULL); + } + } + + inline DWORD CWinException::GetError() const throw () + { + return m_Error; + } + + inline LPCTSTR CWinException::GetErrorString() const throw () + { + return m_szErrorString; + } + + inline const char * CWinException::what() const throw () + { + // Sends the last error string to the debugger (typically displayed in the IDE's output window). + ::OutputDebugString(m_szErrorString); + return "CWinException thrown"; + } + + + //////////////////////////////////// + // Definitions for the CWinApp class + // + + // To begin Win32++, inherit your application class from this one. + // You must run only one instance of the class inherited from this. + inline CWinApp::CWinApp() : m_Callback(NULL), m_hAccel(0), m_pWndAccel(0) + { + try + { + m_csAppStart.Lock(); + assert( 0 == SetnGetThis() ); // Test if this is the first instance of CWinApp + + m_dwTlsIndex = ::TlsAlloc(); + if (m_dwTlsIndex == TLS_OUT_OF_INDEXES) + { + // We only get here in the unlikely event that all TLS indexes are already allocated by this app + // At least 64 TLS indexes per process are allowed. Win32++ requires only one TLS index. + m_csAppStart.Release(); + throw CWinException(_T("CWinApp::CWinApp Failed to allocate TLS Index")); + } + + SetnGetThis(this); + m_csAppStart.Release(); + + // Set the instance handle + #ifdef _WIN32_WCE + m_hInstance = (HINSTANCE)GetModuleHandle(0); + #else + MEMORY_BASIC_INFORMATION mbi = {0}; + VirtualQuery( (LPCVOID)SetnGetThis, &mbi, sizeof(mbi) ); + assert(mbi.AllocationBase); + m_hInstance = (HINSTANCE)mbi.AllocationBase; + #endif + + m_hResource = m_hInstance; + SetCallback(); + + // Assign the special CWnds used by SetWindowPos + m_csMapLock.Lock(); + m_mapHWND.insert(std::make_pair(HWND_TOP, (CWnd*)&wndTop)); + m_mapHWND.insert(std::make_pair(HWND_TOPMOST, (CWnd*)&wndTopMost)); + m_mapHWND.insert(std::make_pair(HWND_NOTOPMOST, (CWnd*)&wndNoTopMost)); + m_mapHWND.insert(std::make_pair(HWND_BOTTOM, (CWnd*)&wndBottom)); + GetApp()->m_csMapLock.Release(); + } + + catch (const CWinException &e) + { + e.what(); + throw; + } + } + + inline CWinApp::~CWinApp() + { + std::vector::iterator iter; + for (iter = m_vTLSData.begin(); iter < m_vTLSData.end(); ++iter) + { + (*iter)->vTmpDCs.clear(); +#ifndef _WIN32_WCE + (*iter)->vTmpMenus.clear(); +#endif + (*iter)->vTmpWnds.clear(); + } + + // Check that all CWnd windows are destroyed + std::map::iterator m; + for (m = m_mapHWND.begin(); m != m_mapHWND.end(); ++m) + { + HWND hWnd = (*m).first; + if (::IsWindow(hWnd)) + ::DestroyWindow(hWnd); + } + m_mapHWND.clear(); + m_mapGDI.clear(); + m_mapHDC.clear(); + m_mapHMENU.clear(); + + // Do remaining tidy up + if (m_dwTlsIndex != TLS_OUT_OF_INDEXES) + { + ::TlsSetValue(GetTlsIndex(), NULL); + ::TlsFree(m_dwTlsIndex); + } + + SetnGetThis((CWinApp*)-1); + } + + inline void CWinApp::AddTmpDC(CDC* pDC) + { + // The TmpMenus are created by GetSybMenu. + // They are removed by CleanupTemps + assert(pDC); + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpDCs.push_back(pDC); // save pDC as a smart pointer + } + + inline void CWinApp::AddTmpGDI(CGDIObject* pObject) + { + // The temporary CGDIObjects are removed by CleanupTemps + assert(pObject); + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpGDIs.push_back(pObject); // save pObject as a smart pointer + } + +#ifndef _WIN32_WCE + inline CMenu* CWinApp::AddTmpMenu(HMENU hMenu) + { + // The TmpMenus are created by GetSybMenu. + // They are removed by CleanupTemps + assert(::IsMenu(hMenu)); + assert(!GetCMenuFromMap(hMenu)); + + CMenu* pMenu = new CMenu; + pMenu->m_hMenu = hMenu; + m_csMapLock.Lock(); + m_mapHMENU.insert(std::make_pair(hMenu, pMenu)); + m_csMapLock.Release(); + pMenu->m_IsTmpMenu = TRUE; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpMenus.push_back(pMenu); // save pMenu as a smart pointer + return pMenu; + } +#endif + + inline CWnd* CWinApp::AddTmpWnd(HWND hWnd) + { + // TmpWnds are created if required to support functions like CWnd::GetParent. + // They are removed by CleanupTemps + // assert(::IsWindow(hWnd)); + assert(!GetCWndFromMap(hWnd)); + + CWnd* pWnd = new CWnd; + pWnd->m_hWnd = hWnd; + pWnd->AddToMap(); + pWnd->m_IsTmpWnd = TRUE; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + pTLSData->vTmpWnds.push_back(pWnd); // save pWnd as a smart pointer + return pWnd; + } + + inline void CWinApp::CleanupTemps() + // Removes all Temporary CWnds and CMenus belonging to this thread + { + // Retrieve the pointer to the TLS Data + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + assert(pTLSData); + + pTLSData->vTmpDCs.clear(); + pTLSData->vTmpGDIs.clear(); + pTLSData->vTmpWnds.clear(); + + + #ifndef _WIN32_WCE + pTLSData->vTmpMenus.clear(); + #endif + } + + inline CDC* CWinApp::GetCDCFromMap(HDC hDC) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CDC pointer mapped to this HDC + CDC* pDC = 0; + m_csMapLock.Lock(); + m = m_mapHDC.find(hDC); + + if (m != m_mapHDC.end()) + pDC = m->second; + + m_csMapLock.Release(); + return pDC; + } + + inline CGDIObject* CWinApp::GetCGDIObjectFromMap(HGDIOBJ hObject) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CGDIObject pointer mapped to this HGDIOBJ + CGDIObject* pObject = 0; + m_csMapLock.Lock(); + m = m_mapGDI.find(hObject); + + if (m != m_mapGDI.end()) + pObject = m->second; + + m_csMapLock.Release(); + return pObject; + } + + inline CMenu* CWinApp::GetCMenuFromMap(HMENU hMenu) + { + std::map::iterator m; + + // Find the CMenu pointer mapped to this HMENU + CMenu* pMenu = 0; + m_csMapLock.Lock(); + m = m_mapHMENU.find(hMenu); + + if (m != m_mapHMENU.end()) + pMenu = m->second; + + m_csMapLock.Release(); + return pMenu; + } + + inline CWnd* CWinApp::GetCWndFromMap(HWND hWnd) + { + // Allocate an iterator for our HWND map + std::map::iterator m; + + // Find the CWnd pointer mapped to this HWND + CWnd* pWnd = 0; + m_csMapLock.Lock(); + m = m_mapHWND.find(hWnd); + + if (m != m_mapHWND.end()) + pWnd = m->second; + + m_csMapLock.Release(); + return pWnd; + } + + inline BOOL CWinApp::InitInstance() + { + // InitInstance contains the initialization code for your application + // You should override this function with the code to run when the application starts. + + // return TRUE to indicate success. FALSE will end the application + return TRUE; + } + + inline int CWinApp::MessageLoop() + { + // This gets any messages queued for the application, and dispatches them. + MSG Msg = {0}; + int status = 1; + LONG lCount = 0; + + while (status != 0) + { + // While idle, perform idle processing until OnIdle returns FALSE + while (!::PeekMessage(&Msg, 0, 0, 0, PM_NOREMOVE) && OnIdle(lCount) == TRUE) + { + ++lCount; + } + + lCount = 0; + + // Now wait until we get a message + if ((status = ::GetMessage(&Msg, NULL, 0, 0)) == -1) + return -1; + + if (!PreTranslateMessage(Msg)) + { + ::TranslateMessage(&Msg); + ::DispatchMessage(&Msg); + } + } + + return LOWORD(Msg.wParam); + } + + inline BOOL CWinApp::OnIdle(LONG lCount) + { + if (lCount == 0) + CleanupTemps(); + + return FALSE; + } + + inline BOOL CWinApp::PreTranslateMessage(MSG Msg) + { + // This functions is called by the MessageLoop. It processes the + // keyboard accelerator keys and calls CWnd::PreTranslateMessage for + // keyboard and mouse events. + + BOOL Processed = FALSE; + + // only pre-translate mouse and keyboard input events + if ((Msg.message >= WM_KEYFIRST && Msg.message <= WM_KEYLAST) || + (Msg.message >= WM_MOUSEFIRST && Msg.message <= WM_MOUSELAST)) + { + // Process keyboard accelerators + if (m_pWndAccel && ::TranslateAccelerator(*m_pWndAccel, m_hAccel, &Msg)) + Processed = TRUE; + else + { + // Search the chain of parents for pretranslated messages. + for (HWND hWnd = Msg.hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd)) + { + CWnd* pWnd = GetCWndFromMap(hWnd); + if (pWnd) + { + Processed = pWnd->PreTranslateMessage(&Msg); + if(Processed) + break; + } + } + } + } + + return Processed; + } + + inline int CWinApp::Run() + { + // InitInstance runs the App's initialization code + if (InitInstance()) + { + // Dispatch the window messages + return MessageLoop(); + } + else + { + TRACE("InitInstance failed! Terminating program\n"); + ::PostQuitMessage(-1); + return -1; + } + } + + inline void CWinApp::SetAccelerators(HACCEL hAccel, CWnd* pWndAccel) + // nID is the resource ID of the accelerator table + // pWndAccel is the window pointer for translated messages + { + assert (hAccel); + assert (pWndAccel); + + m_pWndAccel = pWndAccel; + m_hAccel = hAccel; + } + + inline void CWinApp::SetCallback() + { + // Registers a temporary window class so we can get the callback + // address of CWnd::StaticWindowProc. + // This technique works for all Window versions, including WinCE. + + WNDCLASS wcDefault = {0}; + + LPCTSTR szClassName = _T("Win32++ Temporary Window Class"); + wcDefault.hInstance = GetInstanceHandle(); + wcDefault.lpfnWndProc = CWnd::StaticWindowProc; + wcDefault.lpszClassName = szClassName; + + ::RegisterClass(&wcDefault); + + // Retrieve the class information + ZeroMemory(&wcDefault, sizeof(wcDefault)); + ::GetClassInfo(GetInstanceHandle(), szClassName, &wcDefault); + + // Save the callback address of CWnd::StaticWindowProc + assert(wcDefault.lpfnWndProc); // Assert fails when running UNICODE build on ANSI OS. + m_Callback = wcDefault.lpfnWndProc; + ::UnregisterClass(szClassName, GetInstanceHandle()); + } + + inline CWinApp* CWinApp::SetnGetThis(CWinApp* pThis /*= 0*/) + { + // This function stores the 'this' pointer in a static variable. + // Once stored, it can be used later to return the 'this' pointer. + // CWinApp's Destructor calls this function with a value of -1. + + static CWinApp* pWinApp = 0; + + if ((CWinApp*)-1 == pThis) + pWinApp = 0; + else if (0 == pWinApp) + pWinApp = pThis; + + return pWinApp; + } + + inline void CWinApp::SetResourceHandle(HINSTANCE hResource) + { + // This function can be used to load a resource dll. + // A resource dll can be used to define resources in different languages. + // To use this function, place code like this in InitInstance + // + // HINSTANCE hResource = LoadLibrary(_T("MyResourceDLL.dll")); + // SetResourceHandle(hResource); + + m_hResource = hResource; + } + + inline TLSData* CWinApp::SetTlsIndex() + { + TLSData* pTLSData = (TLSData*)::TlsGetValue(GetTlsIndex()); + if (NULL == pTLSData) + { + pTLSData = new TLSData; + + m_csTLSLock.Lock(); + m_vTLSData.push_back(pTLSData); // store as a Shared_Ptr + m_csTLSLock.Release(); + + ::TlsSetValue(GetTlsIndex(), pTLSData); + } + + return pTLSData; + } + + + //////////////////////////////////////// + // Definitions for the CWnd class + // + inline CWnd::CWnd() : m_hWnd(NULL), m_PrevWindowProc(NULL), m_IsTmpWnd(FALSE) + { + // Note: m_hWnd is set in CWnd::CreateEx(...) + m_pcs = new CREATESTRUCT; // store the CREATESTRICT in a smart pointer + m_pwc = new WNDCLASS; // store the WNDCLASS in a smart pointer + ::ZeroMemory(m_pcs.get(), sizeof(CREATESTRUCT)); + ::ZeroMemory(m_pwc.get(), sizeof(WNDCLASS)); + } + + inline CWnd::~CWnd() + { + // Destroys the window for this object and cleans up resources. + Destroy(); + } + + inline void CWnd::AddToMap() + // Store the window handle and CWnd pointer in the HWND map + { + assert( GetApp() ); + GetApp()->m_csMapLock.Lock(); + + // assert(::IsWindow(m_hWnd)); + assert(!GetApp()->GetCWndFromMap(m_hWnd)); + + GetApp()->m_mapHWND.insert(std::make_pair(m_hWnd, this)); + GetApp()->m_csMapLock.Release(); + } + + inline BOOL CWnd::Attach(HWND hWnd) + // Subclass an existing window and attach it to a CWnd + { + assert( GetApp() ); + assert(::IsWindow(hWnd)); + + // Ensure this thread has the TLS index set + // Note: Perform the attach from the same thread as the window's message loop + GetApp()->SetTlsIndex(); + + // Cleanup any previous attachment + if (m_PrevWindowProc) + Detach(); + CWnd* pWnd = GetApp()->GetCWndFromMap(hWnd); + if (pWnd) + pWnd->Cleanup(); + + Subclass(hWnd); // Set the window's callback to CWnd::StaticWindowProc + AddToMap(); // Store the CWnd pointer in the HWND map + OnCreate(); + OnInitialUpdate(); + + return TRUE; + } + + inline BOOL CWnd::AttachDlgItem(UINT nID, CWnd* pParent) + // Converts a dialog item to a CWnd object + { + assert(pParent->IsWindow()); + + HWND hWnd = ::GetDlgItem(pParent->GetHwnd(), nID); + return Attach(hWnd); + } + + inline void CWnd::CenterWindow() const + // Centers this window over it's parent + { + + // required for multi-monitor support with Dev-C++ and VC6 + #ifndef _WIN32_WCE + #ifndef MONITOR_DEFAULTTONEAREST + #define MONITOR_DEFAULTTONEAREST 0x00000002 + #endif + #ifndef HMONITOR + DECLARE_HANDLE(HMONITOR); + #endif + #ifndef MONITORINFO + typedef struct tagMONITORINFO + { + DWORD cbSize; + RECT rcMonitor; + RECT rcWork; + DWORD dwFlags; + } MONITORINFO, *LPMONITORINFO; + #endif // MONITOR_DEFAULTTONEAREST + #endif // _WIN32_WCE + + assert(::IsWindow(m_hWnd)); + + CRect rc = GetWindowRect(); + CRect rcParent; + CRect rcDesktop; + + // Get screen dimensions excluding task bar + ::SystemParametersInfo(SPI_GETWORKAREA, 0, &rcDesktop, 0); + + // Get the parent window dimensions (parent could be the desktop) + if (GetParent() != NULL) rcParent = GetParent()->GetWindowRect(); + else rcParent = rcDesktop; + + #ifndef _WIN32_WCE + // Import the GetMonitorInfo and MonitorFromWindow functions + HMODULE hUser32 = LoadLibrary(_T("USER32.DLL")); + typedef BOOL (WINAPI* LPGMI)(HMONITOR hMonitor, LPMONITORINFO lpmi); + typedef HMONITOR (WINAPI* LPMFW)(HWND hwnd, DWORD dwFlags); + LPMFW pfnMonitorFromWindow = (LPMFW)::GetProcAddress(hUser32, "MonitorFromWindow"); + #ifdef _UNICODE + LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoW"); + #else + LPGMI pfnGetMonitorInfo = (LPGMI)::GetProcAddress(hUser32, "GetMonitorInfoA"); + #endif + + // Take multi-monitor systems into account + if (pfnGetMonitorInfo && pfnMonitorFromWindow) + { + HMONITOR hActiveMonitor = pfnMonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO mi = { sizeof(mi), 0}; + + if(pfnGetMonitorInfo(hActiveMonitor, &mi)) + { + rcDesktop = mi.rcWork; + if (GetParent() == NULL) rcParent = mi.rcWork; + } + } + FreeLibrary(hUser32); + #endif + + // Calculate point to center the dialog over the portion of parent window on this monitor + rcParent.IntersectRect(rcParent, rcDesktop); + int x = rcParent.left + (rcParent.Width() - rc.Width())/2; + int y = rcParent.top + (rcParent.Height() - rc.Height())/2; + + // Keep the dialog wholly on the monitor display + x = (x < rcDesktop.left)? rcDesktop.left : x; + x = (x > rcDesktop.right - rc.Width())? rcDesktop.right - rc.Width() : x; + y = (y < rcDesktop.top) ? rcDesktop.top: y; + y = (y > rcDesktop.bottom - rc.Height())? rcDesktop.bottom - rc.Height() : y; + + SetWindowPos(0, x, y, 0, 0, SWP_NOSIZE); + } + + inline void CWnd::Cleanup() + // Returns the CWnd to its default state + { + if ( GetApp() ) RemoveFromMap(); + m_hWnd = NULL; + m_PrevWindowProc = NULL; + m_IsTmpWnd = FALSE; + } + + inline HWND CWnd::Create(CWnd* pParent /* = NULL */) + // Creates the window. This is the default method of window creation. + { + + // Test if Win32++ has been started + assert( GetApp() ); + + // Set the WNDCLASS parameters + PreRegisterClass(*m_pwc); + if (m_pwc->lpszClassName) + { + RegisterClass(*m_pwc); + m_pcs->lpszClass = m_pwc->lpszClassName; + } + + // Set the CREATESTRUCT parameters + PreCreate(*m_pcs); + + // Set the Window Class Name + if (!m_pcs->lpszClass) + m_pcs->lpszClass = _T("Win32++ Window"); + + // Set Parent + HWND hWndParent = pParent? pParent->GetHwnd() : 0; + if (!hWndParent && m_pcs->hwndParent) + hWndParent = m_pcs->hwndParent; + + // Set the window style + DWORD dwStyle; + DWORD dwOverlappedStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; + if (m_pcs->style) + dwStyle = m_pcs->style; + else + dwStyle = WS_VISIBLE | ((hWndParent)? WS_CHILD : dwOverlappedStyle); + + // Set window size and position + int x = (m_pcs->cx || m_pcs->cy)? m_pcs->x : CW_USEDEFAULT; + int cx = (m_pcs->cx || m_pcs->cy)? m_pcs->cx : CW_USEDEFAULT; + int y = (m_pcs->cx || m_pcs->cy)? m_pcs->y : CW_USEDEFAULT; + int cy = (m_pcs->cx || m_pcs->cy)? m_pcs->cy : CW_USEDEFAULT; + + // Create the window +#ifndef _WIN32_WCE + CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y, + cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams); +#else + CreateEx(m_pcs->dwExStyle, m_pcs->lpszClass, m_pcs->lpszName, dwStyle, x, y, + cx, cy, pParent, 0, m_pcs->lpCreateParams); +#endif + + return m_hWnd; + } + + inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rc, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/) + // Creates the window by specifying all the window creation parameters + { + int x = rc.left; + int y = rc.top; + int cx = rc.right - rc.left; + int cy = rc.bottom - rc.top; + return CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, x, y, cx, cy, pParent, pMenu, lpParam); + } + + inline HWND CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, CWnd* pParent, CMenu* pMenu, LPVOID lpParam /*= NULL*/) + // Creates the window by specifying all the window creation parameters + { + + assert( GetApp() ); // Test if Win32++ has been started + assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed + + try + { + // Prepare the CWnd if it has been reused + Destroy(); + + // Ensure a window class is registered + std::vector vTChar( MAX_STRING_SIZE+1, _T('\0') ); + TCHAR* ClassName = &vTChar[0]; + if (0 == lpszClassName || 0 == lstrlen(lpszClassName) ) + lstrcpyn (ClassName, _T("Win32++ Window"), MAX_STRING_SIZE); + else + // Create our own local copy of szClassName. + lstrcpyn(ClassName, lpszClassName, MAX_STRING_SIZE); + + WNDCLASS wc = {0}; + wc.lpszClassName = ClassName; + wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + + // Register the window class (if not already registered) + if (!RegisterClass(wc)) + throw CWinException(_T("Failed to register window class")); + + HWND hWndParent = pParent? pParent->GetHwnd() : 0; + + // Ensure this thread has the TLS index set + TLSData* pTLSData = GetApp()->SetTlsIndex(); + + // Store the CWnd pointer in thread local storage + pTLSData->pCWnd = this; + + // Create window +#ifdef _WIN32_WCE + m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, + hWndParent, 0, GetApp()->GetInstanceHandle(), lpParam); +#else + HMENU hMenu = pMenu? pMenu->GetHandle() : NULL; + m_hWnd = ::CreateWindowEx(dwExStyle, ClassName, lpszWindowName, dwStyle, x, y, nWidth, nHeight, + hWndParent, hMenu, GetApp()->GetInstanceHandle(), lpParam); +#endif + + // Now handle window creation failure + if (!m_hWnd) + throw CWinException(_T("Failed to Create Window")); + + // Automatically subclass predefined window class types + ::GetClassInfo(GetApp()->GetInstanceHandle(), lpszClassName, &wc); + if (wc.lpfnWndProc != GetApp()->m_Callback) + { + Subclass(m_hWnd); + + // Send a message to force the HWND to be added to the map + SendMessage(WM_NULL, 0L, 0L); + + OnCreate(); // We missed the WM_CREATE message, so call OnCreate now + } + + // Clear the CWnd pointer from TLS + pTLSData->pCWnd = NULL; + } + + catch (const CWinException &e) + { + TRACE("\n*** Failed to create window ***\n"); + e.what(); // Display the last error message. + + // eat the exception (don't rethrow) + } + + // Window creation is complete. Now call OnInitialUpdate + OnInitialUpdate(); + + return m_hWnd; + } + + inline void CWnd::Destroy() + // Destroys the window and returns the CWnd back to its default state, ready for reuse. + { + if (m_IsTmpWnd) + m_hWnd = NULL; + + if (IsWindow()) + ::DestroyWindow(m_hWnd); + + // Return the CWnd to its default state + Cleanup(); + } + + inline HWND CWnd::Detach() + // Reverse an Attach + { + assert(::IsWindow(m_hWnd)); + assert(0 != m_PrevWindowProc); // Only a subclassed window can be detached + + SetWindowLongPtr(GWLP_WNDPROC, (LONG_PTR)m_PrevWindowProc); + HWND hWnd = m_hWnd; + Cleanup(); + + return hWnd; + } + + inline LRESULT CWnd::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + // Pass messages on to the appropriate default window procedure + // CMDIChild and CMDIFrame override this function + { + return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); + } + + inline CWnd* CWnd::GetAncestor(UINT gaFlags /*= GA_ROOTOWNER*/) const + // The GetAncestor function retrieves a pointer to the ancestor (root parent) + // of the window. Supports Win95. + { + assert(::IsWindow(m_hWnd)); + HWND hWnd = m_hWnd; + + // Load the User32 DLL + typedef HWND WINAPI GETANCESTOR(HWND, UINT); + GETANCESTOR* pfnGetAncestor = NULL; + HMODULE hModule = ::LoadLibrary(_T("USER32.DLL")); + + if (hModule) + { + // Declare a pointer to the GetAncestor function +#ifndef _WIN32_WCE + pfnGetAncestor = (GETANCESTOR*)::GetProcAddress(hModule, "GetAncestor"); +#else + pfnGetAncestor = (GETANCESTOR*)::GetProcAddress(hModule, L"GetAncestor"); +#endif + + if (pfnGetAncestor) + hWnd = (*pfnGetAncestor)(m_hWnd, gaFlags); + + ::FreeLibrary(hModule); + } + + if (!pfnGetAncestor) + { + // Provide our own GetAncestor if necessary + HWND hWndParent = ::GetParent(hWnd); + while (::IsChild(hWndParent, hWnd)) + { + hWnd = hWndParent; + hWndParent = ::GetParent(hWnd); + } + } + + return FromHandle(hWnd); + } + + inline CString CWnd::GetClassName() const + // Retrieves the name of the class to which the specified window belongs. + { + assert(::IsWindow(m_hWnd)); + + CString str; + LPTSTR szStr = str.GetBuffer(MAX_STRING_SIZE+1); + ::GetClassName(m_hWnd, szStr, MAX_STRING_SIZE+1); + str.ReleaseBuffer(); + return str; + } + + inline CString CWnd::GetDlgItemText(int nIDDlgItem) const + // Retrieves the title or text associated with a control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + + int nLength = ::GetWindowTextLength(::GetDlgItem(m_hWnd, nIDDlgItem)); + CString str; + LPTSTR szStr = str.GetBuffer(nLength+1); + ::GetDlgItemText(m_hWnd, nIDDlgItem, szStr, nLength+1); + str.ReleaseBuffer(); + return str; + } + + inline CString CWnd::GetWindowText() const + // Retrieves the text of the window's title bar. + { + assert(::IsWindow(m_hWnd)); + + int nLength = ::GetWindowTextLength(m_hWnd); + CString str; + LPTSTR szStr = str.GetBuffer(nLength+1); + ::GetWindowText(m_hWnd, szStr, nLength+1); + str.ReleaseBuffer(); + return str; + } + + inline BOOL CWnd::OnCommand(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // Override this to handle WM_COMMAND messages, for example + + // switch (LOWORD(wParam)) + // { + // case IDM_FILE_NEW: + // OnFileNew(); + // TRUE; // return TRUE for handled commands + // } + + // return FALSE for unhandled commands + return FALSE; + } + + inline void CWnd::OnCreate() + { + // This function is called when a WM_CREATE message is recieved + // Override it in your derived class to automatically perform tasks + // during window creation. + } + + inline void CWnd::OnDraw(CDC* pDC) + // Called when part of the client area of the window needs to be drawn + { + UNREFERENCED_PARAMETER(pDC); + + // Override this function in your derived class to perform drawing tasks. + } + + inline BOOL CWnd::OnEraseBkgnd(CDC* pDC) + // Called when the background of the window's client area needs to be erased. + { + UNREFERENCED_PARAMETER(pDC); + + // Override this function in your derived class to perform drawing tasks. + + // Return Value: Return FALSE to also permit default erasure of the background + // Return TRUE to prevent default erasure of the background + + return FALSE; + } + + + inline void CWnd::OnInitialUpdate() + { + // This function is called automatically once the window is created + // Override it in your derived class to automatically perform tasks + // after window creation. + } + + inline LRESULT CWnd::MessageReflect(HWND hWndParent, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + // A function used to call OnMessageReflect. You shouldn't need to call or + // override this function. + + HWND hWnd = NULL; + switch (uMsg) + { + case WM_COMMAND: + case WM_CTLCOLORBTN: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORDLG: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLORSCROLLBAR: + case WM_CTLCOLORSTATIC: + case WM_CHARTOITEM: + case WM_VKEYTOITEM: + case WM_HSCROLL: + case WM_VSCROLL: + hWnd = (HWND)lParam; + break; + + case WM_DRAWITEM: + case WM_MEASUREITEM: + case WM_DELETEITEM: + case WM_COMPAREITEM: + hWnd = ::GetDlgItem(hWndParent, (int)wParam); + break; + + case WM_PARENTNOTIFY: + switch(LOWORD(wParam)) + { + case WM_CREATE: + case WM_DESTROY: + hWnd = (HWND)lParam; + break; + } + } + + CWnd* Wnd = GetApp()->GetCWndFromMap(hWnd); + + if (Wnd != NULL) + return Wnd->OnMessageReflect(uMsg, wParam, lParam); + + return 0L; + } + + inline LRESULT CWnd::OnMessageReflect(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(uMsg); + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + // This function processes those special messages (see above) sent + // by some older controls, and reflects them back to the originating CWnd object. + // Override this function in your derrived class to handle these special messages. + + // Your overriding function should look like this ... + + // switch (uMsg) + // { + // Handle your reflected messages here + // } + + // return 0L for unhandled messages + return 0L; + } + + inline LRESULT CWnd::OnNotify(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // You can use either OnNotifyReflect or OnNotify to handle notifications + // Override OnNotifyReflect to handle notifications in the CWnd class that + // generated the notification. OR + // Override OnNotify to handle notifications in the PARENT of the CWnd class + // that generated the notification. + + // Your overriding function should look like this ... + + // switch (((LPNMHDR)lParam)->code) + // { + // Handle your notifications from the CHILD window here + // Return the value recommended by the Windows API documentation. + // For many notifications, the return value doesn't matter, but for some it does. + // } + + // return 0L for unhandled notifications + return 0L; + } + + inline LRESULT CWnd::OnNotifyReflect(WPARAM wParam, LPARAM lParam) + { + UNREFERENCED_PARAMETER(wParam); + UNREFERENCED_PARAMETER(lParam); + + // Override OnNotifyReflect to handle notifications in the CWnd class that + // generated the notification. + + // Your overriding function should look like this ... + + // switch (((LPNMHDR)lParam)->code) + // { + // Handle your notifications from this window here + // Return the value recommended by the Windows API documentation. + // } + + // return 0L for unhandled notifications + return 0L; + } + + inline void CWnd::OnMenuUpdate(UINT nID) + // Called when menu items are about to be displayed + { + UNREFERENCED_PARAMETER(nID); + + // Override this function to modify the behaviour of menu items, + // such as adding or removing checkmarks + } + + inline void CWnd::PreCreate(CREATESTRUCT& cs) + // Called by CWnd::Create to set some window parameters + { + // Test if Win32++ has been started + assert(GetApp()); // Test if Win32++ has been started + + m_pcs->cx = cs.cx; + m_pcs->cy = cs.cy; + m_pcs->dwExStyle = cs.dwExStyle; + m_pcs->hInstance = GetApp()->GetInstanceHandle(); + m_pcs->hMenu = cs.hMenu; + m_pcs->hwndParent = cs.hwndParent; + m_pcs->lpCreateParams = cs.lpCreateParams; + m_pcs->lpszClass = cs.lpszClass; + m_pcs->lpszName = cs.lpszName; + m_pcs->style = cs.style; + m_pcs->x = cs.x; + m_pcs->y = cs.y; + + // Overide this function in your derived class to set the + // CREATESTRUCT values prior to window creation. + // The cs.lpszClass parameter should NOT be specified if the + // PreRegisterClass function is used to create a window class. + } + + inline void CWnd::PreRegisterClass(WNDCLASS& wc) + // Called by CWnd::Create to set some window parameters + // Useful for setting the background brush and cursor + { + // Test if Win32++ has been started + assert( GetApp() ); + + m_pwc->style = wc.style; + m_pwc->lpfnWndProc = CWnd::StaticWindowProc; + m_pwc->cbClsExtra = wc.cbClsExtra; + m_pwc->cbWndExtra = wc.cbWndExtra; + m_pwc->hInstance = GetApp()->GetInstanceHandle(); + m_pwc->hIcon = wc.hIcon; + m_pwc->hCursor = wc.hCursor; + m_pwc->hbrBackground = wc.hbrBackground; + m_pwc->lpszMenuName = wc.lpszMenuName; + m_pwc->lpszClassName = wc.lpszClassName; + + // Overide this function in your derived class to set the + // WNDCLASS values prior to window creation. + + // ADDITIONAL NOTES: + // 1) The lpszClassName must be set for this function to take effect. + // 2) The lpfnWndProc is always CWnd::StaticWindowProc. + // 3) No other defaults are set, so the following settings might prove useful + // wc.hCursor = ::LoadCursor(NULL, IDC_ARROW); + // wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); + // wc.hIcon = ::LoadIcon(NULL, IDI_APPLICATION); + // 4) The styles that can be set here are WNDCLASS styles. These are a different + // set of styles to those set by CREATESTRUCT (used in PreCreate). + // 5) RegisterClassEx is not used because its not supported on WinCE. + // To set a small icon for the window, use SetIconSmall. + } + + inline BOOL CWnd::PreTranslateMessage(MSG* pMsg) + { + UNREFERENCED_PARAMETER(pMsg); + + // Override this function if your class requires input messages to be + // translated before normal processing. Function which translate messages + // include TranslateAccelerator, TranslateMDISysAccel and IsDialogMessage. + // Return TRUE if the message is translated. + + return FALSE; + } + + inline BOOL CWnd::RegisterClass(WNDCLASS& wc) + // A private function used by the PreRegisterClass function to register a + // window class prior to window creation + { + assert( GetApp() ); + assert( (0 != lstrlen(wc.lpszClassName) && ( lstrlen(wc.lpszClassName) <= MAX_STRING_SIZE) ) ); + + // Check to see if this classname is already registered + WNDCLASS wcTest = {0}; + BOOL Done = FALSE; + + if (::GetClassInfo(GetApp()->GetInstanceHandle(), wc.lpszClassName, &wcTest)) + { + wc = wcTest; + Done = TRUE; + } + + if (!Done) + { + // Set defaults + wc.hInstance = GetApp()->GetInstanceHandle(); + wc.lpfnWndProc = CWnd::StaticWindowProc; + + // Register the WNDCLASS structure + if ( !::RegisterClass(&wc) ) + throw CWinException(_T("Failed to register window class")); + + Done = TRUE; + } + + return Done; + } + + inline BOOL CWnd::RemoveFromMap() + { + BOOL Success = FALSE; + + if (GetApp()) + { + + // Allocate an iterator for our HWND map + std::map::iterator m; + + CWinApp* pApp = GetApp(); + if (pApp) + { + // Erase the CWnd pointer entry from the map + pApp->m_csMapLock.Lock(); + for (m = pApp->m_mapHWND.begin(); m != pApp->m_mapHWND.end(); ++m) + { + if (this == m->second) + { + pApp->m_mapHWND.erase(m); + Success = TRUE; + break; + } + } + + pApp->m_csMapLock.Release(); + } + } + + return Success; + } + + inline HICON CWnd::SetIconLarge(int nIcon) + // Sets the large icon associated with the window + { + assert( GetApp() ); + assert(::IsWindow(m_hWnd)); + + HICON hIconLarge = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON, + ::GetSystemMetrics (SM_CXICON), ::GetSystemMetrics (SM_CYICON), 0)); + + if (hIconLarge) + SendMessage (WM_SETICON, WPARAM (ICON_BIG), LPARAM (hIconLarge)); + else + TRACE("**WARNING** SetIconLarge Failed\n"); + + return hIconLarge; + } + + inline HICON CWnd::SetIconSmall(int nIcon) + // Sets the small icon associated with the window + { + assert( GetApp() ); + assert(::IsWindow(m_hWnd)); + + HICON hIconSmall = (HICON) (::LoadImage (GetApp()->GetResourceHandle(), MAKEINTRESOURCE (nIcon), IMAGE_ICON, + ::GetSystemMetrics (SM_CXSMICON), ::GetSystemMetrics (SM_CYSMICON), 0)); + + if (hIconSmall) + SendMessage (WM_SETICON, WPARAM (ICON_SMALL), LPARAM (hIconSmall)); + else + TRACE("**WARNING** SetIconSmall Failed\n"); + + return hIconSmall; + } + + inline LRESULT CALLBACK CWnd::StaticWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + // All CWnd windows direct their messages here. This function redirects the message + // to the CWnd's WndProc function. + { + assert( GetApp() ); + + CWnd* w = GetApp()->GetCWndFromMap(hWnd); + if (0 == w) + { + // The CWnd pointer wasn't found in the map, so add it now + + // Retrieve the pointer to the TLS Data + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + assert(pTLSData); + + // Retrieve pointer to CWnd object from Thread Local Storage TLS + w = pTLSData->pCWnd; + assert(w); // pTLSData->pCWnd is assigned in CreateEx + pTLSData->pCWnd = NULL; + + // Store the CWnd pointer in the HWND map + w->m_hWnd = hWnd; + w->AddToMap(); + } + + return w->WndProc(uMsg, wParam, lParam); + + } // LRESULT CALLBACK StaticWindowProc(...) + + inline void CWnd::Subclass(HWND hWnd) + // A private function used by CreateEx, Attach and AttachDlgItem + { + assert(::IsWindow(hWnd)); + + m_PrevWindowProc = (WNDPROC)::SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)CWnd::StaticWindowProc); + m_hWnd = hWnd; + } + + inline LRESULT CWnd::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + // Override this function in your class derrived from CWnd to handle + // window 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 WndProcDefault + return WndProcDefault(uMsg, wParam, lParam); + } + + inline LRESULT CWnd::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam) + // All WndProc functions should pass unhandled window messages to this function + { + LRESULT lr = 0L; + + switch (uMsg) + { + case UWM_CLEANUPTEMPS: + { + TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex()); + pTLSData->vTmpWnds.clear(); + } + break; + 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; // Note: Some MDI commands require default processing + case WM_CREATE: + OnCreate(); + break; + // An example of how to end the application when the window closes + // If needed, put this in the class you inherit from CWnd + // case WM_DESTROY: + // ::PostQuitMessage(0); + // return 0L; + case WM_NOTIFY: + { + // Do Notification reflection if it came from a CWnd object + HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom; + CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom); + + if (lstrcmp(GetClassName(), _T("ReBarWindow32")) != 0) // Skip notification reflection for rebars to avoid double handling + { + 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); + if (lr) return lr; + } + break; + + case WM_PAINT: + { + // Subclassed controls expect to do their own painting. + // CustomDraw or OwnerDraw are normally used to modify the drawing of controls. + if (m_PrevWindowProc) break; + + 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); + } + } + return 0L; + + 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: + { + // if (m_PrevWindowProc) break; // Suppress for subclassed windows + + LRESULT lr = MessageReflect(m_hWnd, uMsg, wParam, lParam); + if (lr) return lr; // Message processed so return + } + break; // Do default processing when message not already processed + + case UWM_UPDATE_COMMAND: + OnMenuUpdate((UINT)wParam); // Perform menu updates + break; + + } // switch (uMsg) + + // Now hand all messages to the default procedure + if (m_PrevWindowProc) + return ::CallWindowProc(m_PrevWindowProc, m_hWnd, uMsg, wParam, lParam); + else + return FinalWindowProc(uMsg, wParam, lParam); + + } // LRESULT CWnd::WindowProc(...) + + + // + // Wrappers for Win32 API functions + // + + inline CDC* CWnd::BeginPaint(PAINTSTRUCT& ps) const + // The BeginPaint function prepares the specified window for painting and fills a PAINTSTRUCT structure with + // information about the painting. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::BeginPaint(m_hWnd, &ps)); + } + + inline BOOL CWnd::BringWindowToTop() const + // The BringWindowToTop function brings the specified window to the top + // of the Z order. If the window is a top-level window, it is activated. + { + assert(::IsWindow(m_hWnd)); + return ::BringWindowToTop(m_hWnd); + } + + inline LRESULT CWnd::CallWindowProc(WNDPROC lpPrevWndFunc, UINT Msg, WPARAM wParam, LPARAM lParam) const + { + assert(::IsWindow(m_hWnd)); + return ::CallWindowProc(lpPrevWndFunc, m_hWnd, Msg, wParam, lParam); + } + + inline BOOL CWnd::CheckDlgButton(int nIDButton, UINT uCheck) const + // The CheckDlgButton function changes the check state of a button control. + { + assert(::IsWindow(m_hWnd)); + return ::CheckDlgButton(m_hWnd, nIDButton, uCheck); + } + + inline BOOL CWnd::CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) const + // The CheckRadioButton function adds a check mark to (checks) a specified radio button in a group + // and removes a check mark from (clears) all other radio buttons in the group. + { + assert(::IsWindow(m_hWnd)); + return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); + } + + inline CWnd* CWnd::ChildWindowFromPoint(POINT pt) const + // determines which, if any, of the child windows belonging to a parent window contains + // the specified point. The search is restricted to immediate child windows. + // Grandchildren, and deeper descendant windows are not searched. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::ChildWindowFromPoint(m_hWnd, pt)); + } + + inline BOOL CWnd::ClientToScreen(POINT& pt) const + // The ClientToScreen function converts the client-area coordinates of a specified point to screen coordinates. + { + assert(::IsWindow(m_hWnd)); + return ::ClientToScreen(m_hWnd, &pt); + } + + inline BOOL CWnd::ClientToScreen(RECT& rc) const + // The ClientToScreen function converts the client-area coordinates of a specified RECT to screen coordinates. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2); + } + + inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const + // The DeferWindowPos function updates the specified multiple-window – position structure for the window. + { + assert(::IsWindow(m_hWnd)); + return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + inline HDWP CWnd::DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, const RECT& rc, UINT uFlags) const + // The DeferWindowPos function updates the specified multiple-window – position structure for the window. + { + assert(::IsWindow(m_hWnd)); + return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags); + } + + inline LRESULT CWnd::DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) const + // This function provides default processing for any window messages that an application does not process. + { + assert(::IsWindow(m_hWnd)); + return ::DefWindowProc(m_hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::DrawMenuBar() const + // The DrawMenuBar function redraws the menu bar of the specified window. If the menu bar changes after + // the system has created the window, this function must be called to draw the changed menu bar. + { + assert(::IsWindow(m_hWnd)); + return ::DrawMenuBar(m_hWnd); + } + + inline BOOL CWnd::EnableWindow(BOOL bEnable /*= TRUE*/) const + // The EnableWindow function enables or disables mouse and + // keyboard input to the window. + { + assert(::IsWindow(m_hWnd)); + return ::EnableWindow(m_hWnd, bEnable); + } + + inline BOOL CWnd::EndPaint(PAINTSTRUCT& ps) const + // The EndPaint function marks the end of painting in the specified window. This function is required for + // each call to the BeginPaint function, but only after painting is complete. + { + assert(::IsWindow(m_hWnd)); + return ::EndPaint(m_hWnd, &ps); + } + + inline CWnd* CWnd::GetActiveWindow() const + // The GetActiveWindow function retrieves a pointer to the active window attached to the calling + // thread's message queue. + { + return FromHandle( ::GetActiveWindow() ); + } + + inline CWnd* CWnd::GetCapture() const + // The GetCapture function retrieves a pointer to the window (if any) that has captured the mouse. + { + return FromHandle( ::GetCapture() ); + } + + inline ULONG_PTR CWnd::GetClassLongPtr(int nIndex) const + // The GetClassLongPtr function retrieves the specified value from the + // WNDCLASSEX structure associated with the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetClassLongPtr(m_hWnd, nIndex); + } + + inline CRect CWnd::GetClientRect() const + // The GetClientRect function retrieves the coordinates of a window's client area. + // The client coordinates specify the upper-left and lower-right corners of the + // client area. Because client coordinates are relative to the upper-left corner + // of a window's client area, the coordinates of the upper-left corner are (0,0). + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetClientRect(m_hWnd, &rc); + return rc; + } + + inline CDC* CWnd::GetDC() const + // The GetDC function retrieves a handle to a display device context (DC) for the + // client area of the window. + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetDC(m_hWnd), m_hWnd); + } + + inline CDC* CWnd::GetDCEx(HRGN hrgnClip, DWORD flags) const + // The GetDCEx function retrieves a handle to a display device context (DC) for the + // client area or entire area of a window + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetDCEx(m_hWnd, hrgnClip, flags), m_hWnd); + } + + inline CWnd* CWnd::GetDesktopWindow() const + // The GetDesktopWindow function retrieves a pointer to the desktop window. + { + return FromHandle( ::GetDesktopWindow() ); + } + + inline CWnd* CWnd::GetDlgItem(int nIDDlgItem) const + // The GetDlgItem function retrieves a handle to a control in the dialog box. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetDlgItem(m_hWnd, nIDDlgItem) ); + } + + inline UINT CWnd::GetDlgItemInt(int nIDDlgItem, BOOL* lpTranslated, BOOL bSigned) const + // The GetDlgItemInt function translates the text of a specified control in a dialog box into an integer value. + { + assert(::IsWindow(m_hWnd)); + return ::GetDlgItemInt(m_hWnd, nIDDlgItem, lpTranslated, bSigned); + } + + inline CWnd* CWnd::GetFocus() const + // The GetFocus function retrieves a pointer to the window that has the keyboard focus, if the window + // is attached to the calling thread's message queue. + { + return FromHandle( ::GetFocus() ); + } + + inline CFont* CWnd::GetFont() const + // Retrieves the font with which the window is currently drawing its text. + { + assert(::IsWindow(m_hWnd)); + return FromHandle((HFONT)SendMessage(WM_GETFONT, 0, 0)); + } + + inline HICON CWnd::GetIcon(BOOL bBigIcon) const + // Retrieves a handle to the large or small icon associated with a window. + { + assert(::IsWindow(m_hWnd)); + return (HICON)SendMessage(WM_GETICON, (WPARAM)bBigIcon, 0); + } + + inline CWnd* CWnd::GetNextDlgGroupItem(CWnd* pCtl, BOOL bPrevious) const + // The GetNextDlgGroupItem function retrieves a pointer to the first control in a group of controls that + // precedes (or follows) the specified control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + assert(pCtl); + return FromHandle(::GetNextDlgGroupItem(m_hWnd, pCtl->GetHwnd(), bPrevious)); + } + + inline CWnd* CWnd::GetNextDlgTabItem(CWnd* pCtl, BOOL bPrevious) const + // The GetNextDlgTabItem function retrieves a pointer to the first control that has the WS_TABSTOP style + // that precedes (or follows) the specified control. + { + assert(::IsWindow(m_hWnd)); + assert(pCtl); + return FromHandle(::GetNextDlgTabItem(m_hWnd, pCtl->GetHwnd(), bPrevious)); + } + + inline CWnd* CWnd::GetParent() const + // The GetParent function retrieves a pointer to the specified window's parent or owner. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetParent(m_hWnd) ); + } + + inline LONG_PTR CWnd::GetWindowLongPtr(int nIndex) const + // The GetWindowLongPtr function retrieves information about the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowLongPtr(m_hWnd, nIndex); + } + + inline BOOL CWnd::GetScrollInfo(int fnBar, SCROLLINFO& si) const + // The GetScrollInfo function 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(m_hWnd)); + return ::GetScrollInfo(m_hWnd, fnBar, &si); + } + + inline CRect CWnd::GetUpdateRect(BOOL bErase) const + // The GetUpdateRect function retrieves the coordinates of the smallest rectangle that completely + // encloses the update region of the specified window. + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetUpdateRect(m_hWnd, &rc, bErase); + return rc; + } + + inline int CWnd::GetUpdateRgn(CRgn* pRgn, BOOL bErase) const + // The GetUpdateRgn function retrieves the update region of a window by copying it into the specified region. + { + assert(::IsWindow(m_hWnd)); + assert(pRgn); + HRGN hRgn = (HRGN)pRgn->GetHandle(); + return ::GetUpdateRgn(m_hWnd, hRgn, bErase); + } + + inline CWnd* CWnd::GetWindow(UINT uCmd) const + // The GetWindow function retrieves a pointer to a window that has the specified + // relationship (Z-Order or owner) to the specified window. + // Possible uCmd values: GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST, + // GW_HWNDNEXT, GW_HWNDPREV, GW_OWNER + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetWindow(m_hWnd, uCmd) ); + } + + inline CDC* CWnd::GetWindowDC() const + // The GetWindowDC function retrieves the device context (DC) for the entire + // window, including title bar, menus, and scroll bars. + { + assert(::IsWindow(m_hWnd)); + return CDC::AddTempHDC(::GetWindowDC(m_hWnd), m_hWnd); + } + + inline CRect CWnd::GetWindowRect() const + // retrieves the dimensions of the bounding rectangle of the window. + // The dimensions are given in screen coordinates that are relative to the + // upper-left corner of the screen. + { + assert(::IsWindow(m_hWnd)); + CRect rc; + ::GetWindowRect(m_hWnd, &rc); + return rc; + } + + inline int CWnd::GetWindowTextLength() const + // The GetWindowTextLength function retrieves the length, in characters, of the specified window's + // title bar text (if the window has a title bar). + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowTextLength(m_hWnd); + } + + inline void CWnd::Invalidate(BOOL bErase /*= TRUE*/) const + // The Invalidate function adds the entire client area the window's update region. + // The update region represents the portion of the window's client area that must be redrawn. + { + assert(::IsWindow(m_hWnd)); + ::InvalidateRect(m_hWnd, NULL, bErase); + } + + inline BOOL CWnd::InvalidateRect(LPCRECT lpRect, BOOL bErase /*= TRUE*/) const + // The InvalidateRect function adds a rectangle to the window's update region. + // The update region represents the portion of the window's client area that must be redrawn. + { + assert(::IsWindow(m_hWnd)); + return ::InvalidateRect(m_hWnd, lpRect, bErase); + } + + inline BOOL CWnd::InvalidateRgn(CRgn* pRgn, BOOL bErase /*= TRUE*/) const + // The InvalidateRgn function invalidates the client area within the specified region + // by adding it to the current update region of a window. The invalidated region, + // along with all other areas in the update region, is marked for painting when the + // next WM_PAINT message occurs. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::InvalidateRgn(m_hWnd, hRgn, bErase); + } + + inline BOOL CWnd::IsChild(CWnd* pChild) const + // The IsChild function tests whether a window is a child window or descendant window + // of a parent window's CWnd. + { + assert(::IsWindow(m_hWnd)); + return ::IsChild(m_hWnd, pChild->GetHwnd()); + } + + inline BOOL CWnd::IsDialogMessage(LPMSG lpMsg) const + // The IsDialogMessage function determines whether a message is intended for the specified dialog box and, + // if it is, processes the message. + { + assert(::IsWindow(m_hWnd)); + return ::IsDialogMessage(m_hWnd, lpMsg); + } + + inline UINT CWnd::IsDlgButtonChecked(int nIDButton) const + // The IsDlgButtonChecked function determines whether a button control has a check mark next to it + // or whether a three-state button control is grayed, checked, or neither. + { + assert(::IsWindow(m_hWnd)); + return ::IsDlgButtonChecked(m_hWnd, nIDButton); + } + + inline BOOL CWnd::IsWindowEnabled() const + // The IsWindowEnabled function determines whether the window is enabled + // for mouse and keyboard input. + { + assert(::IsWindow(m_hWnd)); + return ::IsWindowEnabled(m_hWnd); + } + + inline BOOL CWnd::IsWindowVisible() const + // The IsWindowVisible function retrieves the visibility state of the window. + { + assert(::IsWindow(m_hWnd)); + return ::IsWindowVisible(m_hWnd); + } + + inline BOOL CWnd::IsWindow() const + // The IsWindow function determines whether the window exists. + { + return ::IsWindow(m_hWnd); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, POINT& pt) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if(pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), &pt, 1); + } + else + ::MapWindowPoints(m_hWnd, NULL, &pt, 1); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, RECT& rc) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if(pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)&rc, 2); + } + else + ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rc, 2); + } + + inline void CWnd::MapWindowPoints(CWnd* pWndTo, LPPOINT ptArray, UINT nCount) const + // The MapWindowPoints function converts (maps) a set of points from a coordinate space relative to one + // window to a coordinate space relative to another window. + { + assert (m_hWnd); + if (pWndTo) + { + assert (pWndTo->GetHwnd()); + ::MapWindowPoints(m_hWnd, pWndTo->GetHwnd(), (LPPOINT)ptArray, nCount); + } + else + ::MapWindowPoints(m_hWnd, NULL, (LPPOINT)ptArray, nCount); + } + + inline int CWnd::MessageBox(LPCTSTR lpText, LPCTSTR lpCaption, UINT uType) const + // The MessageBox function creates, displays, and operates a message box. + // Possible combinations of uType values include: MB_OK, MB_HELP, MB_OKCANCEL, MB_RETRYCANCEL, + // MB_YESNO, MB_YESNOCANCEL, MB_ICONEXCLAMATION, MB_ICONWARNING, MB_ICONERROR (+ many others). + { + assert(::IsWindow(m_hWnd)); + return ::MessageBox(m_hWnd, lpText, lpCaption, uType); + } + + inline BOOL CWnd::MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint /* = TRUE*/) const + // The MoveWindow function changes the position and dimensions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint = TRUE); + } + + inline BOOL CWnd::MoveWindow(const RECT& rc, BOOL bRepaint /* = TRUE*/) const + // The MoveWindow function changes the position and dimensions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, bRepaint); + } + + inline BOOL CWnd::PostMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const + // The PostMessage function places (posts) a message in the message queue + // associated with the thread that created the window and returns without + // waiting for the thread to process the message. + { + assert(::IsWindow(m_hWnd)); + return ::PostMessage(m_hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::PostMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const + // Required by by some macros + { + assert(::IsWindow(m_hWnd)); + return ::PostMessage(hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::RedrawWindow(LPCRECT lpRectUpdate, CRgn* pRgn, UINT flags) const + // The RedrawWindow function updates the specified rectangle or region in a window's client area. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgn, flags); + } + + inline int CWnd::ReleaseDC(CDC* pDC) const + // The ReleaseDC function releases a device context (DC), freeing it for use + // by other applications. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + return ::ReleaseDC(m_hWnd, pDC->GetHDC()); + } + + inline BOOL CWnd::ScreenToClient(POINT& Point) const + // The ScreenToClient function converts the screen coordinates of a specified point on the screen to client-area coordinates. + { + assert(::IsWindow(m_hWnd)); + return ::ScreenToClient(m_hWnd, &Point); + } + + inline BOOL CWnd::ScreenToClient(RECT& rc) const + // The ScreenToClient function converts the screen coordinates of a specified RECT on the screen to client-area coordinates. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rc, 2); + } + + inline LRESULT CWnd::SendDlgItemMessage(int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) const + // The SendDlgItemMessage function sends a message to the specified control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + return ::SendDlgItemMessage(m_hWnd, nIDDlgItem, Msg, wParam, lParam); + } + + inline LRESULT CWnd::SendMessage(UINT uMsg, WPARAM wParam /*= 0L*/, LPARAM lParam /*= 0L*/) const + // The SendMessage function sends the specified message to a window or windows. + // It calls the window procedure for the window and does not return until the + // window procedure has processed the message. + { + assert(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, uMsg, wParam, lParam); + } + + inline LRESULT CWnd::SendMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) const + // Required by by some macros + { + assert(::IsWindow(m_hWnd)); + return ::SendMessage(hWnd, uMsg, wParam, lParam); + } + + inline BOOL CWnd::SendNotifyMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const + // The SendNotifyMessage function sends the specified message to a window or windows. If the window was created by the + // calling thread, SendNotifyMessage calls the window procedure for the window and does not return until the window procedure + // has processed the message. If the window was created by a different thread, SendNotifyMessage passes the message to the + // window procedure and returns immediately; it does not wait for the window procedure to finish processing the message. + { + assert(::IsWindow(m_hWnd)); + return ::SendNotifyMessage(m_hWnd, Msg, wParam, lParam); + } + + inline CWnd* CWnd::SetActiveWindow() const + // The SetActiveWindow function activates the window, but + // not if the application is in the background. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetActiveWindow(m_hWnd) ); + } + + inline CWnd* CWnd::SetCapture() const + // The SetCapture function sets the mouse capture to the window. + // SetCapture captures mouse input either when the mouse is over the capturing + // window, or when the mouse button was pressed while the mouse was over the + // capturing window and the button is still down. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetCapture(m_hWnd) ); + } + + inline ULONG_PTR CWnd::SetClassLongPtr(int nIndex, LONG_PTR dwNewLong) const + // The SetClassLongPtr function replaces the specified value at the specified offset in the + // extra class memory or the WNDCLASSEX structure for the class to which the window belongs. + { + assert(::IsWindow(m_hWnd)); + return ::SetClassLongPtr(m_hWnd, nIndex, dwNewLong); + } + + inline CWnd* CWnd::SetFocus() const + // The SetFocus function sets the keyboard focus to the window. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::SetFocus(m_hWnd) ); + } + + inline void CWnd::SetFont(CFont* pFont, BOOL bRedraw /* = TRUE*/) const + // Specifies the font that the window will use when drawing text. + { + assert(::IsWindow(m_hWnd)); + assert(pFont); + SendMessage(WM_SETFONT, (WPARAM)pFont->GetHandle(), (LPARAM)bRedraw); + } + + inline HICON CWnd::SetIcon(HICON hIcon, BOOL bBigIcon) const + // Associates a new large or small icon with a window. + { + assert(::IsWindow(m_hWnd)); + return (HICON)SendMessage(WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon); + } + + inline BOOL CWnd::SetForegroundWindow() const + // The SetForegroundWindow function puts the thread that created the window into the + // foreground and activates the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetForegroundWindow(m_hWnd); + } + + inline CWnd* CWnd::SetParent(CWnd* pWndParent) const + // The SetParent function changes the parent window of the child window. + { + assert(::IsWindow(m_hWnd)); + if (pWndParent) + { + HWND hParent = pWndParent->GetHwnd(); + return FromHandle(::SetParent(m_hWnd, hParent)); + } + else + return FromHandle(::SetParent(m_hWnd, 0)); + } + + inline BOOL CWnd::SetRedraw(BOOL bRedraw /*= TRUE*/) const + // This function allows changes in that window to be redrawn or prevents changes + // in that window from being redrawn. + { + assert(::IsWindow(m_hWnd)); + return (BOOL)::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0L); + } + + inline LONG_PTR CWnd::SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) const + // The SetWindowLongPtr function changes an attribute of the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong); + } + + inline BOOL CWnd::SetWindowPos(const CWnd* pInsertAfter, int x, int y, int cx, int cy, UINT uFlags) const + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The pInsertAfter can one of: &wndTop, &wndTopMost, &wndBottom, or &wndNoTopMost + { + assert(::IsWindow(m_hWnd)); + HWND hWndInsertAfter = pInsertAfter? pInsertAfter->GetHwnd() : (HWND)0; + return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + inline BOOL CWnd::SetWindowPos(const CWnd* pInsertAfter, const RECT& rc, UINT uFlags) const + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The SetWindowPos function changes the size, position, and Z order of a child, pop-up, + // or top-level window. + // The pInsertAfter can one of: &wndTop, &wndTopMost, &wndBottom, or &wndNoTopMost + { + assert(::IsWindow(m_hWnd)); + HWND hWndInsertAfter = pInsertAfter? pInsertAfter->GetHwnd() : (HWND)0; + return ::SetWindowPos(m_hWnd, hWndInsertAfter, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, uFlags); + } + + inline int CWnd::SetWindowRgn(CRgn* pRgn, BOOL bRedraw /*= TRUE*/) const + // The SetWindowRgn function sets the window region of the window. + // The window region determines the area within the window where the system permits drawing. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + int iResult = ::SetWindowRgn(m_hWnd, hRgn, bRedraw); + if (iResult && pRgn) + pRgn->Detach(); // The system owns the region now + return iResult; + } + + inline BOOL CWnd::SetDlgItemInt(int nIDDlgItem, UINT uValue, BOOL bSigned) const + // The SetDlgItemInt function sets the text of a control in a dialog box to the string representation of a specified integer value. + { + assert(::IsWindow(m_hWnd)); + return ::SetDlgItemInt(m_hWnd, nIDDlgItem, uValue, bSigned); + } + + inline BOOL CWnd::SetDlgItemText(int nIDDlgItem, LPCTSTR lpString) const + // The SetDlgItemText function sets the title or text of a control in a dialog box. + { + assert(::IsWindow(m_hWnd)); + return ::SetDlgItemText(m_hWnd, nIDDlgItem, lpString); + } + + inline UINT_PTR CWnd::SetTimer(UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc) const + // Creates a timer with the specified time-out value. + { + assert(::IsWindow(m_hWnd)); + return ::SetTimer(m_hWnd, nIDEvent, uElapse, lpTimerFunc); + } + + inline BOOL CWnd::SetWindowText(LPCTSTR lpString) const + // The SetWindowText function changes the text of the window's title bar (if it has one). + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowText(m_hWnd, lpString); + } + + inline HRESULT CWnd::SetWindowTheme(LPCWSTR pszSubAppName, LPCWSTR pszSubIdList) const + // Set the XP Theme for a window. + // Exampes: + // SetWindowTheme(NULL, NULL); // Reverts the window's XP theme back to default + // SetWindowTheme(L" ", L" "); // Disables XP theme for the window + { + HRESULT hr = E_NOTIMPL; + +#ifndef _WIN32_WCE + + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + typedef HRESULT (__stdcall *PFNSETWINDOWTHEME)(HWND hWnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + PFNSETWINDOWTHEME pfn = (PFNSETWINDOWTHEME)GetProcAddress(hMod, "SetWindowTheme"); + + hr = (*pfn)(m_hWnd, pszSubAppName, pszSubIdList); + + ::FreeLibrary(hMod); + } + +#endif + + return hr; + } + + inline BOOL CWnd::ShowWindow(int nCmdShow /*= SW_SHOWNORMAL*/) const + // The ShowWindow function sets the window's show state. + { + assert(::IsWindow(m_hWnd)); + return ::ShowWindow(m_hWnd, nCmdShow); + } + + inline BOOL CWnd::UpdateWindow() const + // The UpdateWindow function updates the client area of the window by sending a + // WM_PAINT message to the window if the window's update region is not empty. + // If the update region is empty, no message is sent. + { + assert(::IsWindow(m_hWnd)); + return ::UpdateWindow(m_hWnd); + } + + inline BOOL CWnd::ValidateRect(LPCRECT prc) const + // The ValidateRect function validates the client area within a rectangle by + // removing the rectangle from the update region of the window. + { + assert(::IsWindow(m_hWnd)); + return ::ValidateRect(m_hWnd, prc); + } + + inline BOOL CWnd::ValidateRgn(CRgn* pRgn) const + // The ValidateRgn function validates the client area within a region by + // removing the region from the current update region of the window. + { + assert(::IsWindow(m_hWnd)); + HRGN hRgn = pRgn? (HRGN)pRgn->GetHandle() : NULL; + return ::ValidateRgn(m_hWnd, hRgn); + } + + inline CWnd* CWnd::WindowFromPoint(POINT pt) + // Retrieves the window that contains the specified point (in screen coodinates). + { + return FromHandle(::WindowFromPoint(pt)); + } + + // + // These functions aren't supported on WinCE + // + #ifndef _WIN32_WCE + inline BOOL CWnd::CloseWindow() const + // The CloseWindow function minimizes (but does not destroy) the window. + // To destroy a window, an application can use the Destroy function. + { + assert(::IsWindow(m_hWnd)); + return ::CloseWindow(m_hWnd); + } + + inline int CWnd::DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT uFileType) const + // The DlgDirList function replaces the contents of a list box with the names of the subdirectories and files + // in a specified directory. You can filter the list of names by specifying a set of file attributes. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, uFileType); + } + + inline int CWnd::DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT uFiletype) const + // The DlgDirListComboBox function replaces the contents of a combo box with the names of the subdirectories + // and files in a specified directory. You can filter the list of names by specifying a set of file attributes. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype); + } + + inline BOOL CWnd::DlgDirSelectEx(LPTSTR lpString, int nCount, int nIDListBox) const + // The DlgDirSelectEx function retrieves the current selection from a single-selection list box. It assumes that the list box + // has been filled by the DlgDirList function and that the selection is a drive letter, filename, or directory name. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); + } + + inline BOOL CWnd::DlgDirSelectComboBoxEx(LPTSTR lpString, int nCount, int nIDComboBox) const + // The DlgDirSelectComboBoxEx function retrieves the current selection from a combo box filled by using the + // DlgDirListComboBox function. The selection is interpreted as a drive letter, a file, or a directory name. + { + assert(::IsWindow(m_hWnd)); + return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); + } + + #ifndef WIN32_LEAN_AND_MEAN + inline void CWnd::DragAcceptFiles(BOOL fAccept) const + // Registers whether a window accepts dropped files. + { + assert(::IsWindow(m_hWnd)); + ::DragAcceptFiles(m_hWnd, fAccept); + } + #endif + + inline BOOL CWnd::DrawAnimatedRects(int idAni, RECT& rcFrom, RECT& rcTo) const + // The DrawAnimatedRects function draws a wire-frame rectangle and animates it to indicate the opening of + // an icon or the minimizing or maximizing of a window. + { + assert(::IsWindow(m_hWnd)); + return ::DrawAnimatedRects(m_hWnd, idAni, &rcFrom, &rcTo); + } + + inline BOOL CWnd::DrawCaption(CDC* pDC, RECT& rc, UINT uFlags) const + // The DrawCaption function draws a window caption. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + return ::DrawCaption(m_hWnd, pDC->GetHDC(), &rc, uFlags); + } + + inline BOOL CWnd::EnableScrollBar(UINT uSBflags, UINT uArrows) const + // The EnableScrollBar function enables or disables one or both scroll bar arrows. + { + assert(::IsWindow(m_hWnd)); + return ::EnableScrollBar(m_hWnd, uSBflags, uArrows); + } + + inline CWnd* CWnd::GetLastActivePopup() const + // The GetLastActivePopup function determines which pop-up window owned by the specified window was most recently active. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetLastActivePopup(m_hWnd) ); + } + + inline CMenu* CWnd::GetMenu() const + // The GetMenu function retrieves a handle to the menu assigned to the window. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::GetMenu(m_hWnd)); + } + + inline int CWnd::GetScrollPos(int nBar) const + // The GetScrollPos function retrieves the current position of the scroll box + // (thumb) in the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::GetScrollPos(m_hWnd, nBar); + } + + inline BOOL CWnd::GetScrollRange(int nBar, int& MinPos, int& MaxPos) const + // The GetScrollRange function retrieves the current minimum and maximum scroll box + // (thumb) positions for the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::GetScrollRange(m_hWnd, nBar, &MinPos, &MaxPos ); + } + + inline CMenu* CWnd::GetSystemMenu(BOOL bRevert) const + // The GetSystemMenu function allows the application to access the window menu (also known as the system menu + // or the control menu) for copying and modifying. + { + assert(::IsWindow(m_hWnd)); + return FromHandle(::GetSystemMenu(m_hWnd, bRevert)); + } + + inline CWnd* CWnd::GetTopWindow() const + // The GetTopWindow function examines the Z order of the child windows associated with the parent window and + // retrieves a handle to the child window at the top of the Z order. + { + assert(::IsWindow(m_hWnd)); + return FromHandle( ::GetTopWindow(m_hWnd) ); + } + + inline BOOL CWnd::GetWindowPlacement(WINDOWPLACEMENT& wndpl) const + // The GetWindowPlacement function retrieves the show state and the restored, + // minimized, and maximized positions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::GetWindowPlacement(m_hWnd, &wndpl); + } + + inline BOOL CWnd::HiliteMenuItem(CMenu* pMenu, UINT uItemHilite, UINT uHilite) const + // The HiliteMenuItem function highlights or removes the highlighting from an item in a menu bar. + { + assert(::IsWindow(m_hWnd)); + assert(pMenu); + return ::HiliteMenuItem(m_hWnd, pMenu->GetHandle(), uItemHilite, uHilite); + } + + inline BOOL CWnd::IsIconic() const + // The IsIconic function determines whether the window is minimized (iconic). + { + assert(::IsWindow(m_hWnd)); + return ::IsIconic(m_hWnd); + } + + inline BOOL CWnd::IsZoomed() const + // The IsZoomed function determines whether the window is maximized. + { + assert(::IsWindow(m_hWnd)); + return ::IsZoomed(m_hWnd); + } + + inline BOOL CWnd::KillTimer(UINT_PTR uIDEvent) const + // Destroys the specified timer. + { + assert(::IsWindow(m_hWnd)); + return ::KillTimer(m_hWnd, uIDEvent); + } + + inline BOOL CWnd::LockWindowUpdate() const + // Disables drawing in the window. Only one window can be locked at a time. + // Use UnLockWindowUpdate to re-enable drawing in the window + { + assert(::IsWindow(m_hWnd)); + return ::LockWindowUpdate(m_hWnd); + } + + inline BOOL CWnd::OpenIcon() const + // The OpenIcon function restores a minimized (iconic) window to its previous size and position. + { + assert(::IsWindow(m_hWnd)); + return ::OpenIcon(m_hWnd); + } + + inline void CWnd::Print(CDC* pDC, DWORD dwFlags) const + // Requests that the window draw itself in the specified device context, most commonly in a printer device context. + { + assert(::IsWindow(m_hWnd)); + assert(pDC); + SendMessage(m_hWnd, WM_PRINT, (WPARAM)pDC, (LPARAM)dwFlags); + } + + inline BOOL CWnd::ScrollWindow(int XAmount, int YAmount, LPCRECT lprcScroll, LPCRECT lprcClip) const + // The ScrollWindow function scrolls the contents of the specified window's client area. + { + assert(::IsWindow(m_hWnd)); + return ::ScrollWindow(m_hWnd, XAmount, YAmount, lprcScroll, lprcClip); + } + + inline int CWnd::ScrollWindowEx(int dx, int dy, LPCRECT lprcScroll, LPCRECT lprcClip, CRgn* prgnUpdate, LPRECT lprcUpdate, UINT flags) const + // The ScrollWindow function scrolls the contents of the window's client area. + { + assert(::IsWindow(m_hWnd)); + HRGN hrgnUpdate = prgnUpdate? (HRGN)prgnUpdate->GetHandle() : NULL; + return ::ScrollWindowEx(m_hWnd, dx, dy, lprcScroll, lprcClip, hrgnUpdate, lprcUpdate, flags); + } + + inline BOOL CWnd::SetMenu(CMenu* pMenu) const + // The SetMenu function assigns a menu to the specified window. + // A hMenu of NULL removes the menu. + { + assert(::IsWindow(m_hWnd)); + return ::SetMenu(m_hWnd, pMenu? pMenu->GetHandle() : NULL); + } + + inline int CWnd::SetScrollInfo(int fnBar, const SCROLLINFO& si, BOOL fRedraw) const + // The SetScrollInfo function sets 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(m_hWnd)); + return ::SetScrollInfo(m_hWnd, fnBar, &si, fRedraw); + } + + inline int CWnd::SetScrollPos(int nBar, int nPos, BOOL bRedraw) const + // The SetScrollPos function sets the position of the scroll box (thumb) in + // the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); + } + + inline BOOL CWnd::SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw) const + // The SetScrollRange function sets the minimum and maximum scroll box positions for the scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); + } + + inline BOOL CWnd::SetWindowPlacement(const WINDOWPLACEMENT& wndpl) const + // The SetWindowPlacement function sets the show state and the restored, minimized, + // and maximized positions of the window. + { + assert(::IsWindow(m_hWnd)); + return ::SetWindowPlacement(m_hWnd, &wndpl); + } + + inline BOOL CWnd::ShowOwnedPopups(BOOL fShow) const + // The ShowOwnedPopups function shows or hides all pop-up windows owned by the specified window. + { + assert(::IsWindow(m_hWnd)); + return ::ShowOwnedPopups(m_hWnd, fShow); + } + + inline BOOL CWnd::ShowScrollBar(int nBar, BOOL bShow) const + // The ShowScrollBar function shows or hides the specified scroll bar. + { + assert(::IsWindow(m_hWnd)); + return ::ShowScrollBar(m_hWnd, nBar, bShow); + } + + inline BOOL CWnd::ShowWindowAsync(int nCmdShow) const + // The ShowWindowAsync function sets the show state of a window created by a different thread. + { + assert(::IsWindow(m_hWnd)); + return ::ShowWindowAsync(m_hWnd, nCmdShow); + } + + inline BOOL CWnd::UnLockWindowUpdate() const + // Enables drawing in the window. Only one window can be locked at a time. + // Use LockWindowUpdate to disable drawing in the window + { + assert(::IsWindow(m_hWnd)); + return ::LockWindowUpdate(0); + } + + inline CWnd* CWnd::WindowFromDC(CDC* pDC) const + // The WindowFromDC function returns a handle to the window associated with the specified display device context (DC). + { + assert(pDC); + return FromHandle( ::WindowFromDC(pDC->GetHDC()) ); + } + + + #endif + +}; // namespace Win32xx + + +#endif // _WIN32XX_WINCORE_H_ + Index: include/reactos/libs/win32++/winutils.h =================================================================== --- include/reactos/libs/win32++/winutils.h (revision 0) +++ include/reactos/libs/win32++/winutils.h (working copy) @@ -0,0 +1,658 @@ +// Win32++ Pre-release Version 7.4 +// Released: Not offically released +// +// 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_WINUTILS_H_ +#define _WIN32XX_WINUTILS_H_ + + +// define useful macros from WindowsX.h +#ifndef GET_X_LPARAM + #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#endif +#ifndef GET_Y_LPARAM + #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) +#endif + +// Define our own MIN and MAX macros +// this avoids inconsistencies with Dev-C++ and other compilers, and +// avoids conflicts between typical min/max macros and std::min/std::max +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + + +namespace Win32xx +{ + // Forward declarations + class CPoint; + class CRect; + CWinApp* GetApp(); + + + ///////////////////////////////////////// + // Definition of the CSize class + // This class can be used to replace the SIZE structure + class CSize : public SIZE + { + public: + CSize() { cx = 0; cy = 0; } + CSize(int CX, int CY) { cx = CX; cy = CY; } + CSize(SIZE sz) { cx = sz.cx; cy = sz.cy; } + CSize(POINT pt) { cx = pt.x; cy = pt.y; } + CSize(DWORD dw) { cx = (short)LOWORD(dw); cy = (short)HIWORD(dw); } + void SetSize(int CX, int CY) { cx = CX; cy = CY; } + + // Operators + operator LPSIZE() { return this; } + BOOL operator == (SIZE sz) const { return (cx == sz.cx && cy == sz.cy); } + BOOL operator != (SIZE sz) const { return (cx != sz.cx || cy != sz.cy); } + void operator += (SIZE sz) { cx += sz.cx; cy += sz.cy; } + void operator -= (SIZE sz) { cx -= sz.cx; cy -= sz.cy; } + + // Operators returning CSize + CSize operator - () const { return CSize (-cx, -cy); } + CSize operator + (SIZE sz) const { return CSize (cx + sz.cx, cy + sz.cy); } + CSize operator - (SIZE sz) const { return CSize (cx - sz.cx, cy - sz.cy); } + + // Operators returning CPoint + CPoint operator + (POINT point) const; + CPoint operator - (POINT point) const; + + // Operators returning CRect + CRect operator + (RECT rc) const; + CRect operator - (RECT rc) const; + }; + + + ///////////////////////////////////////// + // Definition of the CPoint class + // This class can be used to replace the POINT structure + class CPoint : public POINT + { + public: + CPoint() { x = 0; y = 0; } + CPoint(int X, int Y) { x = X; y = Y; } + CPoint(POINT pt) { x = pt.x ; y = pt.y; } + CPoint(POINTS pts) { x = pts.x; y = pts.y; } + CPoint(SIZE sz) { x = sz.cx; y = sz.cy; } + CPoint(DWORD dw) { x = (short) LOWORD(dw); y = (short) HIWORD(dw); } + + void Offset(int dx, int dy) { x += dx; y += dy; } + void Offset(POINT pt) { x += pt.x; y += pt.y; } + void Offset(SIZE sz) { x += sz.cx; y += sz.cy; } + void SetPoint(int X, int Y) { x = X; y = Y; } + + // Operators + operator LPPOINT() { return this; } + BOOL operator == (POINT pt) const { return ((x == pt.x) && (y == pt.y)); } + BOOL operator != (POINT pt) const { return ((x != pt.x) || (y != pt.y)); } + void operator += (SIZE sz) { x += sz.cx; y += sz.cy; } + void operator -= (SIZE sz) { x -= sz.cx; y -= sz.cy; } + void operator += (POINT pt) { x += pt.x; y += pt.y; } + void operator -= (POINT pt) { x -= pt.x; y -= pt.y; } + + // Operators returning CPoint + CPoint operator - () const { return CPoint(-x, -y); } + CPoint operator + (SIZE sz) const { return CPoint(x + sz.cx, y + sz.cy); } + CPoint operator - (SIZE sz) const { return CPoint(x - sz.cx, y - sz.cy); } + CPoint operator + (POINT pt) const { return CPoint(x + pt.x, y + pt.y); } + CPoint operator - (POINT pt) const { return CPoint(x - pt.x, y - pt.y); } + + // Operators returning CRect + CRect operator + (RECT rc) const; + CRect operator - (RECT rc) const; + }; + + + ///////////////////////////////////////// + // Definition of the CRect class + // This class can be used to replace the RECT structure. + class CRect : public RECT + { + public: + CRect() { left = top = right = bottom = 0; } + CRect(int l, int t, int r, int b) { left = l; top = t; right = r; bottom = b; } + CRect(RECT rc) { left = rc.left; top = rc.top; right = rc.right; bottom = rc.bottom; } + CRect(POINT pt, SIZE sz) { right = (left = pt.x) + sz.cx; bottom = (top = pt.y) + sz.cy; } + CRect(POINT topLeft, POINT bottomRight) { left = topLeft.x; top = topLeft.y; right = bottomRight.x; bottom = bottomRight.y; } + + BOOL CopyRect(RECT rc) { return ::CopyRect(this, &rc); } + BOOL DeflateRect(int x, int y) { return ::InflateRect(this, -x, -y); } + BOOL DeflateRect(SIZE size) { return ::InflateRect(this, -size.cx, -size.cy); } + BOOL DeflateRect(RECT rc) { return ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); } + BOOL DeflateRect(int l, int t, int r, int b){ return ::InflateRect(this, l - r, t - b); } + BOOL EqualRect(RECT rc) const { return ::EqualRect(&rc, this); } + BOOL InflateRect(int dx, int dy) { return ::InflateRect(this, dx, dy); } + BOOL InflateRect(SIZE sz) { return ::InflateRect(this, sz.cx, sz.cy); } + BOOL InflateRect(RECT rc) { return ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); } + BOOL InflateRect(int l, int t, int r, int b){ return ::InflateRect(this, r - l, b - t); } + BOOL IntersectRect(RECT rc1, RECT rc2) { return ::IntersectRect(this, &rc1, &rc2); } + BOOL IsRectEmpty() const { return ::IsRectEmpty(this);} + BOOL IsRectNull() const { return (left == 0 && right == 0 && top == 0 && bottom == 0); } + CRect MulDiv(int nMult, int nDiv) const { return CRect ((left * nMult) / nDiv, (top * nMult) / nDiv, + (right * nMult) / nDiv, (bottom * nMult) / nDiv); } + void NormalizeRect() { int nTemp; if (left > right) { nTemp = left; left = right; right = nTemp; } + if (top > bottom) { nTemp = top; top = bottom; bottom = nTemp; } } + BOOL OffsetRect(int dx, int dy) { return ::OffsetRect(this, dx, dy); } + BOOL OffsetRect(POINT pt) { return ::OffsetRect(this, pt.x, pt.y); } + BOOL OffsetRect(SIZE size) { return ::OffsetRect(this, size.cx, size.cy); } + BOOL PtInRect(POINT pt) const { return ::PtInRect(this, pt); } + BOOL SetRect(int l, int t, int r, int b) { return ::SetRect(this, l, t, r, b); } + BOOL SetRect(POINT TopLeft, POINT BtmRight) { return ::SetRect(this, TopLeft.x, TopLeft.y, BtmRight.x, BtmRight.y); } + BOOL SetRectEmpty() { return ::SetRectEmpty(this); } + BOOL SubtractRect(RECT rc1, RECT rc2) { return ::SubtractRect(this, &rc1, &rc2); } + BOOL UnionRect(RECT rc1, RECT rc2) { return ::UnionRect(this, &rc1, &rc2); } + + // Reposition rectangle + void MoveToX (int x) { right = Width() + x; left = x; } + void MoveToY (int y) { bottom = Height() + y; top = y; } + void MoveToXY (int x, int y) { MoveToX(x); MoveToY(y); } + void MoveToXY (POINT pt) { MoveToX (pt.x); MoveToY (pt.y); } + + // Attributes + int Height() const { return bottom - top; } + int Width() const { return right - left; } + CSize Size() const { return CSize(Width(), Height()); } + CPoint CenterPoint() const { return CPoint((left + right) / 2, (top + bottom) / 2); } + CPoint TopLeft() const { return CPoint(left, top); } + CPoint BottomRight() const { return CPoint(right, bottom); } + + // operators + operator LPRECT() { return this; } + BOOL operator == (RECT rc) const { return ::EqualRect(this, &rc); } + BOOL operator != (RECT rc) const { return !::EqualRect(this, &rc); } + void operator += (POINT pt) { ::OffsetRect(this, pt.x, pt.y); } + void operator += (SIZE size) { ::OffsetRect(this, size.cx, size.cy); } + void operator += (RECT rc) { ::InflateRect(this, rc.right - rc.left, rc.bottom - rc.top); } + void operator -= (RECT rc) { ::InflateRect(this, rc.left - rc.right, rc.top - rc.bottom); } + void operator -= (POINT pt) { ::OffsetRect(this, -pt.x, -pt.y); } + void operator -= (SIZE sz) { ::OffsetRect(this, -sz.cx, -sz.cy); } + void operator &= (RECT rc) { ::IntersectRect(this, this, &rc); } + void operator |= (RECT rc) { ::UnionRect(this, this, &rc); } + + // Operators returning CRect + CRect operator + (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, pt.x, pt.y); return rc; } + CRect operator - (POINT pt) const { CRect rc(*this); ::OffsetRect(&rc, -pt.x, -pt.y); return rc; } + CRect operator + (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, sz.cx, sz.cy); return rc; } + CRect operator - (SIZE sz) const { CRect rc(*this); ::OffsetRect(&rc, -sz.cx, -sz.cy); return rc; } + CRect operator + (RECT rc) const { CRect rc1(*this); rc1.InflateRect(rc); return rc1; } + CRect operator - (RECT rc) const { CRect rc1(*this); rc1.DeflateRect(rc); return rc1; } + CRect operator & (RECT rc) const { CRect rc1; ::IntersectRect(&rc1, this, &rc); return rc1; } + CRect operator | (RECT rc) const { CRect rc1; ::UnionRect(&rc1, this, &rc); return rc1; } + }; + + // CSize member function definitions + inline CPoint CSize::operator + (POINT pt) const { return CPoint(pt) + *this; } + inline CPoint CSize::operator - (POINT pt) const { return CPoint(pt) - *this; } + inline CRect CSize::operator + (RECT rc) const { return CRect(rc) + *this; } + inline CRect CSize::operator - (RECT rc) const { return CRect(rc) - *this; } + + // CPoint member function definitions + inline CRect CPoint::operator + (RECT rc) const { return CRect(rc) + *this; } + inline CRect CPoint::operator - (RECT rc) const { return CRect(rc) - *this; } + + + //////////////////////////////////////////////////////// + // Classes and functions (typedefs) for text conversions + // + // This section defines the following text conversions: + // 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 WCHAR + // W2A WCHAR to ANSI + // W2BSTR WCHAR to BSTR + // W2OLE WCHAR to OLE + // W2T WCHAR to TCHAR + + // About different character and string types: + // ------------------------------------------ + // char (or CHAR) character types are ANSI (8 bits). + // wchar_t (or WCHAR) character types are Unicode (16 bits). + // TCHAR characters are Unicode if the _UNICODE macro is defined, otherwise they are ANSI. + // BSTR (Basic String) is a type of string used in Visual Basic and COM programming. + // OLE is the same as WCHAR. It is used in Visual Basic and COM programming. + + + // Forward declarations of our classes. They are defined later. + class CA2A; + class CA2W; + class CW2A; + class CW2W; + class CA2BSTR; + class CW2BSTR; + + // typedefs for the well known text conversions + typedef CA2W A2W; + typedef CW2A W2A; + typedef CW2BSTR W2BSTR; + typedef CA2BSTR A2BSTR; + typedef CW2A BSTR2A; + typedef CW2W BSTR2W; + +#ifdef _UNICODE + typedef CA2W A2T; + typedef CW2A T2A; + typedef CW2W T2W; + typedef CW2W W2T; + typedef CW2BSTR T2BSTR; + typedef BSTR2W BSTR2T; +#else + typedef CA2A A2T; + typedef CA2A T2A; + typedef CA2W T2W; + typedef CW2A W2T; + typedef CA2BSTR T2BSTR; + typedef BSTR2A BSTR2T; +#endif + + typedef A2W A2OLE; + typedef T2W T2OLE; + typedef CW2W W2OLE; + typedef W2A OLE2A; + typedef W2T OLE2T; + typedef CW2W OLE2W; + + class CA2W + { + public: + CA2W(LPCSTR pStr) : m_pStr(pStr) + { + if (pStr) + { + // Resize the vector and assign null WCHAR to each element + int length = (int)strlen(pStr)+1; + m_vWideArray.assign(length, L'\0'); + + // Fill our vector with the converted WCHAR array + MultiByteToWideChar(CP_ACP, 0, pStr, -1, &m_vWideArray[0], length); + } + } + ~CA2W() {} + operator LPCWSTR() { return m_pStr? &m_vWideArray[0] : NULL; } + operator LPOLESTR() { return m_pStr? (LPOLESTR)&m_vWideArray[0] : (LPOLESTR)NULL; } + + private: + CA2W(const CA2W&); + CA2W& operator= (const CA2W&); + std::vector m_vWideArray; + LPCSTR m_pStr; + }; + + class CW2A + { + public: + CW2A(LPCWSTR pWStr) : m_pWStr(pWStr) + { + // Resize the vector and assign null char to each element + int length = (int)wcslen(pWStr)+1; + m_vAnsiArray.assign(length, '\0'); + + // Fill our vector with the converted char array + WideCharToMultiByte(CP_ACP, 0, pWStr, -1, &m_vAnsiArray[0], length, NULL,NULL); + } + + ~CW2A() {} + operator LPCSTR() { return m_pWStr? &m_vAnsiArray[0] : NULL; } + + private: + CW2A(const CW2A&); + CW2A& operator= (const CW2A&); + std::vector m_vAnsiArray; + LPCWSTR m_pWStr; + }; + + class CW2W + { + public: + CW2W(LPCWSTR pWStr) : m_pWStr(pWStr) {} + operator LPCWSTR() { return (LPWSTR)m_pWStr; } + operator LPOLESTR() { return (LPOLESTR)m_pWStr; } + + private: + CW2W(const CW2W&); + CW2W& operator= (const CW2W&); + + LPCWSTR m_pWStr; + }; + + class CA2A + { + public: + CA2A(LPCSTR pStr) : m_pStr(pStr) {} + operator LPCSTR() { return (LPSTR)m_pStr; } + + private: + CA2A(const CA2A&); + CA2A& operator= (const CA2A&); + + LPCSTR m_pStr; + }; + + class CW2BSTR + { + public: + CW2BSTR(LPCWSTR pWStr) { m_bstrString = ::SysAllocString(pWStr); } + ~CW2BSTR() { ::SysFreeString(m_bstrString); } + operator BSTR() { return m_bstrString;} + + private: + CW2BSTR(const CW2BSTR&); + CW2BSTR& operator= (const CW2BSTR&); + BSTR m_bstrString; + }; + + class CA2BSTR + { + public: + CA2BSTR(LPCSTR pStr) { m_bstrString = ::SysAllocString(A2W(pStr)); } + ~CA2BSTR() { ::SysFreeString(m_bstrString); } + operator BSTR() { return m_bstrString;} + + private: + CA2BSTR(const CA2BSTR&); + CA2BSTR& operator= (const CA2BSTR&); + BSTR m_bstrString; + }; + + + //////////////////////////////////////// + // Global Functions + // + + inline CWnd* FromHandle(HWND hWnd) + // Returns the CWnd object associated with the window handle + { + assert( GetApp() ); + CWnd* pWnd = hWnd? GetApp()->GetCWndFromMap(hWnd) : 0; + if ( hWnd != NULL && pWnd == 0 ) + { + GetApp()->AddTmpWnd(hWnd); + pWnd = GetApp()->GetCWndFromMap(hWnd); + ::PostMessage(hWnd, UWM_CLEANUPTEMPS, 0, 0); + } + + return pWnd; + } + + + inline CWinApp* GetApp() + // Returns a pointer to the CWinApp derrived class + { + return CWinApp::SetnGetThis(); + } + + inline CPoint GetCursorPos() + { + CPoint pt; + ::GetCursorPos(&pt); + return pt; + } + + inline HBITMAP LoadBitmap (LPCTSTR lpszName) + { + assert(GetApp()); + + HBITMAP hBitmap = (HBITMAP)::LoadImage (GetApp()->GetResourceHandle(), lpszName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + return hBitmap; + } + + inline HBITMAP LoadBitmap (int nID) + { + return LoadBitmap(MAKEINTRESOURCE(nID)); + } + + + inline void TRACE(LPCSTR str) + // TRACE sends a string to the debug/output pane, or an external debugger + { + #ifdef _DEBUG + OutputDebugString(A2T(str)); + #else + UNREFERENCED_PARAMETER(str); // no-op + #endif + } + + inline void TRACE(LPCWSTR str) + // TRACE sends a string to the debug/output pane, or an external debugger + { + #ifdef _DEBUG + OutputDebugString(W2T(str)); + #else + UNREFERENCED_PARAMETER(str); // no-op + #endif + } + + + #ifndef _WIN32_WCE // for Win32/64 operating systems, not WinCE + + inline int GetWinVersion() + { + DWORD dwVersion = GetVersion(); + int Platform = (dwVersion < 0x80000000)? 2:1; + int MajorVer = LOBYTE(LOWORD(dwVersion)); + int MinorVer = HIBYTE(LOWORD(dwVersion)); + + int nVersion = 1000*Platform + 100*MajorVer + MinorVer; + + // Return values and window versions: + // 1400 Windows 95 + // 1410 Windows 98 + // 1490 Windows ME + // 2400 Windows NT + // 2500 Windows 2000 + // 2501 Windows XP + // 2502 Windows Server 2003 + // 2600 Windows Vista and Windows Server 2008 + // 2601 Windows 7 + + return nVersion; + } + + inline int GetComCtlVersion() + { + // Load the Common Controls DLL + HMODULE hComCtl = ::LoadLibraryA("COMCTL32.DLL"); + if (!hComCtl) + return 0; + + int ComCtlVer = 400; + + if (::GetProcAddress(hComCtl, "InitCommonControlsEx")) + { + // InitCommonControlsEx is unique to 4.7 and later + ComCtlVer = 470; + + if (::GetProcAddress(hComCtl, "DllGetVersion")) + { + typedef HRESULT CALLBACK DLLGETVERSION(DLLVERSIONINFO*); + DLLGETVERSION* pfnDLLGetVersion = NULL; + + pfnDLLGetVersion = (DLLGETVERSION*)::GetProcAddress(hComCtl, "DllGetVersion"); + if(pfnDLLGetVersion) + { + DLLVERSIONINFO dvi; + dvi.cbSize = sizeof dvi; + if(NOERROR == pfnDLLGetVersion(&dvi)) + { + DWORD dwVerMajor = dvi.dwMajorVersion; + DWORD dwVerMinor = dvi.dwMinorVersion; + ComCtlVer = 100 * dwVerMajor + dwVerMinor; + } + } + } + else if (::GetProcAddress(hComCtl, "InitializeFlatSB")) + ComCtlVer = 471; // InitializeFlatSB is unique to version 4.71 + } + + ::FreeLibrary(hComCtl); + + // return values and DLL versions + // 400 dll ver 4.00 Windows 95/Windows NT 4.0 + // 470 dll ver 4.70 Internet Explorer 3.x + // 471 dll ver 4.71 Internet Explorer 4.0 + // 472 dll ver 4.72 Internet Explorer 4.01 and Windows 98 + // 580 dll ver 5.80 Internet Explorer 5 + // 581 dll ver 5.81 Windows 2000 and Windows ME + // 582 dll ver 5.82 Windows XP or Vista without XP themes + // 600 dll ver 6.00 Windows XP with XP themes + // 610 dll ver 6.10 Windows Vista with XP themes + // 616 dll ver 6.16 Windows Vista SP1 or Windows 7 with XP themes + + return ComCtlVer; + } + + inline UINT GetSizeofMenuItemInfo() + { + UINT uSize = sizeof(MENUITEMINFO); + // For Win95 and NT, cbSize needs to be 44 + if (1400 == (GetWinVersion()) || (2400 == GetWinVersion())) + uSize = 44; + + return uSize; + } + + inline UINT GetSizeofNonClientMetrics() + { + // This function correctly determines the sizeof NONCLIENTMETRICS + UINT uSize = sizeof (NONCLIENTMETRICS); + + #if (WINVER >= 0x0600) + if (GetWinVersion() < 2600 && (uSize > 500)) // Is OS version less than Vista + uSize -= sizeof(int); // Adjust size back to correct value + #endif + + return uSize; + } + + + + // A global function to report the state of the left mouse button + inline BOOL IsLeftButtonDown() + { + SHORT state; + if (GetSystemMetrics(SM_SWAPBUTTON)) + // Mouse buttons are swapped + state = GetAsyncKeyState(VK_RBUTTON); + else + // Mouse buttons are not swapped + state = GetAsyncKeyState(VK_LBUTTON); + + // returns true if the left mouse button is down + return (state & 0x8000); + } + + inline BOOL IsAeroThemed() + { + BOOL bIsAeroThemed = FALSE; + + // Test if Windows version is XP or greater + if (GetWinVersion() >= 2501) + { + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + // Declare pointers to IsCompositionActive function + FARPROC pIsCompositionActive = ::GetProcAddress(hMod, "IsCompositionActive"); + + if(pIsCompositionActive) + { + if(pIsCompositionActive()) + { + bIsAeroThemed = TRUE; + } + } + ::FreeLibrary(hMod); + } + } + + return bIsAeroThemed; + } + + inline BOOL IsXPThemed() + { + BOOL bIsXPThemed = FALSE; + + // Test if Windows version is XP or greater + if (GetWinVersion() >= 2501) + { + HMODULE hMod = ::LoadLibrary(_T("uxtheme.dll")); + if(hMod) + { + // Declare pointers to functions + FARPROC pIsAppThemed = ::GetProcAddress(hMod, "IsAppThemed"); + FARPROC pIsThemeActive = ::GetProcAddress(hMod, "IsThemeActive"); + + if(pIsAppThemed && pIsThemeActive) + { + if(pIsAppThemed() && pIsThemeActive()) + { + // Test if ComCtl32 dll used is version 6 or later + bIsXPThemed = (GetComCtlVersion() >= 600); + } + } + ::FreeLibrary(hMod); + } + } + + return bIsXPThemed; + } + + #endif // #ifndef _WIN32_WCE + + // Required for WinCE + #ifndef lstrcpyn + inline LPTSTR lstrcpyn(LPTSTR lpstrDest, LPCTSTR lpstrSrc, int nLength) + { + if(NULL == lpstrDest || NULL == lpstrSrc || nLength <= 0) + return NULL; + int nLen = MIN((int)lstrlen(lpstrSrc), nLength - 1); + LPTSTR lpstrRet = (LPTSTR)memcpy(lpstrDest, lpstrSrc, nLen * sizeof(TCHAR)); + lpstrDest[nLen] = _T('\0'); + return lpstrRet; + } + #endif // !lstrcpyn + +} + + +#endif // _WIN32XX_WINUTILS_H_