ReactOS 0.4.16-dev-320-g3bd9ddc
layout.h
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS headers
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: The layout engine of resizable dialog boxes / windows
5 * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6 */
7#pragma once
8#include <assert.h>
9
10typedef struct LAYOUT_INFO {
12 UINT m_uEdges; /* BF_* flags */
17
18typedef struct LAYOUT_DATA {
24
25static __inline void
27{
28 if (bEnableResize)
29 {
30 GetSystemMenu(pData->m_hwndParent, TRUE); /* revert */
31 }
32 else
33 {
34 HMENU hSysMenu = GetSystemMenu(pData->m_hwndParent, FALSE);
38 }
39}
40
41static __inline HDWP
43{
44 if (!IsWindowVisible(pData->m_hwndGrip))
45 return hDwp;
46
49 RECT rcClient;
50 GetClientRect(pData->m_hwndParent, &rcClient);
51
52 if (hDwp)
53 {
54 hDwp = DeferWindowPos(hDwp, pData->m_hwndGrip, NULL,
55 rcClient.right - size.cx, rcClient.bottom - size.cy,
56 size.cx, size.cy, uFlags);
57 }
58 else
59 {
60 SetWindowPos(pData->m_hwndGrip, NULL,
61 rcClient.right - size.cx, rcClient.bottom - size.cy,
62 size.cx, size.cy, uFlags);
63 }
64 return hDwp;
65}
66
67static __inline void
69{
73 DWORD new_style = (bShow ? (style | WS_SIZEBOX) : (style & ~WS_SIZEBOX));
74 if (style != new_style)
75 {
76 SetWindowLongPtrW(pData->m_hwndParent, GWL_STYLE, new_style); /* change style */
77 SetWindowPos(pData->m_hwndParent, NULL, 0, 0, 0, 0, uSWP); /* frame changed */
78 }
79
80 if (!bShow)
81 {
82 ShowWindow(pData->m_hwndGrip, SW_HIDE);
83 return;
84 }
85
86 if (pData->m_hwndGrip == NULL)
87 {
88 /* CORE-19585: WS_GROUP set to avoid navigation over the grip control */
90 pData->m_hwndGrip = CreateWindowExW(0, L"SCROLLBAR", NULL, style,
91 0, 0, 0, 0, pData->m_hwndParent,
93 }
96}
97
98static __inline void
99_layout_GetPercents(LPRECT prcPercents, UINT uEdges)
100{
101 prcPercents->left = (uEdges & BF_LEFT) ? 0 : 100;
102 prcPercents->right = (uEdges & BF_RIGHT) ? 100 : 0;
103 prcPercents->top = (uEdges & BF_TOP) ? 0 : 100;
104 prcPercents->bottom = (uEdges & BF_BOTTOM) ? 100 : 0;
105}
106
107static __inline HDWP
109 const RECT *rcClient)
110{
111 RECT rcChild, NewRect, rcPercents;
112 LONG nWidth, nHeight;
113
114 if (!GetWindowRect(pLayout->m_hwndCtrl, &rcChild))
115 return hDwp;
116 MapWindowPoints(NULL, pData->m_hwndParent, (LPPOINT)&rcChild, 2);
117
118 nWidth = rcClient->right - rcClient->left;
119 nHeight = rcClient->bottom - rcClient->top;
120
121 _layout_GetPercents(&rcPercents, pLayout->m_uEdges);
122 NewRect.left = pLayout->m_margin1.cx + nWidth * rcPercents.left / 100;
123 NewRect.top = pLayout->m_margin1.cy + nHeight * rcPercents.top / 100;
124 NewRect.right = pLayout->m_margin2.cx + nWidth * rcPercents.right / 100;
125 NewRect.bottom = pLayout->m_margin2.cy + nHeight * rcPercents.bottom / 100;
126
127 if (!EqualRect(&NewRect, &rcChild))
128 {
129 hDwp = DeferWindowPos(hDwp, pLayout->m_hwndCtrl, NULL, NewRect.left, NewRect.top,
130 NewRect.right - NewRect.left, NewRect.bottom - NewRect.top,
132 }
133 return hDwp;
134}
135
136static __inline void
138{
139 RECT rcClient;
140 UINT iItem;
141 HDWP hDwp = BeginDeferWindowPos(pData->m_cLayouts + 1);
142 if (hDwp == NULL)
143 return;
144
145 GetClientRect(pData->m_hwndParent, &rcClient);
146
147 for (iItem = 0; iItem < pData->m_cLayouts; ++iItem)
148 hDwp = _layout_DoMoveItem(pData, hDwp, &pData->m_pLayouts[iItem], &rcClient);
149
150 hDwp = _layout_MoveGrip(pData, hDwp);
151 EndDeferWindowPos(hDwp);
152}
153
154static __inline void
156{
157 RECT rcClient, rcChild, rcPercents;
158 LONG nWidth, nHeight;
159 UINT iItem;
160
161 GetClientRect(pData->m_hwndParent, &rcClient);
162 nWidth = rcClient.right - rcClient.left;
163 nHeight = rcClient.bottom - rcClient.top;
164
165 for (iItem = 0; iItem < pData->m_cLayouts; ++iItem)
166 {
167 LAYOUT_INFO *pInfo = &pData->m_pLayouts[iItem];
168 if (pInfo->m_hwndCtrl == NULL)
169 {
170 pInfo->m_hwndCtrl = GetDlgItem(pData->m_hwndParent, pInfo->m_nCtrlID);
171 if (pInfo->m_hwndCtrl == NULL)
172 continue;
173 }
174
175 GetWindowRect(pInfo->m_hwndCtrl, &rcChild);
176 MapWindowPoints(NULL, pData->m_hwndParent, (LPPOINT)&rcChild, 2);
177
178 _layout_GetPercents(&rcPercents, pInfo->m_uEdges);
179 pInfo->m_margin1.cx = rcChild.left - nWidth * rcPercents.left / 100;
180 pInfo->m_margin1.cy = rcChild.top - nHeight * rcPercents.top / 100;
181 pInfo->m_margin2.cx = rcChild.right - nWidth * rcPercents.right / 100;
182 pInfo->m_margin2.cy = rcChild.bottom - nHeight * rcPercents.bottom / 100;
183 }
184}
185
186/* NOTE: Please call LayoutUpdate on parent's WM_SIZE. */
187static __inline void
188LayoutUpdate(HWND ignored1, LAYOUT_DATA *pData, LPCVOID ignored2, UINT ignored3)
189{
190 UNREFERENCED_PARAMETER(ignored1);
191 UNREFERENCED_PARAMETER(ignored2);
192 UNREFERENCED_PARAMETER(ignored3);
193 if (pData == NULL || !pData->m_hwndParent)
194 return;
195 assert(IsWindow(pData->m_hwndParent));
197}
198
199static __inline void
201{
204}
205
206static __inline LAYOUT_DATA *
207LayoutInit(HWND hwndParent, const LAYOUT_INFO *pLayouts, INT cLayouts)
208{
209 BOOL bShowGrip;
210 SIZE_T cb;
212 if (pData == NULL)
213 {
214 assert(0);
215 return NULL;
216 }
217
218 if (cLayouts < 0) /* NOTE: If cLayouts was negative, then don't show size grip */
219 {
220 cLayouts = -cLayouts;
221 bShowGrip = FALSE;
222 }
223 else
224 {
225 bShowGrip = TRUE;
226 }
227
228 cb = cLayouts * sizeof(LAYOUT_INFO);
229 pData->m_cLayouts = cLayouts;
230 pData->m_pLayouts = (LAYOUT_INFO *)HeapAlloc(GetProcessHeap(), 0, cb);
231 if (pData->m_pLayouts == NULL)
232 {
233 assert(0);
235 return NULL;
236 }
237 memcpy(pData->m_pLayouts, pLayouts, cb);
238
240
241 pData->m_hwndParent = hwndParent;
242
243 pData->m_hwndGrip = NULL;
244 if (bShowGrip)
245 LayoutShowGrip(pData, bShowGrip);
246
248 return pData;
249}
250
251static __inline void
253{
254 if (!pData)
255 return;
256 HeapFree(GetProcessHeap(), 0, pData->m_pLayouts);
258}
Arabic default style
Definition: afstyles.h:94
static HWND hwndParent
Definition: cryptui.c:300
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT uFlags
Definition: api.c:59
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
#define assert(x)
Definition: debug.h:53
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
static __inline void LayoutEnableResize(LAYOUT_DATA *pData, BOOL bEnable)
Definition: layout.h:200
static __inline void _layout_ModifySystemMenu(LAYOUT_DATA *pData, BOOL bEnableResize)
Definition: layout.h:26
static __inline void _layout_ArrangeLayout(LAYOUT_DATA *pData)
Definition: layout.h:137
static __inline LAYOUT_DATA * LayoutInit(HWND hwndParent, const LAYOUT_INFO *pLayouts, INT cLayouts)
Definition: layout.h:207
static __inline void LayoutDestroy(LAYOUT_DATA *pData)
Definition: layout.h:252
static __inline HDWP _layout_DoMoveItem(LAYOUT_DATA *pData, HDWP hDwp, const LAYOUT_INFO *pLayout, const RECT *rcClient)
Definition: layout.h:108
static __inline void _layout_InitLayouts(LAYOUT_DATA *pData)
Definition: layout.h:155
static __inline HDWP _layout_MoveGrip(LAYOUT_DATA *pData, HDWP hDwp OPTIONAL)
Definition: layout.h:42
static __inline void LayoutUpdate(HWND ignored1, LAYOUT_DATA *pData, LPCVOID ignored2, UINT ignored3)
Definition: layout.h:188
static __inline void _layout_GetPercents(LPRECT prcPercents, UINT uEdges)
Definition: layout.h:99
static __inline void LayoutShowGrip(LAYOUT_DATA *pData, BOOL bShow)
Definition: layout.h:68
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
unsigned int UINT
Definition: ndis.h:50
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define L(x)
Definition: ntvdm.h:50
#define WS_CHILD
Definition: pedump.c:617
#define WS_SIZEBOX
Definition: pedump.c:642
#define WS_GROUP
Definition: pedump.c:633
long LONG
Definition: pedump.c:60
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
UINT m_cLayouts
Definition: layout.h:22
LAYOUT_INFO * m_pLayouts
Definition: layout.h:21
HWND m_hwndGrip
Definition: layout.h:20
HWND m_hwndParent
Definition: layout.h:19
UINT m_uEdges
Definition: layout.h:12
SIZE m_margin2
Definition: layout.h:15
HWND m_hwndCtrl
Definition: layout.h:13
SIZE m_margin1
Definition: layout.h:14
UINT m_nCtrlID
Definition: layout.h:11
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
_In_ BOOL bEnable
Definition: winddi.h:3426
CONST void * LPCVOID
Definition: windef.h:191
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define SW_HIDE
Definition: winuser.h:771
#define SWP_NOACTIVATE
Definition: winuser.h:1245
#define MF_BYCOMMAND
Definition: winuser.h:202
#define GetWindowLongPtrW
Definition: winuser.h:4832
#define SWP_NOREPOSITION
Definition: winuser.h:1253
#define SWP_FRAMECHANGED
Definition: winuser.h:1243
#define SBS_SIZEGRIP
Definition: winuser.h:332
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define SM_CXVSCROLL
Definition: winuser.h:964
#define SWP_NOMOVE
Definition: winuser.h:1247
#define BF_LEFT
Definition: winuser.h:454
#define SW_SHOWNOACTIVATE
Definition: winuser.h:777
#define SWP_NOSIZE
Definition: winuser.h:1248
#define BF_BOTTOM
Definition: winuser.h:457
HMENU WINAPI GetSystemMenu(_In_ HWND, _In_ BOOL)
BOOL WINAPI EndDeferWindowPos(_In_ HDWP)
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define SM_CYHSCROLL
Definition: winuser.h:965
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
#define SC_SIZE
Definition: winuser.h:2587
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define SWP_NOCOPYBITS
Definition: winuser.h:1246
#define BF_TOP
Definition: winuser.h:455
HWND WINAPI CreateWindowExW(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define BF_RIGHT
Definition: winuser.h:456
BOOL WINAPI RemoveMenu(_In_ HMENU, _In_ UINT, _In_ UINT)
#define SWP_NOOWNERZORDER
Definition: winuser.h:1252
HDWP WINAPI DeferWindowPos(_In_ HDWP, _In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define SWP_NOZORDER
Definition: winuser.h:1250
#define SetWindowLongPtrW
Definition: winuser.h:5358
#define GWL_STYLE
Definition: winuser.h:855
#define SC_RESTORE
Definition: winuser.h:2601
BOOL WINAPI IsWindowVisible(_In_ HWND)
BOOL WINAPI EqualRect(_In_ LPCRECT, _In_ LPCRECT)
int WINAPI GetSystemMetrics(_In_ int)
#define SC_MAXIMIZE
Definition: winuser.h:2591
HDWP WINAPI BeginDeferWindowPos(_In_ int)