rlm@1: /*---------------------------------------------------------------------- rlm@1: Copyright (c) Gipsysoft. All Rights Reserved. rlm@1: File: DialogSizer_Set.cpp rlm@1: Web site: http://gipsysoft.com rlm@1: rlm@1: This software is provided 'as-is', without any express or implied warranty. rlm@1: rlm@1: In no event will the author be held liable for any damages arising from the rlm@1: use of this software. rlm@1: rlm@1: Permission is granted to anyone to use this software for any purpose, including rlm@1: commercial applications, and to alter it and redistribute it freely, subject rlm@1: to the following restrictions: rlm@1: rlm@1: 1) The origin of this software must not be misrepresented; you must not claim rlm@1: that you wrote the original software. If you use this software in a product, rlm@1: an acknowledgment in the product documentation is requested but not required. rlm@1: 2) Altered source versions must be plainly marked as such, and must not be rlm@1: misrepresented as being the original software. Altered source is encouraged rlm@1: to be submitted back to the original author so it can be shared with the rlm@1: community. Please share your changes. rlm@1: 3) This notice may not be removed or altered from any source distribution. rlm@1: rlm@1: Owner: russf@gipsysoft.com rlm@1: Purpose: Main functionality for sizeable dialogs rlm@1: rlm@1: Store a local copy of the user settings rlm@1: Subclass the window rlm@1: Respond to various messages withinn the subclassed window. rlm@1: rlm@1: ----------------------------------------------------------------------*/ rlm@1: // modified by the VBA-rr Team rlm@1: rlm@1: #include "stdafx.h" rlm@1: #include "ResizeDlg.h" rlm@1: #include "VBA.h" rlm@1: #include "Sound.h" rlm@1: #include "WinHelper.h" rlm@1: rlm@1: IMPLEMENT_DYNAMIC(ResizeDlg, CDialog) rlm@1: rlm@1: // moved functions to this file to reduce number of files rlm@1: rlm@1: struct RegistryData rlm@1: { rlm@1: WINDOWPLACEMENT m_wpl; rlm@1: }; rlm@1: rlm@1: struct DialogData // dd rlm@1: { rlm@1: HKEY hkRootSave; rlm@1: LPCTSTR pcszName; rlm@1: rlm@1: // rlm@1: // The number of items contained in the psd member. rlm@1: // Used in the DeferWindowPos structure and in allocating memory rlm@1: int nItemCount; rlm@1: DialogSizerSizingItem *psd; rlm@1: rlm@1: // rlm@1: // We need the smallest to respond to the WM_GETMINMAXINFO message rlm@1: POINT m_ptSmallest; rlm@1: rlm@1: // rlm@1: // We don't strictly speaking need to say how big the biggest can be but rlm@1: POINT m_ptLargest; rlm@1: bool m_bLargestSet; rlm@1: rlm@1: // rlm@1: // we need this to decide how much the window has changed size when we get a WM_SIZE message rlm@1: SIZE m_sizeClient; rlm@1: rlm@1: // rlm@1: // Draw the sizing grip...or not rlm@1: bool m_bMaximised; rlm@1: BOOL m_bShowSizingGrip; rlm@1: rlm@1: WinHelper::CRect m_rcGrip; rlm@1: }; rlm@1: rlm@1: extern bool regEnabled; rlm@1: extern const char *regGetINIPath(); rlm@1: rlm@1: void AssertFailed(char *file, int line, char *exp) rlm@1: { rlm@1: char buffer[1024]; rlm@1: rlm@1: sprintf(buffer, "File %s\nLine %d\nExpression %s\nPress Retry to debug", rlm@1: file, line, exp); rlm@1: systemSoundClearBuffer(); rlm@1: int res = MessageBox(*theApp.m_pMainWnd, buffer, "Assertion failed!", rlm@1: MB_ICONHAND | MB_SETFOREGROUND | MB_TASKMODAL | rlm@1: MB_ABORTRETRYIGNORE); rlm@1: rlm@1: if (res == IDRETRY) rlm@1: { rlm@1: __asm int 3; rlm@1: } rlm@1: else if (res == IDABORT) rlm@1: SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0); rlm@1: } rlm@1: rlm@1: void ApiFailure(char *pcszFilename, int nLine, char *pcszExpression) rlm@1: { rlm@1: const DWORD dwLastError = ::GetLastError(); rlm@1: LPCTSTR lpMsgBuf; rlm@1: (void)::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | rlm@1: FORMAT_MESSAGE_FROM_SYSTEM | rlm@1: FORMAT_MESSAGE_IGNORE_INSERTS, rlm@1: NULL, dwLastError, rlm@1: MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), rlm@1: (LPTSTR) &lpMsgBuf, 0, NULL); rlm@1: rlm@1: char szExeName[ MAX_PATH ]; rlm@1: rlm@1: if (!GetModuleFileName(NULL, szExeName, countof(szExeName))) rlm@1: strcpy(szExeName, ""); rlm@1: rlm@1: char szMessage[ 1024 ]; rlm@1: _snprintf(szMessage, countof(szMessage), rlm@1: "API VERIFY Failure!" rlm@1: "\nProgram: %s" rlm@1: "\n" rlm@1: "\nFile %s" rlm@1: "\nLine %d" rlm@1: "\n" rlm@1: "\nExpression %s" rlm@1: "\n" rlm@1: "\nLast Error %d" rlm@1: "\n %s" rlm@1: "\n\nPress Retry to debug the application", rlm@1: szExeName, rlm@1: pcszFilename, rlm@1: nLine, rlm@1: pcszExpression, rlm@1: dwLastError, rlm@1: lpMsgBuf rlm@1: ); rlm@1: rlm@1: (void)LocalFree((LPVOID)lpMsgBuf); rlm@1: HWND hwndParent = ::GetActiveWindow(); rlm@1: hwndParent = ::GetLastActivePopup(hwndParent); rlm@1: systemSoundClearBuffer(); rlm@1: int nCode = ::MessageBoxA(hwndParent, rlm@1: szMessage, rlm@1: "Debug Helper", rlm@1: MB_TASKMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE | rlm@1: MB_SETFOREGROUND); rlm@1: if (nCode == IDABORT) rlm@1: { rlm@1: ::SendMessage(*theApp.m_pMainWnd, WM_QUIT, 0, 0); rlm@1: } rlm@1: else if (nCode == IDRETRY) rlm@1: __asm int 3; rlm@1: } rlm@1: rlm@1: long FASTCALL RegQueryValueExRecursive(HKEY hKey, rlm@1: LPCTSTR lpValueName, rlm@1: LPDWORD lpReserved, rlm@1: LPDWORD lpType, rlm@1: LPBYTE lpData, rlm@1: LPDWORD lpcbData) rlm@1: { rlm@1: TCHAR szBuffer[ 256 ]; rlm@1: R_ASSERT(lstrlen(lpValueName) < countof(szBuffer)); rlm@1: (void)lstrcpy(szBuffer, lpValueName); rlm@1: rlm@1: LPTSTR pszBuffer = szBuffer; rlm@1: LPTSTR pszLast = szBuffer; rlm@1: while (*pszBuffer) rlm@1: { rlm@1: if (*pszBuffer == _T('\\') || *pszBuffer == _T('/')) rlm@1: { rlm@1: pszLast = pszBuffer; rlm@1: lpValueName = pszLast + 1; rlm@1: } rlm@1: pszBuffer++; rlm@1: } rlm@1: rlm@1: if (!regEnabled) rlm@1: { rlm@1: if (GetPrivateProfileStruct("Viewer", rlm@1: lpValueName, rlm@1: lpData, rlm@1: *lpcbData, rlm@1: regGetINIPath())) rlm@1: { rlm@1: *lpType = REG_BINARY; rlm@1: return ERROR_SUCCESS; rlm@1: } rlm@1: return -1; rlm@1: } rlm@1: rlm@1: bool m_bNeedToCloseKey = false; rlm@1: if (pszLast != szBuffer) rlm@1: { rlm@1: *pszLast = _T('\000'); rlm@1: HKEY hkeyTemp; rlm@1: long lRet = RegOpenKey(hKey, szBuffer, &hkeyTemp); rlm@1: if (lRet != ERROR_SUCCESS) rlm@1: { rlm@1: return lRet; rlm@1: } rlm@1: hKey = hkeyTemp; rlm@1: m_bNeedToCloseKey = true; rlm@1: } rlm@1: rlm@1: long lRet = RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData); rlm@1: if (m_bNeedToCloseKey) rlm@1: { rlm@1: R_VERIFY(RegCloseKey(hKey) == ERROR_SUCCESS); rlm@1: } rlm@1: return lRet; rlm@1: } rlm@1: rlm@1: long FASTCALL RegSetValueExRecursive(HKEY hKey, rlm@1: LPCTSTR lpValueName, rlm@1: DWORD Reserved, rlm@1: DWORD dwType, rlm@1: CONST BYTE*lpData, rlm@1: DWORD cbData) rlm@1: { rlm@1: TCHAR szBuffer[ 256 ]; rlm@1: R_ASSERT(lstrlen(lpValueName) < countof(szBuffer)); rlm@1: (void)lstrcpy(szBuffer, lpValueName); rlm@1: rlm@1: LPTSTR pszBuffer = szBuffer; rlm@1: LPTSTR pszLast = szBuffer; rlm@1: while (*pszBuffer) rlm@1: { rlm@1: if (*pszBuffer == _T('\\') || *pszBuffer == _T('/')) rlm@1: { rlm@1: pszLast = pszBuffer; rlm@1: lpValueName = pszLast + 1; rlm@1: } rlm@1: pszBuffer++; rlm@1: } rlm@1: rlm@1: if (!regEnabled) rlm@1: { rlm@1: if (WritePrivateProfileStruct("Viewer", rlm@1: lpValueName, rlm@1: (LPVOID)lpData, rlm@1: cbData, rlm@1: regGetINIPath())) rlm@1: { rlm@1: return ERROR_SUCCESS; rlm@1: } rlm@1: return -1; rlm@1: } rlm@1: rlm@1: bool m_bNeedToCloseKey = false; rlm@1: if (pszLast != szBuffer) rlm@1: { rlm@1: *pszLast = _T('\000'); rlm@1: HKEY hkeyTemp; rlm@1: long lRet = RegOpenKey(hKey, szBuffer, &hkeyTemp); rlm@1: if (lRet != ERROR_SUCCESS) rlm@1: { rlm@1: lRet = RegCreateKey(hKey, szBuffer, &hkeyTemp); rlm@1: if (lRet != ERROR_SUCCESS) rlm@1: return lRet; rlm@1: } rlm@1: hKey = hkeyTemp; rlm@1: m_bNeedToCloseKey = true; rlm@1: } rlm@1: rlm@1: long lRet = RegSetValueEx(hKey, lpValueName, Reserved, dwType, lpData, cbData); rlm@1: if (m_bNeedToCloseKey) rlm@1: { rlm@1: R_VERIFY(RegCloseKey(hKey) == ERROR_SUCCESS); rlm@1: } rlm@1: return lRet; rlm@1: } rlm@1: rlm@1: int ResizeDlgGetItemCount(const DialogSizerSizingItem *psd) rlm@1: { rlm@1: R_ASSERT(psd); rlm@1: int nCount = 0; rlm@1: while (psd->uSizeInfo != 0xFFFFFFFF) rlm@1: { rlm@1: nCount++; rlm@1: psd++; rlm@1: } rlm@1: return nCount; rlm@1: } rlm@1: rlm@1: void ResizeDlgUpdateGripperRect(const int cx, const int cy, WinHelper::CRect &rcGrip) rlm@1: { rlm@1: const int nGripWidth = GetSystemMetrics(SM_CYVSCROLL); rlm@1: const int nGripHeight = GetSystemMetrics(SM_CXVSCROLL); rlm@1: rcGrip.left = cx - nGripWidth; rlm@1: rcGrip.top = cy - nGripHeight; rlm@1: rcGrip.right = cx; rlm@1: rcGrip.bottom = cy; rlm@1: } rlm@1: rlm@1: void ResizeDlgUpdateGripper(HWND hwnd, DialogData *pdd) rlm@1: { rlm@1: if (pdd->m_bShowSizingGrip) rlm@1: { rlm@1: WinHelper::CRect rcOld(pdd->m_rcGrip); rlm@1: rlm@1: ResizeDlgUpdateGripperRect(pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip); rlm@1: rlm@1: // rlm@1: // We also need to invalidate the combined area of the old and new rectangles rlm@1: // otherwise we would have trail of grippers when we sized the dialog larger rlm@1: // in any axis rlm@1: (void)UnionRect(&rcOld, &rcOld, &pdd->m_rcGrip); rlm@1: (void)InvalidateRect(hwnd, &rcOld, TRUE); rlm@1: } rlm@1: } rlm@1: rlm@1: void ResizeDlgCopyItems(DialogSizerSizingItem *psdDest, const DialogSizerSizingItem *psdSource) rlm@1: // rlm@1: // Will copy all of the items in psdSource into psdDest. rlm@1: { rlm@1: // rlm@1: // Loop til we reach the end rlm@1: while (psdSource->uSizeInfo != 0xFFFFFFFF) rlm@1: { rlm@1: *psdDest = *psdSource; rlm@1: psdDest++; rlm@1: psdSource++; rlm@1: } rlm@1: // And when we do copy the last item rlm@1: *psdDest = *psdSource; rlm@1: } rlm@1: rlm@1: ResizeDlg::ResizeDlg(UINT id, CWnd *parent) rlm@1: : CDialog(id, parent) rlm@1: { rlm@1: dd = NULL; rlm@1: } rlm@1: rlm@1: void *ResizeDlg::AddDialogData() rlm@1: // rlm@1: // Firstly determine if the data already exists, if it does then return that, if not then we will rlm@1: // create and initialise a brand new structure. rlm@1: { rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (!pdd) rlm@1: { rlm@1: pdd = (DialogData *)calloc(1, sizeof(DialogData)); rlm@1: } rlm@1: rlm@1: if (pdd) rlm@1: { rlm@1: // rlm@1: // Store some sizes etc. for later. rlm@1: CRect rc; rlm@1: GetWindowRect(rc); rlm@1: pdd->m_ptSmallest.x = rc.Width(); rlm@1: pdd->m_ptSmallest.y = rc.Height(); rlm@1: rlm@1: GetClientRect(rc); rlm@1: pdd->m_sizeClient = rc.Size(); rlm@1: dd = pdd; rlm@1: ResizeDlgUpdateGripperRect(pdd->m_sizeClient.cx, pdd->m_sizeClient.cy, pdd->m_rcGrip); rlm@1: } rlm@1: return pdd; rlm@1: } rlm@1: rlm@1: BOOL ResizeDlg::SetData(const DialogSizerSizingItem *psd, rlm@1: BOOL bShowSizingGrip, rlm@1: HKEY hkRootSave, rlm@1: LPCTSTR pcszName, rlm@1: SIZE *psizeMax) rlm@1: // rlm@1: // Setting a dialog sizeable involves subclassing the window and handling it's rlm@1: // WM_SIZE messages, if we have a hkRootSave and pcszName then we will also be loading/saving rlm@1: // the size and position of the window from the registry. We load from the registry when we rlm@1: // subclass the window and we save to the registry when we get a WM_DESTROY. rlm@1: // rlm@1: // It will return non-zero for success and zero if it fails rlm@1: { rlm@1: R_ASSERT(psd); rlm@1: R_ASSERT((hkRootSave != NULL && pcszName != NULL) rlm@1: || (hkRootSave == NULL && pcszName == NULL)); rlm@1: // rlm@1: // Make sure all of the parameters are valid. rlm@1: if (::IsWindow(*this) rlm@1: && psd rlm@1: && ((hkRootSave != NULL && pcszName != NULL && rlm@1: !IsBadStringPtr(pcszName, 0xFFFF)) || rlm@1: (hkRootSave == NULL && pcszName == NULL)) rlm@1: && (psizeMax == NULL || !IsBadReadPtr(psizeMax, sizeof(SIZE))) rlm@1: ) rlm@1: { rlm@1: DialogData *pdd = (DialogData *)AddDialogData(); rlm@1: if (pdd) rlm@1: { rlm@1: pdd->hkRootSave = hkRootSave; rlm@1: pdd->pcszName = pcszName; rlm@1: pdd->m_bShowSizingGrip = bShowSizingGrip; rlm@1: pdd->nItemCount = ResizeDlgGetItemCount(psd) + 1; rlm@1: pdd->psd = (DialogSizerSizingItem *) rlm@1: calloc(pdd->nItemCount, rlm@1: sizeof(DialogSizerSizingItem)); rlm@1: if (pdd->psd) rlm@1: { rlm@1: // rlm@1: // Copy all of the user controls etc. for later, this way the user can quite happily rlm@1: // let the structure go out of scope. rlm@1: ResizeDlgCopyItems(pdd->psd, psd); rlm@1: if (psizeMax) rlm@1: { rlm@1: pdd->m_ptLargest.x = psizeMax->cx; rlm@1: pdd->m_ptLargest.y = psizeMax->cy; rlm@1: pdd->m_bLargestSet = true; rlm@1: } rlm@1: rlm@1: // rlm@1: // If the there was save info passed in then we need to make damn good use of it rlm@1: // by attempting to load the RegistryData structure rlm@1: if (hkRootSave && pcszName) rlm@1: { rlm@1: RegistryData rd; rlm@1: DWORD dwSize = sizeof(RegistryData); rlm@1: DWORD dwType = REG_BINARY; rlm@1: if (RegQueryValueExRecursive(hkRootSave, pcszName, NULL, &dwType, reinterpret_cast(&rd), rlm@1: &dwSize) == ERROR_SUCCESS && dwSize == sizeof(rd)) rlm@1: { rlm@1: if (!(GetWindowLong(*this, GWL_STYLE) & WS_VISIBLE)) rlm@1: rd.m_wpl.showCmd = SW_HIDE; rlm@1: rlm@1: VAPI(SetWindowPlacement(&rd.m_wpl)); rlm@1: } rlm@1: } rlm@1: return TRUE; rlm@1: } rlm@1: else rlm@1: { rlm@1: free(pdd); rlm@1: } rlm@1: } rlm@1: } rlm@1: return FALSE; rlm@1: } rlm@1: rlm@1: void ResizeDlg::UpdateWindowSize(const int cx, const int cy, HWND hwnd) rlm@1: { rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (pdd) rlm@1: { rlm@1: const int nDeltaX = cx - pdd->m_sizeClient.cx; rlm@1: const int nDeltaY = cy - pdd->m_sizeClient.cy; rlm@1: WinHelper::CDeferWindowPos def(pdd->nItemCount); rlm@1: WinHelper::CRect rc; rlm@1: const DialogSizerSizingItem *psd = pdd->psd; rlm@1: while (psd->uSizeInfo != 0xFFFFFFFF) rlm@1: { rlm@1: HWND hwndChild = ::GetDlgItem(*this, psd->uControlID); rlm@1: if (::IsWindow(hwndChild)) rlm@1: { rlm@1: VAPI(::GetWindowRect(hwndChild, rc)); rlm@1: (void)::MapWindowPoints(::GetDesktopWindow(), hwnd, rlm@1: (LPPOINT)&rc, 2); rlm@1: rlm@1: // rlm@1: // Adjust the window horizontally rlm@1: if (psd->uSizeInfo & DS_MoveX) rlm@1: { rlm@1: rc.left += nDeltaX; rlm@1: rc.right += nDeltaX; rlm@1: } rlm@1: rlm@1: // rlm@1: // Adjust the window vertically rlm@1: if (psd->uSizeInfo & DS_MoveY) rlm@1: { rlm@1: rc.top += nDeltaY; rlm@1: rc.bottom += nDeltaY; rlm@1: } rlm@1: rlm@1: // rlm@1: // Size the window horizontally rlm@1: if (psd->uSizeInfo & DS_SizeX) rlm@1: { rlm@1: rc.right += nDeltaX; rlm@1: } rlm@1: rlm@1: // rlm@1: // Size the window vertically rlm@1: if (psd->uSizeInfo & DS_SizeY) rlm@1: { rlm@1: rc.bottom += nDeltaY; rlm@1: } rlm@1: rlm@1: (void)def.DeferWindowPos(hwndChild, NULL, rc, rlm@1: SWP_NOACTIVATE | SWP_NOZORDER); rlm@1: } rlm@1: psd++; rlm@1: } rlm@1: rlm@1: pdd->m_sizeClient.cx = cx; rlm@1: pdd->m_sizeClient.cy = cy; rlm@1: rlm@1: // rlm@1: // If we have a sizing grip enabled then adjust it's position rlm@1: ResizeDlgUpdateGripper(hwnd, pdd); rlm@1: } rlm@1: } rlm@1: rlm@1: BOOL ResizeDlg::OnWndMsg(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *res) rlm@1: // Actual window procedure that will handle saving window size/position and moving rlm@1: // the controls whilst the window sizes. rlm@1: { rlm@1: if (dd == NULL) rlm@1: { rlm@1: return CDialog::OnWndMsg(msg, wParam, lParam, res); rlm@1: } rlm@1: switch (msg) rlm@1: { rlm@1: case WM_ERASEBKGND: rlm@1: { rlm@1: BOOL r = CDialog::OnWndMsg(msg, wParam, lParam, res); rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (pdd && pdd->m_bShowSizingGrip && !pdd->m_bMaximised) rlm@1: { rlm@1: VAPI(::DrawFrameControl(reinterpret_cast(wParam), rlm@1: pdd->m_rcGrip, rlm@1: DFC_SCROLL, DFCS_SCROLLSIZEGRIP)); rlm@1: } rlm@1: return r; rlm@1: } rlm@1: case WM_SIZE: rlm@1: { rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (pdd && wParam != SIZE_MINIMIZED) rlm@1: { rlm@1: pdd->m_bMaximised = (wParam == SIZE_MAXIMIZED ? true : false); rlm@1: UpdateWindowSize(LOWORD(lParam), HIWORD(lParam), *this); rlm@1: } rlm@1: break; rlm@1: } rlm@1: case WM_NCHITTEST: rlm@1: { rlm@1: // rlm@1: // If the gripper is enabled then perform a simple hit test on our gripper area. rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (pdd && pdd->m_bShowSizingGrip) rlm@1: { rlm@1: POINT pt = { LOWORD(lParam), HIWORD(lParam) }; rlm@1: (void)ScreenToClient(&pt); rlm@1: if (PtInRect(pdd->m_rcGrip, pt)) rlm@1: return (BOOL)HTBOTTOMRIGHT; rlm@1: } rlm@1: break; rlm@1: } rlm@1: case WM_GETMINMAXINFO: rlm@1: { rlm@1: // rlm@1: // Our opportunity to say that we do not want the dialog to grow or shrink any more. rlm@1: DialogData * pdd = (DialogData *)dd; rlm@1: LPMINMAXINFO lpmmi = reinterpret_cast(lParam); rlm@1: lpmmi->ptMinTrackSize = pdd->m_ptSmallest; rlm@1: if (pdd->m_bLargestSet) rlm@1: { rlm@1: lpmmi->ptMaxTrackSize = pdd->m_ptLargest; rlm@1: } rlm@1: } rlm@1: return (BOOL)0; rlm@1: case WM_NOTIFY: rlm@1: { rlm@1: if (reinterpret_cast(lParam)->code == PSN_SETACTIVE) rlm@1: { rlm@1: CRect rc; rlm@1: VAPI(::GetClientRect(*GetParent(), &rc)); rlm@1: UpdateWindowSize(rc.Width(), rc.Height(), *GetParent()); rlm@1: } rlm@1: break; rlm@1: } rlm@1: case WM_DESTROY: rlm@1: { rlm@1: // rlm@1: // Our opportunty for cleanup. rlm@1: // Simply acquire all of our objects, free the appropriate memory and remove the rlm@1: // properties from the window. If we do not remove the properties then they will constitute rlm@1: // a resource leak. rlm@1: DialogData *pdd = (DialogData *)dd; rlm@1: if (pdd) rlm@1: { rlm@1: RegistryData rd; rlm@1: rd.m_wpl.length = sizeof(rd.m_wpl); rlm@1: VAPI(GetWindowPlacement(&rd.m_wpl)); rlm@1: rlm@1: if (pdd->hkRootSave && pdd->pcszName) rlm@1: { rlm@1: (void)RegSetValueExRecursive(pdd->hkRootSave, pdd->pcszName, rlm@1: NULL, REG_BINARY, rlm@1: reinterpret_cast(&rd), rlm@1: sizeof(rd)); rlm@1: } rlm@1: rlm@1: if (pdd->psd) rlm@1: { rlm@1: free(pdd->psd); rlm@1: } rlm@1: free(pdd); rlm@1: } rlm@1: rlm@1: break; rlm@1: } rlm@1: } rlm@1: return CDialog::OnWndMsg(msg, wParam, lParam, res); rlm@1: } rlm@1: