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