* Sync to trunk HEAD (r53473).
[reactos.git] / dll / win32 / user32 / windows / nonclient.c
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 /* INCLUDES *******************************************************************/
23
24 #include <user32.h>
25
26 #include <wine/debug.h>
27
28 #define HAS_DLGFRAME(Style, ExStyle) \
29 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
30 (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))
31
32 #define HAS_THICKFRAME(Style, ExStyle) \
33 (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
34 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
35
36 #define HAS_THINFRAME(Style, ExStyle) \
37 (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))
38
39 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
40 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
41 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
42 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
43 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
44
45 #ifndef STATE_SYSTEM_OFFSCREEN
46 #define STATE_SYSTEM_OFFSCREEN 0x00010000
47 #endif
48
49 /*
50 * FIXME: This should be moved to a header
51 */
52 VOID
53 IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar);
54 DWORD
55 IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging);
56
57 BOOL WINAPI GdiGradientFill(HDC,PTRIVERTEX,ULONG,PVOID,ULONG,ULONG);
58
59 extern ATOM AtomInternalPos;
60
61 /* PRIVATE FUNCTIONS **********************************************************/
62
63 BOOL
64 IntIsScrollBarVisible(HWND hWnd, INT hBar)
65 {
66 SCROLLBARINFO sbi;
67 sbi.cbSize = sizeof(SCROLLBARINFO);
68 if(!NtUserGetScrollBarInfo(hWnd, hBar, &sbi))
69 return FALSE;
70
71 return !(sbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN);
72 }
73
74 BOOL
75 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
76 {
77 if (Style & WS_MINIMIZE)
78 return TRUE;
79 if (ExStyle & WS_EX_DLGMODALFRAME)
80 return TRUE;
81 if (ExStyle & WS_EX_STATICEDGE)
82 return FALSE;
83 if (Style & WS_THICKFRAME)
84 return TRUE;
85 Style &= WS_CAPTION;
86 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
87 return TRUE;
88 return FALSE;
89 }
90
91 VOID
92 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
93 {
94 DWORD Border = 0;
95
96 if (UserHasWindowEdge(Style, ExStyle))
97 Border += 2;
98 else if (ExStyle & WS_EX_STATICEDGE)
99 Border += 1;
100 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
101 Border += 2;
102 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
103 Border ++;
104 Size->cx = Size->cy = Border;
105 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
106 {
107 Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
108 Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
109 }
110 Size->cx *= GetSystemMetrics(SM_CXBORDER);
111 Size->cy *= GetSystemMetrics(SM_CYBORDER);
112 }
113
114 BOOL
115 UserHasMenu(HWND hWnd, ULONG Style)
116 {
117 return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
118 }
119
120 HICON
121 UserGetWindowIcon(HWND hwnd)
122 {
123 HICON hIcon = 0;
124
125 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
126
127 if (!hIcon)
128 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
129
130 if (!hIcon)
131 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
132
133 if (!hIcon)
134 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM);
135
136 if (!hIcon)
137 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON);
138
139 return hIcon;
140 }
141
142 BOOL
143 UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL Down)
144 {
145 HICON WindowIcon;
146
147 if ((WindowIcon = UserGetWindowIcon(hWnd)))
148 {
149 return DrawIconEx(hDC, Rect->left + 2, Rect->top + 2, WindowIcon,
150 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
151 0, NULL, DI_NORMAL);
152 }
153
154 return FALSE;
155 }
156
157 /*
158 * FIXME:
159 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
160 * wasting precious CPU cycles) every time
161 * - Center the buttons verticaly in the rect
162 */
163 VOID
164 UserDrawCaptionButton(HWND hWnd, LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hDC, BOOL bDown, ULONG Type)
165 {
166 RECT TempRect;
167
168 if (!(Style & WS_SYSMENU))
169 {
170 return;
171 }
172
173 TempRect = *Rect;
174
175 switch (Type)
176 {
177 case DFCS_CAPTIONMIN:
178 {
179 if (ExStyle & WS_EX_TOOLWINDOW)
180 return; /* ToolWindows don't have min/max buttons */
181
182 if (Style & WS_SYSMENU)
183 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
184 if (Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
185 TempRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
186 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
187 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
188 TempRect.top += 2;
189 TempRect.right -= 1;
190
191 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
192 ((Style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN) |
193 (bDown ? DFCS_PUSHED : 0) |
194 ((Style & WS_MINIMIZEBOX) ? 0 : DFCS_INACTIVE));
195 break;
196 }
197 case DFCS_CAPTIONMAX:
198 {
199 if (ExStyle & WS_EX_TOOLWINDOW)
200 return; /* ToolWindows don't have min/max buttons */
201
202 if (Style & WS_SYSMENU)
203 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
204 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
205 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
206 TempRect.top += 2;
207 TempRect.right -= 1;
208
209 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
210 ((Style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
211 (bDown ? DFCS_PUSHED : 0) |
212 ((Style & WS_MAXIMIZEBOX) ? 0 : DFCS_INACTIVE));
213 break;
214 }
215 case DFCS_CAPTIONCLOSE:
216 {
217 HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
218 UINT MenuState = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); /* in case of error MenuState==0xFFFFFFFF */
219
220 /* FIXME: A tool window has a smaller Close button */
221
222 if (ExStyle & WS_EX_TOOLWINDOW)
223 {
224 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSMSIZE);
225 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMSIZE) - 2;
226 }
227 else
228 {
229 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE);
230 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
231 }
232 TempRect.top += 2;
233 TempRect.right -= 2;
234
235 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
236 (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
237 ((!(MenuState & (MF_GRAYED|MF_DISABLED)) && !(GetClassLong(hWnd, GCL_STYLE) & CS_NOCLOSE)) ? 0 : DFCS_INACTIVE)));
238 break;
239 }
240 }
241 }
242
243 VOID
244 UserDrawCaptionButtonWnd(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
245 {
246 RECT WindowRect;
247 SIZE WindowBorder;
248 DWORD Style, ExStyle;
249
250 GetWindowRect(hWnd, &WindowRect);
251 WindowRect.right -= WindowRect.left;
252 WindowRect.bottom -= WindowRect.top;
253 WindowRect.left = WindowRect.top = 0;
254 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
255 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
256 UserGetWindowBorders(Style, ExStyle, &WindowBorder, FALSE);
257 InflateRect(&WindowRect, -WindowBorder.cx, -WindowBorder.cy);
258 UserDrawCaptionButton(hWnd, &WindowRect, Style, ExStyle, hDC, bDown, Type);
259 }
260
261 // Note from Wine:
262 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
263 the call to GetDCEx implying that it is allowed not to use it either.
264 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
265 will cause clipRgn to be deleted after ReleaseDC().
266 Now, how is the "system" supposed to tell what happened?
267 */
268 /*
269 * FIXME:
270 * - Drawing of WS_BORDER after scrollbars
271 * - Correct drawing of size-box
272 */
273 LRESULT
274 DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active)
275 {
276 HDC hDC;
277 DWORD Style, ExStyle;
278 HWND Parent;
279 RECT ClientRect, WindowRect, CurrentRect, TempRect;
280
281 if (!IsWindowVisible(hWnd))
282 return 0;
283
284 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
285
286 hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
287 if (hDC == 0)
288 {
289 return 0;
290 }
291
292 Parent = GetParent(hWnd);
293 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
294 if (Active == -1)
295 {
296 if (ExStyle & WS_EX_MDICHILD)
297 {
298 Active = IsChild(GetForegroundWindow(), hWnd);
299 if (Active)
300 Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));
301 }
302 else
303 {
304 Active = (GetForegroundWindow() == hWnd);
305 }
306 }
307 GetWindowRect(hWnd, &WindowRect);
308 GetClientRect(hWnd, &ClientRect);
309
310 CurrentRect.top = CurrentRect.left = 0;
311 CurrentRect.right = WindowRect.right - WindowRect.left;
312 CurrentRect.bottom = WindowRect.bottom - WindowRect.top;
313
314 /* Draw outer edge */
315 if (UserHasWindowEdge(Style, ExStyle))
316 {
317 DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);
318 } else
319 if (ExStyle & WS_EX_STATICEDGE)
320 {
321 #if 0
322 DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
323 #else
324 SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
325 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
326 PatBlt(hDC, CurrentRect.left, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);
327
328 SelectObject(hDC, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
329 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
330 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);
331
332 InflateRect(&CurrentRect, -1, -1);
333 #endif
334 }
335
336 /* Firstly the "thick" frame */
337 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
338 {
339 DWORD Width =
340 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
341 GetSystemMetrics(SM_CXBORDER);
342 DWORD Height =
343 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
344 GetSystemMetrics(SM_CYBORDER);
345
346 SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :
347 COLOR_INACTIVEBORDER));
348
349 /* Draw frame */
350 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
351 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
352 #ifdef __REACTOS__
353 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
354 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
355 #else
356 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
357 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
358 #endif
359
360 InflateRect(&CurrentRect, -Width, -Height);
361 }
362
363 /* Now the other bit of the frame */
364 if (Style & (WS_DLGFRAME | WS_BORDER) || ExStyle & WS_EX_DLGMODALFRAME)
365 {
366 DWORD Width = GetSystemMetrics(SM_CXBORDER);
367 DWORD Height = GetSystemMetrics(SM_CYBORDER);
368
369 SelectObject(hDC, GetSysColorBrush(
370 (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
371 (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
372 (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
373 COLOR_WINDOWFRAME));
374
375 /* Draw frame */
376 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
377 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
378 #ifdef __REACTOS__
379 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
380 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
381 #else
382 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
383 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
384 #endif
385
386 InflateRect(&CurrentRect, -Width, -Height);
387 }
388
389 /* Draw caption */
390 if ((Style & WS_CAPTION) == WS_CAPTION)
391 {
392 DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;
393 HPEN PreviousPen;
394 BOOL Gradient = FALSE;
395
396 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)
397 {
398 CaptionFlags |= DC_GRADIENT;
399 }
400
401 TempRect = CurrentRect;
402
403 if (Active)
404 {
405 CaptionFlags |= DC_ACTIVE;
406 }
407
408 if (ExStyle & WS_EX_TOOLWINDOW)
409 {
410 CaptionFlags |= DC_SMALLCAP;
411 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1;
412 CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);
413 }
414 else
415 {
416 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;
417 CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);
418 }
419
420 NtUserDrawCaption(hWnd, hDC, &TempRect, CaptionFlags);
421
422 /* Draw buttons */
423 if (Style & WS_SYSMENU)
424 {
425 UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);
426 if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))
427 {
428 UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);
429 UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);
430 }
431 }
432 if(!(Style & WS_MINIMIZE))
433 {
434 /* Line under caption */
435 PreviousPen = SelectObject(hDC, GetStockObject(DC_PEN));
436 SetDCPenColor(hDC, GetSysColor(
437 ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |
438 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
439 COLOR_WINDOWFRAME : COLOR_3DFACE));
440 MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);
441 LineTo(hDC, TempRect.right, TempRect.bottom);
442 SelectObject(hDC, PreviousPen);
443 }
444 }
445
446 if(!(Style & WS_MINIMIZE))
447 {
448 HMENU menu = GetMenu(hWnd);
449 /* Draw menu bar */
450 if (menu && !(Style & WS_CHILD))
451 {
452 TempRect = CurrentRect;
453 TempRect.bottom = TempRect.top + (UINT)NtUserxSetMenuBarHeight(menu, 0);
454 CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, FALSE);
455 }
456
457 if (ExStyle & WS_EX_CLIENTEDGE)
458 {
459 DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
460 }
461
462 /* Draw the scrollbars */
463 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
464 IntIsScrollBarVisible(hWnd, OBJID_VSCROLL) && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
465 {
466 RECT ParentClientRect;
467
468 TempRect = CurrentRect;
469 if (ExStyle & WS_EX_LEFTSCROLLBAR)
470 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
471 else
472 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
473 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
474 FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_BTNFACE));
475 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
476 if(Parent)
477 GetClientRect(Parent, &ParentClientRect);
478 if (HASSIZEGRIP(Style, ExStyle, GetWindowLongPtrW(Parent, GWL_STYLE), WindowRect, ParentClientRect))
479 {
480 DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
481 }
482 IntDrawScrollBar(hWnd, hDC, SB_VERT);
483 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
484 }
485 else
486 {
487 if (Style & WS_VSCROLL && IntIsScrollBarVisible(hWnd, OBJID_VSCROLL))
488 IntDrawScrollBar(hWnd, hDC, SB_VERT);
489 else if (Style & WS_HSCROLL && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
490 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
491 }
492 }
493
494 ReleaseDC(hWnd, hDC);
495 if (hRgn != HRGN_WINDOW)
496 DeleteObject(hRgn); // We use DCX_KEEPCLIPRGN
497
498 return 0;
499 }
500
501 LRESULT
502 DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect)
503 {
504 LRESULT Result = 0;
505 DWORD Style = GetClassLongPtrW(hWnd, GCL_STYLE);
506 DWORD ExStyle;
507 SIZE WindowBorders;
508 RECT OrigRect;
509
510 if (Rect == NULL)
511 {
512 return Result;
513 }
514 OrigRect = *Rect;
515
516 if (CalcSizeStruct)
517 {
518 if (Style & CS_VREDRAW)
519 {
520 Result |= WVR_VREDRAW;
521 }
522 if (Style & CS_HREDRAW)
523 {
524 Result |= WVR_HREDRAW;
525 }
526 Result |= WVR_VALIDRECTS;
527 }
528
529 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
530 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
531
532 if (!(Style & WS_MINIMIZE))
533 {
534 HMENU menu = GetMenu(hWnd);
535
536 if (UserHasWindowEdge(Style, ExStyle))
537 {
538 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
539 InflateRect(Rect, -WindowBorders.cx, -WindowBorders.cy);
540 } else
541 if ((ExStyle & WS_EX_STATICEDGE) || (Style & WS_BORDER))
542 {
543 InflateRect(Rect, -1, -1);
544 }
545
546 if ((Style & WS_CAPTION) == WS_CAPTION)
547 {
548 if (ExStyle & WS_EX_TOOLWINDOW)
549 Rect->top += GetSystemMetrics(SM_CYSMCAPTION);
550 else
551 Rect->top += GetSystemMetrics(SM_CYCAPTION);
552 }
553
554 if (menu && !(Style & WS_CHILD))
555 {
556 HDC hDC = GetWindowDC(hWnd);
557 if(hDC)
558 {
559 RECT CliRect = *Rect;
560 CliRect.bottom -= OrigRect.top;
561 CliRect.right -= OrigRect.left;
562 CliRect.left -= OrigRect.left;
563 CliRect.top -= OrigRect.top;
564 Rect->top += MenuDrawMenuBar(hDC, &CliRect, hWnd, TRUE);
565 ReleaseDC(hWnd, hDC);
566 }
567 }
568
569 if (ExStyle & WS_EX_CLIENTEDGE)
570 {
571 InflateRect(Rect, -2 * GetSystemMetrics(SM_CXBORDER),
572 -2 * GetSystemMetrics(SM_CYBORDER));
573 }
574
575 if(Style & (WS_VSCROLL | WS_HSCROLL))
576 {
577 SCROLLBARINFO sbi;
578 SETSCROLLBARINFO ssbi;
579
580 sbi.cbSize = sizeof(SCROLLBARINFO);
581 if((Style & WS_VSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_VSCROLL, &sbi))
582 {
583 int i;
584 LONG sx = Rect->right;
585
586 sx -= GetSystemMetrics(SM_CXVSCROLL);
587 for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
588 ssbi.rgstate[i] = sbi.rgstate[i];
589 if(sx <= Rect->left)
590 ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
591 else
592 ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
593 NtUserSetScrollBarInfo(hWnd, OBJID_VSCROLL, &ssbi);
594 if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
595 Style &= ~WS_VSCROLL;
596 }
597 else
598 Style &= ~WS_VSCROLL;
599
600 if((Style & WS_HSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_HSCROLL, &sbi))
601 {
602 int i;
603 LONG sy = Rect->bottom;
604
605 sy -= GetSystemMetrics(SM_CYHSCROLL);
606 for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
607 ssbi.rgstate[i] = sbi.rgstate[i];
608 if(sy <= Rect->top)
609 ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
610 else
611 ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
612 NtUserSetScrollBarInfo(hWnd, OBJID_HSCROLL, &ssbi);
613 if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
614 Style &= ~WS_HSCROLL;
615 }
616 else
617 Style &= ~WS_HSCROLL;
618 }
619
620 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL))
621 {
622 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
623 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
624 else
625 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
626 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
627 }
628 else
629 {
630 if (Style & WS_VSCROLL)
631 {
632 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
633 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
634 else
635 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
636 }
637 else if (Style & WS_HSCROLL)
638 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
639 }
640 if (Rect->top > Rect->bottom)
641 Rect->bottom = Rect->top;
642 if (Rect->left > Rect->right)
643 Rect->right = Rect->left;
644 }
645 else
646 {
647 Rect->right = Rect->left;
648 Rect->bottom = Rect->top;
649 }
650
651 return Result;
652 }
653
654 LRESULT
655 DefWndNCActivate(HWND hWnd, WPARAM wParam)
656 {
657 DefWndNCPaint(hWnd, HRGN_WINDOW, wParam);
658 return TRUE;
659 }
660
661 /*
662 * FIXME:
663 * - Check the scrollbar handling
664 */
665 LRESULT
666 DefWndNCHitTest(HWND hWnd, POINT Point)
667 {
668 RECT WindowRect, ClientRect, OrigWndRect;
669 POINT ClientPoint;
670 SIZE WindowBorders;
671 DWORD Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
672 DWORD ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
673
674 GetWindowRect(hWnd, &WindowRect);
675 if (!PtInRect(&WindowRect, Point))
676 {
677 return HTNOWHERE;
678 }
679 OrigWndRect = WindowRect;
680
681 if (UserHasWindowEdge(Style, ExStyle))
682 {
683 LONG XSize, YSize;
684
685 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
686 InflateRect(&WindowRect, -WindowBorders.cx, -WindowBorders.cy);
687 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
688 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
689 if (!PtInRect(&WindowRect, Point))
690 {
691 BOOL ThickFrame;
692
693 ThickFrame = (Style & WS_THICKFRAME);
694 if (Point.y < WindowRect.top)
695 {
696 if(Style & WS_MINIMIZE)
697 return HTCAPTION;
698 if(!ThickFrame)
699 return HTBORDER;
700 if (Point.x < (WindowRect.left + XSize))
701 return HTTOPLEFT;
702 if (Point.x >= (WindowRect.right - XSize))
703 return HTTOPRIGHT;
704 return HTTOP;
705 }
706 if (Point.y >= WindowRect.bottom)
707 {
708 if(Style & WS_MINIMIZE)
709 return HTCAPTION;
710 if(!ThickFrame)
711 return HTBORDER;
712 if (Point.x < (WindowRect.left + XSize))
713 return HTBOTTOMLEFT;
714 if (Point.x >= (WindowRect.right - XSize))
715 return HTBOTTOMRIGHT;
716 return HTBOTTOM;
717 }
718 if (Point.x < WindowRect.left)
719 {
720 if(Style & WS_MINIMIZE)
721 return HTCAPTION;
722 if(!ThickFrame)
723 return HTBORDER;
724 if (Point.y < (WindowRect.top + YSize))
725 return HTTOPLEFT;
726 if (Point.y >= (WindowRect.bottom - YSize))
727 return HTBOTTOMLEFT;
728 return HTLEFT;
729 }
730 if (Point.x >= WindowRect.right)
731 {
732 if(Style & WS_MINIMIZE)
733 return HTCAPTION;
734 if(!ThickFrame)
735 return HTBORDER;
736 if (Point.y < (WindowRect.top + YSize))
737 return HTTOPRIGHT;
738 if (Point.y >= (WindowRect.bottom - YSize))
739 return HTBOTTOMRIGHT;
740 return HTRIGHT;
741 }
742 }
743 }
744 else
745 {
746 if (ExStyle & WS_EX_STATICEDGE)
747 InflateRect(&WindowRect,
748 -GetSystemMetrics(SM_CXBORDER),
749 -GetSystemMetrics(SM_CYBORDER));
750 if (!PtInRect(&WindowRect, Point))
751 return HTBORDER;
752 }
753
754 if ((Style & WS_CAPTION) == WS_CAPTION)
755 {
756 if (ExStyle & WS_EX_TOOLWINDOW)
757 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
758 else
759 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
760 if (!PtInRect(&WindowRect, Point))
761 {
762 if (Style & WS_SYSMENU)
763 {
764 if (ExStyle & WS_EX_TOOLWINDOW)
765 {
766 WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE);
767 }
768 else
769 {
770 if(!(ExStyle & WS_EX_DLGMODALFRAME))
771 WindowRect.left += GetSystemMetrics(SM_CXSIZE);
772 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
773 }
774 }
775 if (Point.x < WindowRect.left)
776 return HTSYSMENU;
777 if (WindowRect.right <= Point.x)
778 return HTCLOSE;
779 if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
780 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
781 if (Point.x >= WindowRect.right)
782 return HTMAXBUTTON;
783 if (Style & WS_MINIMIZEBOX)
784 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
785 if (Point.x >= WindowRect.right)
786 return HTMINBUTTON;
787 return HTCAPTION;
788 }
789 }
790
791 if(!(Style & WS_MINIMIZE))
792 {
793 ClientPoint = Point;
794 ScreenToClient(hWnd, &ClientPoint);
795 GetClientRect(hWnd, &ClientRect);
796
797 if (PtInRect(&ClientRect, ClientPoint))
798 {
799 return HTCLIENT;
800 }
801
802 if (GetMenu(hWnd) && !(Style & WS_CHILD))
803 {
804 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
805 return HTMENU;
806 }
807
808 if (ExStyle & WS_EX_CLIENTEDGE)
809 {
810 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
811 -2 * GetSystemMetrics(SM_CYBORDER));
812 }
813
814 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
815 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
816 {
817 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
818 HWND Parent = GetParent(hWnd);
819
820 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
821 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
822 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
823 else
824 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
825 if (PtInRect(&TempRect, Point))
826 return HTVSCROLL;
827
828 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
829 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
830 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
831 else
832 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
833 if (PtInRect(&TempRect2, Point))
834 return HTHSCROLL;
835
836 TempRect.top = TempRect2.top;
837 TempRect.bottom = TempRect2.bottom;
838 if(Parent)
839 GetClientRect(Parent, &ParentRect);
840 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(Style, ExStyle,
841 GetWindowLongPtrW(Parent, GWL_STYLE), OrigWndRect, ParentRect))
842 {
843 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
844 return HTBOTTOMLEFT;
845 else
846 return HTBOTTOMRIGHT;
847 }
848 }
849 else
850 {
851 if (Style & WS_VSCROLL)
852 {
853 RECT TempRect = WindowRect;
854
855 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
856 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
857 else
858 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
859 if (PtInRect(&TempRect, Point))
860 return HTVSCROLL;
861 } else
862 if (Style & WS_HSCROLL)
863 {
864 RECT TempRect = WindowRect;
865 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
866 if (PtInRect(&TempRect, Point))
867 return HTHSCROLL;
868 }
869 }
870 }
871
872 return HTNOWHERE;
873 }
874
875 VOID
876 DefWndDoButton(HWND hWnd, WPARAM wParam)
877 {
878 MSG Msg;
879 HDC WindowDC;
880 BOOL Pressed = TRUE, OldState;
881 WPARAM SCMsg;
882 HMENU hSysMenu;
883 ULONG ButtonType;
884 DWORD Style;
885 UINT MenuState;
886
887 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
888 switch (wParam)
889 {
890 case HTCLOSE:
891 hSysMenu = GetSystemMenu(hWnd, FALSE);
892 MenuState = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); /* in case of error MenuState==0xFFFFFFFF */
893 if (!(Style & WS_SYSMENU) || (MenuState & (MF_GRAYED|MF_DISABLED)) || (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_NOCLOSE))
894 return;
895 ButtonType = DFCS_CAPTIONCLOSE;
896 SCMsg = SC_CLOSE;
897 break;
898 case HTMINBUTTON:
899 if (!(Style & WS_MINIMIZEBOX))
900 return;
901 ButtonType = DFCS_CAPTIONMIN;
902 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
903 break;
904 case HTMAXBUTTON:
905 if (!(Style & WS_MAXIMIZEBOX))
906 return;
907 ButtonType = DFCS_CAPTIONMAX;
908 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
909 break;
910
911 default:
912 ASSERT(FALSE);
913 return;
914 }
915
916 /*
917 * FIXME: Not sure where to do this, but we must flush the pending
918 * window updates when someone clicks on the close button and at
919 * the same time the window is overlapped with another one. This
920 * looks like a good place for now...
921 */
922 UpdateWindow(hWnd);
923
924 WindowDC = GetWindowDC(hWnd);
925 UserDrawCaptionButtonWnd(hWnd, WindowDC, TRUE, ButtonType);
926
927 SetCapture(hWnd);
928
929 for (;;)
930 {
931 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
932 break;
933
934 if (Msg.message == WM_LBUTTONUP)
935 break;
936
937 if (Msg.message != WM_MOUSEMOVE)
938 continue;
939
940 OldState = Pressed;
941 Pressed = (DefWndNCHitTest(hWnd, Msg.pt) == wParam);
942 if (Pressed != OldState)
943 UserDrawCaptionButtonWnd(hWnd, WindowDC, Pressed, ButtonType);
944 }
945
946 if (Pressed)
947 UserDrawCaptionButtonWnd(hWnd, WindowDC, FALSE, ButtonType);
948 ReleaseCapture();
949 ReleaseDC(hWnd, WindowDC);
950 if (Pressed)
951 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
952 }
953
954
955 LRESULT
956 DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
957 {
958 switch (wParam)
959 {
960 case HTCAPTION:
961 {
962 HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
963 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
964 {
965 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
966 }
967 break;
968 }
969 case HTSYSMENU:
970 {
971 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_SYSMENU)
972 {
973 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
974 lParam);
975 }
976 break;
977 }
978 case HTMENU:
979 {
980 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
981 break;
982 }
983 case HTHSCROLL:
984 {
985 SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
986 break;
987 }
988 case HTVSCROLL:
989 {
990 SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
991 break;
992 }
993 case HTMINBUTTON:
994 case HTMAXBUTTON:
995 case HTCLOSE:
996 {
997 DefWndDoButton(hWnd, wParam);
998 break;
999 }
1000 case HTLEFT:
1001 case HTRIGHT:
1002 case HTTOP:
1003 case HTBOTTOM:
1004 case HTTOPLEFT:
1005 case HTTOPRIGHT:
1006 case HTBOTTOMLEFT:
1007 case HTBOTTOMRIGHT:
1008 {
1009 SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT - WMSZ_LEFT), lParam);
1010 break;
1011 }
1012 }
1013 return(0);
1014 }
1015
1016
1017 LRESULT
1018 DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
1019 {
1020 ULONG Style;
1021
1022 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
1023 switch(wParam)
1024 {
1025 case HTCAPTION:
1026 {
1027 /* Maximize/Restore the window */
1028 if((Style & WS_CAPTION) == WS_CAPTION && (Style & WS_MAXIMIZEBOX))
1029 {
1030 SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
1031 }
1032 break;
1033 }
1034 case HTSYSMENU:
1035 {
1036 SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1037 break;
1038 }
1039 default:
1040 return DefWndNCLButtonDown(hWnd, wParam, lParam);
1041 }
1042 return(0);
1043 }
1044
1045 VOID
1046 DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point)
1047 {
1048 INT ScrollBar;
1049
1050 if ((wParam & 0xfff0) == SC_HSCROLL)
1051 {
1052 if ((wParam & 0x0f) != HTHSCROLL)
1053 return;
1054 ScrollBar = SB_HORZ;
1055 }
1056 else
1057 {
1058 if ((wParam & 0x0f) != HTVSCROLL)
1059 return;
1060 ScrollBar = SB_VERT;
1061 }
1062
1063 /* FIXME */
1064 }
1065
1066 /* PUBLIC FUNCTIONS ***********************************************************/
1067
1068 BOOL WINAPI
1069 RealAdjustWindowRectEx(LPRECT lpRect,
1070 DWORD dwStyle,
1071 BOOL bMenu,
1072 DWORD dwExStyle)
1073 {
1074 SIZE BorderSize;
1075
1076 if (bMenu)
1077 {
1078 lpRect->top -= GetSystemMetrics(SM_CYMENU);
1079 }
1080 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1081 {
1082 if (dwExStyle & WS_EX_TOOLWINDOW)
1083 lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
1084 else
1085 lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
1086 }
1087 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
1088 InflateRect(
1089 lpRect,
1090 BorderSize.cx,
1091 BorderSize.cy);
1092
1093 return TRUE;
1094 }
1095
1096 /*
1097 * @implemented
1098 */
1099 BOOL WINAPI
1100 AdjustWindowRectEx(LPRECT lpRect,
1101 DWORD dwStyle,
1102 BOOL bMenu,
1103 DWORD dwExStyle)
1104 {
1105 BOOL Hook, Ret = FALSE;
1106
1107 LoadUserApiHook();
1108
1109 Hook = BeginIfHookedUserApiHook();
1110
1111 /* Bypass SEH and go direct. */
1112 if (!Hook) return RealAdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
1113
1114 _SEH2_TRY
1115 {
1116 Ret = guah.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
1117 }
1118 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1119 {
1120 }
1121 _SEH2_END;
1122
1123 EndUserApiHook();
1124
1125 return Ret;
1126 }
1127
1128
1129 /*
1130 * @implemented
1131 */
1132 BOOL WINAPI
1133 AdjustWindowRect(LPRECT lpRect,
1134 DWORD dwStyle,
1135 BOOL bMenu)
1136 {
1137 return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
1138 }
1139
1140 // Enabling this will cause captions to draw smoother, but slower:
1141 #define DOUBLE_BUFFER_CAPTION
1142
1143 /*
1144 * @implemented
1145 */
1146 BOOL WINAPI
1147 DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
1148 {
1149 BOOL Hook, Ret = FALSE;
1150
1151 LoadUserApiHook();
1152
1153 Hook = BeginIfHookedUserApiHook();
1154
1155 /* Bypass SEH and go direct. */
1156 if (!Hook) return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
1157
1158 _SEH2_TRY
1159 {
1160 Ret = guah.DrawCaption(hWnd, hDC, lprc, uFlags);
1161 }
1162 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1163 {
1164 }
1165 _SEH2_END;
1166
1167 EndUserApiHook();
1168
1169 return Ret;
1170 }
1171
1172 /*
1173 * @implemented
1174 */
1175 BOOL
1176 WINAPI
1177 DrawCaptionTempW(
1178 HWND hWnd,
1179 HDC hDC,
1180 const RECT *rect,
1181 HFONT hFont,
1182 HICON hIcon,
1183 LPCWSTR str,
1184 UINT uFlags
1185 )
1186 {
1187 UNICODE_STRING Text = {0};
1188 RtlInitUnicodeString(&Text, str);
1189 return NtUserDrawCaptionTemp(hWnd, hDC, rect, hFont, hIcon, &Text, uFlags);
1190 }
1191
1192 /*
1193 * @implemented
1194 */
1195 BOOL
1196 WINAPI
1197 DrawCaptionTempA(
1198 HWND hwnd,
1199 HDC hdc,
1200 const RECT *rect,
1201 HFONT hFont,
1202 HICON hIcon,
1203 LPCSTR str,
1204 UINT uFlags
1205 )
1206 {
1207 LPWSTR strW;
1208 INT len;
1209 BOOL ret = FALSE;
1210
1211 if (!(uFlags & DC_TEXT) || !str)
1212 return DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, NULL, uFlags);
1213
1214 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1215 if ((strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
1216 {
1217 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len );
1218 ret = DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
1219 HeapFree(GetProcessHeap(), 0, strW);
1220 }
1221 return ret;
1222 }
1223
1224 /***********************************************************************
1225 * NcGetInsideRect
1226 *
1227 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1228 * but without the borders (if any).
1229 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1230 */
1231 static void FASTCALL
1232 NcGetInsideRect(HWND Wnd, RECT *Rect)
1233 {
1234 DWORD Style;
1235 DWORD ExStyle;
1236
1237 GetWindowRect(Wnd, Rect);
1238 Rect->right = Rect->right - Rect->left;
1239 Rect->left = 0;
1240 Rect->bottom = Rect->bottom - Rect->top;
1241 Rect->top = 0;
1242
1243 Style = GetWindowLongPtrW(Wnd, GWL_STYLE);
1244 if (0 != (Style & WS_ICONIC))
1245 {
1246 return;
1247 }
1248
1249 /* Remove frame from rectangle */
1250 ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE);
1251 if (HAS_THICKFRAME(Style, ExStyle))
1252 {
1253 InflateRect(Rect, - GetSystemMetrics(SM_CXFRAME), - GetSystemMetrics(SM_CYFRAME));
1254 }
1255 else if (HAS_DLGFRAME(Style, ExStyle))
1256 {
1257 InflateRect(Rect, - GetSystemMetrics(SM_CXDLGFRAME), - GetSystemMetrics(SM_CYDLGFRAME));
1258 }
1259 else if (HAS_THINFRAME(Style, ExStyle))
1260 {
1261 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1262 }
1263
1264 /* We have additional border information if the window
1265 * is a child (but not an MDI child) */
1266 if (0 != (Style & WS_CHILD)
1267 && 0 == (ExStyle & WS_EX_MDICHILD))
1268 {
1269 if (0 != (ExStyle & WS_EX_CLIENTEDGE))
1270 {
1271 InflateRect(Rect, - GetSystemMetrics(SM_CXEDGE), - GetSystemMetrics(SM_CYEDGE));
1272 }
1273 if (0 != (ExStyle & WS_EX_STATICEDGE))
1274 {
1275 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1276 }
1277 }
1278 }
1279
1280 /***********************************************************************
1281 * NcGetSysPopupPos
1282 */
1283 void FASTCALL
1284 NcGetSysPopupPos(HWND Wnd, RECT *Rect)
1285 {
1286 RECT WindowRect;
1287
1288 if (IsIconic(Wnd))
1289 {
1290 GetWindowRect(Wnd, Rect);
1291 }
1292 else
1293 {
1294 NcGetInsideRect(Wnd, Rect);
1295 GetWindowRect(Wnd, &WindowRect);
1296 OffsetRect(Rect, WindowRect.left, WindowRect.top);
1297 if (0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_CHILD))
1298 {
1299 ClientToScreen(GetParent(Wnd), (POINT *) Rect);
1300 }
1301 Rect->right = Rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1302 Rect->bottom = Rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1303 }
1304 }