1 /*
2  * ReactOS User32 Library
3  * - Window non-client area management
4  *
5  * Copyright (C) 2003 ReactOS Team
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include <user32.h>
23 
24 WINE_DEFAULT_DEBUG_CHANNEL(user32);
25 
26 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
27             ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE))  || \
28              ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
29              (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
30              (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
31 
32 
33 /* PRIVATE FUNCTIONS **********************************************************/
34 
35 BOOL
36 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
37 {
38    if (Style & WS_MINIMIZE)
39       return TRUE;
40    if (ExStyle & WS_EX_DLGMODALFRAME)
41       return TRUE;
42    if (ExStyle & WS_EX_STATICEDGE)
43       return FALSE;
44    if (Style & WS_THICKFRAME)
45       return TRUE;
46    Style &= WS_CAPTION;
47    if (Style == WS_DLGFRAME || Style == WS_CAPTION)
48       return TRUE;
49    return FALSE;
50 }
51 
52 VOID
53 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
54 {
55    DWORD Border = 0;
56 
57    if (UserHasWindowEdge(Style, ExStyle))
58       Border += 2;
59    else if (ExStyle & WS_EX_STATICEDGE)
60       Border += 1;
61    if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
62       Border += 2;
63    if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
64       Border ++;
65    Size->cx = Size->cy = Border;
66    if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
67    {
68       Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
69       Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
70    }
71    Size->cx *= GetSystemMetrics(SM_CXBORDER);
72    Size->cy *= GetSystemMetrics(SM_CYBORDER);
73 }
74 
75 /*
76  RealUserDrawCaption: This function is passed through RegisterUserApiHook to uxtheme
77                       to call it when the classic caption is needed to be drawn.
78  */
79 BOOL WINAPI
80 RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags)
81 {
82     ERR("Real DC flags %08x\n",uFlags);
83     return NtUserDrawCaption(hWnd, hDC, lpRc, uFlags);
84 }
85 
86 
87 /* PUBLIC FUNCTIONS ***********************************************************/
88 
89 BOOL WINAPI
90 RealAdjustWindowRectEx(LPRECT lpRect,
91                        DWORD dwStyle,
92                        BOOL bMenu,
93                        DWORD dwExStyle)
94 {
95    SIZE BorderSize;
96 
97    if (bMenu)
98    {
99       lpRect->top -= GetSystemMetrics(SM_CYMENU);
100    }
101    if ((dwStyle & WS_CAPTION) == WS_CAPTION)
102    {
103       if (dwExStyle & WS_EX_TOOLWINDOW)
104          lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
105       else
106          lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
107    }
108    UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
109    InflateRect(
110       lpRect,
111       BorderSize.cx,
112       BorderSize.cy);
113 
114    return TRUE;
115 }
116 
117 /*
118  * @implemented
119  */
120 BOOL
121 WINAPI
122 DECLSPEC_HOTPATCH
123 AdjustWindowRectEx(LPRECT lpRect,
124 		   DWORD dwStyle,
125 		   BOOL bMenu,
126 		   DWORD dwExStyle)
127 {
128    BOOL Hook, Ret = FALSE;
129 
130    LoadUserApiHook();
131 
132    Hook = BeginIfHookedUserApiHook();
133 
134      /* Bypass SEH and go direct. */
135    if (!Hook) return RealAdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
136 
137    _SEH2_TRY
138    {
139       Ret = guah.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
140    }
141    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
142    {
143    }
144    _SEH2_END;
145 
146    EndUserApiHook();
147 
148    return Ret;
149 }
150 
151 
152 /*
153  * @implemented
154  */
155 BOOL
156 WINAPI
157 DECLSPEC_HOTPATCH
158 AdjustWindowRect(LPRECT lpRect,
159 		 DWORD dwStyle,
160 		 BOOL bMenu)
161 {
162    return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
163 }
164 
165 // Enabling this will cause captions to draw smoother, but slower:
166 #define DOUBLE_BUFFER_CAPTION
167 
168 /*
169  * @implemented
170  */
171 BOOL WINAPI
172 DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
173 {
174    BOOL Hook, Ret = FALSE;
175 
176    LoadUserApiHook();
177 
178    Hook = BeginIfHookedUserApiHook();
179 
180    /* Bypass SEH and go direct. */
181    if (!Hook) return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
182 
183    _SEH2_TRY
184    {
185       Ret = guah.DrawCaption(hWnd, hDC, lprc, uFlags);
186    }
187    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
188    {
189    }
190    _SEH2_END;
191 
192    EndUserApiHook();
193 
194    return Ret;
195 }
196 
197 /*
198  * @implemented
199  */
200 BOOL
201 WINAPI
202 DrawCaptionTempW(
203 		 HWND        hWnd,
204 		 HDC         hDC,
205 		 const RECT *rect,
206 		 HFONT       hFont,
207 		 HICON       hIcon,
208 		 LPCWSTR     str,
209 		 UINT        uFlags
210 		 )
211 {
212    UNICODE_STRING Text = {0};
213    RtlInitUnicodeString(&Text, str);
214    return NtUserDrawCaptionTemp(hWnd, hDC, rect, hFont, hIcon, &Text, uFlags);
215 }
216 
217 /*
218  * @implemented
219  */
220 BOOL
221 WINAPI
222 DrawCaptionTempA(
223 		 HWND        hwnd,
224 		 HDC         hdc,
225 		 const RECT *rect,
226 		 HFONT       hFont,
227 		 HICON       hIcon,
228 		 LPCSTR      str,
229 		 UINT        uFlags
230 		 )
231 {
232   LPWSTR strW;
233   INT len;
234   BOOL ret = FALSE;
235 
236   if (!(uFlags & DC_TEXT) || !str)
237     return DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, NULL, uFlags);
238 
239   len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
240   if ((strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
241   {
242     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len );
243     ret = DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
244     HeapFree(GetProcessHeap(), 0, strW);
245   }
246   return ret;
247 }
248