1 // Win32++ Version 7.3
\r
2 // Released: 30th November 2011
\r
6 // url: https://sourceforge.net/projects/win32-framework
\r
9 // Copyright (c) 2005-2011 David Nash
\r
11 // Permission is hereby granted, free of charge, to
\r
12 // any person obtaining a copy of this software and
\r
13 // associated documentation files (the "Software"),
\r
14 // to deal in the Software without restriction, including
\r
15 // without limitation the rights to use, copy, modify,
\r
16 // merge, publish, distribute, sublicense, and/or sell
\r
17 // copies of the Software, and to permit persons to whom
\r
18 // the Software is furnished to do so, subject to the
\r
19 // following conditions:
\r
21 // The above copyright notice and this permission notice
\r
22 // shall be included in all copies or substantial portions
\r
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
\r
26 // ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
\r
27 // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
\r
28 // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
\r
29 // SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
\r
30 // ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
31 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
32 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
\r
33 // OR OTHER DEALINGS IN THE SOFTWARE.
\r
35 ////////////////////////////////////////////////////////
\r
38 ////////////////////////////////////////////////////////
\r
40 // Declaration of the CDialog class
\r
42 // CDialog adds support for dialogs to Win32++. Dialogs are specialised
\r
43 // windows which are a parent window for common controls. Common controls
\r
44 // are special window types such as buttons, edit controls, tree views,
\r
45 // list views, static text etc.
\r
47 // The layout of a dialog is typically defined in a resource script file
\r
48 // (often Resource.rc). While this script file can be constructed manually,
\r
49 // it is often created using a resource editor. If your compiler doesn't
\r
50 // include a resource editor, you might find ResEdit useful. It is a free
\r
51 // resource editor available for download at:
\r
52 // http://www.resedit.net/
\r
54 // CDialog supports modal and modeless dialogs. It also supports the creation
\r
55 // of dialogs defined in a resource script file, as well as those defined in
\r
56 // a dialog template.
\r
58 // Use the Dialog generic program as the starting point for your own dialog
\r
60 // The DlgSubclass sample demonstrates how to use subclassing to customise
\r
61 // the behaviour of common controls in a dialog.
\r
64 #ifndef _WIN32XX_DIALOG_H_
\r
65 #define _WIN32XX_DIALOG_H_
\r
67 #include "wincore.h"
\r
69 #ifndef SWP_NOCOPYBITS
\r
70 #define SWP_NOCOPYBITS 0x0100
\r
73 #define IDLE_TIMER_ID 300
\r
78 class CDialog : public CWnd
\r
81 CDialog(UINT nResID, CWnd* pParent = NULL);
\r
82 CDialog(LPCTSTR lpszResName, CWnd* pParent = NULL);
\r
83 CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent = NULL);
\r
86 // You probably won't need to override these functions
\r
87 virtual void AttachItem(int nID, CWnd& Wnd);
\r
88 virtual HWND Create(CWnd* pParent = NULL);
\r
89 virtual INT_PTR DoModal();
\r
90 virtual HWND DoModeless();
\r
91 virtual void SetDlgParent(CWnd* pParent);
\r
92 BOOL IsModal() const { return m_IsModal; }
\r
93 BOOL IsIndirect() const { return (NULL != m_lpTemplate); }
\r
96 // These are the functions you might wish to override
\r
97 virtual INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
98 virtual INT_PTR DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
99 virtual void EndDialog(INT_PTR nResult);
\r
100 virtual void OnCancel();
\r
101 virtual BOOL OnInitDialog();
\r
102 virtual void OnOK();
\r
103 virtual BOOL PreTranslateMessage(MSG* pMsg);
\r
105 // Can't override these functions
\r
106 static INT_PTR CALLBACK StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
109 static LRESULT CALLBACK StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam);
\r
113 CDialog(const CDialog&); // Disable copy construction
\r
114 CDialog& operator = (const CDialog&); // Disable assignment operator
\r
116 BOOL m_IsModal; // a flag for modal dialogs
\r
117 LPCTSTR m_lpszResName; // the resource name for the dialog
\r
118 LPCDLGTEMPLATE m_lpTemplate; // the dialog template for indirect dialogs
\r
119 HWND m_hParent; // handle to the dialogs's parent window
\r
125 //////////////////////////////////////
\r
126 // Declaration of the CResizer class
\r
128 // The CResizer class can be used to rearrange a dialog's child
\r
129 // windows when the dialog is resized.
\r
131 // To use CResizer, follow the following steps:
\r
132 // 1) Use Initialize to specify the dialog's CWnd, and min and max size.
\r
133 // 3) Use AddChild for each child window
\r
134 // 4) Call HandleMessage from within DialogProc.
\r
137 // Resize Dialog Styles
\r
138 #define RD_STRETCH_WIDTH 0x0001 // The item has a variable width
\r
139 #define RD_STRETCH_HEIGHT 0x0002 // The item has a variable height
\r
141 // Resize Dialog alignments
\r
142 enum Alignment { topleft, topright, bottomleft, bottomright };
\r
147 CResizer() : m_pParent(0), m_xScrollPos(0), m_yScrollPos(0) {}
\r
148 virtual ~CResizer() {}
\r
150 virtual void AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle);
\r
151 virtual void AddChild(HWND hWnd, Alignment corner, DWORD dwStyle);
\r
152 virtual void HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
\r
153 virtual void Initialize(CWnd* pParent, RECT rcMin, RECT rcMax = CRect(0,0,0,0));
\r
154 virtual void OnHScroll(WPARAM wParam, LPARAM lParam);
\r
155 virtual void OnVScroll(WPARAM wParam, LPARAM lParam);
\r
156 virtual void RecalcLayout();
\r
157 CRect GetMinRect() const { return m_rcMin; }
\r
158 CRect GetMaxRect() const { return m_rcMax; }
\r
172 std::vector<ResizeData> m_vResizeData;
\r
186 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\r
191 ////////////////////////////////////
\r
192 // Definitions for the CDialog class
\r
194 inline CDialog::CDialog(LPCTSTR lpszResName, CWnd* pParent/* = NULL*/)
\r
195 : m_IsModal(TRUE), m_lpszResName(lpszResName), m_lpTemplate(NULL)
\r
197 m_hParent = pParent? pParent->GetHwnd() : NULL;
\r
198 ::InitCommonControls();
\r
201 inline CDialog::CDialog(UINT nResID, CWnd* pParent/* = NULL*/)
\r
202 : m_IsModal(TRUE), m_lpszResName(MAKEINTRESOURCE (nResID)), m_lpTemplate(NULL)
\r
204 m_hParent = pParent? pParent->GetHwnd() : NULL;
\r
205 ::InitCommonControls();
\r
208 //For indirect dialogs - created from a dialog box template in memory.
\r
209 inline CDialog::CDialog(LPCDLGTEMPLATE lpTemplate, CWnd* pParent/* = NULL*/)
\r
210 : m_IsModal(TRUE), m_lpszResName(NULL), m_lpTemplate(lpTemplate)
\r
212 m_hParent = pParent? pParent->GetHwnd() : NULL;
\r
213 ::InitCommonControls();
\r
216 inline CDialog::~CDialog()
\r
218 if (m_hWnd != NULL)
\r
221 ::EndDialog(m_hWnd, 0);
\r
227 inline void CDialog::AttachItem(int nID, CWnd& Wnd)
\r
228 // Attach a dialog item to a CWnd
\r
230 Wnd.AttachDlgItem(nID, this);
\r
233 inline HWND CDialog::Create(CWnd* pParent /* = NULL */)
\r
235 // Allow a dialog to be used as a child window
\r
238 SetDlgParent(pParent);
\r
239 return DoModeless();
\r
242 inline INT_PTR CDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
244 // Override this function in your class derrived from CDialog if you wish to handle messages
\r
245 // A typical function might look like this:
\r
249 // case MESSAGE1: // Some Windows API message
\r
250 // OnMessage1(); // A user defined function
\r
251 // break; // Also do default processing
\r
254 // return x; // Don't do default processing, but instead return
\r
255 // // a value recommended by the Windows API documentation
\r
258 // Always pass unhandled messages on to DialogProcDefault
\r
259 return DialogProcDefault(uMsg, wParam, lParam);
\r
262 inline INT_PTR CDialog::DialogProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
263 // All DialogProc functions should pass unhandled messages to this function
\r
270 if (wParam == IDLE_TIMER_ID)
\r
271 GetApp()->CleanupTemps();
\r
273 case UWM_CLEANUPTEMPS:
\r
275 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
276 pTLSData->vTmpWnds.clear();
\r
279 case WM_INITDIALOG:
\r
281 // Center the dialog
\r
284 SetTimer(IDLE_TIMER_ID, 1000, 0);
\r
286 return OnInitDialog();
\r
288 switch (LOWORD (wParam))
\r
298 // Refelect this message if it's from a control
\r
299 CWnd* pWnd = GetApp()->GetCWndFromMap((HWND)lParam);
\r
301 lr = pWnd->OnCommand(wParam, lParam);
\r
303 // Handle user commands
\r
305 lr = OnCommand(wParam, lParam);
\r
309 break; // Some commands require default processing
\r
315 // Do Notification reflection if it came from a CWnd object
\r
316 HWND hwndFrom = ((LPNMHDR)lParam)->hwndFrom;
\r
317 CWnd* pWndFrom = GetApp()->GetCWndFromMap(hwndFrom);
\r
319 if (pWndFrom != NULL)
\r
320 lr = pWndFrom->OnNotifyReflect(wParam, lParam);
\r
323 // Some controls (eg ListView) have child windows.
\r
324 // Reflect those notifications too.
\r
325 CWnd* pWndFromParent = GetApp()->GetCWndFromMap(::GetParent(hwndFrom));
\r
326 if (pWndFromParent != NULL)
\r
327 lr = pWndFromParent->OnNotifyReflect(wParam, lParam);
\r
330 // Handle user notifications
\r
331 if (!lr) lr = OnNotify(wParam, lParam);
\r
333 // Set the return code for notifications
\r
335 SetWindowLongPtr(DWLP_MSGRESULT, (LONG_PTR)lr);
\r
342 if (::GetUpdateRect(m_hWnd, NULL, FALSE))
\r
348 // RedrawWindow can require repainting without an update rect
\r
350 CClientDC dc(this);
\r
357 case WM_ERASEBKGND:
\r
359 CDC dc((HDC)wParam);
\r
360 BOOL bResult = OnEraseBkgnd(&dc);
\r
362 if (bResult) return TRUE;
\r
366 // A set of messages to be reflected back to the control that generated them
\r
367 case WM_CTLCOLORBTN:
\r
368 case WM_CTLCOLOREDIT:
\r
369 case WM_CTLCOLORDLG:
\r
370 case WM_CTLCOLORLISTBOX:
\r
371 case WM_CTLCOLORSCROLLBAR:
\r
372 case WM_CTLCOLORSTATIC:
\r
374 case WM_MEASUREITEM:
\r
375 case WM_DELETEITEM:
\r
376 case WM_COMPAREITEM:
\r
377 case WM_CHARTOITEM:
\r
378 case WM_VKEYTOITEM:
\r
381 case WM_PARENTNOTIFY:
\r
382 return MessageReflect(m_hWnd, uMsg, wParam, lParam);
\r
387 } // INT_PTR CALLBACK CDialog::DialogProc(...)
\r
389 inline INT_PTR CDialog::DoModal()
\r
391 // Create a modal dialog
\r
392 // A modal dialog box must be closed by the user before the application continues
\r
394 assert( GetApp() ); // Test if Win32++ has been started
\r
395 assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
\r
397 INT_PTR nResult = 0;
\r
403 // Ensure this thread has the TLS index set
\r
404 TLSData* pTLSData = GetApp()->SetTlsIndex();
\r
407 BOOL IsHookedHere = FALSE;
\r
408 if (NULL == pTLSData->hHook )
\r
410 pTLSData->hHook = ::SetWindowsHookEx(WH_MSGFILTER, (HOOKPROC)StaticMsgHook, NULL, ::GetCurrentThreadId());
\r
411 IsHookedHere = TRUE;
\r
415 HINSTANCE hInstance = GetApp()->GetInstanceHandle();
\r
416 pTLSData->pCWnd = this;
\r
418 // Create a modal dialog
\r
420 nResult = ::DialogBoxIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
\r
423 if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
\r
424 hInstance = GetApp()->GetResourceHandle();
\r
425 nResult = ::DialogBox(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
\r
430 pTLSData->pCWnd = NULL;
\r
431 GetApp()->CleanupTemps();
\r
436 ::UnhookWindowsHookEx(pTLSData->hHook);
\r
437 pTLSData->hHook = NULL;
\r
442 throw CWinException(_T("Failed to create modal dialog box"));
\r
446 catch (const CWinException &e)
\r
448 TRACE(_T("\n*** Failed to create dialog ***\n"));
\r
449 e.what(); // Display the last error message.
\r
451 // eat the exception (don't rethrow)
\r
457 inline HWND CDialog::DoModeless()
\r
459 assert( GetApp() ); // Test if Win32++ has been started
\r
460 assert(!::IsWindow(m_hWnd)); // Only one window per CWnd instance allowed
\r
466 // Ensure this thread has the TLS index set
\r
467 TLSData* pTLSData = GetApp()->SetTlsIndex();
\r
469 // Store the CWnd pointer in Thread Local Storage
\r
470 pTLSData->pCWnd = this;
\r
472 HINSTANCE hInstance = GetApp()->GetInstanceHandle();
\r
474 // Create a modeless dialog
\r
476 m_hWnd = ::CreateDialogIndirect(hInstance, m_lpTemplate, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
\r
479 if (::FindResource(GetApp()->GetResourceHandle(), m_lpszResName, RT_DIALOG))
\r
480 hInstance = GetApp()->GetResourceHandle();
\r
482 m_hWnd = ::CreateDialog(hInstance, m_lpszResName, m_hParent, (DLGPROC)CDialog::StaticDialogProc);
\r
486 pTLSData->pCWnd = NULL;
\r
488 // Now handle dialog creation failure
\r
490 throw CWinException(_T("Failed to create dialog"));
\r
493 catch (const CWinException &e)
\r
495 TRACE(_T("\n*** Failed to create dialog ***\n"));
\r
496 e.what(); // Display the last error message.
\r
498 // eat the exception (don't rethrow)
\r
504 inline void CDialog::EndDialog(INT_PTR nResult)
\r
506 assert(::IsWindow(m_hWnd));
\r
509 ::EndDialog(m_hWnd, nResult);
\r
516 inline void CDialog::OnCancel()
\r
518 // Override to customize OnCancel behaviour
\r
519 EndDialog(IDCANCEL);
\r
522 inline BOOL CDialog::OnInitDialog()
\r
524 // Called when the dialog is initialized
\r
525 // Override it in your derived class to automatically perform tasks
\r
526 // The return value is used by WM_INITDIALOG
\r
531 inline void CDialog::OnOK()
\r
533 // Override to customize OnOK behaviour
\r
538 inline BOOL CDialog::PreTranslateMessage(MSG* pMsg)
\r
540 // allow the dialog to translate keyboard input
\r
541 if ((pMsg->message >= WM_KEYFIRST) && (pMsg->message <= WM_KEYLAST))
\r
543 // Process dialog keystrokes for modeless dialogs
\r
546 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
547 if (NULL == pTLSData->hHook)
\r
549 if (IsDialogMessage(pMsg))
\r
554 // A modal message loop is running so we can't do IsDialogMessage.
\r
555 // Avoid having modal dialogs create other windows, because those
\r
556 // windows will then use the modal dialog's special message loop.
\r
557 // If you need the dialog to create another window, put it in a
\r
558 // different thread.
\r
566 inline void CDialog::SetDlgParent(CWnd* pParent)
\r
567 // Allows the parent of the dialog to be set before the dialog is created
\r
569 m_hParent = pParent? pParent->GetHwnd() : NULL;
\r
572 inline INT_PTR CALLBACK CDialog::StaticDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
574 // Find the CWnd pointer mapped to this HWND
\r
575 CDialog* w = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
\r
578 // The HWND wasn't in the map, so add it now
\r
579 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
582 // Retrieve pointer to CWnd object from Thread Local Storage TLS
\r
583 w = (CDialog*)pTLSData->pCWnd;
\r
585 pTLSData->pCWnd = NULL;
\r
587 // Store the Window pointer into the HWND map
\r
592 return w->DialogProc(uMsg, wParam, lParam);
\r
594 } // INT_PTR CALLBACK CDialog::StaticDialogProc(...)
\r
597 inline LRESULT CALLBACK CDialog::StaticMsgHook(int nCode, WPARAM wParam, LPARAM lParam)
\r
599 // Used by Modal Dialogs to PreTranslate Messages
\r
600 TLSData* pTLSData = (TLSData*)TlsGetValue(GetApp()->GetTlsIndex());
\r
602 if (nCode == MSGF_DIALOGBOX)
\r
604 MSG* lpMsg = (MSG*) lParam;
\r
606 // only pre-translate keyboard events
\r
607 if ((lpMsg->message >= WM_KEYFIRST && lpMsg->message <= WM_KEYLAST))
\r
609 for (HWND hWnd = lpMsg->hwnd; hWnd != NULL; hWnd = ::GetParent(hWnd))
\r
611 CDialog* pDialog = (CDialog*)GetApp()->GetCWndFromMap(hWnd);
\r
612 if (pDialog && (lstrcmp(pDialog->GetClassName(), _T("#32770")) == 0)) // only for dialogs
\r
614 pDialog->PreTranslateMessage(lpMsg);
\r
621 return ::CallNextHookEx(pTLSData->hHook, nCode, wParam, lParam);
\r
629 /////////////////////////////////////
\r
630 // Definitions for the CResizer class
\r
633 void inline CResizer::AddChild(CWnd* pWnd, Alignment corner, DWORD dwStyle)
\r
634 // Adds a child window (usually a dialog control) to the set of windows managed by
\r
637 // The alignment corner should be set to the closest corner of the dialog. Allowed
\r
638 // values are topleft, topright, bottomleft, and bottomright.
\r
639 // Set bFixedWidth to TRUE if the width should be fixed instead of variable.
\r
640 // Set bFixedHeight to TRUE if the height should be fixed instead of variable.
\r
643 rd.corner = corner;
\r
644 rd.bFixedWidth = !(dwStyle & RD_STRETCH_WIDTH);
\r
645 rd.bFixedHeight = !(dwStyle & RD_STRETCH_HEIGHT);
\r
646 CRect rcInit = pWnd->GetWindowRect();
\r
647 m_pParent->ScreenToClient(rcInit);
\r
648 rd.rcInit = rcInit;
\r
649 rd.hWnd = pWnd->GetHwnd();
\r
651 m_vResizeData.insert(m_vResizeData.begin(), rd);
\r
654 void inline CResizer::AddChild(HWND hWnd, Alignment corner, DWORD dwStyle)
\r
655 // Adds a child window (usually a dialog control) to the set of windows managed by
\r
658 AddChild(FromHandle(hWnd), corner, dwStyle);
\r
661 inline void CResizer::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
671 OnHScroll(wParam, lParam);
\r
676 OnVScroll(wParam, lParam);
\r
681 void inline CResizer::Initialize(CWnd* pParent, RECT rcMin, RECT rcMax)
\r
682 // Sets up the Resizer by specifying the parent window (usually a dialog),
\r
683 // and the minimum and maximum allowed rectangle sizes.
\r
685 assert (NULL != pParent);
\r
687 m_pParent = pParent;
\r
688 m_rcInit = pParent->GetClientRect();
\r
692 // Add scroll bar support to the parent window
\r
693 DWORD dwStyle = (DWORD)m_pParent->GetClassLongPtr(GCL_STYLE);
\r
694 dwStyle |= WS_HSCROLL | WS_VSCROLL;
\r
695 m_pParent->SetClassLongPtr(GCL_STYLE, dwStyle);
\r
698 void inline CResizer::OnHScroll(WPARAM wParam, LPARAM /*lParam*/)
\r
702 switch (LOWORD(wParam))
\r
704 case SB_PAGEUP: // User clicked the scroll bar shaft left of the scroll box.
\r
705 xNewPos = m_xScrollPos - 50;
\r
708 case SB_PAGEDOWN: // User clicked the scroll bar shaft right of the scroll box.
\r
709 xNewPos = m_xScrollPos + 50;
\r
712 case SB_LINEUP: // User clicked the left arrow.
\r
713 xNewPos = m_xScrollPos - 5;
\r
716 case SB_LINEDOWN: // User clicked the right arrow.
\r
717 xNewPos = m_xScrollPos + 5;
\r
720 case SB_THUMBPOSITION: // User dragged the scroll box.
\r
721 xNewPos = HIWORD(wParam);
\r
724 case SB_THUMBTRACK: // User dragging the scroll box.
\r
725 xNewPos = HIWORD(wParam);
\r
729 xNewPos = m_xScrollPos;
\r
732 // Scroll the window.
\r
733 xNewPos = MAX(0, xNewPos);
\r
734 xNewPos = MIN( xNewPos, GetMinRect().Width() - m_pParent->GetClientRect().Width() );
\r
735 int xDelta = xNewPos - m_xScrollPos;
\r
736 m_xScrollPos = xNewPos;
\r
737 m_pParent->ScrollWindow(-xDelta, 0, NULL, NULL);
\r
739 // Reset the scroll bar.
\r
740 SCROLLINFO si = {0};
\r
741 si.cbSize = sizeof(si);
\r
742 si.fMask = SIF_POS;
\r
743 si.nPos = m_xScrollPos;
\r
744 m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
\r
747 void inline CResizer::OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
\r
751 switch (LOWORD(wParam))
\r
753 case SB_PAGEUP: // User clicked the scroll bar shaft above the scroll box.
\r
754 yNewPos = m_yScrollPos - 50;
\r
757 case SB_PAGEDOWN: // User clicked the scroll bar shaft below the scroll box.
\r
758 yNewPos = m_yScrollPos + 50;
\r
761 case SB_LINEUP: // User clicked the top arrow.
\r
762 yNewPos = m_yScrollPos - 5;
\r
765 case SB_LINEDOWN: // User clicked the bottom arrow.
\r
766 yNewPos = m_yScrollPos + 5;
\r
769 case SB_THUMBPOSITION: // User dragged the scroll box.
\r
770 yNewPos = HIWORD(wParam);
\r
773 case SB_THUMBTRACK: // User dragging the scroll box.
\r
774 yNewPos = HIWORD(wParam);
\r
778 yNewPos = m_yScrollPos;
\r
781 // Scroll the window.
\r
782 yNewPos = MAX(0, yNewPos);
\r
783 yNewPos = MIN( yNewPos, GetMinRect().Height() - m_pParent->GetClientRect().Height() );
\r
784 int yDelta = yNewPos - m_yScrollPos;
\r
785 m_yScrollPos = yNewPos;
\r
786 m_pParent->ScrollWindow(0, -yDelta, NULL, NULL);
\r
788 // Reset the scroll bar.
\r
789 SCROLLINFO si = {0};
\r
790 si.cbSize = sizeof(si);
\r
791 si.fMask = SIF_POS;
\r
792 si.nPos = m_yScrollPos;
\r
793 m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
\r
796 void inline CResizer::RecalcLayout()
\r
797 // Repositions the child windows. Call this function when handling
\r
798 // the WM_SIZE message in the parent window.
\r
800 assert (m_rcInit.Width() > 0 && m_rcInit.Height() > 0);
\r
801 assert (NULL != m_pParent);
\r
803 CRect rcCurrent = m_pParent->GetClientRect();
\r
805 // Adjust the scrolling if required
\r
806 m_xScrollPos = MIN(m_xScrollPos, MAX(0, m_rcMin.Width() - rcCurrent.Width() ) );
\r
807 m_yScrollPos = MIN(m_yScrollPos, MAX(0, m_rcMin.Height() - rcCurrent.Height()) );
\r
808 SCROLLINFO si = {0};
\r
809 si.cbSize = sizeof(si);
\r
810 si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
\r
811 si.nMax = m_rcMin.Width();
\r
812 si.nPage = rcCurrent.Width();
\r
813 si.nPos = m_xScrollPos;
\r
814 m_pParent->SetScrollInfo(SB_HORZ, si, TRUE);
\r
815 si.nMax = m_rcMin.Height();
\r
816 si.nPage = rcCurrent.Height();
\r
817 si.nPos = m_yScrollPos;
\r
818 m_pParent->SetScrollInfo(SB_VERT, si, TRUE);
\r
820 rcCurrent.right = MAX( rcCurrent.Width(), m_rcMin.Width() );
\r
821 rcCurrent.bottom = MAX( rcCurrent.Height(), m_rcMin.Height() );
\r
822 if (!m_rcMax.IsRectEmpty())
\r
824 rcCurrent.right = MIN( rcCurrent.Width(), m_rcMax.Width() );
\r
825 rcCurrent.bottom = MIN( rcCurrent.Height(), m_rcMax.Height() );
\r
828 // Declare an iterator to step through the vector
\r
829 std::vector<ResizeData>::iterator iter;
\r
831 for (iter = m_vResizeData.begin(); iter < m_vResizeData.end(); ++iter)
\r
838 // Calculate the new size and position of the child window
\r
839 switch( (*iter).corner )
\r
842 width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
\r
843 height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
\r
844 left = (*iter).rcInit.left;
\r
845 top = (*iter).rcInit.top;
\r
848 width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
\r
849 height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
\r
850 left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
\r
851 top = (*iter).rcInit.top;
\r
854 width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
\r
855 height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
\r
856 left = (*iter).rcInit.left;
\r
857 top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
\r
860 width = (*iter).bFixedWidth? (*iter).rcInit.Width() : (*iter).rcInit.Width() - m_rcInit.Width() + rcCurrent.Width();
\r
861 height = (*iter).bFixedHeight? (*iter).rcInit.Height() : (*iter).rcInit.Height() - m_rcInit.Height() + rcCurrent.Height();
\r
862 left = (*iter).rcInit.right - width - m_rcInit.Width() + rcCurrent.Width();
\r
863 top = (*iter).rcInit.bottom - height - m_rcInit.Height() + rcCurrent.Height();
\r
867 // Position the child window.
\r
868 CRect rc(left - m_xScrollPos, top - m_yScrollPos, left + width - m_xScrollPos, top + height - m_yScrollPos);
\r
869 if ( rc != (*iter).rcOld)
\r
871 CWnd* pWnd = FromHandle((*iter).hWnd);
\r
872 CWnd *pWndPrev = pWnd->GetWindow(GW_HWNDPREV); // Trick to maintain the original tab order.
\r
873 // HWND hWnd = pWndPrev ? pWndPrev->GetHwnd():NULL;
\r
874 pWnd->SetWindowPos(pWndPrev, rc, SWP_NOCOPYBITS);
\r
875 (*iter).rcOld = rc;
\r
880 #endif // #ifndef _WIN32_WCE
\r
882 } // namespace Win32xx
\r
886 #endif // _WIN32XX_DIALOG_H_
\r