diff src/win32/ResizeDlg.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/ResizeDlg.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,609 @@
     1.4 +/*----------------------------------------------------------------------
     1.5 +   Copyright (c)  Gipsysoft. All Rights Reserved.
     1.6 +   File:   DialogSizer_Set.cpp
     1.7 +   Web site: http://gipsysoft.com
     1.8 +
     1.9 +   This software is provided 'as-is', without any express or implied warranty.
    1.10 +
    1.11 +   In no event will the author be held liable for any damages arising from the
    1.12 +   use of this software.
    1.13 +
    1.14 +   Permission is granted to anyone to use this software for any purpose, including
    1.15 +   commercial applications, and to alter it and redistribute it freely, subject
    1.16 +   to the following restrictions:
    1.17 +
    1.18 +   1) The origin of this software must not be misrepresented; you must not claim
    1.19 +   that you wrote the original software. If you use this software in a product,
    1.20 +   an acknowledgment in the product documentation is requested but not required.
    1.21 +   2) Altered source versions must be plainly marked as such, and must not be
    1.22 +   misrepresented as being the original software. Altered source is encouraged
    1.23 +   to be submitted back to the original author so it can be shared with the
    1.24 +   community. Please share your changes.
    1.25 +   3) This notice may not be removed or altered from any source distribution.
    1.26 +
    1.27 +   Owner:  russf@gipsysoft.com
    1.28 +   Purpose:        Main functionality for sizeable dialogs
    1.29 +
    1.30 +   Store a local copy of the user settings
    1.31 +   Subclass the window
    1.32 +   Respond to various messages withinn the subclassed window.
    1.33 +
    1.34 +   ----------------------------------------------------------------------*/
    1.35 +// modified by the VBA-rr Team
    1.36 +
    1.37 +#include "stdafx.h"
    1.38 +#include "ResizeDlg.h"
    1.39 +#include "VBA.h"
    1.40 +#include "Sound.h"
    1.41 +#include "WinHelper.h"
    1.42 +
    1.43 +IMPLEMENT_DYNAMIC(ResizeDlg, CDialog)
    1.44 +
    1.45 +// moved functions to this file to reduce number of files
    1.46 +
    1.47 +struct RegistryData
    1.48 +{
    1.49 +	WINDOWPLACEMENT m_wpl;
    1.50 +};
    1.51 +
    1.52 +struct DialogData       //      dd
    1.53 +{
    1.54 +	HKEY    hkRootSave;
    1.55 +	LPCTSTR pcszName;
    1.56 +
    1.57 +	//
    1.58 +	//    The number of items contained in the psd member.
    1.59 +	//    Used in the DeferWindowPos structure and in allocating memory
    1.60 +	int nItemCount;
    1.61 +	DialogSizerSizingItem *psd;
    1.62 +
    1.63 +	//
    1.64 +	//    We need the smallest to respond to the WM_GETMINMAXINFO message
    1.65 +	POINT m_ptSmallest;
    1.66 +
    1.67 +	//
    1.68 +	//    We don't strictly speaking need to say how big the biggest can be but
    1.69 +	POINT m_ptLargest;
    1.70 +	bool  m_bLargestSet;
    1.71 +
    1.72 +	//
    1.73 +	//    we need this to decide how much the window has changed size when we get a WM_SIZE message
    1.74 +	SIZE m_sizeClient;
    1.75 +
    1.76 +	//
    1.77 +	//    Draw the sizing grip...or not
    1.78 +	bool m_bMaximised;
    1.79 +	BOOL m_bShowSizingGrip;
    1.80 +
    1.81 +	WinHelper::CRect m_rcGrip;
    1.82 +};
    1.83 +
    1.84 +extern bool regEnabled;
    1.85 +extern const char *regGetINIPath();
    1.86 +
    1.87 +void AssertFailed(char *file, int line, char *exp)
    1.88 +{
    1.89 +	char buffer[1024];
    1.90 +
    1.91 +	sprintf(buffer, "File %s\nLine %d\nExpression %s\nPress Retry to debug",
    1.92 +	        file, line, exp);
    1.93 +	systemSoundClearBuffer();
    1.94 +	int res = MessageBox(*theApp.m_pMainWnd, buffer, "Assertion failed!",
    1.95 +	                     MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL |
    1.96 +	                     MB_ABORTRETRYIGNORE);
    1.97 +
    1.98 +	if (res == IDRETRY)
    1.99 +	{
   1.100 +		__asm int 3;
   1.101 +	}
   1.102 +	else if (res == IDABORT)
   1.103 +		SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
   1.104 +}
   1.105 +
   1.106 +void ApiFailure(char *pcszFilename, int nLine, char *pcszExpression)
   1.107 +{
   1.108 +	const DWORD dwLastError = ::GetLastError();
   1.109 +	LPCTSTR     lpMsgBuf;
   1.110 +	(void)::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
   1.111 +	                      FORMAT_MESSAGE_FROM_SYSTEM |
   1.112 +	                      FORMAT_MESSAGE_IGNORE_INSERTS,
   1.113 +	                      NULL, dwLastError,
   1.114 +	                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
   1.115 +	                      (LPTSTR) &lpMsgBuf, 0, NULL);
   1.116 +
   1.117 +	char szExeName[ MAX_PATH ];
   1.118 +
   1.119 +	if (!GetModuleFileName(NULL, szExeName, countof(szExeName)))
   1.120 +		strcpy(szExeName, "<No Program Name>");
   1.121 +
   1.122 +	char szMessage[ 1024 ];
   1.123 +	_snprintf(szMessage, countof(szMessage),
   1.124 +	          "API VERIFY Failure!"
   1.125 +	          "\nProgram: %s"
   1.126 +	          "\n"
   1.127 +	          "\nFile %s"
   1.128 +	          "\nLine %d"
   1.129 +	          "\n"
   1.130 +	          "\nExpression %s"
   1.131 +	          "\n"
   1.132 +	          "\nLast Error %d"
   1.133 +	          "\n           %s"
   1.134 +	          "\n\nPress Retry to debug the application",
   1.135 +	          szExeName,
   1.136 +	          pcszFilename,
   1.137 +	          nLine,
   1.138 +	          pcszExpression,
   1.139 +	          dwLastError,
   1.140 +	          lpMsgBuf
   1.141 +	          );
   1.142 +
   1.143 +	(void)LocalFree((LPVOID)lpMsgBuf);
   1.144 +	HWND hwndParent = ::GetActiveWindow();
   1.145 +	hwndParent = ::GetLastActivePopup(hwndParent);
   1.146 +	systemSoundClearBuffer();
   1.147 +	int nCode = ::MessageBoxA(hwndParent,
   1.148 +	                          szMessage,
   1.149 +	                          "Debug Helper",
   1.150 +	                          MB_TASKMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE |
   1.151 +	                          MB_SETFOREGROUND);
   1.152 +	if (nCode == IDABORT)
   1.153 +	{
   1.154 +		::SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0);
   1.155 +	}
   1.156 +	else if (nCode == IDRETRY)
   1.157 +		__asm int 3;
   1.158 +}
   1.159 +
   1.160 +long FASTCALL RegQueryValueExRecursive(HKEY hKey,
   1.161 +                                       LPCTSTR lpValueName,
   1.162 +                                       LPDWORD lpReserved,
   1.163 +                                       LPDWORD lpType,
   1.164 +                                       LPBYTE lpData,
   1.165 +                                       LPDWORD lpcbData)
   1.166 +{
   1.167 +	TCHAR szBuffer[ 256 ];
   1.168 +	R_ASSERT(lstrlen(lpValueName) < countof(szBuffer));
   1.169 +	(void)lstrcpy(szBuffer, lpValueName);
   1.170 +
   1.171 +	LPTSTR pszBuffer = szBuffer;
   1.172 +	LPTSTR pszLast   = szBuffer;
   1.173 +	while (*pszBuffer)
   1.174 +	{
   1.175 +		if (*pszBuffer == _T('\\') || *pszBuffer == _T('/'))
   1.176 +		{
   1.177 +			pszLast     = pszBuffer;
   1.178 +			lpValueName = pszLast + 1;
   1.179 +		}
   1.180 +		pszBuffer++;
   1.181 +	}
   1.182 +
   1.183 +	if (!regEnabled)
   1.184 +	{
   1.185 +		if (GetPrivateProfileStruct("Viewer",
   1.186 +		                            lpValueName,
   1.187 +		                            lpData,
   1.188 +		                            *lpcbData,
   1.189 +		                            regGetINIPath()))
   1.190 +		{
   1.191 +			*lpType = REG_BINARY;
   1.192 +			return ERROR_SUCCESS;
   1.193 +		}
   1.194 +		return -1;
   1.195 +	}
   1.196 +
   1.197 +	bool m_bNeedToCloseKey = false;
   1.198 +	if (pszLast != szBuffer)
   1.199 +	{
   1.200 +		*pszLast = _T('\000');
   1.201 +		HKEY hkeyTemp;
   1.202 +		long lRet = RegOpenKey(hKey, szBuffer, &hkeyTemp);
   1.203 +		if (lRet != ERROR_SUCCESS)
   1.204 +		{
   1.205 +			return lRet;
   1.206 +		}
   1.207 +		hKey = hkeyTemp;
   1.208 +		m_bNeedToCloseKey = true;
   1.209 +	}
   1.210 +
   1.211 +	long lRet = RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
   1.212 +	if (m_bNeedToCloseKey)
   1.213 +	{
   1.214 +		R_VERIFY(RegCloseKey(hKey) == ERROR_SUCCESS);
   1.215 +	}
   1.216 +	return lRet;
   1.217 +}
   1.218 +
   1.219 +long FASTCALL RegSetValueExRecursive(HKEY hKey,
   1.220 +                                     LPCTSTR lpValueName,
   1.221 +                                     DWORD Reserved,
   1.222 +                                     DWORD dwType,
   1.223 +                                     CONST BYTE*lpData,
   1.224 +                                     DWORD cbData)
   1.225 +{
   1.226 +	TCHAR szBuffer[ 256 ];
   1.227 +	R_ASSERT(lstrlen(lpValueName) < countof(szBuffer));
   1.228 +	(void)lstrcpy(szBuffer, lpValueName);
   1.229 +
   1.230 +	LPTSTR pszBuffer = szBuffer;
   1.231 +	LPTSTR pszLast   = szBuffer;
   1.232 +	while (*pszBuffer)
   1.233 +	{
   1.234 +		if (*pszBuffer == _T('\\') || *pszBuffer == _T('/'))
   1.235 +		{
   1.236 +			pszLast     = pszBuffer;
   1.237 +			lpValueName = pszLast + 1;
   1.238 +		}
   1.239 +		pszBuffer++;
   1.240 +	}
   1.241 +
   1.242 +	if (!regEnabled)
   1.243 +	{
   1.244 +		if (WritePrivateProfileStruct("Viewer",
   1.245 +		                              lpValueName,
   1.246 +		                              (LPVOID)lpData,
   1.247 +		                              cbData,
   1.248 +		                              regGetINIPath()))
   1.249 +		{
   1.250 +			return ERROR_SUCCESS;
   1.251 +		}
   1.252 +		return -1;
   1.253 +	}
   1.254 +
   1.255 +	bool m_bNeedToCloseKey = false;
   1.256 +	if (pszLast != szBuffer)
   1.257 +	{
   1.258 +		*pszLast = _T('\000');
   1.259 +		HKEY hkeyTemp;
   1.260 +		long lRet = RegOpenKey(hKey, szBuffer, &hkeyTemp);
   1.261 +		if (lRet != ERROR_SUCCESS)
   1.262 +		{
   1.263 +			lRet = RegCreateKey(hKey, szBuffer, &hkeyTemp);
   1.264 +			if (lRet != ERROR_SUCCESS)
   1.265 +				return lRet;
   1.266 +		}
   1.267 +		hKey = hkeyTemp;
   1.268 +		m_bNeedToCloseKey = true;
   1.269 +	}
   1.270 +
   1.271 +	long lRet = RegSetValueEx(hKey, lpValueName, Reserved, dwType, lpData, cbData);
   1.272 +	if (m_bNeedToCloseKey)
   1.273 +	{
   1.274 +		R_VERIFY(RegCloseKey(hKey) == ERROR_SUCCESS);
   1.275 +	}
   1.276 +	return lRet;
   1.277 +}
   1.278 +
   1.279 +int ResizeDlgGetItemCount(const DialogSizerSizingItem *psd)
   1.280 +{
   1.281 +	R_ASSERT(psd);
   1.282 +	int nCount = 0;
   1.283 +	while (psd->uSizeInfo != 0xFFFFFFFF)
   1.284 +	{
   1.285 +		nCount++;
   1.286 +		psd++;
   1.287 +	}
   1.288 +	return nCount;
   1.289 +}
   1.290 +
   1.291 +void ResizeDlgUpdateGripperRect(const int cx, const int cy, WinHelper::CRect &rcGrip)
   1.292 +{
   1.293 +	const int nGripWidth  = GetSystemMetrics(SM_CYVSCROLL);
   1.294 +	const int nGripHeight = GetSystemMetrics(SM_CXVSCROLL);
   1.295 +	rcGrip.left   = cx - nGripWidth;
   1.296 +	rcGrip.top    = cy - nGripHeight;
   1.297 +	rcGrip.right  = cx;
   1.298 +	rcGrip.bottom = cy;
   1.299 +}
   1.300 +
   1.301 +void ResizeDlgUpdateGripper(HWND hwnd, DialogData *pdd)
   1.302 +{
   1.303 +	if (pdd->m_bShowSizingGrip)
   1.304 +	{
   1.305 +		WinHelper::CRect rcOld(pdd->m_rcGrip);
   1.306 +
   1.307 +		ResizeDlgUpdateGripperRect(pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip);
   1.308 +
   1.309 +		//
   1.310 +		//        We also need to invalidate the combined area of the old and new rectangles
   1.311 +		//        otherwise we would have trail of grippers when we sized the dialog larger
   1.312 +		//        in any axis
   1.313 +		(void)UnionRect(&rcOld, &rcOld, &pdd->m_rcGrip);
   1.314 +		(void)InvalidateRect(hwnd, &rcOld, TRUE);
   1.315 +	}
   1.316 +}
   1.317 +
   1.318 +void ResizeDlgCopyItems(DialogSizerSizingItem *psdDest, const DialogSizerSizingItem *psdSource)
   1.319 +//
   1.320 +//    Will copy all of the items in psdSource into psdDest.
   1.321 +{
   1.322 +	//
   1.323 +	//    Loop til we reach the end
   1.324 +	while (psdSource->uSizeInfo != 0xFFFFFFFF)
   1.325 +	{
   1.326 +		*psdDest = *psdSource;
   1.327 +		psdDest++;
   1.328 +		psdSource++;
   1.329 +	}
   1.330 +	//    And when we do copy the last item
   1.331 +	*psdDest = *psdSource;
   1.332 +}
   1.333 +
   1.334 +ResizeDlg::ResizeDlg(UINT id, CWnd *parent)
   1.335 +	: CDialog(id, parent)
   1.336 +{
   1.337 +	dd = NULL;
   1.338 +}
   1.339 +
   1.340 +void *ResizeDlg::AddDialogData()
   1.341 +//
   1.342 +//    Firstly determine if the data already exists, if it does then return that, if not then we will
   1.343 +//    create and initialise a brand new structure.
   1.344 +{
   1.345 +	DialogData *pdd = (DialogData *)dd;
   1.346 +	if (!pdd)
   1.347 +	{
   1.348 +		pdd = (DialogData *)calloc(1, sizeof(DialogData));
   1.349 +	}
   1.350 +
   1.351 +	if (pdd)
   1.352 +	{
   1.353 +		//
   1.354 +		//  Store some sizes etc. for later.
   1.355 +		CRect rc;
   1.356 +		GetWindowRect(rc);
   1.357 +		pdd->m_ptSmallest.x = rc.Width();
   1.358 +		pdd->m_ptSmallest.y = rc.Height();
   1.359 +
   1.360 +		GetClientRect(rc);
   1.361 +		pdd->m_sizeClient = rc.Size();
   1.362 +		dd = pdd;
   1.363 +		ResizeDlgUpdateGripperRect(pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip);
   1.364 +	}
   1.365 +	return pdd;
   1.366 +}
   1.367 +
   1.368 +BOOL ResizeDlg::SetData(const DialogSizerSizingItem *psd,
   1.369 +                        BOOL bShowSizingGrip,
   1.370 +                        HKEY hkRootSave,
   1.371 +                        LPCTSTR pcszName,
   1.372 +                        SIZE *psizeMax)
   1.373 +//
   1.374 +//    Setting a dialog sizeable involves subclassing the window and handling it's
   1.375 +//    WM_SIZE messages, if we have a hkRootSave and pcszName then we will also be loading/saving
   1.376 +//    the size and position of the window from the registry. We load from the registry when we
   1.377 +//    subclass the window and we save to the registry when we get a WM_DESTROY.
   1.378 +//
   1.379 +//    It will return non-zero for success and zero if it fails
   1.380 +{
   1.381 +	R_ASSERT(psd);
   1.382 +	R_ASSERT((hkRootSave != NULL && pcszName != NULL)
   1.383 +	         || (hkRootSave == NULL && pcszName == NULL));
   1.384 +	//
   1.385 +	//    Make sure all of the parameters are valid.
   1.386 +	if (::IsWindow(*this)
   1.387 +	    && psd
   1.388 +	    && ((hkRootSave != NULL && pcszName != NULL &&
   1.389 +	         !IsBadStringPtr(pcszName, 0xFFFF)) ||
   1.390 +	        (hkRootSave == NULL && pcszName == NULL))
   1.391 +	    && (psizeMax == NULL || !IsBadReadPtr(psizeMax, sizeof(SIZE)))
   1.392 +	    )
   1.393 +	{
   1.394 +		DialogData *pdd = (DialogData *)AddDialogData();
   1.395 +		if (pdd)
   1.396 +		{
   1.397 +			pdd->hkRootSave        = hkRootSave;
   1.398 +			pdd->pcszName          = pcszName;
   1.399 +			pdd->m_bShowSizingGrip = bShowSizingGrip;
   1.400 +			pdd->nItemCount        = ResizeDlgGetItemCount(psd) + 1;
   1.401 +			pdd->psd = (DialogSizerSizingItem *)
   1.402 +			           calloc(pdd->nItemCount,
   1.403 +			                  sizeof(DialogSizerSizingItem));
   1.404 +			if (pdd->psd)
   1.405 +			{
   1.406 +				//
   1.407 +				//      Copy all of the user controls etc. for later, this way the user can quite happily
   1.408 +				//      let the structure go out of scope.
   1.409 +				ResizeDlgCopyItems(pdd->psd, psd);
   1.410 +				if (psizeMax)
   1.411 +				{
   1.412 +					pdd->m_ptLargest.x = psizeMax->cx;
   1.413 +					pdd->m_ptLargest.y = psizeMax->cy;
   1.414 +					pdd->m_bLargestSet = true;
   1.415 +				}
   1.416 +
   1.417 +				//
   1.418 +				//      If the there was save info passed in then we need to make damn good use of it
   1.419 +				//      by attempting to load the RegistryData structure
   1.420 +				if (hkRootSave && pcszName)
   1.421 +				{
   1.422 +					RegistryData rd;
   1.423 +					DWORD        dwSize = sizeof(RegistryData);
   1.424 +					DWORD        dwType = REG_BINARY;
   1.425 +					if (RegQueryValueExRecursive(hkRootSave, pcszName, NULL, &dwType, reinterpret_cast<LPBYTE>(&rd),
   1.426 +					                             &dwSize) == ERROR_SUCCESS && dwSize == sizeof(rd))
   1.427 +					{
   1.428 +						if (!(GetWindowLong(*this, GWL_STYLE) & WS_VISIBLE))
   1.429 +							rd.m_wpl.showCmd = SW_HIDE;
   1.430 +
   1.431 +						VAPI(SetWindowPlacement(&rd.m_wpl));
   1.432 +					}
   1.433 +				}
   1.434 +				return TRUE;
   1.435 +			}
   1.436 +			else
   1.437 +			{
   1.438 +				free(pdd);
   1.439 +			}
   1.440 +		}
   1.441 +	}
   1.442 +	return FALSE;
   1.443 +}
   1.444 +
   1.445 +void ResizeDlg::UpdateWindowSize(const int cx, const int cy, HWND hwnd)
   1.446 +{
   1.447 +	DialogData *pdd = (DialogData *)dd;
   1.448 +	if (pdd)
   1.449 +	{
   1.450 +		const int nDeltaX = cx - pdd->m_sizeClient.cx;
   1.451 +		const int nDeltaY = cy - pdd->m_sizeClient.cy;
   1.452 +		WinHelper::CDeferWindowPos def(pdd->nItemCount);
   1.453 +		WinHelper::CRect rc;
   1.454 +		const DialogSizerSizingItem *psd = pdd->psd;
   1.455 +		while (psd->uSizeInfo != 0xFFFFFFFF)
   1.456 +		{
   1.457 +			HWND hwndChild = ::GetDlgItem(*this, psd->uControlID);
   1.458 +			if (::IsWindow(hwndChild))
   1.459 +			{
   1.460 +				VAPI(::GetWindowRect(hwndChild, rc));
   1.461 +				(void)::MapWindowPoints(::GetDesktopWindow(),  hwnd,
   1.462 +				                        (LPPOINT)&rc, 2);
   1.463 +
   1.464 +				//
   1.465 +				//      Adjust the window horizontally
   1.466 +				if (psd->uSizeInfo & DS_MoveX)
   1.467 +				{
   1.468 +					rc.left  += nDeltaX;
   1.469 +					rc.right += nDeltaX;
   1.470 +				}
   1.471 +
   1.472 +				//
   1.473 +				//      Adjust the window vertically
   1.474 +				if (psd->uSizeInfo & DS_MoveY)
   1.475 +				{
   1.476 +					rc.top    += nDeltaY;
   1.477 +					rc.bottom += nDeltaY;
   1.478 +				}
   1.479 +
   1.480 +				//
   1.481 +				//      Size the window horizontally
   1.482 +				if (psd->uSizeInfo & DS_SizeX)
   1.483 +				{
   1.484 +					rc.right += nDeltaX;
   1.485 +				}
   1.486 +
   1.487 +				//
   1.488 +				//      Size the window vertically
   1.489 +				if (psd->uSizeInfo & DS_SizeY)
   1.490 +				{
   1.491 +					rc.bottom += nDeltaY;
   1.492 +				}
   1.493 +
   1.494 +				(void)def.DeferWindowPos(hwndChild, NULL, rc,
   1.495 +				                         SWP_NOACTIVATE | SWP_NOZORDER);
   1.496 +			}
   1.497 +			psd++;
   1.498 +		}
   1.499 +
   1.500 +		pdd->m_sizeClient.cx = cx;
   1.501 +		pdd->m_sizeClient.cy = cy;
   1.502 +
   1.503 +		//
   1.504 +		//  If we have a sizing grip enabled then adjust it's position
   1.505 +		ResizeDlgUpdateGripper(hwnd, pdd);
   1.506 +	}
   1.507 +}
   1.508 +
   1.509 +BOOL ResizeDlg::OnWndMsg(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *res)
   1.510 +//    Actual window procedure that will handle saving window size/position and moving
   1.511 +//    the controls whilst the window sizes.
   1.512 +{
   1.513 +	if (dd == NULL)
   1.514 +	{
   1.515 +		return CDialog::OnWndMsg(msg, wParam, lParam, res);
   1.516 +	}
   1.517 +	switch (msg)
   1.518 +	{
   1.519 +	case WM_ERASEBKGND:
   1.520 +	{
   1.521 +		BOOL        r   = CDialog::OnWndMsg(msg, wParam, lParam, res);
   1.522 +		DialogData *pdd = (DialogData *)dd;
   1.523 +		if (pdd && pdd->m_bShowSizingGrip && !pdd->m_bMaximised)
   1.524 +		{
   1.525 +			VAPI(::DrawFrameControl(reinterpret_cast<HDC>(wParam),
   1.526 +			                        pdd->m_rcGrip,
   1.527 +			                        DFC_SCROLL, DFCS_SCROLLSIZEGRIP));
   1.528 +		}
   1.529 +		return r;
   1.530 +	}
   1.531 +	case WM_SIZE:
   1.532 +	{
   1.533 +		DialogData *pdd = (DialogData *)dd;
   1.534 +		if (pdd && wParam != SIZE_MINIMIZED)
   1.535 +		{
   1.536 +			pdd->m_bMaximised = (wParam == SIZE_MAXIMIZED ? true : false);
   1.537 +			UpdateWindowSize(LOWORD(lParam), HIWORD(lParam), *this);
   1.538 +		}
   1.539 +		break;
   1.540 +	}
   1.541 +	case WM_NCHITTEST:
   1.542 +	{
   1.543 +		//
   1.544 +		//        If the gripper is enabled then perform a simple hit test on our gripper area.
   1.545 +		DialogData *pdd = (DialogData *)dd;
   1.546 +		if (pdd && pdd->m_bShowSizingGrip)
   1.547 +		{
   1.548 +			POINT pt = { LOWORD(lParam), HIWORD(lParam) };
   1.549 +			(void)ScreenToClient(&pt);
   1.550 +			if (PtInRect(pdd->m_rcGrip, pt))
   1.551 +				return (BOOL)HTBOTTOMRIGHT;
   1.552 +		}
   1.553 +		break;
   1.554 +	}
   1.555 +	case WM_GETMINMAXINFO:
   1.556 +	{
   1.557 +		//
   1.558 +		//        Our opportunity to say that we do not want the dialog to grow or shrink any more.
   1.559 +		DialogData * pdd   = (DialogData *)dd;
   1.560 +		LPMINMAXINFO lpmmi = reinterpret_cast<LPMINMAXINFO>(lParam);
   1.561 +		lpmmi->ptMinTrackSize = pdd->m_ptSmallest;
   1.562 +		if (pdd->m_bLargestSet)
   1.563 +		{
   1.564 +			lpmmi->ptMaxTrackSize = pdd->m_ptLargest;
   1.565 +		}
   1.566 +	}
   1.567 +		return (BOOL)0;
   1.568 +	case WM_NOTIFY:
   1.569 +	{
   1.570 +		if (reinterpret_cast<LPNMHDR>(lParam)->code == PSN_SETACTIVE)
   1.571 +		{
   1.572 +			CRect rc;
   1.573 +			VAPI(::GetClientRect(*GetParent(), &rc));
   1.574 +			UpdateWindowSize(rc.Width(), rc.Height(), *GetParent());
   1.575 +		}
   1.576 +		break;
   1.577 +	}
   1.578 +	case WM_DESTROY:
   1.579 +	{
   1.580 +		//
   1.581 +		//        Our opportunty for cleanup.
   1.582 +		//        Simply acquire all of our objects, free the appropriate memory and remove the
   1.583 +		//        properties from the window. If we do not remove the properties then they will constitute
   1.584 +		//        a resource leak.
   1.585 +		DialogData *pdd = (DialogData *)dd;
   1.586 +		if (pdd)
   1.587 +		{
   1.588 +			RegistryData rd;
   1.589 +			rd.m_wpl.length = sizeof(rd.m_wpl);
   1.590 +			VAPI(GetWindowPlacement(&rd.m_wpl));
   1.591 +
   1.592 +			if (pdd->hkRootSave && pdd->pcszName)
   1.593 +			{
   1.594 +				(void)RegSetValueExRecursive(pdd->hkRootSave, pdd->pcszName,
   1.595 +				                             NULL, REG_BINARY,
   1.596 +				                             reinterpret_cast<LPBYTE>(&rd),
   1.597 +				                             sizeof(rd));
   1.598 +			}
   1.599 +
   1.600 +			if (pdd->psd)
   1.601 +			{
   1.602 +				free(pdd->psd);
   1.603 +			}
   1.604 +			free(pdd);
   1.605 +		}
   1.606 +
   1.607 +		break;
   1.608 +	}
   1.609 +	}
   1.610 +	return CDialog::OnWndMsg(msg, wParam, lParam, res);
   1.611 +}
   1.612 +