|
1
|
1 #include "stdafx.h"
|
|
|
2 #include "CDialogResizeHelper.h"
|
|
|
3
|
|
|
4 #include "win32_op.h"
|
|
|
5
|
|
|
6 static BOOL GetChildWindowRect2(HWND wnd, HWND wndChild, RECT* child) {
|
|
|
7 RECT temp;
|
|
|
8 if (wndChild == NULL) return FALSE;
|
|
|
9 if (!GetWindowRect(wndChild, &temp)) return FALSE;
|
|
|
10 if (!MapWindowPoints(NULL, wnd, (POINT*)&temp, 2)) return FALSE;
|
|
|
11 *child = temp;
|
|
|
12 return TRUE;
|
|
|
13 }
|
|
|
14
|
|
|
15 static BOOL GetChildWindowRect(HWND wnd, UINT id, RECT* child) {
|
|
|
16 return GetChildWindowRect2(wnd, GetDlgItem(wnd, id), child);
|
|
|
17 }
|
|
|
18
|
|
|
19
|
|
|
20 bool CDialogResizeHelper::EvalRect(UINT id, CRect & out) const {
|
|
|
21 for( auto iter = m_runtime.begin(); iter != m_runtime.end(); ++ iter ) {
|
|
|
22 if ( iter->initData.id == id ) {
|
|
|
23 out = _EvalRect(*iter, this->CurrentSize() );
|
|
|
24 return true;
|
|
|
25 }
|
|
|
26 }
|
|
|
27 return false;
|
|
|
28 }
|
|
|
29
|
|
|
30 CRect CDialogResizeHelper::_EvalRect(runtime_t const & rt, CSize wndSize) const {
|
|
|
31 CRect rc = rt.origRect;
|
|
|
32 int delta_x = wndSize.cx - rt.origWindowSize.cx,
|
|
|
33 delta_y = wndSize.cy - rt.origWindowSize.cy;
|
|
|
34
|
|
|
35 const Param & e = rt.initData;
|
|
|
36 rc.left += pfc::rint32(e.snapLeft * delta_x);
|
|
|
37 rc.right += pfc::rint32(e.snapRight * delta_x);
|
|
|
38 rc.top += pfc::rint32(e.snapTop * delta_y);
|
|
|
39 rc.bottom += pfc::rint32(e.snapBottom * delta_y);
|
|
|
40
|
|
|
41 return rc;
|
|
|
42 }
|
|
|
43
|
|
|
44 CWindow CDialogResizeHelper::ResolveWnd(runtime_t const & rt) const {
|
|
|
45 if ( rt.userHWND != NULL ) return rt.userHWND;
|
|
|
46 return m_thisWnd.GetDlgItem( rt.initData.id );
|
|
|
47 }
|
|
|
48
|
|
|
49 CSize CDialogResizeHelper::CurrentSize() const {
|
|
|
50 CRect rc;
|
|
|
51 WIN32_OP_D( m_thisWnd.GetClientRect(rc) );
|
|
|
52 return rc.Size();
|
|
|
53 }
|
|
|
54
|
|
|
55 void CDialogResizeHelper::OnSize(UINT, CSize newSize)
|
|
|
56 {
|
|
|
57 if (m_thisWnd != NULL) {
|
|
|
58 HDWP hWinPosInfo = BeginDeferWindowPos((int)(m_runtime.size() + (m_sizeGrip != NULL ? 1 : 0)));
|
|
|
59 for (auto iter = m_runtime.begin(); iter != m_runtime.end(); ++ iter) {
|
|
|
60 CRect rc = _EvalRect(*iter, newSize);
|
|
|
61 hWinPosInfo = DeferWindowPos(hWinPosInfo, ResolveWnd(*iter), 0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
|
|
|
62 }
|
|
|
63 if (m_sizeGrip != NULL)
|
|
|
64 {
|
|
|
65 RECT rc, rc_grip;
|
|
|
66 if (m_thisWnd.GetClientRect(&rc) && m_sizeGrip.GetWindowRect(&rc_grip)) {
|
|
|
67 DWORD flags = SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS;
|
|
|
68 if (IsZoomed(m_thisWnd)) flags |= SWP_HIDEWINDOW;
|
|
|
69 else flags |= SWP_SHOWWINDOW;
|
|
|
70 hWinPosInfo = DeferWindowPos(hWinPosInfo, m_sizeGrip, NULL, rc.right - (rc_grip.right - rc_grip.left), rc.bottom - (rc_grip.bottom - rc_grip.top), 0, 0, flags);
|
|
|
71 }
|
|
|
72 }
|
|
|
73 EndDeferWindowPos(hWinPosInfo);
|
|
|
74 //RedrawWindow(m_thisWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
|
|
|
75 }
|
|
|
76 SetMsgHandled(FALSE);
|
|
|
77 }
|
|
|
78
|
|
|
79 void CDialogResizeHelper::OnGetMinMaxInfo(LPMINMAXINFO info) const {
|
|
|
80 CRect r;
|
|
|
81 const DWORD dwStyle = m_thisWnd.GetWindowLong(GWL_STYLE);
|
|
|
82 const DWORD dwExStyle = m_thisWnd.GetWindowLong(GWL_EXSTYLE);
|
|
|
83 if (max_x && max_y)
|
|
|
84 {
|
|
|
85 r.left = 0; r.right = max_x;
|
|
|
86 r.top = 0; r.bottom = max_y;
|
|
|
87 MapDialogRect(m_thisWnd, &r);
|
|
|
88 AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
|
|
|
89 info->ptMaxTrackSize.x = r.right - r.left;
|
|
|
90 info->ptMaxTrackSize.y = r.bottom - r.top;
|
|
|
91 }
|
|
|
92 if (min_x && min_y)
|
|
|
93 {
|
|
|
94 r.left = 0; r.right = min_x;
|
|
|
95 r.top = 0; r.bottom = min_y;
|
|
|
96 MapDialogRect(m_thisWnd, &r);
|
|
|
97 AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
|
|
|
98 info->ptMinTrackSize.x = r.right - r.left;
|
|
|
99 info->ptMinTrackSize.y = r.bottom - r.top;
|
|
|
100 }
|
|
|
101 }
|
|
|
102
|
|
|
103 void CDialogResizeHelper::OnInitDialog(CWindow thisWnd) {
|
|
|
104
|
|
|
105 m_thisWnd = thisWnd;
|
|
|
106 const auto origSize = CurrentSize();
|
|
|
107 for( auto initIter = m_initData.begin(); initIter != m_initData.end(); ++ initIter ) {
|
|
|
108 CRect rc;
|
|
|
109 if (GetChildWindowRect(m_thisWnd, initIter->id, &rc)) {
|
|
|
110 runtime_t rt;
|
|
|
111 rt.origRect = rc;
|
|
|
112 rt.initData = * initIter;
|
|
|
113 rt.origWindowSize = origSize;
|
|
|
114 m_runtime.push_back( std::move(rt) );
|
|
|
115 }
|
|
|
116 }
|
|
|
117 AddSizeGrip();
|
|
|
118 SetMsgHandled(FALSE);
|
|
|
119 }
|
|
|
120 void CDialogResizeHelper::OnDestroy() {
|
|
|
121 m_runtime.clear();
|
|
|
122 m_sizeGrip = NULL; m_thisWnd = NULL;
|
|
|
123 SetMsgHandled(FALSE);
|
|
|
124 }
|
|
|
125
|
|
|
126 void CDialogResizeHelper::AddSizeGrip()
|
|
|
127 {
|
|
|
128 if ( m_autoSizeGrip && m_thisWnd != NULL && m_sizeGrip == NULL)
|
|
|
129 {
|
|
|
130 if (m_thisWnd.GetWindowLong(GWL_STYLE) & WS_POPUP) {
|
|
|
131 m_sizeGrip = CreateWindowEx(0, WC_SCROLLBAR, _T(""), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN,
|
|
|
132 0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
133 m_thisWnd, (HMENU)0, NULL, NULL);
|
|
|
134 if (m_sizeGrip != NULL)
|
|
|
135 {
|
|
|
136 RECT rc, rc_grip;
|
|
|
137 if (m_thisWnd.GetClientRect(&rc) && m_sizeGrip.GetWindowRect(&rc_grip)) {
|
|
|
138 m_sizeGrip.SetWindowPos(NULL, rc.right - (rc_grip.right - rc_grip.left), rc.bottom - (rc_grip.bottom - rc_grip.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
|
|
|
139 }
|
|
|
140 }
|
|
|
141 }
|
|
|
142 }
|
|
|
143 }
|
|
|
144
|
|
|
145
|
|
|
146 void CDialogResizeHelper::InitTable(const Param* table, size_t tableSize) {
|
|
|
147 m_initData.assign( table, table+tableSize );
|
|
|
148 }
|
|
|
149 void CDialogResizeHelper::InitTable(const ParamOld * table, size_t tableSize) {
|
|
|
150 m_initData.resize(tableSize);
|
|
|
151 for (size_t walk = 0; walk < tableSize; ++walk) {
|
|
|
152 const ParamOld in = table[walk];
|
|
|
153 Param entry = {};
|
|
|
154 entry.id = table[walk].id;
|
|
|
155 if (in.flags & CDialogResizeHelperCompat::X_MOVE) entry.snapLeft = entry.snapRight = 1;
|
|
|
156 else if (in.flags & CDialogResizeHelperCompat::X_SIZE) entry.snapRight = 1;
|
|
|
157 if (in.flags & CDialogResizeHelperCompat::Y_MOVE) entry.snapTop = entry.snapBottom = 1;
|
|
|
158 else if (in.flags & CDialogResizeHelperCompat::Y_SIZE) entry.snapBottom = 1;
|
|
|
159 m_initData[walk] = entry;
|
|
|
160 }
|
|
|
161 }
|
|
|
162 void CDialogResizeHelper::InitMinMax(const CRect & range) {
|
|
|
163 min_x = range.left; min_y = range.top; max_x = range.right; max_y = range.bottom;
|
|
|
164 }
|
|
|
165
|
|
|
166 void CDialogResizeHelper::AddControl(Param const & initData, CWindow wnd) {
|
|
|
167 CRect rc;
|
|
|
168 if ( wnd == NULL ) {
|
|
|
169 PFC_ASSERT( initData.id != 0 );
|
|
|
170 WIN32_OP_D(GetChildWindowRect(m_thisWnd, initData.id, rc));
|
|
|
171 } else {
|
|
|
172 WIN32_OP_D(GetChildWindowRect2(m_thisWnd, wnd, rc));
|
|
|
173 }
|
|
|
174
|
|
|
175 runtime_t rt;
|
|
|
176 rt.initData = initData;
|
|
|
177 rt.userHWND = wnd;
|
|
|
178 rt.origRect = rc;
|
|
|
179 rt.origWindowSize = this->CurrentSize();
|
|
|
180 m_runtime.push_back( std::move(rt) );
|
|
|
181 }
|
|
|
182
|
|
|
183 bool CDialogResizeHelper::RemoveControl(CWindow wnd) {
|
|
|
184 return pfc::remove_if_t( m_runtime, [wnd] (runtime_t const & rt) {
|
|
|
185 return rt.userHWND == wnd;
|
|
|
186 } ) > 0;
|
|
|
187 }
|
|
|
188
|
|
|
189 bool CDialogResizeHelper::HaveControl(CWindow wnd) const {
|
|
|
190 for( auto i = m_runtime.begin(); i != m_runtime.end(); ++ i ) {
|
|
|
191 if ( i->userHWND == wnd ) return true;
|
|
|
192 }
|
|
|
193 return false;
|
|
|
194 }
|