OSDN Git Service

fix ticket #18663
[yamy/yamy.git] / layoutmanager.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // layoutmanager.cpp\r
3 \r
4 \r
5 #include "layoutmanager.h"\r
6 #include "windowstool.h"\r
7 \r
8 #include <windowsx.h>\r
9 \r
10 \r
11 //\r
12 LayoutManager::LayoutManager(HWND i_hwnd)\r
13                 : m_hwnd(i_hwnd),\r
14                 m_smallestRestriction(RESTRICT_NONE),\r
15                 m_largestRestriction(RESTRICT_NONE)\r
16 {\r
17 }\r
18 \r
19 // restrict the smallest size of the window to the current size of it or\r
20 // specified by i_size\r
21 void LayoutManager::restrictSmallestSize(Restrict i_restrict, SIZE *i_size)\r
22 {\r
23         m_smallestRestriction = i_restrict;\r
24         if (i_size)\r
25                 m_smallestSize = *i_size;\r
26         else {\r
27                 RECT rc;\r
28                 GetWindowRect(m_hwnd, &rc);\r
29                 m_smallestSize.cx = rc.right - rc.left;\r
30                 m_smallestSize.cy = rc.bottom - rc.top;\r
31         }\r
32 }\r
33 \r
34 \r
35 // restrict the largest size of the window to the current size of it or\r
36 // specified by i_size\r
37 void LayoutManager::restrictLargestSize(Restrict i_restrict, SIZE *i_size)\r
38 {\r
39         m_largestRestriction = i_restrict;\r
40         if (i_size)\r
41                 m_largestSize = *i_size;\r
42         else {\r
43                 RECT rc;\r
44                 GetWindowRect(m_hwnd, &rc);\r
45                 m_largestSize.cx = rc.right - rc.left;\r
46                 m_largestSize.cy = rc.bottom - rc.top;\r
47         }\r
48 }\r
49 \r
50 //\r
51 bool LayoutManager::addItem(HWND i_hwnd, Origin i_originLeft,\r
52                                                         Origin i_originTop,\r
53                                                         Origin i_originRight, Origin i_originBottom)\r
54 {\r
55         Item item;\r
56         if (!i_hwnd)\r
57                 return false;\r
58         item.m_hwnd = i_hwnd;\r
59 #ifdef MAYU64\r
60         if (!(GetWindowLongPtr(i_hwnd, GWL_STYLE) & WS_CHILD))\r
61 #else\r
62         if (!(GetWindowLong(i_hwnd, GWL_STYLE) & WS_CHILD))\r
63 #endif\r
64                 return false;\r
65         item.m_hwndParent = GetParent(i_hwnd);\r
66         if (!item.m_hwndParent)\r
67                 return false;\r
68         getChildWindowRect(item.m_hwnd, &item.m_rc);\r
69         GetWindowRect(item.m_hwndParent, &item.m_rcParent);\r
70         item.m_origin[0] = i_originLeft;\r
71         item.m_origin[1] = i_originTop;\r
72         item.m_origin[2] = i_originRight;\r
73         item.m_origin[3] = i_originBottom;\r
74 \r
75         m_items.push_back(item);\r
76         return true;\r
77 }\r
78 \r
79 //\r
80 void LayoutManager::adjust() const\r
81 {\r
82         for (Items::const_iterator i = m_items.begin(); i != m_items.end(); ++ i) {\r
83                 RECT rc;\r
84                 GetWindowRect(i->m_hwndParent, &rc);\r
85 \r
86                 struct {\r
87                         int m_width, m_pos;\r
88                         int m_curWidth;\r
89                         LONG *m_out;\r
90                 }\r
91                 pos[4] = {\r
92                         { rcWidth(&i->m_rcParent), i->m_rc.left, rcWidth(&rc), &rc.left },\r
93                         { rcHeight(&i->m_rcParent), i->m_rc.top, rcHeight(&rc), &rc.top },\r
94                         { rcWidth(&i->m_rcParent), i->m_rc.right, rcWidth(&rc), &rc.right },\r
95                         { rcHeight(&i->m_rcParent), i->m_rc.bottom, rcHeight(&rc), &rc.bottom }\r
96                 };\r
97                 for (int j = 0; j < 4; ++ j) {\r
98                         switch (i->m_origin[j]) {\r
99                         case ORIGIN_LEFT_EDGE:\r
100                                 *pos[j].m_out = pos[j].m_pos;\r
101                                 break;\r
102                         case ORIGIN_CENTER:\r
103                                 *pos[j].m_out = pos[j].m_curWidth / 2\r
104                                                                 - (pos[j].m_width / 2 - pos[j].m_pos);\r
105                                 break;\r
106                         case ORIGIN_RIGHT_EDGE:\r
107                                 *pos[j].m_out = pos[j].m_curWidth\r
108                                                                 - (pos[j].m_width - pos[j].m_pos);\r
109                                 break;\r
110                         }\r
111                 }\r
112                 MoveWindow(i->m_hwnd, rc.left, rc.top,\r
113                                    rcWidth(&rc), rcHeight(&rc), FALSE);\r
114         }\r
115 }\r
116 \r
117 \r
118 // draw size box\r
119 BOOL LayoutManager::wmPaint()\r
120 {\r
121         PAINTSTRUCT ps;\r
122         HDC hdc = BeginPaint(m_hwnd, &ps);\r
123         RECT rc;\r
124         GetClientRect(m_hwnd, &rc);\r
125         rc.left = rc.right - GetSystemMetrics(SM_CXHTHUMB);\r
126         rc.top = rc.bottom - GetSystemMetrics(SM_CYVTHUMB);\r
127         DrawFrameControl(hdc, &rc, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);\r
128         EndPaint(m_hwnd, &ps);\r
129         return TRUE;\r
130 }\r
131 \r
132 \r
133 // size restriction\r
134 BOOL LayoutManager::wmSizing(int i_edge, RECT *io_rc)\r
135 {\r
136         switch (i_edge) {\r
137         case WMSZ_TOPLEFT:\r
138         case WMSZ_LEFT:\r
139         case WMSZ_BOTTOMLEFT:\r
140                 if (m_smallestRestriction & RESTRICT_HORIZONTALLY)\r
141                         if (io_rc->right - io_rc->left < m_smallestSize.cx)\r
142                                 io_rc->left = io_rc->right - m_smallestSize.cx;\r
143                 if (m_largestRestriction & RESTRICT_HORIZONTALLY)\r
144                         if (m_largestSize.cx < io_rc->right - io_rc->left)\r
145                                 io_rc->left = io_rc->right - m_largestSize.cx;\r
146                 break;\r
147         }\r
148         switch (i_edge) {\r
149         case WMSZ_TOPRIGHT:\r
150         case WMSZ_RIGHT:\r
151         case WMSZ_BOTTOMRIGHT:\r
152                 if (m_smallestRestriction & RESTRICT_HORIZONTALLY)\r
153                         if (io_rc->right - io_rc->left < m_smallestSize.cx)\r
154                                 io_rc->right = io_rc->left + m_smallestSize.cx;\r
155                 if (m_largestRestriction & RESTRICT_HORIZONTALLY)\r
156                         if (m_largestSize.cx < io_rc->right - io_rc->left)\r
157                                 io_rc->right = io_rc->left + m_largestSize.cx;\r
158                 break;\r
159         }\r
160         switch (i_edge) {\r
161         case WMSZ_TOP:\r
162         case WMSZ_TOPLEFT:\r
163         case WMSZ_TOPRIGHT:\r
164                 if (m_smallestRestriction & RESTRICT_VERTICALLY)\r
165                         if (io_rc->bottom - io_rc->top < m_smallestSize.cy)\r
166                                 io_rc->top = io_rc->bottom - m_smallestSize.cy;\r
167                 if (m_largestRestriction & RESTRICT_VERTICALLY)\r
168                         if (m_largestSize.cy < io_rc->bottom - io_rc->top)\r
169                                 io_rc->top = io_rc->bottom - m_largestSize.cy;\r
170                 break;\r
171         }\r
172         switch (i_edge) {\r
173         case WMSZ_BOTTOM:\r
174         case WMSZ_BOTTOMLEFT:\r
175         case WMSZ_BOTTOMRIGHT:\r
176                 if (m_smallestRestriction & RESTRICT_VERTICALLY)\r
177                         if (io_rc->bottom - io_rc->top < m_smallestSize.cy)\r
178                                 io_rc->bottom = io_rc->top + m_smallestSize.cy;\r
179                 if (m_largestRestriction & RESTRICT_VERTICALLY)\r
180                         if (m_largestSize.cy < io_rc->bottom - io_rc->top)\r
181                                 io_rc->bottom = io_rc->top + m_largestSize.cy;\r
182                 break;\r
183         }\r
184         return TRUE;\r
185 }\r
186 \r
187 \r
188 // hittest for size box\r
189 BOOL LayoutManager::wmNcHitTest(int i_x, int i_y)\r
190 {\r
191         POINT p = { i_x, i_y };\r
192         ScreenToClient(m_hwnd, &p);\r
193         RECT rc;\r
194         GetClientRect(m_hwnd, &rc);\r
195         if (rc.right - GetSystemMetrics(SM_CXHTHUMB) <= p.x &&\r
196                         rc.bottom - GetSystemMetrics(SM_CYVTHUMB) <= p.y) {\r
197 #ifdef MAYU64\r
198                 SetWindowLongPtr(m_hwnd, DWLP_MSGRESULT, HTBOTTOMRIGHT);\r
199 #else\r
200                 SetWindowLong(m_hwnd, DWL_MSGRESULT, HTBOTTOMRIGHT);\r
201 #endif\r
202                 return TRUE;\r
203         }\r
204         return FALSE;\r
205 }\r
206 \r
207 \r
208 // WM_SIZE\r
209 BOOL LayoutManager::wmSize(DWORD /* i_fwSizeType */, short /* i_nWidth */,\r
210                                                    short /* i_nHeight */)\r
211 {\r
212         adjust();\r
213         RedrawWindow(m_hwnd, NULL, NULL,\r
214                                  RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);\r
215         return TRUE;\r
216 }\r
217 \r
218 \r
219 // forward message\r
220 BOOL LayoutManager::defaultWMHandler(UINT i_message,\r
221                                                                          WPARAM i_wParam, LPARAM i_lParam)\r
222 {\r
223         switch (i_message) {\r
224         case WM_SIZE:\r
225                 return wmSize(i_wParam, LOWORD(i_lParam), HIWORD(i_lParam));\r
226         case WM_PAINT:\r
227                 return wmPaint();\r
228         case WM_SIZING:\r
229                 return wmSizing(i_wParam, reinterpret_cast<RECT *>(i_lParam));\r
230         case WM_NCHITTEST:\r
231                 return wmNcHitTest(GET_X_LPARAM(i_lParam), GET_Y_LPARAM(i_lParam));\r
232         }\r
233         return FALSE;\r
234 }\r