Fix user32 build mostly tested in trunk. Some local changes still not committed.
[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 Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 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 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; see the file COPYING.LIB.
19 * If not, write to the Free Software Foundation,
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 /* INCLUDES *******************************************************************/
24
25 #include <user32.h>
26
27 #include <wine/debug.h>
28
29 #define HAS_DLGFRAME(Style, ExStyle) \
30 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
31 (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))
32
33 #define HAS_THICKFRAME(Style, ExStyle) \
34 (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
35 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
36
37 #define HAS_THINFRAME(Style, ExStyle) \
38 (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))
39
40 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
41 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
42 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
43 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
44 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
45
46 #ifndef STATE_SYSTEM_OFFSCREEN
47 #define STATE_SYSTEM_OFFSCREEN 0x00010000
48 #endif
49
50 /*
51 * FIXME: This should be moved to a header
52 */
53 VOID
54 IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar);
55 DWORD
56 IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging);
57
58 BOOL WINAPI GdiGradientFill(HDC,PTRIVERTEX,ULONG,PVOID,ULONG,ULONG);
59
60 extern ATOM AtomInternalPos;
61
62 /* PRIVATE FUNCTIONS **********************************************************/
63
64 BOOL
65 IntIsScrollBarVisible(HWND hWnd, INT hBar)
66 {
67 SCROLLBARINFO sbi;
68 sbi.cbSize = sizeof(SCROLLBARINFO);
69 if(!NtUserGetScrollBarInfo(hWnd, hBar, &sbi))
70 return FALSE;
71
72 return !(sbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN);
73 }
74
75 BOOL
76 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
77 {
78 if (Style & WS_MINIMIZE)
79 return TRUE;
80 if (ExStyle & WS_EX_DLGMODALFRAME)
81 return TRUE;
82 if (ExStyle & WS_EX_STATICEDGE)
83 return FALSE;
84 if (Style & WS_THICKFRAME)
85 return TRUE;
86 Style &= WS_CAPTION;
87 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
88 return TRUE;
89 return FALSE;
90 }
91
92 VOID
93 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
94 {
95 DWORD Border = 0;
96
97 if (UserHasWindowEdge(Style, ExStyle))
98 Border += 2;
99 else if (ExStyle & WS_EX_STATICEDGE)
100 Border += 1;
101 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
102 Border += 2;
103 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
104 Border ++;
105 Size->cx = Size->cy = Border;
106 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
107 {
108 Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
109 Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
110 }
111 Size->cx *= GetSystemMetrics(SM_CXBORDER);
112 Size->cy *= GetSystemMetrics(SM_CYBORDER);
113 }
114
115 BOOL
116 UserHasMenu(HWND hWnd, ULONG Style)
117 {
118 return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
119 }
120
121 HICON
122 UserGetWindowIcon(HWND hwnd)
123 {
124 HICON hIcon = 0;
125
126 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
127
128 if (!hIcon)
129 SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
130
131 if (!hIcon)
132 SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR)&hIcon);
133
134 if (!hIcon)
135 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM);
136
137 if (!hIcon)
138 hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON);
139
140 return hIcon;
141 }
142
143 BOOL
144 UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL Down)
145 {
146 HICON WindowIcon;
147
148 if ((WindowIcon = UserGetWindowIcon(hWnd)))
149 {
150 return DrawIconEx(hDC, Rect->left + 2, Rect->top + 2, WindowIcon,
151 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
152 0, NULL, DI_NORMAL);
153 }
154
155 return FALSE;
156 }
157
158 /*
159 * FIXME:
160 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
161 * wasting precious CPU cycles) every time
162 * - Center the buttons verticaly in the rect
163 */
164 VOID
165 UserDrawCaptionButton(LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hDC, BOOL bDown, ULONG Type)
166 {
167 RECT TempRect;
168
169 if (!(Style & WS_SYSMENU))
170 {
171 return;
172 }
173
174 TempRect = *Rect;
175
176 switch (Type)
177 {
178 case DFCS_CAPTIONMIN:
179 {
180 if (ExStyle & WS_EX_TOOLWINDOW)
181 return; /* ToolWindows don't have min/max buttons */
182
183 if (Style & WS_SYSMENU)
184 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
185 if (Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
186 TempRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
187 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
188 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
189 TempRect.top += 2;
190 TempRect.right -= 1;
191
192 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
193 ((Style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN) |
194 (bDown ? DFCS_PUSHED : 0) |
195 ((Style & WS_MINIMIZEBOX) ? 0 : DFCS_INACTIVE));
196 break;
197 }
198 case DFCS_CAPTIONMAX:
199 {
200 if (ExStyle & WS_EX_TOOLWINDOW)
201 return; /* ToolWindows don't have min/max buttons */
202
203 if (Style & WS_SYSMENU)
204 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
205 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
206 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
207 TempRect.top += 2;
208 TempRect.right -= 1;
209
210 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
211 ((Style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
212 (bDown ? DFCS_PUSHED : 0) |
213 ((Style & WS_MAXIMIZEBOX) ? 0 : DFCS_INACTIVE));
214 break;
215 }
216 case DFCS_CAPTIONCLOSE:
217 {
218 /* FIXME: A tool window has a smaller Close button */
219
220 if (ExStyle & WS_EX_TOOLWINDOW)
221 {
222 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSMSIZE);
223 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMSIZE) - 2;
224 }
225 else
226 {
227 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE);
228 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
229 }
230 TempRect.top += 2;
231 TempRect.right -= 2;
232
233 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
234 (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
235 ((Style & WS_SYSMENU) ? 0 : DFCS_INACTIVE)));
236 break;
237 }
238 }
239 }
240
241 VOID
242 UserDrawCaptionButtonWnd(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
243 {
244 RECT WindowRect;
245 SIZE WindowBorder;
246 DWORD Style, ExStyle;
247
248 GetWindowRect(hWnd, &WindowRect);
249 WindowRect.right -= WindowRect.left;
250 WindowRect.bottom -= WindowRect.top;
251 WindowRect.left = WindowRect.top = 0;
252 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
253 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
254 UserGetWindowBorders(Style, ExStyle, &WindowBorder, FALSE);
255 InflateRect(&WindowRect, -WindowBorder.cx, -WindowBorder.cy);
256 UserDrawCaptionButton(&WindowRect, Style, ExStyle, hDC, bDown, Type);
257 }
258
259 // Note from Wine:
260 /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
261 the call to GetDCEx implying that it is allowed not to use it either.
262 However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
263 will cause clipRgn to be deleted after ReleaseDC().
264 Now, how is the "system" supposed to tell what happened?
265 */
266 /*
267 * FIXME:
268 * - Drawing of WS_BORDER after scrollbars
269 * - Correct drawing of size-box
270 */
271 LRESULT
272 DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active)
273 {
274 HDC hDC;
275 DWORD Style, ExStyle;
276 HWND Parent;
277 RECT ClientRect, WindowRect, CurrentRect, TempRect;
278
279 if (!IsWindowVisible(hWnd))
280 return 0;
281
282 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
283
284 hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
285 if (hDC == 0)
286 {
287 return 0;
288 }
289
290 Parent = GetParent(hWnd);
291 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
292 if (Active == -1)
293 {
294 if (ExStyle & WS_EX_MDICHILD)
295 {
296 Active = IsChild(GetForegroundWindow(), hWnd);
297 if (Active)
298 Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));
299 }
300 else
301 {
302 Active = (GetForegroundWindow() == hWnd);
303 }
304 }
305 GetWindowRect(hWnd, &WindowRect);
306 GetClientRect(hWnd, &ClientRect);
307
308 CurrentRect.top = CurrentRect.left = 0;
309 CurrentRect.right = WindowRect.right - WindowRect.left;
310 CurrentRect.bottom = WindowRect.bottom - WindowRect.top;
311
312 /* Draw outer edge */
313 if (UserHasWindowEdge(Style, ExStyle))
314 {
315 DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);
316 } else
317 if (ExStyle & WS_EX_STATICEDGE)
318 {
319 #if 0
320 DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
321 #else
322 SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
323 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
324 PatBlt(hDC, CurrentRect.left, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);
325
326 SelectObject(hDC, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
327 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
328 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);
329
330 InflateRect(&CurrentRect, -1, -1);
331 #endif
332 }
333
334 /* Firstly the "thick" frame */
335 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
336 {
337 DWORD Width =
338 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
339 GetSystemMetrics(SM_CXBORDER);
340 DWORD Height =
341 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
342 GetSystemMetrics(SM_CYBORDER);
343
344 SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :
345 COLOR_INACTIVEBORDER));
346
347 /* Draw frame */
348 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
349 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
350 #ifdef __REACTOS__
351 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
352 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
353 #else
354 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
355 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
356 #endif
357
358 InflateRect(&CurrentRect, -Width, -Height);
359 }
360
361 /* Now the other bit of the frame */
362 if (Style & (WS_DLGFRAME | WS_BORDER) || ExStyle & WS_EX_DLGMODALFRAME)
363 {
364 DWORD Width = GetSystemMetrics(SM_CXBORDER);
365 DWORD Height = GetSystemMetrics(SM_CYBORDER);
366
367 SelectObject(hDC, GetSysColorBrush(
368 (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
369 (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
370 (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
371 COLOR_WINDOWFRAME));
372
373 /* Draw frame */
374 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
375 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
376 #ifdef __REACTOS__
377 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
378 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
379 #else
380 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
381 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
382 #endif
383
384 InflateRect(&CurrentRect, -Width, -Height);
385 }
386
387 /* Draw caption */
388 if ((Style & WS_CAPTION) == WS_CAPTION)
389 {
390 DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;
391 HPEN PreviousPen;
392 BOOL Gradient = FALSE;
393
394 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)
395 {
396 CaptionFlags |= DC_GRADIENT;
397 }
398
399 TempRect = CurrentRect;
400
401 if (Active)
402 {
403 CaptionFlags |= DC_ACTIVE;
404 }
405
406 if (ExStyle & WS_EX_TOOLWINDOW)
407 {
408 CaptionFlags |= DC_SMALLCAP;
409 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1;
410 CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);
411 }
412 else
413 {
414 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;
415 CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);
416 }
417
418 NtUserDrawCaption(hWnd, hDC, &TempRect, CaptionFlags);
419
420 /* Draw buttons */
421 if (Style & WS_SYSMENU)
422 {
423 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);
424 if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))
425 {
426 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);
427 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);
428 }
429 }
430 if(!(Style & WS_MINIMIZE))
431 {
432 /* Line under caption */
433 PreviousPen = SelectObject(hDC, GetStockObject(DC_PEN));
434 SetDCPenColor(hDC, GetSysColor(
435 ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |
436 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
437 COLOR_WINDOWFRAME : COLOR_3DFACE));
438 MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);
439 LineTo(hDC, TempRect.right, TempRect.bottom);
440 SelectObject(hDC, PreviousPen);
441 }
442 }
443
444 if(!(Style & WS_MINIMIZE))
445 {
446 HMENU menu = GetMenu(hWnd);
447 /* Draw menu bar */
448 if (menu && !(Style & WS_CHILD))
449 {
450 TempRect = CurrentRect;
451 TempRect.bottom = TempRect.top + (UINT)NtUserSetMenuBarHeight(menu, 0);
452 CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, FALSE);
453 }
454
455 if (ExStyle & WS_EX_CLIENTEDGE)
456 {
457 DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
458 }
459
460 /* Draw the scrollbars */
461 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
462 IntIsScrollBarVisible(hWnd, OBJID_VSCROLL) && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
463 {
464 RECT ParentClientRect;
465
466 TempRect = CurrentRect;
467 if (ExStyle & WS_EX_LEFTSCROLLBAR)
468 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
469 else
470 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
471 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
472 FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_BTNFACE));
473 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
474 if(Parent)
475 GetClientRect(Parent, &ParentClientRect);
476 if (HASSIZEGRIP(Style, ExStyle, GetWindowLongPtrW(Parent, GWL_STYLE), WindowRect, ParentClientRect))
477 {
478 DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
479 }
480 IntDrawScrollBar(hWnd, hDC, SB_VERT);
481 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
482 }
483 else
484 {
485 if (Style & WS_VSCROLL && IntIsScrollBarVisible(hWnd, OBJID_VSCROLL))
486 IntDrawScrollBar(hWnd, hDC, SB_VERT);
487 else if (Style & WS_HSCROLL && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
488 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
489 }
490 }
491
492 ReleaseDC(hWnd, hDC);
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 }