Mercurial > vba-linux
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 +