From: Frank Li Date: Sun, 9 Nov 2008 04:50:49 +0000 (+0800) Subject: Add ext and utils X-Git-Url: http://git.sourceforge.jp/view?p=tortoisegit%2FTortoiseGitJp.git;a=commitdiff_plain;h=c11b32ea70cf865a5510d7462ec4a7e15ece8ce3 Add ext and utils --- diff --git a/Git/CrashReport.h b/Git/CrashReport.h new file mode 100644 index 0000000..ed02d37 --- /dev/null +++ b/Git/CrashReport.h @@ -0,0 +1,172 @@ +#pragma once + +// Client crash callback +typedef BOOL (CALLBACK *LPGETLOGFILE) (LPVOID lpvState); +// Stack trace callback +typedef void (*TraceCallbackFunction)(DWORD_PTR address, const char *ImageName, + const char *FunctionName, DWORD functionDisp, + const char *Filename, DWORD LineNumber, DWORD lineDisp, + void *data); + +typedef LPVOID (*InstallEx)(LPGETLOGFILE pfn, LPCSTR lpcszTo, LPCSTR lpcszSubject, BOOL bUseUI); +typedef void (*UninstallEx)(LPVOID lpState); +typedef void (*EnableUI)(void); +typedef void (*DisableUI)(void); +typedef void (*EnableHandler)(void); +typedef void (*DisableHandler)(void); +typedef void (*AddFileEx)(LPVOID lpState, LPCSTR lpFile, LPCSTR lpDesc); +typedef void (*AddRegistryEx)(LPVOID lpState, LPCSTR lpRegistry, LPCSTR lpDesc); +typedef void (*AddEventLogEx)(LPVOID lpState, LPCSTR lpEventLog, LPCSTR lpDesc); + +/** + * \ingroup CrashRpt + * This class wraps the most important functions the CrashRpt-library + * offers. To learn more about the CrashRpt-library go to + * http://www.codeproject.com/debug/crash_report.asp \n + * To compile the library you need the WTL. You can get the WTL + * directly from Microsoft: + * http://www.microsoft.com/downloads/details.aspx?FamilyID=128e26ee-2112-4cf7-b28e-7727d9a1f288&DisplayLang=en \n + * \n + * Many changes were made to the library so if you read the + * article on CodeProject also read the change log in the source + * folder.\n + * The most important changes are: + * - stack trace is included in the report, with symbols/linenumbers if available + * - "save" button so the user can save the report instead of directly send it + * - can be used by multiple applications + * - zlib linked statically, so no need to ship the zlib.dll separately + * \n + * To use the library just include the header file "CrashReport.h" + * \code + * #include "CrashReport.h" + * \endcode + * Then you can either declare an instance of the class CCrashReport + * somewhere globally in your application like this: + * \code + * CCrashReport g_crasher("report@mycompany.com", "Crash report for MyApplication"); + * \endcode + * that way you can't add registry keys or additional files to the report, but + * it's the fastest and easiest way to use the library. + * Another way is to declare a global variable and initialize it in e.g. InitInstance() + * \code + * CCrashReport g_crasher; + * //then somewhere in InitInstance. + * g_crasher.AddFile("mylogfile.log", "this is a log file"); + * g_crasher.AddRegistry("HKCU\\Software\\MyCompany\\MyProgram"); + * \endcode + * + * + * \remark the dll is dynamically linked at runtime. So the main application + * will still work even if the dll is not shipped. + * + */ +class CCrashReport +{ +public: + /** + * Construct the CrashReport-Object. This loads the dll + * and initializes it. + * \param lpTo the mail address the crash report should be sent to + * \param lpSubject the mail subject + */ + CCrashReport(LPCSTR lpTo = NULL, LPCSTR lpSubject = NULL, BOOL bUseUI = TRUE) + { + InstallEx pfnInstallEx; + TCHAR szFileName[_MAX_PATH]; + GetModuleFileName(NULL, szFileName, _MAX_FNAME); + + // C:\Programme\TortoiseSVN\bin\TortoiseProc.exe -> C:\Programme\TortoiseSVN\bin\CrashRpt.dll + CString strFilename = szFileName; + strFilename = strFilename.Left(strFilename.ReverseFind(_T('\\')) + 1); + strFilename += _T("CrashRpt.dll"); + + m_hDll = LoadLibrary(strFilename); + if (m_hDll) + { + pfnInstallEx = (InstallEx)GetProcAddress(m_hDll, "InstallEx"); + if ( pfnInstallEx ) + { + m_lpvState = pfnInstallEx(NULL, lpTo, lpSubject, bUseUI); + } + } + } + ~CCrashReport() + { + UninstallEx pfnUninstallEx; + if ((m_hDll)&&(m_lpvState)) + { + pfnUninstallEx = (UninstallEx)GetProcAddress(m_hDll, "UninstallEx"); + pfnUninstallEx(m_lpvState); + } + FreeLibrary(m_hDll); + } + /** + * Adds a file which will be included in the crash report. Use this + * if your application generates log-files or the like. + * \param lpFile the full path to the file + * \param lpDesc a description of the file, used in the crash report dialog + */ + void AddFile(LPCSTR lpFile, LPCSTR lpDesc) + { + AddFileEx pfnAddFileEx; + if ((m_hDll)&&(m_lpvState)) + { + pfnAddFileEx = (AddFileEx)GetProcAddress(m_hDll, "AddFileEx"); + (pfnAddFileEx)(m_lpvState, lpFile, lpDesc); + } + } + /** + * Adds a whole registry tree to the crash report. + * \param lpFile the full registry path, e.g. "HKLM\\Software\\MyApplication" + * \param lpDesc a description of the generated registry file, used in the crash report dialog + */ + void AddRegistry(LPCSTR lpFile, LPCSTR lpDesc) + { + AddRegistryEx pfnAddRegistryEx; + if ((m_hDll)&&(m_lpvState)) + { + pfnAddRegistryEx = (AddRegistryEx)GetProcAddress(m_hDll, "AddRegistryHiveEx"); + (pfnAddRegistryEx)(m_lpvState, lpFile, lpDesc); + } + } + /** + * Adds a system Event Log to the crash report. + * \param lpFile + * \param lpDesc + */ + void AddEventLog(LPCSTR lpFile, LPCSTR lpDesc) + { + AddEventLogEx pfnAddEventLogEx; + if ((m_hDll)&&(m_lpvState)) + { + pfnAddEventLogEx = (AddEventLogEx)GetProcAddress(m_hDll, "AddEventLogEx"); + (pfnAddEventLogEx)(m_lpvState, lpFile, lpDesc); + } + } + + + void Enable(BOOL bEnable) + { + EnableHandler pfnEnableHandler; + DisableHandler pfnDisableHandler; + if ((m_hDll)&&(m_lpvState)) + { + if (bEnable) + { + pfnEnableHandler = (EnableHandler)GetProcAddress(m_hDll, "EnableHandlerEx"); + (pfnEnableHandler)(); + } + else + { + OutputDebugString(_T("Calling DisableHandlerEx\n")); + + pfnDisableHandler = (DisableHandler)GetProcAddress(m_hDll, "DisableHandlerEx"); + (pfnDisableHandler)(); + } + } + } + +private: + HMODULE m_hDll; + LPVOID m_lpvState; +}; \ No newline at end of file diff --git a/Git/Git.vcproj b/Git/Git.vcproj new file mode 100644 index 0000000..bf46a55 --- /dev/null +++ b/Git/Git.vcproj @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TortoiseShell/GitAdminDir.cpp b/Git/GitAdminDir.cpp similarity index 100% rename from TortoiseShell/GitAdminDir.cpp rename to Git/GitAdminDir.cpp diff --git a/TortoiseShell/GitAdminDir.h b/Git/GitAdminDir.h similarity index 100% rename from TortoiseShell/GitAdminDir.h rename to Git/GitAdminDir.h diff --git a/Git/GitRev.cpp b/Git/GitRev.cpp new file mode 100644 index 0000000..3c918ad --- /dev/null +++ b/Git/GitRev.cpp @@ -0,0 +1,10 @@ +#include "StdAfx.h" +#include "GitRev.h" + +GitRev::GitRev(void) +{ +} + +GitRev::~GitRev(void) +{ +} diff --git a/Git/GitRev.h b/Git/GitRev.h new file mode 100644 index 0000000..48445c5 --- /dev/null +++ b/Git/GitRev.h @@ -0,0 +1,8 @@ +#pragma once + +class GitRev +{ +public: + GitRev(void); + ~GitRev(void); +}; diff --git a/TortoiseShell/GitStatus.cpp b/Git/GitStatus.cpp similarity index 94% rename from TortoiseShell/GitStatus.cpp rename to Git/GitStatus.cpp index 3759b12..0deea23 100644 --- a/TortoiseShell/GitStatus.cpp +++ b/Git/GitStatus.cpp @@ -18,7 +18,7 @@ // #include "stdafx.h" -#include "resource.h" +//#include "resource.h" #include "..\TortoiseShell\resource.h" //#include "git_config.h" #include "GitStatus.h" @@ -26,11 +26,11 @@ //#include "GitGlobal.h" //#include "GitHelpers.h" #ifdef _MFC_VER -# include "Git.h" -# include "MessageBox.h" -# include "registry.h" -# include "TGitPath.h" -# include "PathUtils.h" +//# include "Git.h" +//# include "MessageBox.h" +//# include "registry.h" +//# include "TGitPath.h" +//# include "PathUtils.h" #endif GitStatus::GitStatus(bool * pbCanceled) @@ -103,7 +103,8 @@ void GitStatus::ClearPool() #ifdef _MFC_VER CString GitStatus::GetLastErrorMsg() const { - return Git::GetErrorString(m_err); +// return Git::GetErrorString(m_err); + return CString(""); } #else stdstring GitStatus::GetLastErrorMsg() const @@ -336,7 +337,7 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false return youngest; #endif - return ""; + return CString(""); } git_wc_status2_t * GitStatus::GetFirstFileStatus(const CTGitPath& path, CTGitPath& retPath, bool update, git_depth_t depth, bool bNoIgnore /* = true */, bool bNoExternals /* = false */) { @@ -566,6 +567,7 @@ void GitStatus::GetStatusString(HINSTANCE hInst, git_wc_status_kind status, TCHA #ifdef _MFC_VER CString GitStatus::GetDepthString(git_depth_t depth) { +#if 0 CString sDepth; switch (depth) { @@ -586,6 +588,8 @@ CString GitStatus::GetDepthString(git_depth_t depth) break; } return sDepth; +#endif + return CString(""); } #endif @@ -759,7 +763,7 @@ void GitStatus::SetFilter(const CTGitPathList& fileList) m_filterFileList.clear(); for(int fileIndex = 0; fileIndex < fileList.GetCount(); fileIndex++) { - m_filterFileList.push_back(fileList[fileIndex].GetGitApiPath(m_pool)); +// m_filterFileList.push_back(fileList[fileIndex].GetGitApiPath(m_pool)); } // Sort the list so that we can do binary searches std::sort(m_filterFileList.begin(), m_filterFileList.end()); diff --git a/TortoiseShell/GitStatus.h b/Git/GitStatus.h similarity index 95% rename from TortoiseShell/GitStatus.h rename to Git/GitStatus.h index 7a8cc05..e36ec17 100644 --- a/TortoiseShell/GitStatus.h +++ b/Git/GitStatus.h @@ -1,7 +1,7 @@ #pragma once #ifdef _MFC_VER -# include "SVNPrompt.h" +//# include "SVNPrompt.h" #endif #include "TGitPath.h" @@ -128,7 +128,7 @@ public: * Returns the string representation of a depth. */ #ifdef _MFC_VER - static CString GetDepthString(Git_depth_t depth); + static CString GetDepthString(git_depth_t depth); #endif static void GetDepthString(HINSTANCE hInst, git_depth_t depth, TCHAR * string, int size, WORD lang); @@ -220,7 +220,7 @@ private: git_error_t * m_err; ///< Subversion error baton #ifdef _MFC_VER - GitPrompt m_prompt; +// GitPrompt m_prompt; #endif /** diff --git a/Git/ReadMe.txt b/Git/ReadMe.txt new file mode 100644 index 0000000..fc8a068 --- /dev/null +++ b/Git/ReadMe.txt @@ -0,0 +1,39 @@ +======================================================================== + STATIC LIBRARY : Git Project Overview +======================================================================== + +AppWizard has created this Git library project for you. + +This file contains a summary of what you will find in each of the files that +make up your Git application. + + +Git.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + + +///////////////////////////////////////////////////////////////////////////// + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Git.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +The compiler and linker switches have been modified to support MFC. Using the +MFC ClassWizard with this project requires that you add several files to the +project, including "resource.h", "Git.rc" and a "Git.h" that +includes resource.h. If you add an rc file to a static library, you may +experience difficulties due to the limitation that only one rc file may be +present in a Dll or Exe. This problem may be overcome by including the +library's .rc file into the parent project's .rc file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/TortoiseShell/TGitPath.cpp b/Git/TGitPath.cpp similarity index 96% rename from TortoiseShell/TGitPath.cpp rename to Git/TGitPath.cpp index 55b69c5..fa469f2 100644 --- a/TortoiseShell/TGitPath.cpp +++ b/Git/TGitPath.cpp @@ -24,8 +24,8 @@ #include #if defined(_MFC_VER) -#include "MessageBox.h" -#include "AppUtils.h" +//#include "MessageBox.h" +//#include "AppUtils.h" #endif using namespace std; @@ -835,7 +835,7 @@ bool CTGitPathList::LoadFromFile(const CTGitPath& filename) TRACE("CFileException loading target file list\n"); TCHAR error[10000] = {0}; pE->GetErrorMessage(error, 10000); - CMessageBox::Show(NULL, error, _T("TortoiseGit"), MB_ICONERROR); +// CMessageBox::Show(NULL, error, _T("TortoiseGit"), MB_ICONERROR); pE->Delete(); return false; } diff --git a/TortoiseShell/TGitPath.h b/Git/TGitPath.h similarity index 96% rename from TortoiseShell/TGitPath.h rename to Git/TGitPath.h index 3998185..c49ce61 100644 --- a/TortoiseShell/TGitPath.h +++ b/Git/TGitPath.h @@ -5,7 +5,7 @@ class CTGitPath public: CTGitPath(void); ~CTGitPath(void); -explicit CTGitPath(const CString& sUnknownPath); + CTGitPath(const CString& sUnknownPath); public: /** * Set the path as an UTF8 string with forward slashes diff --git a/Git/stdafx.cpp b/Git/stdafx.cpp new file mode 100644 index 0000000..4d0cd56 --- /dev/null +++ b/Git/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Git.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Git/stdafx.h b/Git/stdafx.h new file mode 100644 index 0000000..9327402 --- /dev/null +++ b/Git/stdafx.h @@ -0,0 +1,47 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +#include +#include // MFC core and standard components + +#include +#include +#include + +#pragma warning(push) +#pragma warning(disable: 4702) // Unreachable code warnings in xtree +#include +#include +#include +#include +#include +#pragma warning(pop) + + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT +#include +#include +#include +#include +#include // MFC extensions +#include // MFC support for ribbons and control bars + +#include + +// TODO: reference additional headers your program requires here diff --git a/Git/targetver.h b/Git/targetver.h new file mode 100644 index 0000000..f583181 --- /dev/null +++ b/Git/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/Utils/BugTraqAssociations.h b/Utils/BugTraqAssociations.h index 15795c6..e0c82ac 100644 --- a/Utils/BugTraqAssociations.h +++ b/Utils/BugTraqAssociations.h @@ -17,7 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // #pragma once -#include "TSVNPath.h" +#include "TGitPath.h" struct CBugTraqProvider { diff --git a/Utils/Hooks.h b/Utils/Hooks.h index 5aef06a..b72fd82 100644 --- a/Utils/Hooks.h +++ b/Utils/Hooks.h @@ -1,6 +1,6 @@ -// TortoiseSVN - a Windows shell extension for easy version control +// TortoiseGit - a Windows shell extension for easy version control -// Copyright (C) 2006-2008 - TortoiseSVN +// Copyright (C) 2006-2008 - TortoiseGit // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -19,8 +19,9 @@ #pragma once #include #include "registry.h" -#include "TSVNPath.h" -#include "SVNRev.h" +#include "TGitPath.h" +#include "GitRev.h" +#include "GitStatus.h" /** * \ingroup TortoiseProc @@ -47,7 +48,7 @@ class hookkey { public: hooktype htype; - CTSVNPath path; + CTGitPath path; bool operator < (const hookkey& hk) const { @@ -81,12 +82,12 @@ class CHooks : public std::map private: CHooks(); ~CHooks(); - void AddPathParam(CString& sCmd, const CTSVNPathList& pathList); - void AddDepthParam(CString& sCmd, svn_depth_t depth); - void AddCWDParam(CString& sCmd, const CTSVNPathList& pathList); + void AddPathParam(CString& sCmd, const CTGitPathList& pathList); + void AddDepthParam(CString& sCmd, git_depth_t depth); + void AddCWDParam(CString& sCmd, const CTGitPathList& pathList); void AddErrorParam(CString& sCmd, const CString& error); void AddParam(CString& sCmd, const CString& param); - CTSVNPath AddMessageFileParam(CString& sCmd, const CString& message); + CTGitPath AddMessageFileParam(CString& sCmd, const CString& message); public: /// Create the singleton. Call this at the start of the program. static bool Create(); @@ -106,7 +107,7 @@ public: /** * Adds a new hook script. To make the change persistent, call Save(). */ - void Add(hooktype ht, const CTSVNPath& Path, LPCTSTR szCmd, + void Add(hooktype ht, const CTGitPath& Path, LPCTSTR szCmd, bool bWait, bool bShow); /// returns the string representation of the hook type. @@ -125,7 +126,7 @@ public: * in \c pathList, separated by newlines. The hook script can parse this * file to get all the paths the update is about to be done on. */ - bool StartUpdate(const CTSVNPathList& pathList, DWORD& exitcode, + bool StartUpdate(const CTGitPathList& pathList, DWORD& exitcode, CString& error); /** * Executes the Pre-Update-Hook that first matches one of the paths in @@ -143,8 +144,8 @@ public: * to the \c bRecursive parameter. And the string "%REVISION%" is replaced with * the string representation of \c rev. */ - bool PreUpdate(const CTSVNPathList& pathList, svn_depth_t depth, - SVNRev rev, DWORD& exitcode, CString& error); + bool PreUpdate(const CTGitPathList& pathList, git_depth_t depth, + GitRev rev, DWORD& exitcode, CString& error); /** * Executes the Post-Update-Hook that first matches one of the paths in * \c pathList. @@ -161,8 +162,8 @@ public: * to the \c bRecursive parameter. And the string "%REVISION%" is replaced with * the string representation of \c rev. */ - bool PostUpdate(const CTSVNPathList& pathList, svn_depth_t depth, - SVNRev rev, DWORD& exitcode, CString& error); + bool PostUpdate(const CTGitPathList& pathList, git_depth_t depth, + GitRev rev, DWORD& exitcode, CString& error); /** * Executes the Start-Commit-Hook that first matches one of the paths in @@ -179,7 +180,7 @@ public: * \c message. If the script finishes successfully, contents of this file * is read back into \c message parameter. */ - bool StartCommit(const CTSVNPathList& pathList, CString& message, + bool StartCommit(const CTGitPathList& pathList, CString& message, DWORD& exitcode, CString& error); /** * Executes the Pre-Commit-Hook that first matches one of the paths in @@ -194,10 +195,10 @@ public: * in \c pathList, separated by newlines. The hook script can parse this * file to get all the paths the update is about to be done on. * The string "%DEPTH%" is replaced with the numerical value (string) of the - * svn_depth_t parameter. See the Subversion source documentation about the + * Git_depth_t parameter. See the Subversion source documentation about the * values. */ - bool PreCommit(const CTSVNPathList& pathList, svn_depth_t depth, + bool PreCommit(const CTGitPathList& pathList, git_depth_t depth, const CString& message, DWORD& exitcode, CString& error); /** @@ -214,11 +215,11 @@ public: * in \c pathList, separated by newlines. The hook script can parse this * file to get all the paths the commit is about to be done on. * The string "%DEPTH%" is replaced with the numerical value (string) of the - * svn_depth_t parameter. See the Subversion source documentation about the + * Git_depth_t parameter. See the Subversion source documentation about the * values. */ - bool PostCommit(const CTSVNPathList& pathList, svn_depth_t depth, - SVNRev rev, const CString& message, + bool PostCommit(const CTGitPathList& pathList, git_depth_t depth, + GitRev rev, const CString& message, DWORD& exitcode, CString& error); private: @@ -235,6 +236,6 @@ private: * Find the hook script information for the hook type \c t which matches a * path in \c pathList. */ - hookiterator FindItem(hooktype t, const CTSVNPathList& pathList); + hookiterator FindItem(hooktype t, const CTGitPathList& pathList); static CHooks * m_pInstance; }; diff --git a/Utils/MiscUI/DIB.cpp b/Utils/MiscUI/DIB.cpp index edf35c8..3060aeb 100644 --- a/Utils/MiscUI/DIB.cpp +++ b/Utils/MiscUI/DIB.cpp @@ -17,7 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // #include "stdafx.h" -#include "stdex_vector.h" +#include "../stdex_vector.h" #include "DIB.h" CDib::CDib() diff --git a/Utils/MiscUI/FileDropEdit.h b/Utils/MiscUI/FileDropEdit.h index b03deab..dd39a47 100644 --- a/Utils/MiscUI/FileDropEdit.h +++ b/Utils/MiscUI/FileDropEdit.h @@ -18,8 +18,8 @@ // #pragma once -#include "DragDropImpl.h" -#include "UnicodeUtils.h" +#include "../DragDropImpl.h" +#include "../UnicodeUtils.h" /** * \ingroup Utils diff --git a/Utils/MiscUI/HistoryCombo.cpp b/Utils/MiscUI/HistoryCombo.cpp index cea0df8..135affb 100644 --- a/Utils/MiscUI/HistoryCombo.cpp +++ b/Utils/MiscUI/HistoryCombo.cpp @@ -18,7 +18,7 @@ // #include "stdafx.h" #include "HistoryCombo.h" -#include "registry.h" +#include "../registry.h" #ifdef HISTORYCOMBO_WITH_SYSIMAGELIST #include "SysImageList.h" diff --git a/Utils/MiscUI/HyperLink.cpp b/Utils/MiscUI/HyperLink.cpp index fc4fae3..cf7ff33 100644 --- a/Utils/MiscUI/HyperLink.cpp +++ b/Utils/MiscUI/HyperLink.cpp @@ -45,7 +45,6 @@ CHyperLink::~CHyperLink() m_UnderlineFont.DeleteObject(); } - BOOL CHyperLink::DestroyWindow() { KillTimer(m_nTimerID); diff --git a/Utils/PathWatcher.cpp b/Utils/PathWatcher.cpp index adeffa9..429bcad 100644 --- a/Utils/PathWatcher.cpp +++ b/Utils/PathWatcher.cpp @@ -77,7 +77,7 @@ void CPathWatcher::Stop() m_hCompPort = INVALID_HANDLE_VALUE; } -bool CPathWatcher::RemovePathAndChildren(const CTSVNPath& path) +bool CPathWatcher::RemovePathAndChildren(const CTGitPath& path) { bool bRemoved = false; AutoLocker lock(m_critSec); @@ -94,7 +94,7 @@ repeat: return bRemoved; } -bool CPathWatcher::AddPath(const CTSVNPath& path) +bool CPathWatcher::AddPath(const CTGitPath& path) { AutoLocker lock(m_critSec); for (int i=0; im_DirPath.GetLength()+(pnotify->FileNameLength/sizeof(WCHAR)))] = 0; pnotify = (PFILE_NOTIFY_INFORMATION)((LPBYTE)pnotify + nOffset); ATLTRACE(_T("change notification: %s\n"), buf); - m_changedPaths.AddPath(CTSVNPath(buf)); + m_changedPaths.AddPath(CTGitPath(buf)); if ((ULONG_PTR)pnotify - (ULONG_PTR)pdi->m_Buffer > READ_DIR_CHANGE_BUFFER_SIZE) break; } while (nOffset); @@ -350,7 +350,7 @@ void CPathWatcher::ClearInfoMap() m_hCompPort = INVALID_HANDLE_VALUE; } -CPathWatcher::CDirWatchInfo::CDirWatchInfo(HANDLE hDir, const CTSVNPath& DirectoryName) : +CPathWatcher::CDirWatchInfo::CDirWatchInfo(HANDLE hDir, const CTGitPath& DirectoryName) : m_hDir(hDir), m_DirName(DirectoryName) { diff --git a/Utils/PathWatcher.h b/Utils/PathWatcher.h index 21bddb7..5337186 100644 --- a/Utils/PathWatcher.h +++ b/Utils/PathWatcher.h @@ -1,4 +1,4 @@ -// TortoiseSVN - a Windows shell extension for easy version control +// TortoiseGit - a Windows shell extension for easy version control // External Cache Copyright (C) 2007-2008 - TortoiseSVN @@ -17,7 +17,7 @@ // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // #pragma once -#include "TSVNPath.h" +#include "TGitPath.h" #define READ_DIR_CHANGE_BUFFER_SIZE 4096 @@ -46,11 +46,11 @@ public: * watched recursively, then the new path is just ignored and the method * returns false. */ - bool AddPath(const CTSVNPath& path); + bool AddPath(const CTGitPath& path); /** * Removes a path and all its children from the watched list. */ - bool RemovePathAndChildren(const CTSVNPath& path); + bool RemovePathAndChildren(const CTGitPath& path); /** * Returns the number of recursively watched paths. @@ -71,7 +71,7 @@ public: * Returns the list of paths which maybe got changed, i.e., for which * a change notification was received. */ - CTSVNPathList GetChangedPaths() {return m_changedPaths;} + CTGitPathList GetChangedPaths() {return m_changedPaths;} /** * Clears the list of changed paths @@ -90,8 +90,8 @@ private: HANDLE m_hCompPort; volatile LONG m_bRunning; - CTSVNPathList watchedPaths; ///< list of watched paths. - CTSVNPathList m_changedPaths; ///< list of paths which got changed + CTGitPathList watchedPaths; ///< list of watched paths. + CTGitPathList m_changedPaths; ///< list of paths which got changed /** * Helper class: provides information about watched directories. @@ -102,7 +102,7 @@ private: CDirWatchInfo(); // private & not implemented CDirWatchInfo & operator=(const CDirWatchInfo & rhs);//so that they're aren't accidentally used. -- you'll get a linker error public: - CDirWatchInfo(HANDLE hDir, const CTSVNPath& DirectoryName); + CDirWatchInfo(HANDLE hDir, const CTGitPath& DirectoryName); ~CDirWatchInfo(); protected: @@ -110,7 +110,7 @@ private: bool CloseDirectoryHandle(); HANDLE m_hDir; ///< handle to the directory that we're watching - CTSVNPath m_DirName; ///< the directory that we're watching + CTGitPath m_DirName; ///< the directory that we're watching CHAR m_Buffer[READ_DIR_CHANGE_BUFFER_SIZE]; ///< buffer for ReadDirectoryChangesW DWORD m_dwBufLength; ///< length or returned data from ReadDirectoryChangesW -- ignored?... OVERLAPPED m_Overlapped; diff --git a/Utils/SysImageList.cpp b/Utils/SysImageList.cpp index 25af5d6..044cbcf 100644 --- a/Utils/SysImageList.cpp +++ b/Utils/SysImageList.cpp @@ -18,7 +18,7 @@ // #include "stdafx.h" #include "SysImageList.h" -#include "TSVNPath.h" +#include "TGitPath.h" // Singleton constructor and destructor (private) @@ -119,7 +119,7 @@ int CSysImageList::GetFileIconIndex(const CString& file) const return sfi.iIcon; } -int CSysImageList::GetPathIconIndex(const CTSVNPath& filePath) const +int CSysImageList::GetPathIconIndex(const CTGitPath& filePath) const { CString strExtension = filePath.GetFileExtension(); strExtension.MakeUpper(); diff --git a/Utils/SysImageList.h b/Utils/SysImageList.h index 2ad9366..8de8817 100644 --- a/Utils/SysImageList.h +++ b/Utils/SysImageList.h @@ -18,7 +18,7 @@ // #pragma once -class CTSVNPath; +class CTGitPath; /** * \ingroup Utils @@ -69,10 +69,10 @@ public: int GetFileIconIndex(const CString& file) const; /** - * Get the index for a SVN-style path file. + * Get the index for a Git-style path file. * Uses a cache to speed things up */ - int GetPathIconIndex(const CTSVNPath& file) const; + int GetPathIconIndex(const CTGitPath& file) const; private: static CSysImageList *instance; diff --git a/Utils/TempFile.h b/Utils/TempFile.h index 81feb68..e754b29 100644 --- a/Utils/TempFile.h +++ b/Utils/TempFile.h @@ -18,8 +18,8 @@ // #pragma once -#include "TSVNPath.h" -#include "SVNRev.h" +#include "TGitPath.h" +#include "GitRev.h" /** * \ingroup Utils diff --git a/Utils/UnicodeUtils.h b/Utils/UnicodeUtils.h index e33a317..f926a19 100644 --- a/Utils/UnicodeUtils.h +++ b/Utils/UnicodeUtils.h @@ -19,7 +19,7 @@ #pragma once #include - +#include #pragma warning (push,1) #ifndef stdstring typedef std::wstring wide_string; diff --git a/Utils/Utils.vcproj b/Utils/Utils.vcproj new file mode 100644 index 0000000..2479407 --- /dev/null +++ b/Utils/Utils.vcproj @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Utils/stdafx.cpp b/Utils/stdafx.cpp new file mode 100644 index 0000000..e818e3b --- /dev/null +++ b/Utils/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Utils.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Utils/stdafx.h b/Utils/stdafx.h new file mode 100644 index 0000000..9327402 --- /dev/null +++ b/Utils/stdafx.h @@ -0,0 +1,47 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#endif + +#include +#include // MFC core and standard components + +#include +#include +#include + +#pragma warning(push) +#pragma warning(disable: 4702) // Unreachable code warnings in xtree +#include +#include +#include +#include +#include +#pragma warning(pop) + + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT +#include +#include +#include +#include +#include // MFC extensions +#include // MFC support for ribbons and control bars + +#include + +// TODO: reference additional headers your program requires here diff --git a/Utils/targetver.h b/Utils/targetver.h new file mode 100644 index 0000000..f583181 --- /dev/null +++ b/Utils/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/ext/ResizableLib/ResizableComboBox.cpp b/ext/ResizableLib/ResizableComboBox.cpp new file mode 100644 index 0000000..1a749e3 --- /dev/null +++ b/ext/ResizableLib/ResizableComboBox.cpp @@ -0,0 +1,225 @@ +// ResizableComboBox.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000-2004 by Paolo Messina +// (http://www.geocities.com/ppescher - ppescher@hotmail.com) +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableComboBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboBox + +CResizableComboBox::CResizableComboBox() +{ + m_bClipMaxHeight = TRUE; + m_bIntegralHeight = TRUE; +} + +CResizableComboBox::~CResizableComboBox() +{ + if (m_ctrlListBox.GetSafeHwnd() != NULL) + m_ctrlListBox.UnsubclassWindow(); +} + + +BEGIN_MESSAGE_MAP(CResizableComboBox, CComboBox) + //{{AFX_MSG_MAP(CResizableComboBox) + ON_WM_CTLCOLOR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboBox message handlers + +HBRUSH CResizableComboBox::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) +{ + HBRUSH hbr = CComboBox::OnCtlColor(pDC, pWnd, nCtlColor); + + if (nCtlColor == CTLCOLOR_LISTBOX) + { + if (!(GetStyle() & CBS_SIMPLE) + && (m_ctrlListBox.m_hWnd == NULL)) + { + TRACE("ComboLBox: 0x%08X\n", pWnd->m_hWnd); + + // attach to the owned listbox + m_ctrlListBox.m_pOwnerCombo = this; + m_ctrlListBox.SubclassWindow(pWnd->m_hWnd); + } + } + + return hbr; +} + +LRESULT CResizableComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case CB_GETDROPPEDCONTROLRECT: + *(LPRECT)lParam = m_rectDropDown; + MapWindowPoints(NULL, (LPRECT)lParam); + return TRUE; + } + + LRESULT lResult = CComboBox::WindowProc(message, wParam, lParam); + + // if listbox is attached, update horizontal extent + + switch (message) + { + case CB_INSERTSTRING: + case CB_ADDSTRING: + if (lResult != CB_ERR && lResult != CB_ERRSPACE) + UpdateHorizontalExtent((LPCTSTR)lParam); + break; + + case CB_DIR: + if (lResult != CB_ERR && lResult != CB_ERRSPACE) + InitHorizontalExtent(); + break; + + case CB_RESETCONTENT: + InitHorizontalExtent(); + break; + } + + return lResult; +} + +void CResizableComboBox::InitHorizontalExtent() +{ + CClientDC dc(this); + CFont* pOldFont = dc.SelectObject(GetFont()); + + CString str; + + m_iExtent = 0; + int n = GetCount(); + for (int i=0; i m_iExtent) + m_iExtent = cx; + } + + SetHorizontalExtent(m_iExtent + + LOWORD(GetDialogBaseUnits())); + + dc.SelectObject(pOldFont); +} + +void CResizableComboBox::UpdateHorizontalExtent(LPCTSTR szText) +{ + CClientDC dc(this); + CFont* pOldFont = dc.SelectObject(GetFont()); + + int cx = dc.GetTextExtent(szText, lstrlen(szText)).cx; + if (cx > m_iExtent) + { + m_iExtent = cx; + + SetHorizontalExtent(m_iExtent + + LOWORD(GetDialogBaseUnits())); + } + + dc.SelectObject(pOldFont); +} + +void CResizableComboBox::PreSubclassWindow() +{ + ASSERT(GetStyle() & CBS_NOINTEGRALHEIGHT); + + InitHorizontalExtent(); + + GetDroppedControlRect(&m_rectDropDown); + ::MapWindowPoints(NULL, GetSafeHwnd(), + (LPPOINT)&m_rectDropDown, 2); + + CComboBox::PreSubclassWindow(); +} + +int CResizableComboBox::MakeIntegralHeight(const int height) +{ + int inth = height; // integral height (result) + int availh = height; // available height + int n = GetCount(); + + DWORD dwStyle = GetStyle(); + + if (!m_bIntegralHeight || n == 0) + return inth; + + if (dwStyle & CBS_OWNERDRAWVARIABLE) + { + inth = 0; // try to reach availh by integral steps + int i = 0; + // use items below the first visible + for (i=GetTopIndex(); availh>0 && i0 && i>=0; i--) + { + int h = GetItemHeight(i); + if (h == CB_ERR) + break; + + inth += h; + availh -= h; + } + // scroll into view + SetTopIndex(i); + + if (!m_bClipMaxHeight) // it can be higher than all the items + { + // to fill the remaining height, use last item + int h = GetItemHeight(n-1); + if (h != CB_ERR) + { + inth += availh - availh % h; + } + } + } + else + { + // every item has the same height (take the first) + int h = GetItemHeight(0); + if (h != CB_ERR && n != CB_ERR) + { + int rows = availh / h; + // can't be higher than all the items + if (m_bClipMaxHeight && rows > n) + rows = n; + inth = rows * h; + // scroll into view + if (n - rows < GetTopIndex()) + SetTopIndex(n-rows); + } + } + + return inth; +} diff --git a/ext/ResizableLib/ResizableComboBox.h b/ext/ResizableLib/ResizableComboBox.h new file mode 100644 index 0000000..2f93210 --- /dev/null +++ b/ext/ResizableLib/ResizableComboBox.h @@ -0,0 +1,82 @@ +#if !defined(AFX_RESIZABLECOMBOBOX_H__CAEDF06D_C4F5_49E4_A783_AD7D894CF9A0__INCLUDED_) +#define AFX_RESIZABLECOMBOBOX_H__CAEDF06D_C4F5_49E4_A783_AD7D894CF9A0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizableComboBox.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000-2004 by Paolo Messina +// (http://www.geocities.com/ppescher - ppescher@hotmail.com) +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableComboLBox.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboBox window + +class CResizableComboBox : public CComboBox +{ + friend class CResizableComboLBox; + +// Construction +public: + CResizableComboBox(); + +// Attributes +public: + +protected: + CResizableComboLBox m_ctrlListBox; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableComboBox) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual void PreSubclassWindow(); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizableComboBox(); + +protected: + RECT m_rectDropDown; + BOOL m_bClipMaxHeight; + BOOL m_bIntegralHeight; + int m_iExtent; + + void InitHorizontalExtent(); + void UpdateHorizontalExtent(LPCTSTR szText); + int MakeIntegralHeight(const int height); + +// Generated message map functions +protected: + //{{AFX_MSG(CResizableComboBox) + afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLECOMBOBOX_H__CAEDF06D_C4F5_49E4_A783_AD7D894CF9A0__INCLUDED_) diff --git a/ext/ResizableLib/ResizableComboLBox.cpp b/ext/ResizableLib/ResizableComboLBox.cpp new file mode 100644 index 0000000..da3a240 --- /dev/null +++ b/ext/ResizableLib/ResizableComboLBox.cpp @@ -0,0 +1,313 @@ +// ResizableComboLBox.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000-2004 by Paolo Messina +// (http://www.geocities.com/ppescher - ppescher@hotmail.com) +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableComboLBox.h" +#include "ResizableComboBox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboLBox + +CResizableComboLBox::CResizableComboLBox() +{ + m_dwAddToStyle = WS_THICKFRAME; + m_dwAddToStyleEx = 0;//WS_EX_CLIENTEDGE; + m_bSizing = FALSE; +} + +CResizableComboLBox::~CResizableComboLBox() +{ + +} + + +BEGIN_MESSAGE_MAP(CResizableComboLBox, CWnd) + //{{AFX_MSG_MAP(CResizableComboLBox) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_NCHITTEST() + ON_WM_CAPTURECHANGED() + ON_WM_WINDOWPOSCHANGING() + ON_WM_WINDOWPOSCHANGED() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboLBox message handlers + +void CResizableComboLBox::PreSubclassWindow() +{ + CWnd::PreSubclassWindow(); + + InitializeControl(); +} + +BOOL CResizableComboLBox::IsRTL() +{ + return (GetExStyle() & WS_EX_LAYOUTRTL); +} + +void CResizableComboLBox::InitializeControl() +{ + CRect rect; + m_pOwnerCombo->GetWindowRect(&rect); + m_sizeAfterSizing.cx = rect.Width(); + m_sizeAfterSizing.cy = -rect.Height(); + m_pOwnerCombo->GetDroppedControlRect(&rect); + m_sizeAfterSizing.cy += rect.Height(); + m_sizeMin.cy = m_sizeAfterSizing.cy-2; + + // change window's style + ModifyStyleEx(0, m_dwAddToStyleEx); + ModifyStyle(0, m_dwAddToStyle, SWP_FRAMECHANGED); + + // count hscroll if present + if (GetStyle() & WS_HSCROLL) + m_sizeAfterSizing.cy += GetSystemMetrics(SM_CYHSCROLL); + + SetWindowPos(NULL, 0, 0, m_sizeAfterSizing.cx, m_sizeAfterSizing.cy, + SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE); +} + +void CResizableComboLBox::OnMouseMove(UINT nFlags, CPoint point) +{ + CPoint pt = point; + MapWindowPoints(NULL, &pt, 1); // to screen coord + + if (!m_bSizing) + { + // since mouse is captured we need to change the cursor manually + LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y)); + SendMessage(WM_SETCURSOR, (WPARAM)m_hWnd, MAKELPARAM(ht, WM_MOUSEMOVE)); + + CWnd::OnMouseMove(nFlags, point); + return; + } + + // during resize + CRect rect = m_rcBeforeSizing; + CSize relMove = pt - m_ptBeforeSizing; + + switch (m_nHitTest) + { + case HTBOTTOM: + rect.bottom += relMove.cy; + break; + case HTBOTTOMRIGHT: + rect.bottom += relMove.cy; + rect.right += relMove.cx; + break; + case HTRIGHT: + rect.right += relMove.cx; + break; + case HTBOTTOMLEFT: + rect.bottom += relMove.cy; + rect.left += relMove.cx; + break; + case HTLEFT: + rect.left += relMove.cx; + break; + } + + // move window (if right-aligned it needs refresh) + UINT nCopyFlag = (GetExStyle() & WS_EX_RIGHT) ? SWP_NOCOPYBITS : 0; + SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), + SWP_NOACTIVATE|SWP_NOZORDER|nCopyFlag); +} + +void CResizableComboLBox::OnLButtonDown(UINT nFlags, CPoint point) +{ + CPoint pt = point; + MapWindowPoints(NULL, &pt, 1); // to screen coord + + LRESULT ht = SendMessage(WM_NCHITTEST, 0, MAKELPARAM(pt.x, pt.y)); + + if (ht == HTBOTTOM || ht == HTRIGHT || ht == HTBOTTOMRIGHT + || ht == HTLEFT || ht == HTBOTTOMLEFT) + { + // start resizing + m_bSizing = TRUE; + m_nHitTest = ht; + GetWindowRect(&m_rcBeforeSizing); + m_ptBeforeSizing = pt; + } + else + CWnd::OnLButtonDown(nFlags, point); +} + +void CResizableComboLBox::OnLButtonUp(UINT nFlags, CPoint point) +{ + CWnd::OnLButtonUp(nFlags, point); + + EndSizing(); +} + +#if _MSC_VER < 1400 +UINT CResizableComboLBox::OnNcHitTest(CPoint point) +#else +LRESULT CResizableComboLBox::OnNcHitTest(CPoint point) +#endif +{ + CRect rcClient; + GetClientRect(&rcClient); + MapWindowPoints(NULL, &rcClient); + + // ask for default hit-test value + UINT_PTR ht = CWnd::OnNcHitTest(point); + + // disable improper resizing (based on layout setting) + switch (ht) + { + case HTTOPRIGHT: + if (!IsRTL() && point.y > rcClient.top) + ht = HTRIGHT; + else + ht = HTBORDER; + break; + case HTTOPLEFT: + if (IsRTL() && point.y > rcClient.top) + ht = HTLEFT; + else + ht = HTBORDER; + break; + + case HTBOTTOMLEFT: + if (!IsRTL() && point.y > rcClient.bottom) + ht = HTBOTTOM; + else if (!IsRTL()) + ht = HTBORDER; + break; + case HTBOTTOMRIGHT: + if (IsRTL() && point.y > rcClient.bottom) + ht = HTBOTTOM; + else if (IsRTL()) + ht = HTBORDER; + break; + + case HTLEFT: + if (!IsRTL()) + ht = HTBORDER; + break; + case HTRIGHT: + if (IsRTL()) + ht = HTBORDER; + break; + + case HTTOP: + ht = HTBORDER; + } + + return ht; +} + +void CResizableComboLBox::OnCaptureChanged(CWnd *pWnd) +{ + EndSizing(); + + CWnd::OnCaptureChanged(pWnd); +} + +void CResizableComboLBox::EndSizing() +{ + m_bSizing = FALSE; + CRect rect; + GetWindowRect(&rect); + m_sizeAfterSizing = rect.Size(); +} + +void CResizableComboLBox::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) +{ + if (!m_bSizing) + { + // restore the size when the drop-down list becomes visible + lpwndpos->cx = m_sizeAfterSizing.cx; + lpwndpos->cy = m_sizeAfterSizing.cy; + } + ApplyLimitsToPos(lpwndpos); + + CWnd::OnWindowPosChanging(lpwndpos); +} + +void CResizableComboLBox::OnWindowPosChanged(WINDOWPOS FAR* lpwndpos) +{ + // default implementation sends a WM_SIZE message + // that can change the size again to force integral height + + // since we do that manually during resize, we should also + // update the horizontal scrollbar + SendMessage(WM_HSCROLL, SB_ENDSCROLL, 0); + + GetWindowRect(&m_pOwnerCombo->m_rectDropDown); + ::MapWindowPoints(NULL, m_pOwnerCombo->GetSafeHwnd(), + (LPPOINT)&m_pOwnerCombo->m_rectDropDown, 2); + + CWnd::OnWindowPosChanged(lpwndpos); +} + +void CResizableComboLBox::ApplyLimitsToPos(WINDOWPOS* lpwndpos) +{ + //TRACE(">H w(%d)\n", lpwndpos->cy); + // to adjust horizontally, use window rect + + // min width can't be less than combo's + CRect rect; + m_pOwnerCombo->GetWindowRect(&rect); + m_sizeMin.cx = rect.Width(); + + // apply horizontal limits + if (lpwndpos->cx < m_sizeMin.cx) + lpwndpos->cx = m_sizeMin.cx; + + // fix horizontal alignment + rect = CRect(0, 0, lpwndpos->cx, lpwndpos->cy); + m_pOwnerCombo->MapWindowPoints(NULL, &rect); + lpwndpos->x = rect.left; + + // to adjust vertically, use client rect + + // get client rect + rect = CRect(CPoint(lpwndpos->x, lpwndpos->y), + CSize(lpwndpos->cx, lpwndpos->cy)); + SendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&rect); + CSize sizeClient = rect.Size(); + + // apply vertical limits + if (sizeClient.cy < m_sizeMin.cy) + sizeClient.cy = m_sizeMin.cy; + + //TRACE(">H c(%d)\n", sizeClient.cy); + // adjust height, if needed + sizeClient.cy = m_pOwnerCombo->MakeIntegralHeight(sizeClient.cy); + //TRACE(">H c(%d)\n", sizeClient.cy); + + // back to window rect + rect = CRect(0, 0, 1, sizeClient.cy); + DWORD dwStyle = GetStyle(); + ::AdjustWindowRectEx(&rect, dwStyle, FALSE, GetExStyle()); + lpwndpos->cy = rect.Height(); + if (dwStyle & WS_HSCROLL) + lpwndpos->cy += GetSystemMetrics(SM_CYHSCROLL); + + //TRACE("H c(%d) w(%d)\n", sizeClient.cy, lpwndpos->cy); +} + diff --git a/ext/ResizableLib/ResizableComboLBox.h b/ext/ResizableLib/ResizableComboLBox.h new file mode 100644 index 0000000..352826e --- /dev/null +++ b/ext/ResizableLib/ResizableComboLBox.h @@ -0,0 +1,110 @@ +#if !defined(AFX_RESIZABLECOMBOLBOX_H__INCLUDED_) +#define AFX_RESIZABLECOMBOLBOX_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizableComboLBox.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableGrip.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableComboLBox window + +class CResizableComboBox; + +class CResizableComboLBox : public CWnd, public CResizableGrip +{ + friend class CResizableComboBox; + +// Construction +public: + CResizableComboLBox(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableComboLBox) + protected: + virtual void PreSubclassWindow(); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizableComboLBox(); + +private: + CPoint m_ptBeforeSizing; // screen coords + CRect m_rcBeforeSizing; // screen coords + CSize m_sizeAfterSizing; // screen coords + LONG_PTR m_nHitTest; // current resize operation + BOOL m_bSizing; + + void InitializeControl(); + +protected: + DWORD m_dwAddToStyle; + DWORD m_dwAddToStyleEx; + CSize m_sizeMin; // initial size (minimum) + CResizableComboBox* m_pOwnerCombo; // owner combobox + + void ApplyLimitsToPos(WINDOWPOS* lpwndpos); + void EndSizing(); + + BOOL IsRTL(); + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + + // Generated message map functions +protected: + //{{AFX_MSG(CResizableComboLBox) + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); +#if _MSC_VER < 1400 + afx_msg UINT OnNcHitTest(CPoint point); +#else + afx_msg LRESULT OnNcHitTest(CPoint point); +#endif + afx_msg void OnCaptureChanged(CWnd *pWnd); + afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos); + afx_msg void OnWindowPosChanged(WINDOWPOS FAR* lpwndpos); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLECOMBOLBOX_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableDialog.cpp b/ext/ResizableLib/ResizableDialog.cpp new file mode 100644 index 0000000..58d2031 --- /dev/null +++ b/ext/ResizableLib/ResizableDialog.cpp @@ -0,0 +1,178 @@ +// ResizableDialog.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableDialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableDialog + +inline void CResizableDialog::PrivateConstruct() +{ + m_bEnableSaveRestore = FALSE; + m_dwGripTempState = 1; +} + +CResizableDialog::CResizableDialog() +{ + PrivateConstruct(); +} + +CResizableDialog::CResizableDialog(UINT nIDTemplate, CWnd* pParentWnd) + : CDialog(nIDTemplate, pParentWnd) +{ + PrivateConstruct(); +} + +CResizableDialog::CResizableDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd) + : CDialog(lpszTemplateName, pParentWnd) +{ + PrivateConstruct(); +} + +CResizableDialog::~CResizableDialog() +{ +} + + +BEGIN_MESSAGE_MAP(CResizableDialog, CDialog) + //{{AFX_MSG_MAP(CResizableDialog) + ON_WM_GETMINMAXINFO() + ON_WM_SIZE() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + ON_WM_NCCREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableDialog message handlers + +BOOL CResizableDialog::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CDialog::OnNcCreate(lpCreateStruct)) + return FALSE; + + // child dialogs don't want resizable border or size grip, + // nor they can handle the min/max size constraints + BOOL bChild = lpCreateStruct->style & WS_CHILD; + + // create and init the size-grip + if (!CreateSizeGrip(!bChild)) + return FALSE; + + if (!bChild) + { + // set the initial size as the min track size + SetMinTrackSize(CSize(lpCreateStruct->cx, lpCreateStruct->cy)); + } + + MakeResizable(lpCreateStruct); + + return TRUE; +} + +void CResizableDialog::OnDestroy() +{ + if (m_bEnableSaveRestore) + SaveWindowRect(m_sSection, m_bRectOnly); + + // remove child windows + RemoveAllAnchors(); + + CDialog::OnDestroy(); +} + +void CResizableDialog::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW) + return; // arrangement not needed + + if (nType == SIZE_MAXIMIZED) + HideSizeGrip(&m_dwGripTempState); + else + ShowSizeGrip(&m_dwGripTempState); + + // update grip and layout + UpdateSizeGrip(); + ArrangeLayout(); + // on Vista, the redrawing doesn't work right, so we have to work + // around this by invalidating the whole dialog so the DWM recognizes + // that it has to update the application window. + OSVERSIONINFOEX inf; + SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX)); + inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + GetVersionEx((OSVERSIONINFO *)&inf); + WORD fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion); + if (fullver >= 0x0600) + Invalidate(); +} + +void CResizableDialog::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); +} + +// NOTE: this must be called after setting the layout +// to have the dialog and its controls displayed properly +void CResizableDialog::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly) +{ + m_sSection = pszSection; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + LoadWindowRect(pszSection, bRectOnly); + + CMenu* pMenu = GetMenu(); + if ( pMenu ) + DrawMenuBar(); +} + +BOOL CResizableDialog::OnEraseBkgnd(CDC* pDC) +{ + ClipChildren(pDC, FALSE); + + BOOL bRet = CDialog::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +LRESULT CResizableDialog::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CDialog::WindowProc(message, wParam, lParam); + + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CDialog::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} diff --git a/ext/ResizableLib/ResizableDialog.h b/ext/ResizableLib/ResizableDialog.h new file mode 100644 index 0000000..247105f --- /dev/null +++ b/ext/ResizableLib/ResizableDialog.h @@ -0,0 +1,104 @@ +#if !defined(AFX_RESIZABLEDIALOG_H__INCLUDED_) +#define AFX_RESIZABLEDIALOG_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizableDialog.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableGrip.h" +#include "ResizableMinMax.h" +#include "ResizableWndState.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableDialog window + +class CResizableDialog : public CDialog, public CResizableLayout, + public CResizableGrip, public CResizableMinMax, + public CResizableWndState +{ + +// Construction +public: + CResizableDialog(); + CResizableDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL); + CResizableDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL); + +// Attributes +private: + // support for temporarily hiding the grip + DWORD m_dwGripTempState; + + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableDialog) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizableDialog(); + +// used internally +private: + void PrivateConstruct(); + +// callable from derived classes +protected: + // section to use in app's profile + void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE); + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +// Generated message map functions +protected: + //{{AFX_MSG(CResizableDialog) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnDestroy(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEDIALOG_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableFormView.cpp b/ext/ResizableLib/ResizableFormView.cpp new file mode 100644 index 0000000..1c7aa85 --- /dev/null +++ b/ext/ResizableLib/ResizableFormView.cpp @@ -0,0 +1,223 @@ +// ResizableFormView.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableFormView.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableFormView + +IMPLEMENT_DYNAMIC(CResizableFormView, CFormView) + +inline void CResizableFormView::PrivateConstruct() +{ + m_dwGripTempState = GHR_SCROLLBAR | GHR_ALIGNMENT | GHR_MAXIMIZED; +} + +CResizableFormView::CResizableFormView(UINT nIDTemplate) + : CFormView(nIDTemplate) +{ + PrivateConstruct(); +} + +CResizableFormView::CResizableFormView(LPCTSTR lpszTemplateName) + : CFormView(lpszTemplateName) +{ + PrivateConstruct(); +} + +CResizableFormView::~CResizableFormView() +{ +} + + +BEGIN_MESSAGE_MAP(CResizableFormView, CFormView) + //{{AFX_MSG_MAP(CResizableFormView) + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_NCCREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableFormView diagnostics + +#ifdef _DEBUG +void CResizableFormView::AssertValid() const +{ + CFormView::AssertValid(); +} + +void CResizableFormView::Dump(CDumpContext& dc) const +{ + CFormView::Dump(dc); +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CResizableFormView message handlers + +void CResizableFormView::OnSize(UINT nType, int cx, int cy) +{ + CFormView::OnSize(nType, cx, cy); + + CWnd* pParent = GetParentFrame(); + + // hide size grip when parent is maximized + if (pParent->IsZoomed()) + HideSizeGrip(&m_dwGripTempState, GHR_MAXIMIZED); + else + ShowSizeGrip(&m_dwGripTempState, GHR_MAXIMIZED); + + // hide size grip when there are scrollbars + CSize size = GetTotalSize(); + if ((cx < size.cx || cy < size.cy) && (m_nMapMode >= 0)) + HideSizeGrip(&m_dwGripTempState, GHR_SCROLLBAR); + else + ShowSizeGrip(&m_dwGripTempState, GHR_SCROLLBAR); + + // hide size grip when the parent frame window is not resizable + // or the form is not bottom-right aligned (e.g. there's a statusbar) + DWORD dwStyle = pParent->GetStyle(); + CRect rect, rectChild; + GetWindowRect(rect); + + BOOL bCanResize = TRUE; // whether the grip can size the frame + for (HWND hWndChild = ::GetWindow(m_hWnd, GW_HWNDFIRST); hWndChild != NULL; + hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT)) + { + ::GetWindowRect(hWndChild, rectChild); + //! @todo check RTL layouts! + if (rectChild.right > rect.right || rectChild.bottom > rect.bottom) + { + bCanResize = FALSE; + break; + } + } + if ((dwStyle & WS_THICKFRAME) && bCanResize) + ShowSizeGrip(&m_dwGripTempState, GHR_ALIGNMENT); + else + HideSizeGrip(&m_dwGripTempState, GHR_ALIGNMENT); + + // update grip and layout + UpdateSizeGrip(); + ArrangeLayout(); +} + +void CResizableFormView::GetTotalClientRect(LPRECT lpRect) const +{ + GetClientRect(lpRect); + + // get dialog template's size + // (this is set in CFormView::Create) + CSize sizeTotal, sizePage, sizeLine; + int nMapMode = 0; + GetDeviceScrollSizes(nMapMode, sizeTotal, sizePage, sizeLine); + + // otherwise, give the correct size if scrollbars active + + if (nMapMode < 0) // scrollbars disabled + return; + + // enlarge reported client area when needed + CRect rect(lpRect); + if (rect.Width() < sizeTotal.cx) + rect.right = rect.left + sizeTotal.cx; + if (rect.Height() < sizeTotal.cy) + rect.bottom = rect.top + sizeTotal.cy; + + rect.OffsetRect(-GetDeviceScrollPosition()); + *lpRect = rect; +} + +BOOL CResizableFormView::OnEraseBkgnd(CDC* pDC) +{ + ClipChildren(pDC, FALSE); + + BOOL bRet = CFormView::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +void CResizableFormView::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); +} + +void CResizableFormView::OnDestroy() +{ + RemoveAllAnchors(); + + CFormView::OnDestroy(); +} + +LRESULT CResizableFormView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message == WM_INITDIALOG) + return (LRESULT)OnInitDialog(); + + if (message != WM_NCCALCSIZE || wParam == 0) + return CFormView::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CFormView::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} + +BOOL CResizableFormView::OnInitDialog() +{ + const MSG* pMsg = GetCurrentMessage(); + + BOOL bRet = (BOOL)CFormView::WindowProc(pMsg->message, pMsg->wParam, pMsg->lParam); + + // we need to associate member variables with control IDs + UpdateData(FALSE); + + // set default scroll size + CRect rectTemplate; + GetWindowRect(rectTemplate); + SetScrollSizes(MM_TEXT, rectTemplate.Size()); + + return bRet; +} + +BOOL CResizableFormView::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CFormView::OnNcCreate(lpCreateStruct)) + return FALSE; + + // create and init the size-grip + if (!CreateSizeGrip()) + return FALSE; + + return TRUE; +} diff --git a/ext/ResizableLib/ResizableFormView.h b/ext/ResizableLib/ResizableFormView.h new file mode 100644 index 0000000..5cc762b --- /dev/null +++ b/ext/ResizableLib/ResizableFormView.h @@ -0,0 +1,110 @@ +#if !defined(AFX_RESIZABLEFORMVIEW_H__INCLUDED_) +#define AFX_RESIZABLEFORMVIEW_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizableFormView.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableGrip.h" +#include "ResizableMinMax.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableFormView form view + +#include + +class CResizableFormView : public CFormView, public CResizableLayout, + public CResizableGrip, public CResizableMinMax +{ + DECLARE_DYNAMIC(CResizableFormView) + +// Construction +protected: // must derive your own class + CResizableFormView(UINT nIDTemplate); + CResizableFormView(LPCTSTR lpszTemplateName); + virtual ~CResizableFormView(); + +private: + void PrivateConstruct(); + + // support for temporarily hiding the grip + DWORD m_dwGripTempState; + enum GripHideReason // bitmask + { + GHR_MAXIMIZED = 0x01, + GHR_SCROLLBAR = 0x02, + GHR_ALIGNMENT = 0x04, + }; + +// called from base class +protected: + + virtual void GetTotalClientRect(LPRECT lpRect) const; + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + + +// Attributes +public: + +// Operations +public: + +// Overrides +public: + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableFormView) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions + //{{AFX_MSG(CResizableFormView) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnDestroy(); + virtual BOOL OnInitDialog(); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEFORMVIEW_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableFrame.cpp b/ext/ResizableLib/ResizableFrame.cpp new file mode 100644 index 0000000..4089ec2 --- /dev/null +++ b/ext/ResizableLib/ResizableFrame.cpp @@ -0,0 +1,117 @@ +// ResizableFrame.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableFrame.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableFrame + +IMPLEMENT_DYNCREATE(CResizableFrame, CFrameWnd) + +CResizableFrame::CResizableFrame() +{ + m_bEnableSaveRestore = FALSE; +} + +CResizableFrame::~CResizableFrame() +{ +} + + +BEGIN_MESSAGE_MAP(CResizableFrame, CFrameWnd) + //{{AFX_MSG_MAP(CResizableFrame) + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_NCCREATE() + ON_WM_WINDOWPOSCHANGING() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableFrame message handlers + +void CResizableFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); + + CView* pView = GetActiveView(); + if (pView == NULL) + return; + + ChainMinMaxInfo(lpMMI, this, pView); +} + +// NOTE: this must be called after setting the layout +// to have the view and its controls displayed properly +BOOL CResizableFrame::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly) +{ + m_sSection = pszSection; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + return LoadWindowRect(pszSection, bRectOnly); +} + +void CResizableFrame::OnDestroy() +{ + if (m_bEnableSaveRestore) + SaveWindowRect(m_sSection, m_bRectOnly); + + CFrameWnd::OnDestroy(); +} + +BOOL CResizableFrame::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CFrameWnd::OnNcCreate(lpCreateStruct)) + return FALSE; + + MakeResizable(lpCreateStruct); + + return TRUE; +} + +LRESULT CResizableFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CFrameWnd::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CFrameWnd::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} + +// TODO: implement this in CResizableMinMax +// We definitely need pluggable message handlers ala WTL! +void CResizableFrame::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) +{ + if ((lpwndpos->flags & (SWP_NOSIZE|SWP_NOMOVE)) != (SWP_NOSIZE|SWP_NOMOVE)) + CFrameWnd::OnWindowPosChanging(lpwndpos); +} diff --git a/ext/ResizableLib/ResizableFrame.h b/ext/ResizableLib/ResizableFrame.h new file mode 100644 index 0000000..5e6e107 --- /dev/null +++ b/ext/ResizableLib/ResizableFrame.h @@ -0,0 +1,89 @@ +#if !defined(AFX_RESIZABLEFRAME_H__INCLUDED_) +#define AFX_RESIZABLEFRAME_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ResizableFrame.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableMinMax.h" +#include "ResizableWndState.h" +#include "ResizableLayout.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableFrame frame + +class CResizableFrame : public CFrameWnd, public CResizableMinMax, + public CResizableWndState, public CResizableLayout +{ + DECLARE_DYNCREATE(CResizableFrame) +protected: + CResizableFrame(); // protected constructor used by dynamic creation + +// Attributes +protected: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableFrame) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CResizableFrame(); + + BOOL EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE); + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +private: + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +protected: + // Generated message map functions + //{{AFX_MSG(CResizableFrame) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnDestroy(); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEFRAME_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableGrip.cpp b/ext/ResizableLib/ResizableGrip.cpp new file mode 100644 index 0000000..1cfe57b --- /dev/null +++ b/ext/ResizableLib/ResizableGrip.cpp @@ -0,0 +1,328 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableGrip class. + */ + +#include "stdafx.h" +#include "ResizableGrip.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizableGrip::CResizableGrip() +{ + m_nShowCount = 0; +} + +CResizableGrip::~CResizableGrip() +{ + +} + +void CResizableGrip::UpdateSizeGrip() +{ + if (!::IsWindow(m_wndGrip.m_hWnd)) + return; + + // size-grip goes bottom right in the client area + // (any right-to-left adjustment should go here) + + RECT rect; + GetResizableWnd()->GetClientRect(&rect); + + rect.left = rect.right - m_wndGrip.m_size.cx; + rect.top = rect.bottom - m_wndGrip.m_size.cy; + + // must stay below other children + m_wndGrip.SetWindowPos(&CWnd::wndBottom, rect.left, rect.top, 0, 0, + SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOREPOSITION + | (IsSizeGripVisible() ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); +} + +// pbStatus points to a variable, maintained by the caller, that +// holds its visibility status. Initialize the variable with 1 +// to allow to temporarily hide the grip, 0 to allow to +// temporarily show the grip (with respect to the dwMask bit). + +// NB: visibility is effective only after an update + +void CResizableGrip::ShowSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/) +{ + ASSERT(pStatus != NULL); + + if (!(*pStatus & dwMask)) + { + m_nShowCount++; + (*pStatus) |= dwMask; + } +} + +void CResizableGrip::HideSizeGrip(DWORD* pStatus, DWORD dwMask /*= 1*/) +{ + ASSERT(pStatus != NULL); + + if (*pStatus & dwMask) + { + m_nShowCount--; + (*pStatus) &= ~dwMask; + } +} + +BOOL CResizableGrip::IsSizeGripVisible() +{ + // NB: visibility is effective only after an update + return (m_nShowCount > 0); +} + +void CResizableGrip::SetSizeGripVisibility(BOOL bVisible) +{ + if (bVisible) + m_nShowCount = 1; + else + m_nShowCount = 0; +} + +BOOL CResizableGrip::SetSizeGripBkMode(int nBkMode) +{ + if (::IsWindow(m_wndGrip.m_hWnd)) + { + if (nBkMode == OPAQUE) + m_wndGrip.SetTransparency(FALSE); + else if (nBkMode == TRANSPARENT) + m_wndGrip.SetTransparency(TRUE); + else + return FALSE; + return TRUE; + } + return FALSE; +} + +void CResizableGrip::SetSizeGripShape(BOOL bTriangular) +{ + if (::IsWindow(m_wndGrip.m_hWnd)) + m_wndGrip.SetTriangularShape(bTriangular); +} + +BOOL CResizableGrip::CreateSizeGrip(BOOL bVisible /*= TRUE*/, + BOOL bTriangular /*= TRUE*/, BOOL bTransparent /*= FALSE*/) +{ + // create grip + CRect rect(0 , 0, m_wndGrip.m_size.cx, m_wndGrip.m_size.cy); + BOOL bRet = m_wndGrip.Create(WS_CHILD | WS_CLIPSIBLINGS + | SBS_SIZEGRIP, rect, GetResizableWnd(), 0); + + if (bRet) + { + // set options + m_wndGrip.SetTriangularShape(bTriangular); + m_wndGrip.SetTransparency(bTransparent); + SetSizeGripVisibility(bVisible); + + // update position + UpdateSizeGrip(); + } + + return bRet; +} + +///////////////////////////////////////////////////////////////////////////// +// CSizeGrip implementation + +BOOL CResizableGrip::CSizeGrip::IsRTL() +{ + return GetExStyle() & WS_EX_LAYOUTRTL; +} + +BOOL CResizableGrip::CSizeGrip::PreCreateWindow(CREATESTRUCT& cs) +{ + // set window size + m_size.cx = GetSystemMetrics(SM_CXVSCROLL); + m_size.cy = GetSystemMetrics(SM_CYHSCROLL); + + cs.cx = m_size.cx; + cs.cy = m_size.cy; + + return CScrollBar::PreCreateWindow(cs); +} + +LRESULT CResizableGrip::CSizeGrip::WindowProc(UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_GETDLGCODE: + // fix to prevent the control to gain focus, using arrow keys + // (standard grip returns DLGC_WANTARROWS, like any standard scrollbar) + return DLGC_STATIC; + + case WM_SETFOCUS: + // fix to prevent the control to gain focus, if set directly + // (for example when it's the only one control in a dialog) + return 0; + + case WM_NCHITTEST: + // choose proper cursor shape + if (IsRTL()) + return HTBOTTOMLEFT; + else + return HTBOTTOMRIGHT; + break; + + case WM_SETTINGCHANGE: + { + // update grip's size + CSize sizeOld = m_size; + m_size.cx = GetSystemMetrics(SM_CXVSCROLL); + m_size.cy = GetSystemMetrics(SM_CYHSCROLL); + + // resize transparency bitmaps + if (m_bTransparent) + { + CClientDC dc(this); + + // destroy bitmaps + m_bmGrip.DeleteObject(); + m_bmMask.DeleteObject(); + + // re-create bitmaps + m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy); + m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL); + } + + // re-calc shape + if (m_bTriangular) + SetTriangularShape(m_bTriangular); + + // reposition the grip + CRect rect; + GetWindowRect(rect); + rect.InflateRect(m_size.cx - sizeOld.cx, m_size.cy - sizeOld.cy, 0, 0); + ::MapWindowPoints(NULL, GetParent()->GetSafeHwnd(), (LPPOINT)&rect, 2); + MoveWindow(rect, TRUE); + } + break; + + case WM_DESTROY: + // perform clean up + if (m_bTransparent) + SetTransparency(FALSE); + break; + + case WM_PAINT: + case WM_PRINTCLIENT: + if (m_bTransparent) + { + PAINTSTRUCT ps; + CDC* pDC = (message == WM_PAINT && wParam == 0) ? + BeginPaint(&ps) : CDC::FromHandle((HDC)wParam); + + // select bitmaps + CBitmap *pOldGrip, *pOldMask; + + pOldGrip = m_dcGrip.SelectObject(&m_bmGrip); + pOldMask = m_dcMask.SelectObject(&m_bmMask); + + // obtain original grip bitmap, make the mask and prepare masked bitmap + CScrollBar::WindowProc(message, (WPARAM)m_dcGrip.GetSafeHdc(), lParam); + m_dcGrip.SetBkColor(m_dcGrip.GetPixel(0, 0)); + m_dcMask.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCCOPY); + m_dcGrip.BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, 0x00220326); + + // draw transparently + pDC->BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcMask, 0, 0, SRCAND); + pDC->BitBlt(0, 0, m_size.cx, m_size.cy, &m_dcGrip, 0, 0, SRCPAINT); + + // unselect bitmaps + m_dcGrip.SelectObject(pOldGrip); + m_dcMask.SelectObject(pOldMask); + + if (message == WM_PAINT && wParam == 0) + EndPaint(&ps); + return 0; + } + break; + } + + return CScrollBar::WindowProc(message, wParam, lParam); +} + +void CResizableGrip::CSizeGrip::SetTransparency(BOOL bActivate) +{ + // creates or deletes DCs and Bitmaps used for + // implementing a transparent size grip + + if (bActivate && !m_bTransparent) + { + m_bTransparent = TRUE; + + CClientDC dc(this); + + // create memory DCs and bitmaps + m_dcGrip.CreateCompatibleDC(&dc); + m_bmGrip.CreateCompatibleBitmap(&dc, m_size.cx, m_size.cy); + + m_dcMask.CreateCompatibleDC(&dc); + m_bmMask.CreateBitmap(m_size.cx, m_size.cy, 1, 1, NULL); + } + else if (!bActivate && m_bTransparent) + { + m_bTransparent = FALSE; + + // destroy memory DCs and bitmaps + m_dcGrip.DeleteDC(); + m_bmGrip.DeleteObject(); + + m_dcMask.DeleteDC(); + m_bmMask.DeleteObject(); + } +} + +void CResizableGrip::CSizeGrip::SetTriangularShape(BOOL bEnable) +{ + m_bTriangular = bEnable; + + if (bEnable) + { + // set a triangular window region + CRect rect; + GetWindowRect(rect); + rect.OffsetRect(-rect.TopLeft()); + POINT arrPoints[] = + { + { rect.left, rect.bottom }, + { rect.right, rect.bottom }, + { rect.right, rect.top } + }; + CRgn rgnGrip; + rgnGrip.CreatePolygonRgn(arrPoints, 3, WINDING); + SetWindowRgn((HRGN)rgnGrip.Detach(), IsWindowVisible()); + } + else + { + SetWindowRgn((HRGN)NULL, IsWindowVisible()); + } +} diff --git a/ext/ResizableLib/ResizableGrip.h b/ext/ResizableLib/ResizableGrip.h new file mode 100644 index 0000000..4f65e94 --- /dev/null +++ b/ext/ResizableLib/ResizableGrip.h @@ -0,0 +1,94 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableGrip class. + */ + +#if !defined(AFX_RESIZABLEGRIP_H__INCLUDED_) +#define AFX_RESIZABLEGRIP_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief brief_description +/*! + * long_description + */ +class CResizableGrip +{ +private: + class CSizeGrip : public CScrollBar + { + public: + CSizeGrip() + { + m_bTransparent = FALSE; + m_bTriangular = FALSE; + } + + void SetTriangularShape(BOOL bEnable); + void SetTransparency(BOOL bActivate); + + BOOL IsRTL(); // right-to-left layout support + + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + + SIZE m_size; // holds grip size + + protected: + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + + BOOL m_bTriangular; // triangular shape active + BOOL m_bTransparent; // transparency active + + // memory DCs and bitmaps for transparent grip + CDC m_dcGrip, m_dcMask; + CBitmap m_bmGrip, m_bmMask; + }; + + CSizeGrip m_wndGrip; // grip control + int m_nShowCount; // support for hiding the grip + +protected: + // create a size grip, with options + BOOL CreateSizeGrip(BOOL bVisible = TRUE, + BOOL bTriangular = TRUE, BOOL bTransparent = FALSE); + + BOOL IsSizeGripVisible(); // TRUE if grip is set to be visible + void SetSizeGripVisibility(BOOL bVisible); // set default visibility + void UpdateSizeGrip(); // update the grip's visibility and position + void ShowSizeGrip(DWORD* pStatus, DWORD dwMask = 1); // temp show the size grip + void HideSizeGrip(DWORD* pStatus, DWORD dwMask = 1); // temp hide the size grip + BOOL SetSizeGripBkMode(int nBkMode); // like CDC::SetBkMode + void SetSizeGripShape(BOOL bTriangular); + + virtual CWnd* GetResizableWnd() const = 0; + +public: + CResizableGrip(); + virtual ~CResizableGrip(); +}; + +// @} +#endif // !defined(AFX_RESIZABLEGRIP_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableLayout.cpp b/ext/ResizableLib/ResizableLayout.cpp new file mode 100644 index 0000000..e838670 --- /dev/null +++ b/ext/ResizableLib/ResizableLayout.cpp @@ -0,0 +1,882 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableLayout class. + */ + +#include "stdafx.h" +#include "ResizableLayout.h" +#include "ResizableVersion.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +/*! + * @internal Constant used to detect clipping and refresh properties + * + * @note In August 2002 Platform SDK, some guy at MS thought it was time + * to add the missing symbol BS_TYPEMASK, but forgot its original + * meaning and so now he's telling us not to use that symbol because + * its value is likely to change in the future SDK releases, including + * all the BS_* style bits in the mask, not just the button's type + * as the symbol's name suggests. + * @n So now we're forced to define another symbol, great! + */ +#define _BS_TYPEMASK 0x0000000FL + +/*! + * This function adds a new control to the layout manager and sets anchor + * points for its top-left and bottom-right corners. + * + * @param hWnd Window handle to the control to be added + * @param anchorTopLeft Anchor point for the top-left corner + * @param anchorBottomRight Anchor point for the bottom-right corner + * + * @remarks Overlapping controls, like group boxes and the controls inside, + * must be added from the outer controls to the inner ones, to let + * the clipping routines work correctly. + * + * @sa AddAnchorCallback RemoveAnchor + */ +void CResizableLayout::AddAnchor(HWND hWnd, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight) +{ + CWnd* pParent = GetResizableWnd(); + + // child window must be valid + ASSERT(::IsWindow(hWnd)); + // must be child of parent window + ASSERT(::IsChild(pParent->GetSafeHwnd(), hWnd)); + + // get parent window's rect + CRect rectParent; + GetTotalClientRect(&rectParent); + // and child control's rect + CRect rectChild; + ::GetWindowRect(hWnd, &rectChild); + ::MapWindowPoints(NULL, pParent->m_hWnd, (LPPOINT)&rectChild, 2); + + // adjust position, if client area has been scrolled + rectChild.OffsetRect(-rectParent.TopLeft()); + + // go calculate margins + CSize marginTopLeft, marginBottomRight; + + // calculate margin for the top-left corner + + marginTopLeft.cx = rectChild.left - rectParent.Width() * anchorTopLeft.cx / 100; + marginTopLeft.cy = rectChild.top - rectParent.Height() * anchorTopLeft.cy / 100; + + // calculate margin for the bottom-right corner + + marginBottomRight.cx = rectChild.right - rectParent.Width() * anchorBottomRight.cx / 100; + marginBottomRight.cy = rectChild.bottom - rectParent.Height() * anchorBottomRight.cy / 100; + + // prepare the structure + LAYOUTINFO layout(hWnd, anchorTopLeft, marginTopLeft, + anchorBottomRight, marginBottomRight); + + // get control's window class + GetClassName(hWnd, layout.sWndClass, MAX_PATH); + + // initialize resize properties (overridable) + InitResizeProperties(layout); + + // must not be already there! + // (this is probably due to a duplicate call to AddAnchor) + POSITION pos; + ASSERT(!m_mapLayout.Lookup(hWnd, pos)); + + // add to the list and the map + pos = m_listLayout.AddTail(layout); + m_mapLayout.SetAt(hWnd, pos); +} + +/*! + * This function adds a placeholder to the layout manager, that will be + * dinamically set by a callback function whenever required. + * + * @return The return value is an integer used to distinguish between + * different placeholders in the callback implementation. + * + * @remarks You must override @ref ArrangeLayoutCallback to provide layout + * information. + * + * @sa AddAnchor ArrangeLayoutCallback ArrangeLayout + */ +UINT_PTR CResizableLayout::AddAnchorCallback() +{ + // one callback control cannot rely upon another callback control's + // size and/or position (they're updated all together at the end) + // it can however use a non-callback control, calling GetAnchorPosition() + + // add to the list + LAYOUTINFO layout; + layout.nCallbackID = m_listLayoutCB.GetCount() + 1; + m_listLayoutCB.AddTail(layout); + return layout.nCallbackID; +} + +/*! + * This function is called for each placeholder added to the layout manager + * and must be overridden to provide the necessary layout information. + * + * @param layout Reference to a LAYOUTINFO structure to be filled with + * layout information for the specified placeholder. + * On input, nCallbackID is the identification number + * returned by AddAnchorCallback. On output, anchor points and + * the window handle must be set and valid. + * + * @return The return value is @c TRUE if the layout information has been + * provided successfully, @c FALSE to skip this placeholder. + * + * @remarks When implementing this function, unknown placeholders should be + * passed to the base class. Unhandled cases will fire an assertion + * in the debug version. + * + * @sa AddAnchorCallback ArrangeLayout LAYOUTINFO + */ +BOOL CResizableLayout::ArrangeLayoutCallback(LAYOUTINFO& layout) const +{ + UNREFERENCED_PARAMETER(layout); + + ASSERT(FALSE); // must be overridden, if callback is used + + return FALSE; // no useful output data +} + +/*! + * This function should be called in resizable window classes whenever the + * controls layout should be updated, usually after a resize operation. + * + * @remarks All the controls added to the layout are moved and resized at + * once for performace reasons, so all the controls are in their + * old position when AddAnchorCallback is called. + * To know where a control will be placed use GetAnchorPosition. + * + * @sa AddAnchor AddAnchorCallback ArrangeLayoutCallback GetAnchorPosition + */ +void CResizableLayout::ArrangeLayout() const +{ + // common vars + UINT uFlags; + LAYOUTINFO layout; + CRect rectParent, rectChild; + INT_PTR count = m_listLayout.GetCount(); + INT_PTR countCB = m_listLayoutCB.GetCount(); + + if (count + countCB == 0) + return; + + // get parent window's rect + GetTotalClientRect(&rectParent); + + // reposition child windows + HDWP hdwp = ::BeginDeferWindowPos (static_cast(count + countCB)); + + POSITION pos = m_listLayout.GetHeadPosition(); + while (pos != NULL) + { + // get layout info + layout = m_listLayout.GetNext(pos); + + // calculate new child's position, size and flags for SetWindowPos + CalcNewChildPosition(layout, rectParent, rectChild, uFlags); + + // only if size or position changed + if ((uFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE)) + { + hdwp = ::DeferWindowPos(hdwp, layout.hWnd, NULL, rectChild.left, + rectChild.top, rectChild.Width(), rectChild.Height(), uFlags); + } + } + + // for callback items you may use GetAnchorPosition to know the + // new position and size of a non-callback item after resizing + + pos = m_listLayoutCB.GetHeadPosition(); + while (pos != NULL) + { + // get layout info + layout = m_listLayoutCB.GetNext(pos); + // request layout data + if (!ArrangeLayoutCallback(layout)) + continue; + + // calculate new child's position, size and flags for SetWindowPos + CalcNewChildPosition(layout, rectParent, rectChild, uFlags); + + // only if size or position changed + if ((uFlags & (SWP_NOMOVE|SWP_NOSIZE)) != (SWP_NOMOVE|SWP_NOSIZE)) + { + hdwp = ::DeferWindowPos(hdwp, layout.hWnd, NULL, rectChild.left, + rectChild.top, rectChild.Width(), rectChild.Height(), uFlags); + } + } + + // finally move all the windows at once + ::EndDeferWindowPos(hdwp); +} + +/*! + * @internal This function adds or removes a control window region + * to or from the specified clipping region, according to its layout + * properties. + */ +void CResizableLayout::ClipChildWindow(const LAYOUTINFO& layout, + CRgn* pRegion) const +{ + // obtain window position + CRect rect; + ::GetWindowRect(layout.hWnd, &rect); +#if (_WIN32_WINNT >= 0x0501) + //! @todo decide when to clip client only or non-client too (themes?) + //! (leave disabled meanwhile, until I find a good solution) + //! @note wizard97 with watermark bitmap and themes won't look good! + // if (real_WIN32_WINNT >= 0x501) + // ::SendMessage(layout.hWnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect); +#endif + ::MapWindowPoints(NULL, GetResizableWnd()->m_hWnd, (LPPOINT)&rect, 2); + + // use window region if any + CRgn rgn; + rgn.CreateRectRgn(0,0,0,0); + switch (::GetWindowRgn(layout.hWnd, rgn)) + { + case COMPLEXREGION: + case SIMPLEREGION: + rgn.OffsetRgn(rect.TopLeft()); + break; + + default: + rgn.SetRectRgn(&rect); + } + + // get the clipping property + BOOL bClipping = layout.properties.bAskClipping ? + LikesClipping(layout) : layout.properties.bCachedLikesClipping; + + // modify region accordingly + if (bClipping) + pRegion->CombineRgn(pRegion, &rgn, RGN_DIFF); + else + pRegion->CombineRgn(pRegion, &rgn, RGN_OR); +} + +/*! + * This function retrieves the clipping region for the current layout. + * It can be used to draw directly inside the region, without applying + * clipping as the ClipChildren function does. + * + * @param pRegion Pointer to a CRegion object that holds the + * calculated clipping region upon return + * + * @deprecated For anti-flickering ClipChildren should be preferred + * as it is more complete for platform compatibility. + * It will probably become a private function. + */ +void CResizableLayout::GetClippingRegion(CRgn* pRegion) const +{ + CWnd* pWnd = GetResizableWnd(); + + // System's default clipping area is screen's size, + // not enough for max track size, for example: + // if screen is 1024 x 768 and resizing border is 4 pixels, + // maximized size is 1024+4*2=1032 x 768+4*2=776, + // but max track size is 4 pixels bigger 1036 x 780 (don't ask me why!) + // So, if you resize the window to maximum size, the last 4 pixels + // are clipped out by the default clipping region, that gets created + // as soon as you call clipping functions (my guess). + + // reset clipping region to the whole client area + CRect rect; + pWnd->GetClientRect(&rect); + pRegion->CreateRectRgnIndirect(&rect); + + // clip only anchored controls + LAYOUTINFO layout; + POSITION pos = m_listLayout.GetHeadPosition(); + while (pos != NULL) + { + // get layout info + layout = m_listLayout.GetNext(pos); + + if (::IsWindowVisible(layout.hWnd)) + ClipChildWindow(layout, pRegion); + } + pos = m_listLayoutCB.GetHeadPosition(); + while (pos != NULL) + { + // get layout info + layout = m_listLayoutCB.GetNext(pos); + // request data + if (!ArrangeLayoutCallback(layout)) + continue; + + if (::IsWindowVisible(layout.hWnd)) + ClipChildWindow(layout, pRegion); + } +//! @todo Has XP changed this??? It doesn't seem correct anymore! +/* + // fix for RTL layouts (1 pixel of horz offset) + if (pWnd->GetExStyle() & WS_EX_LAYOUTRTL) + pRegion->OffsetRgn(-1,0); +*/ +} + +//! @internal @brief Implements GetAncestor(pWnd->GetSafeHwnd(), GA_ROOT) +inline CWnd* GetRootParentWnd(CWnd* pWnd) +{ + // GetAncestor API not present, emulate + if (!(pWnd->GetStyle() & WS_CHILD)) + return NULL; + while (pWnd->GetStyle() & WS_CHILD) + pWnd = pWnd->GetParent(); + return pWnd; +} + +/*! + * This function enables or restores clipping on the specified DC when + * appropriate. It should be called whenever drawing on the window client + * area to avoid flickering. + * + * @param pDC Pointer to the target device context + * @param bUndo Flag that specifies wether to restore the clipping region + * + * @return The return value is @c TRUE if the clipping region has been + * modified, @c FALSE if clipping was not necessary. + * + * @remarks For anti-flickering to work, you should wrap your + * @c WM_ERASEBKGND message handler inside a pair of calls to + * this function, with the last parameter set to @c TRUE first + * and to @c FALSE at the end. + */ +BOOL CResizableLayout::ClipChildren(CDC* pDC, BOOL bUndo) +{ +#if (_WIN32_WINNT >= 0x0501 && !defined(RSZLIB_NO_XP_DOUBLE_BUFFER)) + // clipping not necessary when double-buffering enabled + if (real_WIN32_WINNT >= 0x0501) + { + CWnd *pWnd = GetRootParentWnd(GetResizableWnd()); + if (pWnd == NULL) + pWnd = GetResizableWnd(); + if (pWnd->GetExStyle() & WS_EX_COMPOSITED) + return FALSE; + } +#endif + + HDC hDC = pDC->GetSafeHdc(); + HWND hWnd = GetResizableWnd()->GetSafeHwnd(); + + m_nOldClipRgn = -1; // invalid region by default + + // Some controls (such as transparent toolbars and standard controls + // with XP theme enabled) send a WM_ERASEBKGND msg to the parent + // to draw themselves, in which case we must not enable clipping. + + // We check that the window associated with the DC is the + // resizable window and not a child control. + + if (!bUndo && (hWnd == ::WindowFromDC(hDC))) + { + // save old DC clipping region + m_nOldClipRgn = ::GetClipRgn(hDC, m_hOldClipRgn); + + // clip out supported child windows + CRgn rgnClip; + GetClippingRegion(&rgnClip); + ::ExtSelectClipRgn(hDC, rgnClip, RGN_AND); + + return TRUE; + } + + // restore old clipping region, only if modified and valid + if (bUndo && m_nOldClipRgn >= 0) + { + if (m_nOldClipRgn == 1) + ::SelectClipRgn(hDC, m_hOldClipRgn); + else + ::SelectClipRgn(hDC, NULL); + + return TRUE; + } + + return FALSE; +} + +/*! + * This function is used by this class, and should be used by derived + * classes too, in place of the standard GetClientRect. It can be useful + * for windows with scrollbars or expanding windows, to provide the true + * client area, including even those parts which are not visible. + * + * @param lpRect Pointer to the RECT structure that holds the result + * + * @remarks Override this function to provide the client area the class uses + * to perform layout calculations, both when adding controls and + * when rearranging the layout. + * @n The base implementation simply calls @c GetClientRect + */ +void CResizableLayout::GetTotalClientRect(LPRECT lpRect) const +{ + GetResizableWnd()->GetClientRect(lpRect); +} + +/*! + * This function is used to determine if a control needs to be painted when + * it is moved or resized by the layout manager. + * + * @param layout Reference to a @c LAYOUTINFO structure for the control + * @param rectOld Reference to a @c RECT structure that holds the control + * position and size before the layout update + * @param rectNew Reference to a @c RECT structure that holds the control + * position and size after the layout update + * + * @return The return value is @c TRUE if the control should be freshly + * painted after a layout update, @c FALSE if not necessary. + * + * @remarks The default implementation tries to identify windows that + * need refresh by their class name and window style. + * @n Override this function if you need a different behavior or if + * you have custom controls that fail to be identified. + * + * @sa LikesClipping InitResizeProperties + */ +BOOL CResizableLayout::NeedsRefresh(const LAYOUTINFO& layout, + const CRect& rectOld, const CRect& rectNew) const +{ + if (layout.bMsgSupport) + { + REFRESHPROPERTY refresh; + refresh.rcOld = rectOld; + refresh.rcNew = rectNew; + if (Send_NeedsRefresh(layout.hWnd, &refresh)) + return refresh.bNeedsRefresh; + } + + int nDiffWidth = (rectNew.Width() - rectOld.Width()); + int nDiffHeight = (rectNew.Height() - rectOld.Height()); + + // is the same size? + if (nDiffWidth == 0 && nDiffHeight == 0) + return FALSE; + + // optimistic, no need to refresh + BOOL bRefresh = FALSE; + + // window classes that need refresh when resized + if (0 == lstrcmp(layout.sWndClass, WC_STATIC)) + { + DWORD style = ::GetWindowLong(layout.hWnd, GWL_STYLE); + + switch (style & SS_TYPEMASK) + { + case SS_LEFT: + case SS_CENTER: + case SS_RIGHT: + // word-wrapped text + bRefresh = bRefresh || (nDiffWidth != 0); + // vertically centered text + if (style & SS_CENTERIMAGE) + bRefresh = bRefresh || (nDiffHeight != 0); + break; + + case SS_LEFTNOWORDWRAP: + // text with ellipsis + if (style & SS_ELLIPSISMASK) + bRefresh = bRefresh || (nDiffWidth != 0); + // vertically centered text + if (style & SS_CENTERIMAGE) + bRefresh = bRefresh || (nDiffHeight != 0); + break; + + case SS_ENHMETAFILE: + case SS_BITMAP: + case SS_ICON: + // images + case SS_BLACKFRAME: + case SS_GRAYFRAME: + case SS_WHITEFRAME: + case SS_ETCHEDFRAME: + // and frames + bRefresh = TRUE; + break; + } + return bRefresh; + } + + // window classes that don't redraw client area correctly + // when the hor scroll pos changes due to a resizing + BOOL bHScroll = FALSE; + if (0 == lstrcmp(layout.sWndClass, WC_LISTBOX)) + bHScroll = TRUE; + + // fix for horizontally scrollable windows, if wider + if (bHScroll && (nDiffWidth > 0)) + { + // get max scroll position + SCROLLINFO info; + info.cbSize = sizeof(SCROLLINFO); + info.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + if (::GetScrollInfo(layout.hWnd, SB_HORZ, &info)) + { + // subtract the page size + info.nMax -= __max(info.nPage - 1, 0); + } + + // resizing will cause the text to scroll on the right + // because the scrollbar is going beyond the right limit + if ((info.nMax > 0) && (info.nPos + nDiffWidth > info.nMax)) + { + // needs repainting, due to horiz scrolling + bRefresh = TRUE; + } + } + + return bRefresh; +} + +/*! + * This function is used to determine if a control can be safely clipped + * out of the parent window client area when it is repainted, usually + * after a resize operation. + * + * @param layout Reference to a @c LAYOUTINFO structure for the control + * + * @return The return value is @c TRUE if clipping is supported by the + * control, @c FALSE otherwise. + * + * @remarks The default implementation tries to identify @a clippable + * windows by their class name and window style. + * @n Override this function if you need a different behavior or if + * you have custom controls that fail to be identified. + * + * @sa NeedsRefresh InitResizeProperties + */ +BOOL CResizableLayout::LikesClipping(const LAYOUTINFO& layout) const +{ + if (layout.bMsgSupport) + { + CLIPPINGPROPERTY clipping; + if (Send_LikesClipping(layout.hWnd, &clipping)) + return clipping.bLikesClipping; + } + + DWORD style = ::GetWindowLong(layout.hWnd, GWL_STYLE); + + // skip windows that wants background repainted + if (0 == lstrcmp(layout.sWndClass, WC_BUTTON)) + { + CRect rect; + switch (style & _BS_TYPEMASK) + { + case BS_GROUPBOX: + return FALSE; + + case BS_OWNERDRAW: + // ownerdraw buttons must return correct hittest code + // to notify their transparency to the system and this library + // or they could use the registered message (more reliable) + ::GetWindowRect(layout.hWnd, &rect); + ::SendMessage(layout.hWnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rect); + if ( HTTRANSPARENT == ::SendMessage(layout.hWnd, + WM_NCHITTEST, 0, MAKELPARAM(rect.left, rect.top)) ) + return FALSE; + break; + } + return TRUE; + } + else if (0 == lstrcmp(layout.sWndClass, WC_STATIC)) + { + switch (style & SS_TYPEMASK) + { + case SS_LEFT: + case SS_CENTER: + case SS_RIGHT: + case SS_LEFTNOWORDWRAP: + // text + case SS_BLACKRECT: + case SS_GRAYRECT: + case SS_WHITERECT: + // filled rects + case SS_ETCHEDHORZ: + case SS_ETCHEDVERT: + // etched lines + case SS_BITMAP: + // bitmaps + return TRUE; + break; + + case SS_ICON: + case SS_ENHMETAFILE: + if (style & SS_CENTERIMAGE) + return FALSE; + return TRUE; + break; + + default: + return FALSE; + } + } + + // assume the others like clipping + return TRUE; +} + + +/*! + * @internal This function calculates the new size and position of a + * control in the layout and flags for @c SetWindowPos + */ +void CResizableLayout::CalcNewChildPosition(const LAYOUTINFO& layout, + const CRect &rectParent, CRect &rectChild, UINT& uFlags) const +{ + CWnd* pParent = GetResizableWnd(); + + ::GetWindowRect(layout.hWnd, &rectChild); + ::MapWindowPoints(NULL, pParent->m_hWnd, (LPPOINT)&rectChild, 2); + + CRect rectNew; + + // calculate new top-left corner + rectNew.left = layout.marginTopLeft.cx + rectParent.Width() * layout.anchorTopLeft.cx / 100; + rectNew.top = layout.marginTopLeft.cy + rectParent.Height() * layout.anchorTopLeft.cy / 100; + + // calculate new bottom-right corner + rectNew.right = layout.marginBottomRight.cx + rectParent.Width() * layout.anchorBottomRight.cx / 100; + rectNew.bottom = layout.marginBottomRight.cy + rectParent.Height() * layout.anchorBottomRight.cy / 100; + + // adjust position, if client area has been scrolled + rectNew.OffsetRect(rectParent.TopLeft()); + + // get the refresh property + BOOL bRefresh = layout.properties.bAskRefresh ? + NeedsRefresh(layout, rectChild, rectNew) : layout.properties.bCachedNeedsRefresh; + + // set flags + uFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION; + if (bRefresh) + uFlags |= SWP_NOCOPYBITS; + if (rectNew.TopLeft() == rectChild.TopLeft()) + uFlags |= SWP_NOMOVE; + if (rectNew.Size() == rectChild.Size()) + uFlags |= SWP_NOSIZE; + + // update rect + rectChild = rectNew; +} + +/*! + * This function calculates the top, left, bottom, right margins for a + * given size of the specified control. + * + * @param hWnd Window handle to a control in the layout + * @param sizeChild Size of the control to use in calculations + * @param rectMargins Holds the calculated margins + * + * @return The return value is @c TRUE if successful, @c FALSE otherwise + * + * @remarks This function can be used to infer the parent window size + * from the size of one of its child controls. + * It is used to implement cascading of size constraints. + */ +BOOL CResizableLayout::GetAnchorMargins(HWND hWnd, const CSize &sizeChild, CRect &rectMargins) const +{ + POSITION pos; + if (!m_mapLayout.Lookup(hWnd, pos)) + return FALSE; + + const LAYOUTINFO& layout = m_listLayout.GetAt(pos); + + // augmented size, relative to anchor points + CSize size = sizeChild + layout.marginTopLeft - layout.marginBottomRight; + + // percent of parent size occupied by this control + CSize percent(layout.anchorBottomRight.cx - layout.anchorTopLeft.cx, + layout.anchorBottomRight.cy - layout.anchorTopLeft.cy); + + // calculate total margins + rectMargins.left = size.cx * layout.anchorTopLeft.cx / percent.cx + layout.marginTopLeft.cx; + rectMargins.top = size.cy * layout.anchorTopLeft.cy / percent.cy + layout.marginTopLeft.cy; + rectMargins.right = size.cx * (100 - layout.anchorBottomRight.cx) / percent.cx - layout.marginBottomRight.cx; + rectMargins.bottom = size.cy * (100 - layout.anchorBottomRight.cy) / percent.cy - layout.marginBottomRight.cy; + + return TRUE; +} + +/*! + * This function is used to set the initial resize properties of a control + * in the layout, that are stored in the @c properties member of the + * related @c LAYOUTINFO structure. + * + * @param layout Reference to the @c LAYOUTINFO structure to be set + * + * @remarks The various flags are used to specify whether the resize + * properties (clipping, refresh) can change at run-time, and a new + * call to the property querying functions is needed at every + * layout update, or they are static properties, and the cached + * value is used whenever necessary. + * @n The default implementation sends a registered message to the + * control, giving it the opportunity to specify its resize + * properties, which takes precedence if the message is supported. + * It then sets the @a clipping property as static, calling + * @c LikesClipping only once, and the @a refresh property as + * dynamic, causing @c NeedsRefresh to be called every time. + * @n This should be right for most situations, as the need for + * @a refresh usually depends on the size fo a control, while the + * support for @a clipping is usually linked to the specific type + * of control, which is unlikely to change at run-time, but you can + * still override this function if a different beahvior is needed. + * + * @sa LikesClipping NeedsRefresh LAYOUTINFO RESIZEPROPERTIES + */ +void CResizableLayout::InitResizeProperties(LAYOUTINFO &layout) const +{ + // check if custom window supports this library + // (properties must be correctly set by the window) + layout.bMsgSupport = Send_QueryProperties(layout.hWnd, &layout.properties); + + // default properties + if (!layout.bMsgSupport) + { + // clipping property is assumed as static + layout.properties.bAskClipping = FALSE; + layout.properties.bCachedLikesClipping = LikesClipping(layout); + // refresh property is assumed as dynamic + layout.properties.bAskRefresh = TRUE; + } +} + +/*! + * This function modifies a window to enable resizing functionality. + * This affects the window style, size, system menu and appearance. + * + * @param lpCreateStruct Pointer to a @c CREATESTRUCT structure, usually + * passed by the system to the window procedure in a @c WM_CREATE + * or @c WM_NCCREATE + * + * @remarks The function is intended to be called only inside a @c WM_CREATE + * or @c WM_NCCREATE message handler. + */ +void CResizableLayout::MakeResizable(LPCREATESTRUCT lpCreateStruct) +{ + if (lpCreateStruct->style & WS_CHILD) + return; + + CWnd* pWnd = GetResizableWnd(); + +#if (_WIN32_WINNT >= 0x0501 && !defined(RSZLIB_NO_XP_DOUBLE_BUFFER)) + // enable double-buffering on supported platforms + pWnd->ModifyStyleEx(0, WS_EX_COMPOSITED); +#endif + + if (!(lpCreateStruct->style & WS_THICKFRAME)) + { + // set resizable style + pWnd->ModifyStyle(DS_MODALFRAME, WS_THICKFRAME); + // keep client area + CRect rect(CPoint(lpCreateStruct->x, lpCreateStruct->y), + CSize(lpCreateStruct->cx, lpCreateStruct->cy)); + pWnd->SendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&rect); + // adjust size to reflect new style + ::AdjustWindowRectEx(&rect, pWnd->GetStyle(), + ::IsMenu(pWnd->GetMenu()->GetSafeHmenu()), pWnd->GetExStyle()); + pWnd->SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(), + SWP_NOSENDCHANGING|SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOREPOSITION); + // update dimensions + lpCreateStruct->cx = rect.Width(); + lpCreateStruct->cy = rect.Height(); + } +} + +/*! + * This function should be called inside the parent window @c WM_NCCALCSIZE + * message handler to help eliminate flickering. + * + * @param bAfterDefault Flag that specifies wether the call is made before + * or after the default handler + * @param lpncsp Pointer to the @c NCCALCSIZE_PARAMS structure that is + * passed to the message handler + * @param lResult Reference to the result of the message handler. + * It contains the default handler result on input and the value to + * return from the window procedure on output. + * + * @remarks This function fixes the annoying flickering effect that is + * visible when resizing the top or left edges of the window + * (at least on a "left to right" Windows localized version). + */ +void CResizableLayout::HandleNcCalcSize(BOOL bAfterDefault, LPNCCALCSIZE_PARAMS lpncsp, LRESULT &lResult) +{ + // prevent useless complication when size is not changing + // prevent recursion when resetting the window region (see below) + if ((lpncsp->lppos->flags & SWP_NOSIZE) +#if (_WIN32_WINNT >= 0x0501) + || m_bNoRecursion +#endif + ) + return; + + if (!bAfterDefault) + { + // save a copy before default handler gets called + m_rectClientBefore = lpncsp->rgrc[2]; + } + else // after default WM_NCCALCSIZE msg processing + { + if (lResult != 0) + { + // default handler already uses an advanced validation policy, give up + return; + } + // default calculated client rect + RECT &rectClientAfter = lpncsp->rgrc[0]; + + // intersection between old and new client area is to be preserved + // set source and destination rects to this intersection + RECT &rectPreserve = lpncsp->rgrc[1]; + ::IntersectRect(&rectPreserve, &rectClientAfter, &m_rectClientBefore); + lpncsp->rgrc[2] = rectPreserve; + + lResult = WVR_VALIDRECTS; + + // FIX: window region must be updated before the result of the + // WM_NCCALCSIZE message gets processed by the system, + // otherwise the old window region will clip the client + // area during the preservation process. + // This is especially evident on WinXP when the non-client + // area is rendered with Visual Styles enabled and the + // windows have a non rectangular region. +#if (_WIN32_WINNT >= 0x0501) + //! @todo change rt check to only if themed frame. what about custom wnd region? + if (real_WIN32_WINNT >= 0x0501) + { + CWnd* pWnd = GetResizableWnd(); + DWORD dwStyle = pWnd->GetStyle(); + if ((dwStyle & (WS_CAPTION|WS_MAXIMIZE)) == WS_CAPTION) + { + m_bNoRecursion = TRUE; + pWnd->SetWindowRgn(NULL, FALSE); + m_bNoRecursion = FALSE; + } + } +#endif + } +} diff --git a/ext/ResizableLib/ResizableLayout.h b/ext/ResizableLib/ResizableLayout.h new file mode 100644 index 0000000..3108d5b --- /dev/null +++ b/ext/ResizableLib/ResizableLayout.h @@ -0,0 +1,304 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableLayout class. + */ + +#if !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_) +#define AFX_RESIZABLELAYOUT_H__INCLUDED_ + +#include +#include "ResizableMsgSupport.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief Special type for layout alignment +/*! + * Implements anchor points as a percentage of the parent window client area. + * Control corners are always kept at a fixed distance from their anchor points, + * thus allowing a control to resize proportionally as the parent window is resized. + */ +typedef struct tagANCHOR +{ + int cx; //!< horizontal component, in percent + int cy; //!< vertical component, in percent + + tagANCHOR() {} + + tagANCHOR(int x, int y) + { + cx = x; + cy = y; + } + +} ANCHOR, *PANCHOR, *LPANCHOR; + +/*! @defgroup ConstAnchors Alignment Constants + * Define common layout alignment constants for anchor points. + * @{ + */ + //! Anchor to the top-left corner + const ANCHOR TOP_LEFT(0, 0); + //! Anchor to the top edge and center horizontally + const ANCHOR TOP_CENTER(50, 0); + //! Anchor to the top-right corner + const ANCHOR TOP_RIGHT(100, 0); + //! Anchor to the left edge and center vertically + const ANCHOR MIDDLE_LEFT(0, 50); + //! Anchor to the center + const ANCHOR MIDDLE_CENTER(50, 50); + //! Anchor to the right edge and center vertically + const ANCHOR MIDDLE_RIGHT(100, 50); + //! Anchor to the bottom-left corner + const ANCHOR BOTTOM_LEFT(0, 100); + //! Anchor to the bottom edge and center horizontally + const ANCHOR BOTTOM_CENTER(50, 100); + //! Anchor to the bottom-right corner + const ANCHOR BOTTOM_RIGHT(100, 100); +// @} + +//! @brief Holds a control layout settings +/*! + * Layout settings specify how a control must be moved and resized with respect to + * the parent window and how it reacts to dynamic changes to its size when painting + * its client area, with special care for flickering. + */ +typedef struct tagLAYOUTINFO +{ + //! Handle of the window the layout of which is being defined + HWND hWnd; + //! Identification number assigned to the callback slot + UINT_PTR nCallbackID; + + //! Window class name to identify standard controls + TCHAR sWndClass[MAX_PATH]; + + //! Anchor point for the top-left corner + ANCHOR anchorTopLeft; + //! Fixed distance for the top-left corner + SIZE marginTopLeft; + + //! Anchor point for the bottom-right corner + ANCHOR anchorBottomRight; + //! Fixed distance for the bottom-right corner + SIZE marginBottomRight; + + //! Flag that enables support for custom windows + BOOL bMsgSupport; + //! Redraw settings for anti-flickering and proper painting + RESIZEPROPERTIES properties; + + tagLAYOUTINFO() : hWnd(NULL), nCallbackID(0), bMsgSupport(FALSE) + { + sWndClass[0] = 0; + } + + tagLAYOUTINFO(HWND hwnd, ANCHOR tl_type, SIZE tl_margin, + ANCHOR br_type, SIZE br_margin) + : + hWnd(hwnd), nCallbackID(0), bMsgSupport(FALSE), + anchorTopLeft(tl_type), marginTopLeft(tl_margin), + anchorBottomRight(br_type), marginBottomRight(br_margin) + { + sWndClass[0] = 0; + } + +} LAYOUTINFO, *PLAYOUTINFO, *LPLAYOUTINFO; + +//! @brief Layout manager implementation +/*! + * Derive from this class to implement resizable windows, adding the ability + * to dinamically resize and reposition child controls. + * Special care is taken to ensure a smooth animation during the resize + * operations performed by the users, without annoying flickering effects. + */ +class CResizableLayout +{ +private: + //@{ + //! @brief Collection of layout settings for each control + CMap m_mapLayout; + CList m_listLayout; + CList m_listLayoutCB; + //@} + + //@{ + //! @brief Used for clipping implementation + HRGN m_hOldClipRgn; + int m_nOldClipRgn; + //@} + + //@{ + //! @brief Used for advanced anti-flickering + RECT m_rectClientBefore; + BOOL m_bNoRecursion; + //@} + + //! @brief Apply clipping settings for the specified control + void ClipChildWindow(const LAYOUTINFO &layout, CRgn* pRegion) const; + + //! @brief Helper function to calculate new layout + void CalcNewChildPosition(const LAYOUTINFO &layout, + const CRect &rectParent, CRect &rectChild, UINT& uFlags) const; + +protected: + //! @brief Override to initialize resize properties (clipping, refresh) + virtual void InitResizeProperties(LAYOUTINFO& layout) const; + + //! @brief Override to specify clipping for unsupported windows + virtual BOOL LikesClipping(const LAYOUTINFO &layout) const; + + //! @brief Override to specify refresh for unsupported windows + virtual BOOL NeedsRefresh(const LAYOUTINFO &layout, + const CRect &rectOld, const CRect &rectNew) const; + + //! @brief Clip controls in the layout out of the specified device context + BOOL ClipChildren(CDC* pDC, BOOL bUndo); + + //! @brief Get the layout clipping region + void GetClippingRegion(CRgn* pRegion) const; + + //! @brief Override for scrollable or expanding parent windows + virtual void GetTotalClientRect(LPRECT lpRect) const; + + //@{ + //! @brief Add anchor points for the specified control to the layout + void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight); + + void AddAnchor(HWND hWnd, ANCHOR anchorTopLeft) + { + AddAnchor(hWnd, anchorTopLeft, anchorTopLeft); + } + + void AddAnchor(UINT nID, ANCHOR anchorTopLeft, ANCHOR anchorBottomRight) + { + AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID), + anchorTopLeft, anchorBottomRight); + } + + void AddAnchor(UINT nID, ANCHOR anchorTopLeft) + { + AddAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID), + anchorTopLeft, anchorTopLeft); + } + //@} + + //! @brief Add a callback slot to the layout for dynamic controls or anchor points + UINT_PTR AddAnchorCallback(); + + //@{ + //! @brief Get position and size of a control in the layout from the parent's client area + BOOL GetAnchorPosition(HWND hWnd, const CRect &rectParent, + CRect &rectChild, UINT* lpFlags = NULL) const + { + POSITION pos; + if (!m_mapLayout.Lookup(hWnd, pos)) + return FALSE; + + UINT uTmpFlags; + CalcNewChildPosition(m_listLayout.GetAt(pos), rectParent, rectChild, + (lpFlags != NULL) ? (*lpFlags) : uTmpFlags); + return TRUE; + } + + BOOL GetAnchorPosition(UINT nID, const CRect &rectParent, + CRect &rectChild, UINT* lpFlags = NULL) const + { + return GetAnchorPosition(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID), + rectParent, rectChild, lpFlags); + } + //@} + + //@{ + //! @brief Get margins surrounding a control in the layout with the given size + BOOL GetAnchorMargins(HWND hWnd, const CSize &sizeChild, CRect &rectMargins) const; + + BOOL GetAnchorMargins(UINT nID, const CSize &sizeChild, CRect &rectMargins) const + { + return GetAnchorMargins(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID), + sizeChild, rectMargins); + } + //@} + + //@{ + //! @brief Remove a control from the layout + BOOL RemoveAnchor(HWND hWnd) + { + POSITION pos; + if (!m_mapLayout.Lookup(hWnd, pos)) + return FALSE; + + m_listLayout.RemoveAt(pos); + return m_mapLayout.RemoveKey(hWnd); + } + + BOOL RemoveAnchor(UINT nID) + { + return RemoveAnchor(::GetDlgItem(GetResizableWnd()->GetSafeHwnd(), nID)); + } + //@} + + //! @brief Reset the layout content + void RemoveAllAnchors() + { + m_mapLayout.RemoveAll(); + m_listLayout.RemoveAll(); + m_listLayoutCB.RemoveAll(); + } + + //! @brief Reposition and size all the controls in the layout + void ArrangeLayout() const; + + //! @brief Override to provide dynamic control's layout info + virtual BOOL ArrangeLayoutCallback(LAYOUTINFO& layout) const; + + //! @brief Override to provide the parent window + virtual CWnd* GetResizableWnd() const = 0; + + //! @brief Enhance anti-flickering + void HandleNcCalcSize(BOOL bAfterDefault, LPNCCALCSIZE_PARAMS lpncsp, LRESULT& lResult); + + //! @brief Enable resizable style for top level parent windows + void MakeResizable(LPCREATESTRUCT lpCreateStruct); + +public: + CResizableLayout() + { + m_bNoRecursion = FALSE; + m_hOldClipRgn = ::CreateRectRgn(0,0,0,0); + m_nOldClipRgn = 0; + } + + virtual ~CResizableLayout() + { + // just for safety + RemoveAllAnchors(); + + DeleteObject(m_hOldClipRgn); + } +}; + +// @} +#endif // !defined(AFX_RESIZABLELAYOUT_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableLib.vcproj b/ext/ResizableLib/ResizableLib.vcproj new file mode 100644 index 0000000..db50a1e --- /dev/null +++ b/ext/ResizableLib/ResizableLib.vcproj @@ -0,0 +1,561 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/ResizableLib/ResizableMDIChild.cpp b/ext/ResizableLib/ResizableMDIChild.cpp new file mode 100644 index 0000000..e6819a2 --- /dev/null +++ b/ext/ResizableLib/ResizableMDIChild.cpp @@ -0,0 +1,128 @@ +// ResizableMDIChild.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableMDIChild.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIChild + +IMPLEMENT_DYNCREATE(CResizableMDIChild, CMDIChildWnd) + +CResizableMDIChild::CResizableMDIChild() +{ + m_bEnableSaveRestore = FALSE; +} + +CResizableMDIChild::~CResizableMDIChild() +{ +} + + +BEGIN_MESSAGE_MAP(CResizableMDIChild, CMDIChildWnd) + //{{AFX_MSG_MAP(CResizableMDIChild) + ON_WM_GETMINMAXINFO() + ON_WM_SIZE() + ON_WM_DESTROY() + ON_WM_NCCREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIChild message handlers + +void CResizableMDIChild::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + // MDI should call default implementation + CMDIChildWnd::OnGetMinMaxInfo(lpMMI); + + MinMaxInfo(lpMMI); + + CWnd* pView = GetDlgItem(AFX_IDW_PANE_FIRST);//GetActiveView(); + if (pView != NULL) + ChainMinMaxInfo(lpMMI, this, pView); +} + +void CResizableMDIChild::OnSize(UINT nType, int cx, int cy) +{ + CMDIChildWnd::OnSize(nType, cx, cy); + +/* Why was this necessary??? + + // make sure the MDI parent frame doesn't clip + // this child window when it is maximized + if (nType == SIZE_MAXIMIZED) + { + CMDIFrameWnd* pFrame = GetMDIFrame(); + + CRect rect; + pFrame->GetWindowRect(rect); + pFrame->MoveWindow(rect); + } +/*/ +} + +// NOTE: this must be called after setting the layout +// to have the view and its controls displayed properly +BOOL CResizableMDIChild::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly) +{ + m_sSection = pszSection; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + return LoadWindowRect(pszSection, bRectOnly); +} + +void CResizableMDIChild::OnDestroy() +{ + if (m_bEnableSaveRestore) + SaveWindowRect(m_sSection, m_bRectOnly); + + CMDIChildWnd::OnDestroy(); +} + + +LRESULT CResizableMDIChild::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CMDIChildWnd::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CMDIChildWnd::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} + +BOOL CResizableMDIChild::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CMDIChildWnd::OnNcCreate(lpCreateStruct)) + return FALSE; + ModifyStyle(0, WS_CLIPCHILDREN); + return TRUE; +} diff --git a/ext/ResizableLib/ResizableMDIChild.h b/ext/ResizableLib/ResizableMDIChild.h new file mode 100644 index 0000000..874d1ad --- /dev/null +++ b/ext/ResizableLib/ResizableMDIChild.h @@ -0,0 +1,89 @@ +#if !defined(AFX_RESIZABLEMDICHILD_H__INCLUDED_) +#define AFX_RESIZABLEMDICHILD_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ResizableMDIChild.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableMinMax.h" +#include "ResizableWndState.h" +#include "ResizableLayout.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIChild frame + +class CResizableMDIChild : public CMDIChildWnd, public CResizableMinMax, + public CResizableWndState, public CResizableLayout +{ + DECLARE_DYNCREATE(CResizableMDIChild) +protected: + CResizableMDIChild(); // protected constructor used by dynamic creation + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableMDIChild) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CResizableMDIChild(); + + BOOL EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE); + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +private: + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +protected: + // Generated message map functions + //{{AFX_MSG(CResizableMDIChild) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnDestroy(); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEMDICHILD_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableMDIFrame.cpp b/ext/ResizableLib/ResizableMDIFrame.cpp new file mode 100644 index 0000000..cf26e7e --- /dev/null +++ b/ext/ResizableLib/ResizableMDIFrame.cpp @@ -0,0 +1,121 @@ +// ResizableMDIFrame.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableMDIFrame.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIFrame + +IMPLEMENT_DYNCREATE(CResizableMDIFrame, CMDIFrameWnd) + +CResizableMDIFrame::CResizableMDIFrame() +{ + m_bEnableSaveRestore = FALSE; +} + +CResizableMDIFrame::~CResizableMDIFrame() +{ +} + + +BEGIN_MESSAGE_MAP(CResizableMDIFrame, CMDIFrameWnd) + //{{AFX_MSG_MAP(CResizableMDIFrame) + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_NCCREATE() + ON_WM_WINDOWPOSCHANGING() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIFrame message handlers + +void CResizableMDIFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + // MDI should call default implementation + CMDIFrameWnd::OnGetMinMaxInfo(lpMMI); + + MinMaxInfo(lpMMI); + + BOOL bMaximized = FALSE; + CMDIChildWnd* pChild = MDIGetActive(&bMaximized); + if (pChild != NULL && bMaximized) + ChainMinMaxInfo(lpMMI, this, pChild); +} + +// NOTE: this must be called after setting the layout +// to have the view and its controls displayed properly +BOOL CResizableMDIFrame::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly) +{ + m_sSection = pszSection; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + return LoadWindowRect(pszSection, bRectOnly); +} + +void CResizableMDIFrame::OnDestroy() +{ + if (m_bEnableSaveRestore) + SaveWindowRect(m_sSection, m_bRectOnly); + + CMDIFrameWnd::OnDestroy(); +} + +BOOL CResizableMDIFrame::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CMDIFrameWnd::OnNcCreate(lpCreateStruct)) + return FALSE; + + MakeResizable(lpCreateStruct); + + return TRUE; +} + +LRESULT CResizableMDIFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CMDIFrameWnd::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CMDIFrameWnd::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} + +void CResizableMDIFrame::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos) +{ + CMDIFrameWnd::OnWindowPosChanging(lpwndpos); + + // since this window class doesn't have the style CS_HREDRAW|CS_VREDRAW + // the client area is not invalidated during a resize operation and + // this prevents the system from using WM_NCCALCSIZE to validate rects + Invalidate(); +} diff --git a/ext/ResizableLib/ResizableMDIFrame.h b/ext/ResizableLib/ResizableMDIFrame.h new file mode 100644 index 0000000..a4fe4f0 --- /dev/null +++ b/ext/ResizableLib/ResizableMDIFrame.h @@ -0,0 +1,90 @@ +// ResizableMDIFrame.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZABLEMDIFRAME_H__INCLUDED_) +#define AFX_RESIZABLEMDIFRAME_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ResizableMinMax.h" +#include "ResizableWndState.h" +#include "ResizableLayout.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableMDIFrame frame + +class CResizableMDIFrame : public CMDIFrameWnd, public CResizableMinMax, + public CResizableWndState, public CResizableLayout +{ + DECLARE_DYNCREATE(CResizableMDIFrame) +protected: + CResizableMDIFrame(); // protected constructor used by dynamic creation + +// Attributes +protected: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableMDIFrame) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + virtual ~CResizableMDIFrame(); + + BOOL EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE); + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +private: + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +protected: + // Generated message map functions + //{{AFX_MSG(CResizableMDIFrame) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnDestroy(); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnWindowPosChanging(WINDOWPOS FAR* lpwndpos); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEMDIFRAME_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableMinMax.cpp b/ext/ResizableLib/ResizableMinMax.cpp new file mode 100644 index 0000000..2c1e1ab --- /dev/null +++ b/ext/ResizableLib/ResizableMinMax.cpp @@ -0,0 +1,190 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableMinMax class. + */ + +#include "stdafx.h" +#include "ResizableMinMax.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizableMinMax::CResizableMinMax() +{ + m_bUseMinTrack = FALSE; + m_bUseMaxTrack = FALSE; + m_bUseMaxRect = FALSE; +} + +CResizableMinMax::~CResizableMinMax() +{ + +} + +void CResizableMinMax::MinMaxInfo(LPMINMAXINFO lpMMI) +{ + if (m_bUseMinTrack) + lpMMI->ptMinTrackSize = m_ptMinTrackSize; + + if (m_bUseMaxTrack) + lpMMI->ptMaxTrackSize = m_ptMaxTrackSize; + + if (m_bUseMaxRect) + { + lpMMI->ptMaxPosition = m_ptMaxPos; + lpMMI->ptMaxSize = m_ptMaxSize; + } +} + +void CResizableMinMax::ChainMinMaxInfo(LPMINMAXINFO lpMMI, CWnd* pParentFrame, CWnd* pWnd) +{ + // get the extra size from child to parent + CRect rectClient, rectWnd; + if ((pParentFrame->GetStyle() & WS_CHILD) && pParentFrame->IsZoomed()) + pParentFrame->GetClientRect(rectWnd); + else + pParentFrame->GetWindowRect(rectWnd); + pParentFrame->RepositionBars(0, 0xFFFF, + AFX_IDW_PANE_FIRST, CWnd::reposQuery, rectClient); + CSize sizeExtra = rectWnd.Size() - rectClient.Size(); + + ChainMinMaxInfo(lpMMI, pWnd->GetSafeHwnd(), sizeExtra); +} + +void CResizableMinMax::ChainMinMaxInfo(LPMINMAXINFO lpMMI, HWND hWndChild, CSize sizeExtra) +{ + // ask the child window for track size + MINMAXINFO mmiChild = *lpMMI; + ::SendMessage(hWndChild, WM_GETMINMAXINFO, 0, (LPARAM)&mmiChild); + BOOL bRetMax = (lpMMI->ptMaxTrackSize.x != mmiChild.ptMaxTrackSize.x + || lpMMI->ptMaxTrackSize.y != mmiChild.ptMaxTrackSize.y); + BOOL bRetMin = (lpMMI->ptMinTrackSize.x != mmiChild.ptMinTrackSize.x + || lpMMI->ptMinTrackSize.y != mmiChild.ptMinTrackSize.y); + + // add static extra size + mmiChild.ptMaxTrackSize = sizeExtra + mmiChild.ptMaxTrackSize; + mmiChild.ptMinTrackSize = sizeExtra + mmiChild.ptMinTrackSize; + + // min size is the largest + if (bRetMin) + { + lpMMI->ptMinTrackSize.x = __max(lpMMI->ptMinTrackSize.x, + mmiChild.ptMinTrackSize.x); + lpMMI->ptMinTrackSize.y = __max(lpMMI->ptMinTrackSize.y, + mmiChild.ptMinTrackSize.y); + } + // max size is the shortest + if (bRetMax) + { + lpMMI->ptMaxTrackSize.x = __min(lpMMI->ptMaxTrackSize.x, + mmiChild.ptMaxTrackSize.x); + lpMMI->ptMaxTrackSize.y = __min(lpMMI->ptMaxTrackSize.y, + mmiChild.ptMaxTrackSize.y); + } +} + +BOOL CResizableMinMax::CalcSizeExtra(HWND /*hWndChild*/, CSize /*sizeChild*/, CSize& /*sizeExtra*/) +{ + // should be overridden if you use ChainMinMaxInfoCB + ASSERT(FALSE); + return FALSE; +} + +void CResizableMinMax::ChainMinMaxInfoCB(LPMINMAXINFO lpMMI, HWND hWndChild) +{ + // ask the child window for track size + MINMAXINFO mmiChild = *lpMMI; + ::SendMessage(hWndChild, WM_GETMINMAXINFO, 0, (LPARAM)&mmiChild); + BOOL bRetMax = (lpMMI->ptMaxTrackSize.x != mmiChild.ptMaxTrackSize.x + || lpMMI->ptMaxTrackSize.y != mmiChild.ptMaxTrackSize.y); + BOOL bRetMin = (lpMMI->ptMinTrackSize.x != mmiChild.ptMinTrackSize.x + || lpMMI->ptMinTrackSize.y != mmiChild.ptMinTrackSize.y); + + // use a callback to determine extra size + CSize sizeExtra(0, 0); + bRetMax = bRetMax && CalcSizeExtra(hWndChild, mmiChild.ptMaxTrackSize, sizeExtra); + mmiChild.ptMaxTrackSize = sizeExtra + mmiChild.ptMaxTrackSize; + bRetMin = bRetMin && CalcSizeExtra(hWndChild, mmiChild.ptMinTrackSize, sizeExtra); + mmiChild.ptMinTrackSize = sizeExtra + mmiChild.ptMinTrackSize; + + // min size is the largest + if (bRetMin) + { + lpMMI->ptMinTrackSize.x = __max(lpMMI->ptMinTrackSize.x, + mmiChild.ptMinTrackSize.x); + lpMMI->ptMinTrackSize.y = __max(lpMMI->ptMinTrackSize.y, + mmiChild.ptMinTrackSize.y); + } + // max size is the shortest + if (bRetMax) + { + lpMMI->ptMaxTrackSize.x = __min(lpMMI->ptMaxTrackSize.x, + mmiChild.ptMaxTrackSize.x); + lpMMI->ptMaxTrackSize.y = __min(lpMMI->ptMaxTrackSize.y, + mmiChild.ptMaxTrackSize.y); + } +} + +void CResizableMinMax::SetMaximizedRect(const CRect& rc) +{ + m_bUseMaxRect = TRUE; + + m_ptMaxPos = rc.TopLeft(); + m_ptMaxSize.x = rc.Width(); + m_ptMaxSize.y = rc.Height(); +} + +void CResizableMinMax::ResetMaximizedRect() +{ + m_bUseMaxRect = FALSE; +} + +void CResizableMinMax::SetMinTrackSize(const CSize& size) +{ + m_bUseMinTrack = TRUE; + + m_ptMinTrackSize.x = size.cx; + m_ptMinTrackSize.y = size.cy; +} + +void CResizableMinMax::ResetMinTrackSize() +{ + m_bUseMinTrack = FALSE; +} + +void CResizableMinMax::SetMaxTrackSize(const CSize& size) +{ + m_bUseMaxTrack = TRUE; + + m_ptMaxTrackSize.x = size.cx; + m_ptMaxTrackSize.y = size.cy; +} + +void CResizableMinMax::ResetMaxTrackSize() +{ + m_bUseMaxTrack = FALSE; +} diff --git a/ext/ResizableLib/ResizableMinMax.h b/ext/ResizableLib/ResizableMinMax.h new file mode 100644 index 0000000..430925c --- /dev/null +++ b/ext/ResizableLib/ResizableMinMax.h @@ -0,0 +1,80 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableMinMax class. + */ + +#if !defined(AFX_RESIZABLEMINMAX_H__INCLUDED_) +#define AFX_RESIZABLEMINMAX_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief brief_description +/*! + * long_description + */ +class CResizableMinMax +{ +// Attributes +private: + // flags + BOOL m_bUseMaxTrack; + BOOL m_bUseMinTrack; + BOOL m_bUseMaxRect; + + POINT m_ptMinTrackSize; // min tracking size + POINT m_ptMaxTrackSize; // max tracking size + POINT m_ptMaxPos; // maximized position + POINT m_ptMaxSize; // maximized size + +public: + CResizableMinMax(); + virtual ~CResizableMinMax(); + +protected: + void MinMaxInfo(LPMINMAXINFO lpMMI); + void ChainMinMaxInfo(LPMINMAXINFO lpMMI, CWnd* pParentFrame, CWnd* pWnd); + + void ChainMinMaxInfo(LPMINMAXINFO lpMMI, HWND hWndChild, CSize sizeExtra); + + void ChainMinMaxInfo(LPMINMAXINFO lpMMI, CWnd* pParentWnd, UINT nID, CSize sizeExtra) + { + ChainMinMaxInfo(lpMMI, + ::GetDlgItem(pParentWnd->GetSafeHwnd(), nID), sizeExtra); + } + + void ChainMinMaxInfoCB(LPMINMAXINFO lpMMI, HWND hWndChild); + virtual BOOL CalcSizeExtra(HWND hWndChild, CSize sizeChild, CSize& sizeExtra); + + void SetMaximizedRect(const CRect& rc); // set window rect when maximized + void ResetMaximizedRect(); // reset to default maximized rect + void SetMinTrackSize(const CSize& size); // set minimum tracking size + void ResetMinTrackSize(); // reset to default minimum tracking size + void SetMaxTrackSize(const CSize& size); // set maximum tracking size + void ResetMaxTrackSize(); // reset to default maximum tracking size +}; + +// @} +#endif // !defined(AFX_RESIZABLEMINMAX_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableMsgSupport.cpp b/ext/ResizableLib/ResizableMsgSupport.cpp new file mode 100644 index 0000000..dbc41e1 --- /dev/null +++ b/ext/ResizableLib/ResizableMsgSupport.cpp @@ -0,0 +1,34 @@ +// ResizableMsgSupport.cpp: support messages for custom resizable wnds +// +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000-2002 by Paolo Messina +// (http://www.geocities.com/ppescher - ppescher@yahoo.com) +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableMsgSupport.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// Registered message to communicate with the library + +// static intializer must be called before user code +#pragma warning(disable:4073) +#pragma init_seg(lib) + +const UINT WMU_RESIZESUPPORT = ::RegisterWindowMessage(TEXT("WMU_RESIZESUPPORT")); + diff --git a/ext/ResizableLib/ResizableMsgSupport.h b/ext/ResizableLib/ResizableMsgSupport.h new file mode 100644 index 0000000..02a055b --- /dev/null +++ b/ext/ResizableLib/ResizableMsgSupport.h @@ -0,0 +1,103 @@ +// ResizableMsgSupport.h: some declarations to support custom resizable wnds +// +///////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2000-2002 by Paolo Messina +// (http://www.geocities.com/ppescher - ppescher@yahoo.com) +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_) +#define AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +typedef struct tagRESIZEPROPERTIES +{ + // wether to ask for resizing properties every time + BOOL bAskClipping; + BOOL bAskRefresh; + // otherwise, use the cached properties + BOOL bCachedLikesClipping; + BOOL bCachedNeedsRefresh; + + // initialize with valid data + tagRESIZEPROPERTIES() : bAskClipping(TRUE), bAskRefresh(TRUE) {} + +} RESIZEPROPERTIES, *PRESIZEPROPERTIES, *LPRESIZEPROPERTIES; + + +typedef struct tagCLIPPINGPROPERTY +{ + BOOL bLikesClipping; + + // initialize with valid data + tagCLIPPINGPROPERTY() : bLikesClipping(FALSE) {} + +} CLIPPINGPROPERTY, *PCLIPPINGPROPERTY, *LPCLIPPINGPROPERTY; + + +typedef struct tagREFRESHPROPERTY +{ + BOOL bNeedsRefresh; + RECT rcOld; + RECT rcNew; + + // initialize with valid data + tagREFRESHPROPERTY() : bNeedsRefresh(TRUE) {} + +} REFRESHPROPERTY, *PREFRESHPROPERTY, *LPREFRESHPROPERTY; + + +// registered message to communicate with the library +extern const UINT WMU_RESIZESUPPORT; + +// if the message is implemented the returned value must be non-zero +// the default window procedure returns zero for unhandled messages + +// wParam is one of the following RSZSUP_* values, lParam as specified +enum ResizeSupport +{ + RSZSUP_QUERYPROPERTIES = 101, // lParam = LPRESIZEPROPERTIES + RSZSUP_LIKESCLIPPING = 102, // lParam = LPCLIPPINGPROPERTY + RSZSUP_NEEDSREFRESH = 103, // lParam = LPREFRESHPROPERTY + RSZSUP_SHEETPAGEEXHACK = 104, // lParam = HWND (source prop.page) +}; + +///////////////////////////////////////////////////////////////////////////// +// utility functions + +inline BOOL Send_QueryProperties(HWND hWnd, LPRESIZEPROPERTIES pResizeProperties) +{ + return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT, + RSZSUP_QUERYPROPERTIES, (LPARAM)pResizeProperties)); +} + +inline BOOL Send_LikesClipping(HWND hWnd, LPCLIPPINGPROPERTY pClippingProperty) +{ + return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT, + RSZSUP_LIKESCLIPPING, (LPARAM)pClippingProperty)); +} + +inline BOOL Send_NeedsRefresh(HWND hWnd, LPREFRESHPROPERTY pRefreshProperty) +{ + return (0 != SendMessage(hWnd, WMU_RESIZESUPPORT, + RSZSUP_NEEDSREFRESH, (LPARAM)pRefreshProperty)); +} + +inline void Post_SheetPageExHack(HWND hWndSheet, HWND hWndPage) +{ + PostMessage(hWndSheet, WMU_RESIZESUPPORT, + RSZSUP_SHEETPAGEEXHACK, (LPARAM)hWndPage); +} + +#endif // !defined(AFX_RESIZABLEMSGSUPPORT_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizablePage.cpp b/ext/ResizableLib/ResizablePage.cpp new file mode 100644 index 0000000..472a40d --- /dev/null +++ b/ext/ResizableLib/ResizablePage.cpp @@ -0,0 +1,120 @@ +// ResizablePage.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizablePage.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizablePage + +IMPLEMENT_DYNCREATE(CResizablePage, CPropertyPage) + +CResizablePage::CResizablePage() +{ +} + +CResizablePage::CResizablePage(UINT nIDTemplate, UINT nIDCaption) + : CPropertyPage(nIDTemplate, nIDCaption) +{ +} + +CResizablePage::CResizablePage(LPCTSTR lpszTemplateName, UINT nIDCaption) + : CPropertyPage(lpszTemplateName, nIDCaption) +{ +} + +CResizablePage::~CResizablePage() +{ +} + + +BEGIN_MESSAGE_MAP(CResizablePage, CPropertyPage) + //{{AFX_MSG_MAP(CResizablePage) + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CResizablePage message handlers + +void CResizablePage::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + ArrangeLayout(); +} + +BOOL CResizablePage::OnEraseBkgnd(CDC* pDC) +{ + ClipChildren(pDC, FALSE); + + BOOL bRet = CPropertyPage::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +void CResizablePage::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); +} + +BOOL CResizablePage::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // set the initial size as the min track size + CRect rc; + GetWindowRect(&rc); + SetMinTrackSize(rc.Size()); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CResizablePage::OnDestroy() +{ + // remove child windows + RemoveAllAnchors(); + + CPropertyPage::OnDestroy(); +} + +LRESULT CResizablePage::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CPropertyPage::WindowProc(message, wParam, lParam); + + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CPropertyPage::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} diff --git a/ext/ResizableLib/ResizablePage.h b/ext/ResizableLib/ResizablePage.h new file mode 100644 index 0000000..d28219a --- /dev/null +++ b/ext/ResizableLib/ResizablePage.h @@ -0,0 +1,87 @@ +#if !defined(AFX_RESIZABLEPAGE_H__INCLUDED_) +#define AFX_RESIZABLEPAGE_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizablePage.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableMinMax.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizablePage window + +class CResizablePage : public CPropertyPage, public CResizableLayout, + public CResizableMinMax +{ + DECLARE_DYNCREATE(CResizablePage) + +// Construction +public: + CResizablePage(); + CResizablePage(UINT nIDTemplate, UINT nIDCaption = 0); + CResizablePage(LPCTSTR lpszTemplateName, UINT nIDCaption = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizablePage) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizablePage(); + +// callable from derived classes +protected: + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +// Generated message map functions +protected: + //{{AFX_MSG(CResizablePage) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEPAGE_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizablePageEx.cpp b/ext/ResizableLib/ResizablePageEx.cpp new file mode 100644 index 0000000..68dac64 --- /dev/null +++ b/ext/ResizableLib/ResizablePageEx.cpp @@ -0,0 +1,158 @@ +// ResizablePageEx.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizablePageEx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizablePageEx + +IMPLEMENT_DYNCREATE(CResizablePageEx, CPropertyPageEx) + +CResizablePageEx::CResizablePageEx() +{ +} + +CResizablePageEx::CResizablePageEx(UINT nIDTemplate, UINT nIDCaption, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle) + : CPropertyPageEx(nIDTemplate, nIDCaption, nIDHeaderTitle, nIDHeaderSubTitle) +{ +} + +CResizablePageEx::CResizablePageEx(LPCTSTR lpszTemplateName, UINT nIDCaption, UINT nIDHeaderTitle, UINT nIDHeaderSubTitle) + : CPropertyPageEx(lpszTemplateName, nIDCaption, nIDHeaderTitle, nIDHeaderSubTitle) +{ +} + +CResizablePageEx::~CResizablePageEx() +{ +} + + +BEGIN_MESSAGE_MAP(CResizablePageEx, CPropertyPageEx) + //{{AFX_MSG_MAP(CResizablePageEx) + ON_WM_SIZE() + ON_WM_ERASEBKGND() + ON_WM_GETMINMAXINFO() + ON_WM_DESTROY() + ON_WM_CTLCOLOR() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CResizablePageEx message handlers + +void CResizablePageEx::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + ArrangeLayout(); + + if (m_psp.dwFlags & PSP_HIDEHEADER) + Invalidate(); +} + +BOOL CResizablePageEx::OnEraseBkgnd(CDC* pDC) +{ + ClipChildren(pDC, FALSE); + + BOOL bRet = CPropertyPageEx::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +void CResizablePageEx::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); +} + +BOOL CResizablePageEx::OnInitDialog() +{ + CPropertyPageEx::OnInitDialog(); + + // set the initial size as the min track size + CRect rc; + GetWindowRect(&rc); + SetMinTrackSize(rc.Size()); + + // HACK: temporarily abandon subclassing + // CAUSE: system subclasses this window after this message + // ISSUE: our WindowProc is not the first to be called + // and we miss some painting related messages + if (Attach(UnsubclassWindow())) + { + CWnd* pParent = GetParent(); + pParent->LockWindowUpdate(); + Post_SheetPageExHack(pParent->GetSafeHwnd(), m_hWnd); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CResizablePageEx::OnDestroy() +{ + // remove child windows + RemoveAllAnchors(); + + CPropertyPageEx::OnDestroy(); +} + +HBRUSH CResizablePageEx::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) +{ + // NOTE: this message couldn't be catched without the above hack + + HBRUSH hbr = CPropertyPageEx::OnCtlColor(pDC, pWnd, nCtlColor); + if (hbr && (m_psp.dwFlags & PSP_HIDEHEADER)) + { + // reposition origin of background brush + // used for transparent effect on page controls + // (needed with double-buffering and XP themes) + CRect rect; + pWnd->GetWindowRect(rect); + pWnd->SendMessage(WM_NCCALCSIZE, FALSE, (LPARAM)&rect); + ScreenToClient(rect); + CPoint pt(-rect.TopLeft()); + HDC hDC = pDC->GetSafeHdc(); + ::LPtoDP(hDC, &pt, 1); + ::UnrealizeObject(hbr); + ::SetBrushOrgEx(hDC, pt.x, pt.y, NULL); + } + return hbr; +} + +LRESULT CResizablePageEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0) + return CPropertyPageEx::WindowProc(message, wParam, lParam); + + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CPropertyPageEx::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} diff --git a/ext/ResizableLib/ResizablePageEx.h b/ext/ResizableLib/ResizablePageEx.h new file mode 100644 index 0000000..0adb261 --- /dev/null +++ b/ext/ResizableLib/ResizablePageEx.h @@ -0,0 +1,88 @@ +#if !defined(AFX_RESIZABLEPAGEEX_H__INCLUDED_) +#define AFX_RESIZABLEPAGEEX_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// ResizablePageEx.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableMinMax.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizablePageEx window + +class CResizablePageEx : public CPropertyPageEx, public CResizableLayout, + public CResizableMinMax +{ + DECLARE_DYNCREATE(CResizablePageEx) + +// Construction +public: + CResizablePageEx(); + CResizablePageEx(UINT nIDTemplate, UINT nIDCaption = 0, UINT nIDHeaderTitle = 0, UINT nIDHeaderSubTitle = 0); + CResizablePageEx(LPCTSTR lpszTemplateName, UINT nIDCaption = 0, UINT nIDHeaderTitle = 0, UINT nIDHeaderSubTitle = 0); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizablePageEx) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizablePageEx(); + +// callable from derived classes +protected: + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +// Generated message map functions +protected: + //{{AFX_MSG(CResizablePageEx) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLEPAGEEX_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableSheet.cpp b/ext/ResizableLib/ResizableSheet.cpp new file mode 100644 index 0000000..9c69cd0 --- /dev/null +++ b/ext/ResizableLib/ResizableSheet.cpp @@ -0,0 +1,420 @@ +// ResizableSheet.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableSheet.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableSheet + +IMPLEMENT_DYNAMIC(CResizableSheet, CPropertySheet) + +inline void CResizableSheet::PrivateConstruct() +{ + m_bEnableSaveRestore = FALSE; + m_bSavePage = FALSE; + m_dwGripTempState = 1; + m_bLayoutDone = FALSE; +} + +inline BOOL CResizableSheet::IsWizard() const +{ + return (m_psh.dwFlags & PSH_WIZARD); +} + +CResizableSheet::CResizableSheet() +{ + PrivateConstruct(); +} + +CResizableSheet::CResizableSheet(UINT nIDCaption, CWnd *pParentWnd, UINT iSelectPage) + : CPropertySheet(nIDCaption, pParentWnd, iSelectPage) +{ + PrivateConstruct(); +} + +CResizableSheet::CResizableSheet(LPCTSTR pszCaption, CWnd *pParentWnd, UINT iSelectPage) + : CPropertySheet(pszCaption, pParentWnd, iSelectPage) +{ + PrivateConstruct(); +} + +CResizableSheet::~CResizableSheet() +{ +} + +BEGIN_MESSAGE_MAP(CResizableSheet, CPropertySheet) + //{{AFX_MSG_MAP(CResizableSheet) + ON_WM_GETMINMAXINFO() + ON_WM_SIZE() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + ON_WM_NCCREATE() + //}}AFX_MSG_MAP + ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableSheet message handlers + +BOOL CResizableSheet::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CPropertySheet::OnNcCreate(lpCreateStruct)) + return FALSE; + + // child dialogs don't want resizable border or size grip, + // nor they can handle the min/max size constraints + BOOL bChild = lpCreateStruct->style & WS_CHILD; + + // create and init the size-grip + if (!CreateSizeGrip(!bChild)) + return FALSE; + + MakeResizable(lpCreateStruct); + + return TRUE; +} + +BOOL CResizableSheet::OnInitDialog() +{ + BOOL bResult = CPropertySheet::OnInitDialog(); + + // set the initial size as the min track size + CRect rc; + GetWindowRect(&rc); + SetMinTrackSize(rc.Size()); + + // initialize layout + PresetLayout(); + m_bLayoutDone = TRUE; + + return bResult; +} + +void CResizableSheet::OnDestroy() +{ + if (m_bEnableSaveRestore) + { + SaveWindowRect(m_sSection, m_bRectOnly); + if (m_bSavePage) + SavePage(m_sSection); + } + + RemoveAllAnchors(); + + CPropertySheet::OnDestroy(); +} + +// maps an index to a button ID and vice-versa +static UINT _propButtons[] = +{ + IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP, + ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH +}; +const int _propButtonsCount = sizeof(_propButtons)/sizeof(UINT); + +// horizontal line in wizard mode +#define ID_WIZLINE ID_WIZFINISH+1 + +void CResizableSheet::PresetLayout() +{ + // set the initial size as the min track size + CRect rc; + GetWindowRect(&rc); + SetMinTrackSize(rc.Size()); + + if (GetStyle() & WS_CHILD) + { + GetClientRect(&rc); + GetTabControl()->MoveWindow(&rc); + } + + if (IsWizard()) // wizard mode + { + // hide tab control + GetTabControl()->ShowWindow(SW_HIDE); + + AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT); + } + else // tab mode + { + AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT); + } + + // add a callback for active page (which can change at run-time) + m_nCallbackID = AddAnchorCallback(); + + // use *total* parent size to have correct margins + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + GetActivePage()->GetWindowRect(&rectPage); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectPage, 2); + + // pre-calculate margins + m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft(); + m_sizePageBR = rectPage.BottomRight() - rectSheet.BottomRight(); + + // add all possible buttons, if they exist + for (int i = 0; i < _propButtonsCount; i++) + { + if (NULL != GetDlgItem(_propButtons[i])) + AddAnchor(_propButtons[i], BOTTOM_RIGHT); + } + + // prevent flickering + GetTabControl()->ModifyStyle(0, WS_CLIPSIBLINGS); +} + +BOOL CResizableSheet::ArrangeLayoutCallback(LAYOUTINFO &layout) const +{ + if (layout.nCallbackID != m_nCallbackID) // we only added 1 callback + return CResizableLayout::ArrangeLayoutCallback(layout); + + // set layout info for active page + layout.hWnd = (HWND)::SendMessage(m_hWnd, PSM_GETCURRENTPAGEHWND, 0, 0); + if (!::IsWindow(layout.hWnd)) + return FALSE; + + // set margins + if (IsWizard()) // wizard mode + { + // use pre-calculated margins + layout.marginTopLeft = m_sizePageTL; + layout.marginBottomRight = m_sizePageBR; + } + else // tab mode + { + CTabCtrl* pTab = GetTabControl(); + ASSERT(pTab != NULL); + + // get tab position after resizing and calc page rect + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage)) + return FALSE; // no page yet + + // temporarily resize the tab control to calc page size + CRect rectSave; + pTab->GetWindowRect(rectSave); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2); + pTab->SetRedraw(FALSE); + pTab->MoveWindow(rectPage, FALSE); + pTab->AdjustRect(FALSE, &rectPage); + pTab->MoveWindow(rectSave, FALSE); + pTab->SetRedraw(TRUE); + + // set margins + layout.marginTopLeft = rectPage.TopLeft() - rectSheet.TopLeft(); + layout.marginBottomRight = rectPage.BottomRight() - rectSheet.BottomRight(); + } + + // set anchor types + layout.anchorTopLeft = TOP_LEFT; + layout.anchorBottomRight = BOTTOM_RIGHT; + + // use this layout info + return TRUE; +} + +void CResizableSheet::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW) + return; // arrangement not needed + + if (nType == SIZE_MAXIMIZED) + HideSizeGrip(&m_dwGripTempState); + else + ShowSizeGrip(&m_dwGripTempState); + + // update grip and layout + UpdateSizeGrip(); + ArrangeLayout(); +} + +BOOL CResizableSheet::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/) +{ + // update new wizard page + // active page changes after this notification + PostMessage(WM_SIZE); + + return FALSE; // continue routing +} + +BOOL CResizableSheet::OnEraseBkgnd(CDC* pDC) +{ + ClipChildren(pDC, FALSE); + + BOOL bRet = CPropertySheet::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +BOOL CResizableSheet::CalcSizeExtra(HWND /*hWndChild*/, CSize sizeChild, CSize &sizeExtra) +{ + CTabCtrl* pTab = GetTabControl(); + if (!pTab) + return FALSE; + + // get margins of tabcontrol + CRect rectMargins; + if (!GetAnchorMargins(pTab->m_hWnd, sizeChild, rectMargins)) + return FALSE; + + // get margin caused by tabcontrol + CRect rectTabMargins(0,0,0,0); + + // get tab position after resizing and calc page rect + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage)) + return FALSE; // no page yet + + // temporarily resize the tab control to calc page size + CRect rectSave; + pTab->GetWindowRect(rectSave); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2); + pTab->SetRedraw(FALSE); + pTab->MoveWindow(rectPage, FALSE); + pTab->AdjustRect(TRUE, &rectTabMargins); + pTab->MoveWindow(rectSave, FALSE); + pTab->SetRedraw(TRUE); + + // add non-client size + ::AdjustWindowRectEx(&rectTabMargins, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + + // compute extra size + sizeExtra = rectMargins.TopLeft() + rectMargins.BottomRight() + + rectTabMargins.Size(); + return TRUE; +} + +void CResizableSheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); + + CTabCtrl* pTab = GetTabControl(); + if (!pTab) + return; + + int nCount = GetPageCount(); + for (int idx = 0; idx < nCount; ++idx) + { + if (IsWizard()) // wizard mode + { + // use pre-calculated margins + CRect rectExtra(-CPoint(m_sizePageTL), -CPoint(m_sizePageBR)); + // add non-client size + ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + ChainMinMaxInfo(lpMMI, *GetPage(idx), rectExtra.Size()); + } + else // tab mode + { + ChainMinMaxInfoCB(lpMMI, *GetPage(idx)); + } + } +} + +// protected members + +int CResizableSheet::GetMinWidth() +{ + CWnd* pWnd = NULL; + CRect rectWnd, rectSheet; + GetTotalClientRect(&rectSheet); + + int max = 0, min = rectSheet.Width(); + // search for leftmost and rightmost button margins + for (int i = 0; i < 7; i++) + { + pWnd = GetDlgItem(_propButtons[i]); + // exclude not present or hidden buttons + if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE)) + continue; + + // left position is relative to the right border + // of the parent window (negative value) + pWnd->GetWindowRect(&rectWnd); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectWnd, 2); + int left = rectSheet.right - rectWnd.left; + int right = rectSheet.right - rectWnd.right; + + if (left > max) + max = left; + if (right < min) + min = right; + } + + // sizing border width + int border = GetSystemMetrics(SM_CXSIZEFRAME); + + // compute total width + return max + min + 2*border; +} + + +// NOTE: this must be called after all the other settings +// to have the window and its controls displayed properly +void CResizableSheet::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage) +{ + m_sSection = pszSection; + m_bSavePage = bWithPage; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + LoadWindowRect(pszSection, bRectOnly); + { + LoadPage(pszSection); + ArrangeLayout(); // needs refresh + } +} + +void CResizableSheet::RefreshLayout() +{ + SendMessage(WM_SIZE); +} + +LRESULT CResizableSheet::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0 || !m_bLayoutDone) + return CPropertySheet::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CPropertySheet::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} diff --git a/ext/ResizableLib/ResizableSheet.h b/ext/ResizableLib/ResizableSheet.h new file mode 100644 index 0000000..08a07c1 --- /dev/null +++ b/ext/ResizableLib/ResizableSheet.h @@ -0,0 +1,121 @@ +#if !defined(AFX_RESIZABLESHEET_H__INCLUDED_) +#define AFX_RESIZABLESHEET_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableGrip.h" +#include "ResizableMinMax.h" +#include "ResizableSheetState.h" + +///////////////////////////////////////////////////////////////////////////// +// ResizableSheet.h : header file +// + +class CResizableSheet : public CPropertySheet, public CResizableLayout, + public CResizableGrip, public CResizableMinMax, + public CResizableSheetState +{ + DECLARE_DYNAMIC(CResizableSheet) + +// Construction +public: + CResizableSheet(); + CResizableSheet(UINT nIDCaption, CWnd *pParentWnd = NULL, UINT iSelectPage = 0); + CResizableSheet(LPCTSTR pszCaption, CWnd *pParentWnd = NULL, UINT iSelectPage = 0); + +// Attributes +private: + // support for temporarily hiding the grip + DWORD m_dwGripTempState; + + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + BOOL m_bSavePage; + + // layout vars + UINT_PTR m_nCallbackID; + CSize m_sizePageTL, m_sizePageBR; + BOOL m_bLayoutDone; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableSheet) + public: + virtual BOOL OnInitDialog(); + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + protected: + +// Implementation +public: + virtual ~CResizableSheet(); + +// used internally +private: + void PrivateConstruct(); + + BOOL IsWizard() const; + +// callable from derived classes +protected: + void PresetLayout(); + void RefreshLayout(); + + // section to use in app's profile + void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE, + BOOL bWithPage = FALSE); + int GetMinWidth(); // minimum width to display all buttons + + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +// Generated message map functions +protected: + virtual BOOL CalcSizeExtra(HWND hWndChild, CSize sizeChild, CSize& sizeExtra); + virtual BOOL ArrangeLayoutCallback(LAYOUTINFO& layout) const; + //{{AFX_MSG(CResizableSheet) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnDestroy(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + afx_msg BOOL OnPageChanging(NMHDR* pNotifyStruct, LRESULT* pResult); + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif // AFX_RESIZABLESHEET_H__INCLUDED_ diff --git a/ext/ResizableLib/ResizableSheetEx.cpp b/ext/ResizableLib/ResizableSheetEx.cpp new file mode 100644 index 0000000..7acf76e --- /dev/null +++ b/ext/ResizableLib/ResizableSheetEx.cpp @@ -0,0 +1,527 @@ +// ResizableSheetEx.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableSheetEx.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableSheetEx + +IMPLEMENT_DYNAMIC(CResizableSheetEx, CPropertySheetEx) + +inline void CResizableSheetEx::PrivateConstruct() +{ + m_bEnableSaveRestore = FALSE; + m_bSavePage = FALSE; + m_dwGripTempState = 1; + m_bLayoutDone = FALSE; +} + +inline BOOL CResizableSheetEx::IsWizard() const +{ + return (m_psh.dwFlags & PSH_WIZARD); +} + +inline BOOL CResizableSheetEx::IsWizard97() const +{ + return (m_psh.dwFlags & (PSH_IE4WIZARD97 | PSH_IE5WIZARD97)); +} + +CResizableSheetEx::CResizableSheetEx() +{ + PrivateConstruct(); +} + +CResizableSheetEx::CResizableSheetEx(UINT nIDCaption, CWnd* pParentWnd, + UINT iSelectPage, HBITMAP hbmWatermark, HPALETTE hpalWatermark, + HBITMAP hbmHeader) +: CPropertySheetEx(nIDCaption, pParentWnd, iSelectPage, + hbmWatermark, hpalWatermark, hbmHeader) +{ + PrivateConstruct(); +} + +CResizableSheetEx::CResizableSheetEx(LPCTSTR pszCaption, CWnd* pParentWnd, + UINT iSelectPage, HBITMAP hbmWatermark, HPALETTE hpalWatermark, + HBITMAP hbmHeader) +: CPropertySheetEx(pszCaption, pParentWnd, iSelectPage, + hbmWatermark, hpalWatermark, hbmHeader) +{ + PrivateConstruct(); +} + + +CResizableSheetEx::~CResizableSheetEx() +{ +} + +BEGIN_MESSAGE_MAP(CResizableSheetEx, CPropertySheetEx) + //{{AFX_MSG_MAP(CResizableSheetEx) + ON_WM_GETMINMAXINFO() + ON_WM_SIZE() + ON_WM_DESTROY() + ON_WM_ERASEBKGND() + ON_WM_NCCREATE() + //}}AFX_MSG_MAP + ON_NOTIFY_REFLECT_EX(PSN_SETACTIVE, OnPageChanging) + ON_REGISTERED_MESSAGE(WMU_RESIZESUPPORT, OnResizeSupport) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableSheetEx message handlers + +BOOL CResizableSheetEx::OnNcCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (!CPropertySheetEx::OnNcCreate(lpCreateStruct)) + return FALSE; + + // child dialogs don't want resizable border or size grip, + // nor they can handle the min/max size constraints + BOOL bChild = lpCreateStruct->style & WS_CHILD; + + // create and init the size-grip + if (!CreateSizeGrip(!bChild)) + return FALSE; + + MakeResizable(lpCreateStruct); + + return TRUE; +} + +BOOL CResizableSheetEx::OnInitDialog() +{ + BOOL bResult = CPropertySheetEx::OnInitDialog(); + + // set the initial size as the min track size + CRect rc; + GetWindowRect(&rc); + SetMinTrackSize(rc.Size()); + + // initialize layout + PresetLayout(); + m_bLayoutDone = TRUE; + + return bResult; +} + +LRESULT CResizableSheetEx::OnResizeSupport(WPARAM wParam, LPARAM lParam) +{ + switch (wParam) + { + case RSZSUP_SHEETPAGEEXHACK: + { + // a window object must be still associated to the page handle + // but MFC subclassing has been turned off to allow the system + // to subclass it first, so we can catch all the messages + CWnd* pWnd = CWnd::FromHandlePermanent((HWND)lParam); + if (pWnd == NULL) + return 0; + + // suclass the window again and refresh page and sheet + pWnd->SubclassWindow(pWnd->Detach()); + RefreshLayout(); + pWnd->SendMessage(WM_SIZE); + Invalidate(); + UnlockWindowUpdate(); + + if (pWnd->IsWindowVisible()) + { + // send lost PSN_SETACTIVE notification message + CPropertyPage* pPage = DYNAMIC_DOWNCAST(CPropertyPage, pWnd); + if (pPage != NULL) + SetActivePage(pPage); + } + } + break; + + default: + return FALSE; + } + return TRUE; +} + +void CResizableSheetEx::OnDestroy() +{ + if (m_bEnableSaveRestore) + { + SaveWindowRect(m_sSection, m_bRectOnly); + if (m_bSavePage) + SavePage(m_sSection); + } + + RemoveAllAnchors(); + + CPropertySheetEx::OnDestroy(); +} + +// maps an index to a button ID and vice-versa +static UINT _propButtons[] = +{ + IDOK, IDCANCEL, ID_APPLY_NOW, IDHELP, + ID_WIZBACK, ID_WIZNEXT, ID_WIZFINISH +}; +const int _propButtonsCount = sizeof(_propButtons)/sizeof(UINT); + +// horizontal line in wizard mode +#define ID_WIZLINE ID_WIZFINISH+1 +#define ID_WIZLINEHDR ID_WIZFINISH+2 + +void CResizableSheetEx::PresetLayout() +{ + if (IsWizard() || IsWizard97()) // wizard mode + { + // hide tab control + GetTabControl()->ShowWindow(SW_HIDE); + + AddAnchor(ID_WIZLINE, BOTTOM_LEFT, BOTTOM_RIGHT); + + if (IsWizard97()) // add header line for wizard97 dialogs + AddAnchor(ID_WIZLINEHDR, TOP_LEFT, TOP_RIGHT); + } + else // tab mode + { + AddAnchor(AFX_IDC_TAB_CONTROL, TOP_LEFT, BOTTOM_RIGHT); + } + + // add a callback for active page (which can change at run-time) + m_nCallbackID = AddAnchorCallback(); + + // use *total* parent size to have correct margins + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + GetActivePage()->GetWindowRect(&rectPage); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectPage, 2); + + // pre-calculate margins + m_sizePageTL = rectPage.TopLeft() - rectSheet.TopLeft(); + m_sizePageBR = rectPage.BottomRight() - rectSheet.BottomRight(); + + // add all possible buttons, if they exist + for (int i = 0; i < _propButtonsCount; i++) + { + if (NULL != GetDlgItem(_propButtons[i])) + AddAnchor(_propButtons[i], BOTTOM_RIGHT); + } +} + +BOOL CResizableSheetEx::ArrangeLayoutCallback(LAYOUTINFO &layout) const +{ + if (layout.nCallbackID != m_nCallbackID) // we only added 1 callback + return CResizableLayout::ArrangeLayoutCallback(layout); + + // set layout info for active page + layout.hWnd = (HWND)::SendMessage(GetSafeHwnd(), PSM_GETCURRENTPAGEHWND, 0, 0); + if (!::IsWindow(layout.hWnd)) + return FALSE; + + // set margins + if (IsWizard()) // wizard mode + { + // use pre-calculated margins + layout.marginTopLeft = m_sizePageTL; + layout.marginBottomRight = m_sizePageBR; + } + else if (IsWizard97()) // wizard 97 + { + // use pre-calculated margins + layout.marginTopLeft = m_sizePageTL; + layout.marginBottomRight = m_sizePageBR; + + if (!(GetActivePage()->m_psp.dwFlags & PSP_HIDEHEADER)) + { + // add header vertical offset + CRect rectLine, rectSheet; + GetTotalClientRect(&rectSheet); + GetAnchorPosition(ID_WIZLINEHDR, rectSheet, rectLine); + + layout.marginTopLeft.cy = rectLine.bottom; + } + } + else // tab mode + { + CTabCtrl* pTab = GetTabControl(); + ASSERT(pTab != NULL); + + // get tab position after resizing and calc page rect + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage)) + return FALSE; // no page yet + + // temporarily resize the tab control to calc page size + CRect rectSave; + pTab->GetWindowRect(rectSave); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2); + pTab->SetRedraw(FALSE); + pTab->MoveWindow(rectPage, FALSE); + pTab->AdjustRect(FALSE, &rectPage); + pTab->MoveWindow(rectSave, FALSE); + pTab->SetRedraw(TRUE); + + // set margins + layout.marginTopLeft = rectPage.TopLeft() - rectSheet.TopLeft(); + layout.marginBottomRight = rectPage.BottomRight() - rectSheet.BottomRight(); + } + + // set anchor types + layout.anchorTopLeft = TOP_LEFT; + layout.anchorBottomRight = BOTTOM_RIGHT; + + // use this layout info + return TRUE; +} + +void CResizableSheetEx::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + if (nType == SIZE_MAXHIDE || nType == SIZE_MAXSHOW) + return; // arrangement not needed + + if (nType == SIZE_MAXIMIZED) + HideSizeGrip(&m_dwGripTempState); + else + ShowSizeGrip(&m_dwGripTempState); + + // update grip and layout + UpdateSizeGrip(); + ArrangeLayout(); + + if (IsWizard97()) + { + // refresh header area + CRect rect; + GetHeaderRect(rect); + InvalidateRect(rect, FALSE); + } +} + +BOOL CResizableSheetEx::OnPageChanging(NMHDR* /*pNotifyStruct*/, LRESULT* /*pResult*/) +{ + // update new wizard page + // active page changes after this notification + PostMessage(WM_SIZE); + + return FALSE; // continue routing +} + +BOOL CResizableSheetEx::OnEraseBkgnd(CDC* pDC) +{ + if (ClipChildren(pDC, FALSE)) + { + // when clipping, remove header from clipping area + if (IsWizard97()) + { + // clip header area out + CRect rect; + GetHeaderRect(rect); + pDC->ExcludeClipRect(rect); + } + } + + BOOL bRet = CPropertySheetEx::OnEraseBkgnd(pDC); + + ClipChildren(pDC, TRUE); + + return bRet; +} + +BOOL CResizableSheetEx::CalcSizeExtra(HWND /*hWndChild*/, CSize sizeChild, CSize &sizeExtra) +{ + CTabCtrl* pTab = GetTabControl(); + if (!pTab) + return FALSE; + + // get margins of tabcontrol + CRect rectMargins; + if (!GetAnchorMargins(pTab->m_hWnd, sizeChild, rectMargins)) + return FALSE; + + // get margin caused by tabcontrol + CRect rectTabMargins(0,0,0,0); + + // get tab position after resizing and calc page rect + CRect rectPage, rectSheet; + GetTotalClientRect(&rectSheet); + + if (!GetAnchorPosition(pTab->m_hWnd, rectSheet, rectPage)) + return FALSE; // no page yet + + // temporarily resize the tab control to calc page size + CRect rectSave; + pTab->GetWindowRect(rectSave); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectSave, 2); + pTab->SetRedraw(FALSE); + pTab->MoveWindow(rectPage, FALSE); + pTab->AdjustRect(TRUE, &rectTabMargins); + pTab->MoveWindow(rectSave, FALSE); + pTab->SetRedraw(TRUE); + + // add non-client size + ::AdjustWindowRectEx(&rectTabMargins, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + + // compute extra size + sizeExtra = rectMargins.TopLeft() + rectMargins.BottomRight() + + rectTabMargins.Size(); + return TRUE; +} + +void CResizableSheetEx::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + MinMaxInfo(lpMMI); + + CTabCtrl* pTab = GetTabControl(); + if (!pTab) + return; + + int nCount = GetPageCount(); + for (int idx = 0; idx < nCount; ++idx) + { + if (IsWizard()) // wizard mode + { + // use pre-calculated margins + CRect rectExtra(-CPoint(m_sizePageTL), -CPoint(m_sizePageBR)); + // add non-client size + ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + ChainMinMaxInfo(lpMMI, *GetPage(idx), rectExtra.Size()); + } + else if (IsWizard97()) // wizard 97 + { + // use pre-calculated margins + CRect rectExtra(-CPoint(m_sizePageTL), -CPoint(m_sizePageBR)); + + if (!(GetPage(idx)->m_psp.dwFlags & PSP_HIDEHEADER)) + { + // add header vertical offset + CRect rectLine, rectSheet; + GetTotalClientRect(&rectSheet); + GetAnchorPosition(ID_WIZLINEHDR, rectSheet, rectLine); + + rectExtra.top = -rectLine.bottom; + } + // add non-client size + ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + ChainMinMaxInfo(lpMMI, *GetPage(idx), rectExtra.Size()); + } + else // tab mode + { + ChainMinMaxInfoCB(lpMMI, *GetPage(idx)); + } + } +} + +// protected members + +void CResizableSheetEx::GetHeaderRect(LPRECT lpRect) +{ + CWnd* pWizLineHdr = GetDlgItem(ID_WIZLINEHDR); + if (pWizLineHdr != NULL && pWizLineHdr->IsWindowVisible()) + { + pWizLineHdr->GetWindowRect(lpRect); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)lpRect, 2); + LONG bottom = lpRect->top; + GetClientRect(lpRect); + lpRect->bottom = bottom; + } + else + ::SetRectEmpty(lpRect); +} + +int CResizableSheetEx::GetMinWidth() +{ + CWnd* pWnd = NULL; + CRect rectWnd, rectSheet; + GetTotalClientRect(&rectSheet); + + int max = 0, min = rectSheet.Width(); + // search for leftmost and rightmost button margins + for (int i = 0; i < 7; i++) + { + pWnd = GetDlgItem(_propButtons[i]); + // exclude not present or hidden buttons + if (pWnd == NULL || !(pWnd->GetStyle() & WS_VISIBLE)) + continue; + + // left position is relative to the right border + // of the parent window (negative value) + pWnd->GetWindowRect(&rectWnd); + ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rectWnd, 2); + int left = rectSheet.right - rectWnd.left; + int right = rectSheet.right - rectWnd.right; + + if (left > max) + max = left; + if (right < min) + min = right; + } + + // sizing border width + int border = GetSystemMetrics(SM_CXSIZEFRAME); + + // compute total width + return max + min + 2*border; +} + +// NOTE: this must be called after all the other settings +// to have the window and its controls displayed properly +void CResizableSheetEx::EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly, BOOL bWithPage) +{ + m_sSection = pszSection; + m_bSavePage = bWithPage; + + m_bEnableSaveRestore = TRUE; + m_bRectOnly = bRectOnly; + + // restore immediately + LoadWindowRect(pszSection, bRectOnly); + if (bWithPage) + { + LoadPage(pszSection); + ArrangeLayout(); // needs refresh + } +} + +void CResizableSheetEx::RefreshLayout() +{ + SendMessage(WM_SIZE); +} + +LRESULT CResizableSheetEx::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + if (message != WM_NCCALCSIZE || wParam == 0 || !m_bLayoutDone) + return CPropertySheetEx::WindowProc(message, wParam, lParam); + + // specifying valid rects needs controls already anchored + LRESULT lResult = 0; + HandleNcCalcSize(FALSE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + lResult = CPropertySheetEx::WindowProc(message, wParam, lParam); + HandleNcCalcSize(TRUE, (LPNCCALCSIZE_PARAMS)lParam, lResult); + return lResult; +} diff --git a/ext/ResizableLib/ResizableSheetEx.h b/ext/ResizableLib/ResizableSheetEx.h new file mode 100644 index 0000000..cbbea0d --- /dev/null +++ b/ext/ResizableLib/ResizableSheetEx.h @@ -0,0 +1,130 @@ +#if !defined(AFX_RESIZABLESHEETEX_H__INCLUDED_) +#define AFX_RESIZABLESHEETEX_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "ResizableLayout.h" +#include "ResizableGrip.h" +#include "ResizableMinMax.h" +#include "ResizableSheetState.h" + +///////////////////////////////////////////////////////////////////////////// +// ResizableSheetEx.h : header file +// + +class CResizableSheetEx : public CPropertySheetEx, public CResizableLayout, + public CResizableGrip, public CResizableMinMax, + public CResizableSheetState +{ + DECLARE_DYNAMIC(CResizableSheetEx) + +// Construction +public: + CResizableSheetEx(); + CResizableSheetEx(UINT nIDCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0, + HBITMAP hbmWatermark = NULL, HPALETTE hpalWatermark = NULL, HBITMAP hbmHeader = NULL); + CResizableSheetEx(LPCTSTR pszCaption, CWnd* pParentWnd = NULL, UINT iSelectPage = 0, + HBITMAP hbmWatermark = NULL, HPALETTE hpalWatermark = NULL, HBITMAP hbmHeader = NULL); + +// Attributes +private: + // support for temporarily hiding the grip + DWORD m_dwGripTempState; + + // flags + BOOL m_bEnableSaveRestore; + BOOL m_bRectOnly; + BOOL m_bSavePage; + + // layout vars + UINT_PTR m_nCallbackID; + CSize m_sizePageTL, m_sizePageBR; + BOOL m_bLayoutDone; + + // internal status + CString m_sSection; // section name (identifies a parent window) + +// Operations +public: + enum + { + PSH_IE4WIZARD97 = 0x00002000, + PSH_IE5WIZARD97 = 0x01000000, + }; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableSheetEx) + public: + virtual BOOL OnInitDialog(); + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizableSheetEx(); + +// used internally +private: + void PrivateConstruct(); + + BOOL IsWizard() const; + BOOL IsWizard97() const; + +// callable from derived classes +protected: + void RefreshLayout(); + void PresetLayout(); + + // section to use in app's profile + void EnableSaveRestore(LPCTSTR pszSection, BOOL bRectOnly = FALSE, + BOOL bWithPage = FALSE); + int GetMinWidth(); // minimum width to display all buttons + + + virtual CWnd* GetResizableWnd() const + { + // make the layout know its parent window + return CWnd::FromHandle(m_hWnd); + }; + +// Generated message map functions +protected: + void GetHeaderRect(LPRECT lpRect); + virtual BOOL CalcSizeExtra(HWND hWndChild, CSize sizeChild, CSize& sizeExtra); + virtual BOOL ArrangeLayoutCallback(LAYOUTINFO& layout) const; + //{{AFX_MSG(CResizableSheetEx) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnDestroy(); + afx_msg BOOL OnEraseBkgnd(CDC* pDC); + afx_msg BOOL OnNcCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + afx_msg BOOL OnPageChanging(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg LRESULT OnResizeSupport(WPARAM wParam, LPARAM lParam); + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif // AFX_RESIZABLESHEETEX_H__INCLUDED_ diff --git a/ext/ResizableLib/ResizableSheetState.cpp b/ext/ResizableLib/ResizableSheetState.cpp new file mode 100644 index 0000000..f9f28e0 --- /dev/null +++ b/ext/ResizableLib/ResizableSheetState.cpp @@ -0,0 +1,99 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableSheetState class. + */ + +#include "stdafx.h" +#include "ResizableSheetState.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizableSheetState::CResizableSheetState() +{ + +} + +CResizableSheetState::~CResizableSheetState() +{ + +} + +// used to save/restore active page +// either in the registry or a private .INI file +// depending on your application settings + +#define ACTIVEPAGE_ENT _T("ActivePage") + +/*! + * This function saves the current property sheet active page using the base + * class persist method. + * @sa CResizableState::WriteState + * + * @param pszName String that identifies stored settings + * + * @return Returns @a TRUE if successful, @a FALSE otherwise + */ +BOOL CResizableSheetState::SavePage(LPCTSTR pszName) +{ + // saves active page index, or the initial page if problems + // cannot use GetActivePage, because it always fails + + CPropertySheet* pSheet = DYNAMIC_DOWNCAST(CPropertySheet, GetResizableWnd()); + if (pSheet == NULL) + return FALSE; + + int page = pSheet->m_psh.nStartPage; + CTabCtrl *pTab = pSheet->GetTabControl(); + if (pTab != NULL) + page = pTab->GetCurSel(); + if (page < 0) + page = pSheet->m_psh.nStartPage; + + CString data, id; + _itot(page, data.GetBuffer(10), 10); + id = CString(pszName) + ACTIVEPAGE_ENT; + return WriteState(id, data); +} + +/*! + * This function loads the active page using the base class persist method. + * @sa CResizableState::ReadState + * + * @param pszName String that identifies stored settings + * + * @return Returns @a TRUE if successful, @a FALSE otherwise + */ +BOOL CResizableSheetState::LoadPage(LPCTSTR pszName) +{ + // restore active page, zero (the first) if not found + + CString data, id; + id = CString(pszName) + ACTIVEPAGE_ENT; + if (!ReadState(id, data)) + return FALSE; + + int page = _ttoi(data); + CPropertySheet* pSheet = DYNAMIC_DOWNCAST(CPropertySheet, GetResizableWnd()); + if (pSheet != NULL) + return pSheet->SetActivePage(page); + return FALSE; +} diff --git a/ext/ResizableLib/ResizableSheetState.h b/ext/ResizableLib/ResizableSheetState.h new file mode 100644 index 0000000..9f61aed --- /dev/null +++ b/ext/ResizableLib/ResizableSheetState.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableSheetState class. + */ + +#if !defined(AFX_RESIZABLESHEETSTATE_H__INCLUDED_) +#define AFX_RESIZABLESHEETSTATE_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ResizableWndState.h" + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief Persists active page in property sheets or wizard dialogs +/*! + * Derive from this class when you want to persist the active page + * in property sheets or wizard dialogs. + * This class is used in the provided resizable counterparts of + * the standard MFC property sheet classes. + */ +class CResizableSheetState : public CResizableWndState +{ +protected: + + //! @brief Load and set the active property page + BOOL LoadPage(LPCTSTR pszName); + + //! @brief Save the current active property page + BOOL SavePage(LPCTSTR pszName); + + //! @brief Override to provide the parent window + virtual CWnd* GetResizableWnd() const = 0; + +public: + CResizableSheetState(); + virtual ~CResizableSheetState(); +}; + +// @} +#endif // !defined(AFX_RESIZABLESHEETSTATE_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableSplitterWnd.cpp b/ext/ResizableLib/ResizableSplitterWnd.cpp new file mode 100644 index 0000000..4f24e12 --- /dev/null +++ b/ext/ResizableLib/ResizableSplitterWnd.cpp @@ -0,0 +1,137 @@ +// ResizableSplitterWnd.cpp : implementation file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableSplitterWnd.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CResizableSplitterWnd + +IMPLEMENT_DYNAMIC(CResizableSplitterWnd, CSplitterWnd) + +CResizableSplitterWnd::CResizableSplitterWnd() +{ +} + +CResizableSplitterWnd::~CResizableSplitterWnd() +{ +} + +BEGIN_MESSAGE_MAP(CResizableSplitterWnd, CSplitterWnd) + //{{AFX_MSG_MAP(CResizableSplitterWnd) + ON_WM_GETMINMAXINFO() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CResizableSplitterWnd message handlers + +void CResizableSplitterWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) +{ + if ((GetStyle() & SPLS_DYNAMIC_SPLIT) && + GetRowCount() == 1 && GetColumnCount() == 1) + { + CWnd* pPane = GetActivePane(); + if (pPane != NULL) + { + // get the extra size from child to parent + CRect rectClient, rectWnd; + GetWindowRect(rectWnd); + pPane->GetWindowRect(rectClient); + CSize sizeExtra = rectWnd.Size() - rectClient.Size(); + + ChainMinMaxInfo(lpMMI, pPane->m_hWnd, sizeExtra); + } + } + else if (!(GetStyle() & SPLS_DYNAMIC_SPLIT)) + { + ASSERT(m_nCols > 0 && m_nRows > 0); + + CSize sizeMin(0,0), sizeMax(0,0); + for (int col = 0; col < m_nCols; ++col) + { + // calc min and max width for each column + int min = 0; + int max = LONG_MAX; + for (int row = 0; row < m_nRows; ++row) + { + CWnd* pWnd = GetPane(row, col); + // ask the child window for track size + MINMAXINFO mmiChild = *lpMMI; + mmiChild.ptMinTrackSize.x = 0; + mmiChild.ptMaxTrackSize.x = LONG_MAX; + ::SendMessage(pWnd->GetSafeHwnd(), WM_GETMINMAXINFO, 0, (LPARAM)&mmiChild); + max = __min(max, mmiChild.ptMaxTrackSize.x); + min = __max(min, mmiChild.ptMinTrackSize.x); + } + // sum all column widths + if (sizeMax.cx == LONG_MAX || max == LONG_MAX) + sizeMax.cx = LONG_MAX; + else + sizeMax.cx += max + m_cxSplitterGap; + sizeMin.cx += min + m_cxSplitterGap; + } + for (int row = 0; row < m_nRows; ++row) + { + // calc min and max height for each row + int min = 0; + int max = LONG_MAX; + for (int col = 0; col < m_nCols; ++col) + { + CWnd* pWnd = GetPane(row, col); + // ask the child window for track size + MINMAXINFO mmiChild = *lpMMI; + mmiChild.ptMinTrackSize.y = 0; + mmiChild.ptMaxTrackSize.y = LONG_MAX; + ::SendMessage(pWnd->GetSafeHwnd(), WM_GETMINMAXINFO, 0, (LPARAM)&mmiChild); + max = __min(max, mmiChild.ptMaxTrackSize.y); + min = __max(min, mmiChild.ptMinTrackSize.y); + } + // sum all row heights + if (sizeMax.cy == LONG_MAX || max == LONG_MAX) + sizeMax.cy = LONG_MAX; + else + sizeMax.cy += max + m_cySplitterGap; + sizeMin.cy += min + m_cySplitterGap; + } + // adjust total size: add the client border and + // we counted one splitter more than necessary + sizeMax.cx += 2*m_cxBorder - m_cxSplitterGap; + sizeMax.cy += 2*m_cyBorder - m_cySplitterGap; + sizeMin.cx += 2*m_cxBorder - m_cxSplitterGap; + sizeMin.cy += 2*m_cyBorder - m_cySplitterGap; + // add non-client size + CRect rectExtra(0,0,0,0); + ::AdjustWindowRectEx(&rectExtra, GetStyle(), !(GetStyle() & WS_CHILD) && + ::IsMenu(GetMenu()->GetSafeHmenu()), GetExStyle()); + sizeMax += rectExtra.Size(); + sizeMin += rectExtra.Size(); + // set minmax info + lpMMI->ptMinTrackSize.x = __max(lpMMI->ptMinTrackSize.x, sizeMin.cx); + lpMMI->ptMinTrackSize.y = __max(lpMMI->ptMinTrackSize.y, sizeMin.cy); + lpMMI->ptMaxTrackSize.x = __min(lpMMI->ptMaxTrackSize.x, sizeMax.cx); + lpMMI->ptMaxTrackSize.y = __min(lpMMI->ptMaxTrackSize.y, sizeMax.cy); + } +} diff --git a/ext/ResizableLib/ResizableSplitterWnd.h b/ext/ResizableLib/ResizableSplitterWnd.h new file mode 100644 index 0000000..6d33947 --- /dev/null +++ b/ext/ResizableLib/ResizableSplitterWnd.h @@ -0,0 +1,68 @@ +// ResizableSplitterWnd.h : header file +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZABLESPLITTERWND_H__INCLUDED_) +#define AFX_RESIZABLESPLITTERWND_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ResizableMinMax.h" + +///////////////////////////////////////////////////////////////////////////// +// CResizableSplitterWnd frame with splitter + +class CResizableSplitterWnd : public CSplitterWnd, public CResizableMinMax +{ + DECLARE_DYNAMIC(CResizableSplitterWnd) + +// Construction +public: + CResizableSplitterWnd(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CResizableSplitterWnd) + protected: + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CResizableSplitterWnd(); + + // Generated message map functions + //{{AFX_MSG(CResizableSplitterWnd) + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLESPLITTERWND_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableState.cpp b/ext/ResizableLib/ResizableState.cpp new file mode 100644 index 0000000..90faa58 --- /dev/null +++ b/ext/ResizableLib/ResizableState.cpp @@ -0,0 +1,135 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableState class. + */ + +#include "stdafx.h" +#include "ResizableState.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizableState::CResizableState() +{ + m_sStorePath = m_sDefaultStorePath; +} + +CResizableState::~CResizableState() +{ + +} + +// static intializer must be called before user code +#pragma warning(disable:4073) +#pragma init_seg(lib) +CString CResizableState::m_sDefaultStorePath(_T("ResizableState")); + +/*! + * Static function to set the default path used to store state information. + * This path is used to initialize all the instances of this class. + * @sa GetDefaultStateStore GetStateStore SetStateStore + * + * @param szPath String that specifies the new path to be set + */ +void CResizableState::SetDefaultStateStore(LPCTSTR szPath) +{ + m_sDefaultStorePath = szPath; +} + +/*! + * Static function to retrieve the default path used to store state + * information. + * This path is used to initialize all the instances of this class. + * @sa SetDefaultStateStore GetStateStore SetStateStore + * + * @return The return value is a string that specifies the current path + */ +LPCTSTR CResizableState::GetDefaultStateStore() +{ + return m_sDefaultStorePath; +} + +/*! + * This function sets the path used to store state information by + * the current instance of the class. + * @sa GetStateStore GetDefaultStateStore SetDefaultStateStore + * + * @param szPath String that specifies the new path to be set + */ +void CResizableState::SetStateStore(LPCTSTR szPath) +{ + m_sStorePath = szPath; +} + +/*! + * This function retrieves the path used to store state information by + * the current instance of the class. + * @sa SetStateStore GetDefaultStateStore SetDefaultStateStore + * + * @return The return value is a string that specifies the current path + */ +LPCTSTR CResizableState::GetStateStore() +{ + return m_sStorePath; +} + +/*! + * This function writes state information and associates it with some + * identification text for later retrieval. + * The base implementation uses the application profile to persist state + * information, but this function can be overridden to implement + * different methods. + * + * @param szId String that identifies the stored settings + * @param szState String that represents the state information to store + * + * @return The return value is @a TRUE if settings have been successfully + * stored, @a FALSE otherwise. + */ +BOOL CResizableState::WriteState(LPCTSTR szId, LPCTSTR szState) +{ + return AfxGetApp()->WriteProfileString(GetStateStore(), szId, szState); +} + +/*! + * This function reads state information previously associated with some + * identification text. + * The base implementation uses the application profile to persist state + * information, but this function can be overridden to implement + * different methods. + * + * @param szId String that identifies the stored settings + * @param rsState String to be filled with the retrieved state information + * + * @return The return value is @a TRUE if settings have been successfully + * retrieved, @a FALSE otherwise. + */ +BOOL CResizableState::ReadState(LPCTSTR szId, CString &rsState) +{ + rsState = AfxGetApp()->GetProfileString(GetStateStore(), szId); + return !rsState.IsEmpty(); +} diff --git a/ext/ResizableLib/ResizableState.h b/ext/ResizableLib/ResizableState.h new file mode 100644 index 0000000..161a17a --- /dev/null +++ b/ext/ResizableLib/ResizableState.h @@ -0,0 +1,77 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableState class. + */ + +#if !defined(AFX_RESIZABLESTATE_H__INCLUDED_) +#define AFX_RESIZABLESTATE_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief Provides basic persisting capabilities +/*! + * Derive from this class to persist user interface settings, or anything + * suitable. The base implementation uses the application profile, which can + * be set to either the Registry or an INI File. Other storing methods + * can be implemented in derived classes. + */ +class CResizableState +{ + static CString m_sDefaultStorePath; + CString m_sStorePath; + +protected: + + //! @brief Get default path where state is stored + static LPCTSTR GetDefaultStateStore(); + + //! @brief Set default path where state is stored + static void SetDefaultStateStore(LPCTSTR szPath); + + //! @brief Get current path where state is stored + LPCTSTR GetStateStore(); + + //! @brief Set current path where state is stored + void SetStateStore(LPCTSTR szPath); + + //! @name Overridables + //@{ + + //! @brief Read state information + virtual BOOL ReadState(LPCTSTR szId, CString& rsState); + + //! @brief Write state information + virtual BOOL WriteState(LPCTSTR szId, LPCTSTR szState); + + //@} + +public: + CResizableState(); + virtual ~CResizableState(); +}; + +// @} +#endif // !defined(AFX_RESIZABLESTATE_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableVersion.cpp b/ext/ResizableLib/ResizableVersion.cpp new file mode 100644 index 0000000..68846ef --- /dev/null +++ b/ext/ResizableLib/ResizableVersion.cpp @@ -0,0 +1,190 @@ +// ResizableVersion.cpp: implementation of the CResizableVersion class. +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" +#include "ResizableVersion.h" + +////////////////////////////////////////////////////////////////////// +// Static initializer object (with macros to hide in ClassView) + +// static intializer must be called before user code +#pragma warning(disable:4073) +#pragma init_seg(lib) + +#ifdef _UNDEFINED_ +#define BEGIN_HIDDEN { +#define END_HIDDEN } +#else +#define BEGIN_HIDDEN +#define END_HIDDEN +#endif + +BEGIN_HIDDEN +struct _VersionInitializer +{ + _VersionInitializer() + { + InitRealVersions(); + }; +}; +END_HIDDEN + +// The one and only version-check object +static _VersionInitializer g_version; + +////////////////////////////////////////////////////////////////////// +// Private implementation + +// DLL Version support +#include + +static DLLVERSIONINFO g_dviCommCtrls; +static OSVERSIONINFOEX g_osviWindows; + +static void CheckOsVersion() +{ + // Try calling GetVersionEx using the OSVERSIONINFOEX structure. + SecureZeroMemory(&g_osviWindows, sizeof(OSVERSIONINFOEX)); + g_osviWindows.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if (GetVersionEx((LPOSVERSIONINFO)&g_osviWindows)) + return; + + // If that fails, try using the OSVERSIONINFO structure. + g_osviWindows.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + if (GetVersionEx((LPOSVERSIONINFO)&g_osviWindows)) + return; + + // When all the above fails, set values for the worst case + g_osviWindows.dwMajorVersion = 4; + g_osviWindows.dwMinorVersion = 0; + g_osviWindows.dwBuildNumber = 0; + g_osviWindows.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS; + g_osviWindows.szCSDVersion[0] = TEXT('\0'); +} + +static void CheckCommCtrlsVersion() +{ + // Check Common Controls version + SecureZeroMemory(&g_dviCommCtrls, sizeof(DLLVERSIONINFO)); + HMODULE hMod = ::LoadLibrary(_T("comctl32.dll")); + if (hMod != NULL) + { + // Get the version function + DLLGETVERSIONPROC pfnDllGetVersion; + pfnDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hMod, "DllGetVersion"); + + if (pfnDllGetVersion != NULL) + { + // Obtain version information + g_dviCommCtrls.cbSize = sizeof(DLLVERSIONINFO); + if (SUCCEEDED(pfnDllGetVersion(&g_dviCommCtrls))) + { + ::FreeLibrary(hMod); + return; + } + } + + ::FreeLibrary(hMod); + } + + // Set values for the worst case + g_dviCommCtrls.dwMajorVersion = 4; + g_dviCommCtrls.dwMinorVersion = 0; + g_dviCommCtrls.dwBuildNumber = 0; + g_dviCommCtrls.dwPlatformID = DLLVER_PLATFORM_WINDOWS; +} + + +////////////////////////////////////////////////////////////////////// +// Exported global symbols + +DWORD realWINVER = 0; + +#ifdef _WIN32_WINDOWS +DWORD real_WIN32_WINDOWS = 0; +#endif + +#ifdef _WIN32_WINNT +DWORD real_WIN32_WINNT = 0; +#endif + +#ifdef _WIN32_IE +DWORD real_WIN32_IE = 0; +#endif + +// macro to convert version numbers to hex format +#define CNV_OS_VER(x) ((BYTE)(((BYTE)(x) / 10 * 16) | ((BYTE)(x) % 10))) + +void InitRealVersions() +{ + CheckCommCtrlsVersion(); + CheckOsVersion(); + + // set real version values + + realWINVER = MAKEWORD(CNV_OS_VER(g_osviWindows.dwMinorVersion), + CNV_OS_VER(g_osviWindows.dwMajorVersion)); + +#ifdef _WIN32_WINDOWS + if (g_osviWindows.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + real_WIN32_WINDOWS = realWINVER; + else + real_WIN32_WINDOWS = 0; +#endif + +#ifdef _WIN32_WINNT + if (g_osviWindows.dwPlatformId == VER_PLATFORM_WIN32_NT) + real_WIN32_WINNT = realWINVER; + else + real_WIN32_WINNT = 0; +#endif + +#ifdef _WIN32_IE + switch (g_dviCommCtrls.dwMajorVersion) + { + case 4: + switch (g_dviCommCtrls.dwMinorVersion) + { + case 70: + real_WIN32_IE = 0x0300; + break; + case 71: + real_WIN32_IE = 0x0400; + break; + case 72: + real_WIN32_IE = 0x0401; + break; + default: + real_WIN32_IE = 0x0200; + } + break; + case 5: + if (g_dviCommCtrls.dwMinorVersion > 80) + real_WIN32_IE = 0x0501; + else + real_WIN32_IE = 0x0500; + break; + case 6: + real_WIN32_IE = 0x0600; // includes checks for 0x0560 (IE6) + break; + default: + real_WIN32_IE = 0; + } +#endif +} diff --git a/ext/ResizableLib/ResizableVersion.h b/ext/ResizableLib/ResizableVersion.h new file mode 100644 index 0000000..fbb2f9b --- /dev/null +++ b/ext/ResizableLib/ResizableVersion.h @@ -0,0 +1,52 @@ +// ResizableVersion.h: interface for the CResizableVersion class. +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZABLEVERSION_H__INCLUDED_) +#define AFX_RESIZABLEVERSION_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// global variables that hold actual version numbers +// retrieved and adapted at run-time to be equivalent +// to preprocessor macros that set the target platform + +extern DWORD realWINVER; + +#ifdef _WIN32_WINDOWS +extern DWORD real_WIN32_WINDOWS; +#endif + +#ifdef _WIN32_WINNT +extern DWORD real_WIN32_WINNT; +#endif + +#ifdef _WIN32_IE +extern DWORD real_WIN32_IE; +#endif + +// called automatically by a static initializer +// (if not appropriate can be called later) +// to setup global version numbers + +void InitRealVersions(); + + +#endif // !defined(AFX_RESIZABLEVERSION_H__INCLUDED_) diff --git a/ext/ResizableLib/ResizableWndState.cpp b/ext/ResizableLib/ResizableWndState.cpp new file mode 100644 index 0000000..18caf1a --- /dev/null +++ b/ext/ResizableLib/ResizableWndState.cpp @@ -0,0 +1,137 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004,2008 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Implementation of the CResizableWndState class. + */ + +#include "stdafx.h" +#include "ResizableWndState.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CResizableWndState::CResizableWndState() +{ + +} + +CResizableWndState::~CResizableWndState() +{ + +} + +// used to save/restore window's size and position +// either in the registry or a private .INI file +// depending on your application settings + +#define PLACEMENT_ENT _T("WindowPlacement") +#define PLACEMENT_FMT _T("%d,%d,%d,%d,%d,%d,%d,%d") + +/*! + * This function saves the current window position and size using the base + * class persist method. Minimized and maximized state is also optionally + * preserved. + * @sa CResizableState::WriteState + * @note Window coordinates are in the form used by the system functions + * GetWindowPlacement and SetWindowPlacement. + * + * @param pszName String that identifies stored settings + * @param bRectOnly Flag that specifies wether to ignore min/max state + * + * @return Returns @a TRUE if successful, @a FALSE otherwise + */ +BOOL CResizableWndState::SaveWindowRect(LPCTSTR pszName, BOOL bRectOnly) +{ + CString data, id; + WINDOWPLACEMENT wp; + + SecureZeroMemory(&wp, sizeof(WINDOWPLACEMENT)); + wp.length = sizeof(WINDOWPLACEMENT); + if (!GetResizableWnd()->GetWindowPlacement(&wp)) + return FALSE; + + // use workspace coordinates + RECT& rc = wp.rcNormalPosition; + + if (bRectOnly) // save size/pos only (normal state) + { + data.Format(PLACEMENT_FMT, rc.left, rc.top, + rc.right, rc.bottom, SW_SHOWNORMAL, 0, 0, 0); + } + else // save also min/max state + { + data.Format(PLACEMENT_FMT, rc.left, rc.top, + rc.right, rc.bottom, wp.showCmd, wp.flags, + wp.ptMinPosition.x, wp.ptMinPosition.y); + } + + id = CString(pszName) + PLACEMENT_ENT; + return WriteState(id, data); +} + +/*! + * This function loads and set the current window position and size using + * the base class persist method. Minimized and maximized state is also + * optionally preserved. + * @sa CResizableState::WriteState + * @note Window coordinates are in the form used by the system functions + * GetWindowPlacement and SetWindowPlacement. + * + * @param pszName String that identifies stored settings + * @param bRectOnly Flag that specifies wether to ignore min/max state + * + * @return Returns @a TRUE if successful, @a FALSE otherwise + */ +BOOL CResizableWndState::LoadWindowRect(LPCTSTR pszName, BOOL bRectOnly) +{ + CString data, id; + WINDOWPLACEMENT wp; + + id = CString(pszName) + PLACEMENT_ENT; + if (!ReadState(id, data)) // never saved before + return FALSE; + + SecureZeroMemory(&wp, sizeof(WINDOWPLACEMENT)); + wp.length = sizeof(WINDOWPLACEMENT); + if (!GetResizableWnd()->GetWindowPlacement(&wp)) + return FALSE; + + // use workspace coordinates + RECT& rc = wp.rcNormalPosition; + + if (_stscanf(data, PLACEMENT_FMT, &rc.left, &rc.top, + &rc.right, &rc.bottom, &wp.showCmd, &wp.flags, + &wp.ptMinPosition.x, &wp.ptMinPosition.y) == 8) + { + if (bRectOnly) // restore size/pos only + { + wp.showCmd = SW_SHOWNORMAL; + wp.flags = 0; + return GetResizableWnd()->SetWindowPlacement(&wp); + } + else // restore also max state + { + if (wp.showCmd == SW_SHOWMINIMIZED) + wp.showCmd = SW_SHOWNORMAL; + return GetResizableWnd()->SetWindowPlacement(&wp); + } + } + return FALSE; +} diff --git a/ext/ResizableLib/ResizableWndState.h b/ext/ResizableLib/ResizableWndState.h new file mode 100644 index 0000000..1f87d26 --- /dev/null +++ b/ext/ResizableLib/ResizableWndState.h @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +/*! + * @file + * @brief Interface for the CResizableWndState class. + */ + +#if !defined(AFX_RESIZABLEWNDSTATE_H__INCLUDED_) +#define AFX_RESIZABLEWNDSTATE_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "ResizableState.h" + +/*! @addtogroup CoreComponents + * @{ + */ + +//! @brief Persists window position, size and state +/*! + * Derive from this class when you want to persist the size, position and + * minimized/maximized state of top level windows. + * This class is used in the provided resizable counterparts of + * the standard MFC window and dialog classes. + */ +class CResizableWndState : public CResizableState +{ +protected: + + //! @brief Load and set the window position and size + BOOL LoadWindowRect(LPCTSTR pszName, BOOL bRectOnly); + + //! @brief Save the current window position and size + BOOL SaveWindowRect(LPCTSTR pszName, BOOL bRectOnly); + + //! @brief Override to provide the parent window + virtual CWnd* GetResizableWnd() const = 0; + +public: + CResizableWndState(); + virtual ~CResizableWndState(); +}; + +// @} +#endif // !defined(AFX_RESIZABLEWNDSTATE_H__INCLUDED_) diff --git a/ext/ResizableLib/StdAfx.cpp b/ext/ResizableLib/StdAfx.cpp new file mode 100644 index 0000000..e634be5 --- /dev/null +++ b/ext/ResizableLib/StdAfx.cpp @@ -0,0 +1,6 @@ +// stdafx.cpp : source file that includes just the standard includes +// ResizableLib.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + diff --git a/ext/ResizableLib/StdAfx.h b/ext/ResizableLib/StdAfx.h new file mode 100644 index 0000000..62f5a9c --- /dev/null +++ b/ext/ResizableLib/StdAfx.h @@ -0,0 +1,75 @@ +// stdafx.h : include file for standard system include files, or project +// specific include files that are used frequently, but are changed infrequently +// +///////////////////////////////////////////////////////////////////////////// +// +// This file is part of ResizableLib +// http://sourceforge.net/projects/resizablelib +// +// Copyright (C) 2000-2004 by Paolo Messina +// http://www.geocities.com/ppescher - mailto:ppescher@hotmail.com +// +// The contents of this file are subject to the Artistic License (the "License"). +// You may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// http://www.opensource.org/licenses/artistic-license.html +// +// If you find this code useful, credits would be nice! +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_RESIZABLESTDAFX_H__INCLUDED_) +#define AFX_RESIZABLESTDAFX_H__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// Set max target Windows platform +#define WINVER 0x0501 +#define _WIN32_WINNT 0x0501 + +// Use target Common Controls version for compatibility +// with CPropertyPageEx, CPropertySheetEx +#define _WIN32_IE 0x0500 + +// let us be spared from a flood of deprecation warnings. +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#define _CRT_SECURE_NO_DEPRECATE 1 +#define _SECURE_SCL_DEPRECATE 0 +#define _HAS_ITERATOR_DEBUGGING 0 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC support for Windows Common Controls +#include +#include +#include + +#ifndef WS_EX_LAYOUTRTL +#pragma message("Please update your Windows header files, get the latest SDK") +#pragma message("WinUser.h is out of date!") + +#define WS_EX_LAYOUTRTL 0x00400000 +#endif + +#ifndef WC_BUTTON +#pragma message("Please update your Windows header files, get the latest SDK") +#pragma message("CommCtrl.h is out of date!") + +#define WC_BUTTON TEXT("Button") +#define WC_STATIC TEXT("Static") +#define WC_EDIT TEXT("Edit") +#define WC_LISTBOX TEXT("ListBox") +#define WC_COMBOBOX TEXT("ComboBox") +#define WC_SCROLLBAR TEXT("ScrollBar") +#endif + +#define RSZLIB_NO_XP_DOUBLE_BUFFER + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_RESIZABLESTDAFX_H__INCLUDED_)