Merge from amd64-branch:
[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
493 return 0;
494 }
495
496 LRESULT
497 DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect)
498 {
499 LRESULT Result = 0;
500 DWORD Style = GetClassLongPtrW(hWnd, GCL_STYLE);
501 DWORD ExStyle;
502 SIZE WindowBorders;
503 RECT OrigRect;
504
505 if (Rect == NULL)
506 {
507 return Result;
508 }
509 OrigRect = *Rect;
510
511 if (CalcSizeStruct)
512 {
513 if (Style & CS_VREDRAW)
514 {
515 Result |= WVR_VREDRAW;
516 }
517 if (Style & CS_HREDRAW)
518 {
519 Result |= WVR_HREDRAW;
520 }
521 Result |= WVR_VALIDRECTS;
522 }
523
524 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
525 ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
526
527 if (!(Style & WS_MINIMIZE))
528 {
529 HMENU menu = GetMenu(hWnd);
530
531 if (UserHasWindowEdge(Style, ExStyle))
532 {
533 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
534 InflateRect(Rect, -WindowBorders.cx, -WindowBorders.cy);
535 } else
536 if ((ExStyle & WS_EX_STATICEDGE) || (Style & WS_BORDER))
537 {
538 InflateRect(Rect, -1, -1);
539 }
540
541 if ((Style & WS_CAPTION) == WS_CAPTION)
542 {
543 if (ExStyle & WS_EX_TOOLWINDOW)
544 Rect->top += GetSystemMetrics(SM_CYSMCAPTION);
545 else
546 Rect->top += GetSystemMetrics(SM_CYCAPTION);
547 }
548
549 if (menu && !(Style & WS_CHILD))
550 {
551 HDC hDC = GetWindowDC(hWnd);
552 if(hDC)
553 {
554 RECT CliRect = *Rect;
555 CliRect.bottom -= OrigRect.top;
556 CliRect.right -= OrigRect.left;
557 CliRect.left -= OrigRect.left;
558 CliRect.top -= OrigRect.top;
559 Rect->top += MenuDrawMenuBar(hDC, &CliRect, hWnd, TRUE);
560 ReleaseDC(hWnd, hDC);
561 }
562 }
563
564 if (ExStyle & WS_EX_CLIENTEDGE)
565 {
566 InflateRect(Rect, -2 * GetSystemMetrics(SM_CXBORDER),
567 -2 * GetSystemMetrics(SM_CYBORDER));
568 }
569
570 if(Style & (WS_VSCROLL | WS_HSCROLL))
571 {
572 SCROLLBARINFO sbi;
573 SETSCROLLBARINFO ssbi;
574
575 sbi.cbSize = sizeof(SCROLLBARINFO);
576 if((Style & WS_VSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_VSCROLL, &sbi))
577 {
578 int i;
579 LONG sx = Rect->right;
580
581 sx -= GetSystemMetrics(SM_CXVSCROLL);
582 for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
583 ssbi.rgstate[i] = sbi.rgstate[i];
584 if(sx <= Rect->left)
585 ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
586 else
587 ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
588 NtUserSetScrollBarInfo(hWnd, OBJID_VSCROLL, &ssbi);
589 if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
590 Style &= ~WS_VSCROLL;
591 }
592 else
593 Style &= ~WS_VSCROLL;
594
595 if((Style & WS_HSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_HSCROLL, &sbi))
596 {
597 int i;
598 LONG sy = Rect->bottom;
599
600 sy -= GetSystemMetrics(SM_CYHSCROLL);
601 for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
602 ssbi.rgstate[i] = sbi.rgstate[i];
603 if(sy <= Rect->top)
604 ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
605 else
606 ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
607 NtUserSetScrollBarInfo(hWnd, OBJID_HSCROLL, &ssbi);
608 if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
609 Style &= ~WS_HSCROLL;
610 }
611 else
612 Style &= ~WS_HSCROLL;
613 }
614
615 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL))
616 {
617 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
618 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
619 else
620 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
621 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
622 }
623 else
624 {
625 if (Style & WS_VSCROLL)
626 {
627 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
628 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
629 else
630 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
631 }
632 else if (Style & WS_HSCROLL)
633 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
634 }
635 if (Rect->top > Rect->bottom)
636 Rect->bottom = Rect->top;
637 if (Rect->left > Rect->right)
638 Rect->right = Rect->left;
639 }
640 else
641 {
642 Rect->right = Rect->left;
643 Rect->bottom = Rect->top;
644 }
645
646 return Result;
647 }
648
649 LRESULT
650 DefWndNCActivate(HWND hWnd, WPARAM wParam)
651 {
652 DefWndNCPaint(hWnd, (HRGN)1, wParam);
653 return TRUE;
654 }
655
656 /*
657 * FIXME:
658 * - Check the scrollbar handling
659 */
660 LRESULT
661 DefWndNCHitTest(HWND hWnd, POINT Point)
662 {
663 RECT WindowRect, ClientRect, OrigWndRect;
664 POINT ClientPoint;
665 SIZE WindowBorders;
666 ULONG Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
667 ULONG ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
668
669 GetWindowRect(hWnd, &WindowRect);
670 if (!PtInRect(&WindowRect, Point))
671 {
672 return HTNOWHERE;
673 }
674 OrigWndRect = WindowRect;
675
676 if (UserHasWindowEdge(Style, ExStyle))
677 {
678 LONG XSize, YSize;
679
680 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
681 InflateRect(&WindowRect, -WindowBorders.cx, -WindowBorders.cy);
682 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
683 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
684 if (!PtInRect(&WindowRect, Point))
685 {
686 BOOL ThickFrame;
687
688 ThickFrame = (Style & WS_THICKFRAME);
689 if (Point.y < WindowRect.top)
690 {
691 if(Style & WS_MINIMIZE)
692 return HTCAPTION;
693 if(!ThickFrame)
694 return HTBORDER;
695 if (Point.x < (WindowRect.left + XSize))
696 return HTTOPLEFT;
697 if (Point.x >= (WindowRect.right - XSize))
698 return HTTOPRIGHT;
699 return HTTOP;
700 }
701 if (Point.y >= WindowRect.bottom)
702 {
703 if(Style & WS_MINIMIZE)
704 return HTCAPTION;
705 if(!ThickFrame)
706 return HTBORDER;
707 if (Point.x < (WindowRect.left + XSize))
708 return HTBOTTOMLEFT;
709 if (Point.x >= (WindowRect.right - XSize))
710 return HTBOTTOMRIGHT;
711 return HTBOTTOM;
712 }
713 if (Point.x < WindowRect.left)
714 {
715 if(Style & WS_MINIMIZE)
716 return HTCAPTION;
717 if(!ThickFrame)
718 return HTBORDER;
719 if (Point.y < (WindowRect.top + YSize))
720 return HTTOPLEFT;
721 if (Point.y >= (WindowRect.bottom - YSize))
722 return HTBOTTOMLEFT;
723 return HTLEFT;
724 }
725 if (Point.x >= WindowRect.right)
726 {
727 if(Style & WS_MINIMIZE)
728 return HTCAPTION;
729 if(!ThickFrame)
730 return HTBORDER;
731 if (Point.y < (WindowRect.top + YSize))
732 return HTTOPRIGHT;
733 if (Point.y >= (WindowRect.bottom - YSize))
734 return HTBOTTOMRIGHT;
735 return HTRIGHT;
736 }
737 }
738 }
739 else
740 {
741 if (ExStyle & WS_EX_STATICEDGE)
742 InflateRect(&WindowRect,
743 -GetSystemMetrics(SM_CXBORDER),
744 -GetSystemMetrics(SM_CYBORDER));
745 if (!PtInRect(&WindowRect, Point))
746 return HTBORDER;
747 }
748
749 if ((Style & WS_CAPTION) == WS_CAPTION)
750 {
751 if (ExStyle & WS_EX_TOOLWINDOW)
752 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
753 else
754 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
755 if (!PtInRect(&WindowRect, Point))
756 {
757 if (Style & WS_SYSMENU)
758 {
759 if (ExStyle & WS_EX_TOOLWINDOW)
760 {
761 WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE);
762 }
763 else
764 {
765 if(!(ExStyle & WS_EX_DLGMODALFRAME))
766 WindowRect.left += GetSystemMetrics(SM_CXSIZE);
767 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
768 }
769 }
770 if (Point.x < WindowRect.left)
771 return HTSYSMENU;
772 if (WindowRect.right <= Point.x)
773 return HTCLOSE;
774 if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
775 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
776 if (Point.x >= WindowRect.right)
777 return HTMAXBUTTON;
778 if (Style & WS_MINIMIZEBOX)
779 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
780 if (Point.x >= WindowRect.right)
781 return HTMINBUTTON;
782 return HTCAPTION;
783 }
784 }
785
786 if(!(Style & WS_MINIMIZE))
787 {
788 HMENU menu;
789
790 ClientPoint = Point;
791 ScreenToClient(hWnd, &ClientPoint);
792 GetClientRect(hWnd, &ClientRect);
793
794 if (PtInRect(&ClientRect, ClientPoint))
795 {
796 return HTCLIENT;
797 }
798
799 if ((menu = GetMenu(hWnd)) && !(Style & WS_CHILD))
800 {
801 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
802 return HTMENU;
803 }
804
805 if (ExStyle & WS_EX_CLIENTEDGE)
806 {
807 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
808 -2 * GetSystemMetrics(SM_CYBORDER));
809 }
810
811 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
812 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
813 {
814 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
815 HWND Parent = GetParent(hWnd);
816
817 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
818 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
819 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
820 else
821 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
822 if (PtInRect(&TempRect, Point))
823 return HTVSCROLL;
824
825 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
826 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
827 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
828 else
829 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
830 if (PtInRect(&TempRect2, Point))
831 return HTHSCROLL;
832
833 TempRect.top = TempRect2.top;
834 TempRect.bottom = TempRect2.bottom;
835 if(Parent)
836 GetClientRect(Parent, &ParentRect);
837 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(Style, ExStyle,
838 GetWindowLongPtrW(Parent, GWL_STYLE), OrigWndRect, ParentRect))
839 {
840 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
841 return HTBOTTOMLEFT;
842 else
843 return HTBOTTOMRIGHT;
844 }
845 }
846 else
847 {
848 if (Style & WS_VSCROLL)
849 {
850 RECT TempRect = WindowRect;
851
852 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
853 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
854 else
855 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
856 if (PtInRect(&TempRect, Point))
857 return HTVSCROLL;
858 } else
859 if (Style & WS_HSCROLL)
860 {
861 RECT TempRect = WindowRect;
862 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
863 if (PtInRect(&TempRect, Point))
864 return HTHSCROLL;
865 }
866 }
867 }
868
869 return HTNOWHERE;
870 }
871
872 VOID
873 DefWndDoButton(HWND hWnd, WPARAM wParam)
874 {
875 MSG Msg;
876 HDC WindowDC;
877 BOOL Pressed = TRUE, OldState;
878 WPARAM SCMsg;
879 ULONG ButtonType, Style;
880
881 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
882 switch (wParam)
883 {
884 case HTCLOSE:
885 if (!(Style & WS_SYSMENU))
886 return;
887 ButtonType = DFCS_CAPTIONCLOSE;
888 SCMsg = SC_CLOSE;
889 break;
890 case HTMINBUTTON:
891 if (!(Style & WS_MINIMIZEBOX))
892 return;
893 ButtonType = DFCS_CAPTIONMIN;
894 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
895 break;
896 case HTMAXBUTTON:
897 if (!(Style & WS_MAXIMIZEBOX))
898 return;
899 ButtonType = DFCS_CAPTIONMAX;
900 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
901 break;
902
903 default:
904 ASSERT(FALSE);
905 return;
906 }
907
908 /*
909 * FIXME: Not sure where to do this, but we must flush the pending
910 * window updates when someone clicks on the close button and at
911 * the same time the window is overlapped with another one. This
912 * looks like a good place for now...
913 */
914 UpdateWindow(hWnd);
915
916 WindowDC = GetWindowDC(hWnd);
917 UserDrawCaptionButtonWnd(hWnd, WindowDC, TRUE, ButtonType);
918
919 SetCapture(hWnd);
920
921 for (;;)
922 {
923 if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
924 break;
925
926 if (Msg.message == WM_LBUTTONUP)
927 break;
928
929 if (Msg.message != WM_MOUSEMOVE)
930 continue;
931
932 OldState = Pressed;
933 Pressed = (DefWndNCHitTest(hWnd, Msg.pt) == wParam);
934 if (Pressed != OldState)
935 UserDrawCaptionButtonWnd(hWnd, WindowDC, Pressed, ButtonType);
936 }
937
938 if (Pressed)
939 UserDrawCaptionButtonWnd(hWnd, WindowDC, FALSE, ButtonType);
940 ReleaseCapture();
941 ReleaseDC(hWnd, WindowDC);
942 if (Pressed)
943 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
944 }
945
946
947 LRESULT
948 DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
949 {
950 switch (wParam)
951 {
952 case HTCAPTION:
953 {
954 HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
955 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
956 {
957 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
958 }
959 break;
960 }
961 case HTSYSMENU:
962 {
963 if (GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_SYSMENU)
964 {
965 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
966 lParam);
967 }
968 break;
969 }
970 case HTMENU:
971 {
972 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
973 break;
974 }
975 case HTHSCROLL:
976 {
977 SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
978 break;
979 }
980 case HTVSCROLL:
981 {
982 SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
983 break;
984 }
985 case HTMINBUTTON:
986 case HTMAXBUTTON:
987 case HTCLOSE:
988 {
989 DefWndDoButton(hWnd, wParam);
990 break;
991 }
992 case HTLEFT:
993 case HTRIGHT:
994 case HTTOP:
995 case HTBOTTOM:
996 case HTTOPLEFT:
997 case HTTOPRIGHT:
998 case HTBOTTOMLEFT:
999 case HTBOTTOMRIGHT:
1000 {
1001 SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT - WMSZ_LEFT), lParam);
1002 break;
1003 }
1004 }
1005 return(0);
1006 }
1007
1008
1009 LRESULT
1010 DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
1011 {
1012 ULONG Style;
1013
1014 Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
1015 switch(wParam)
1016 {
1017 case HTCAPTION:
1018 {
1019 /* Maximize/Restore the window */
1020 if((Style & WS_CAPTION) == WS_CAPTION && (Style & WS_MAXIMIZEBOX))
1021 {
1022 SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
1023 }
1024 break;
1025 }
1026 case HTSYSMENU:
1027 {
1028 SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
1029 break;
1030 }
1031 default:
1032 return DefWndNCLButtonDown(hWnd, wParam, lParam);
1033 }
1034 return(0);
1035 }
1036
1037 VOID
1038 DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point)
1039 {
1040 INT ScrollBar;
1041
1042 if ((wParam & 0xfff0) == SC_HSCROLL)
1043 {
1044 if ((wParam & 0x0f) != HTHSCROLL)
1045 return;
1046 ScrollBar = SB_HORZ;
1047 }
1048 else
1049 {
1050 if ((wParam & 0x0f) != HTVSCROLL)
1051 return;
1052 ScrollBar = SB_VERT;
1053 }
1054
1055 /* FIXME */
1056 }
1057
1058 /* PUBLIC FUNCTIONS ***********************************************************/
1059
1060 BOOL WINAPI
1061 RealAdjustWindowRectEx(LPRECT lpRect,
1062 DWORD dwStyle,
1063 BOOL bMenu,
1064 DWORD dwExStyle)
1065 {
1066 SIZE BorderSize;
1067
1068 if (bMenu)
1069 {
1070 lpRect->top -= GetSystemMetrics(SM_CYMENU);
1071 }
1072 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1073 {
1074 if (dwExStyle & WS_EX_TOOLWINDOW)
1075 lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
1076 else
1077 lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
1078 }
1079 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
1080 InflateRect(
1081 lpRect,
1082 BorderSize.cx,
1083 BorderSize.cy);
1084
1085 return TRUE;
1086 }
1087
1088 /*
1089 * @implemented
1090 */
1091 BOOL WINAPI
1092 AdjustWindowRectEx(LPRECT lpRect,
1093 DWORD dwStyle,
1094 BOOL bMenu,
1095 DWORD dwExStyle)
1096 {
1097 BOOL Hook, Ret = FALSE;
1098
1099 LOADUSERAPIHOOK
1100
1101 Hook = BeginIfHookedUserApiHook();
1102
1103 /* Bypass SEH and go direct. */
1104 if (!Hook) return RealAdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
1105
1106 _SEH2_TRY
1107 {
1108 Ret = guah.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
1109 }
1110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1111 {
1112 }
1113 _SEH2_END;
1114
1115 EndUserApiHook();
1116
1117 return Ret;
1118 }
1119
1120
1121 /*
1122 * @implemented
1123 */
1124 BOOL WINAPI
1125 AdjustWindowRect(LPRECT lpRect,
1126 DWORD dwStyle,
1127 BOOL bMenu)
1128 {
1129 return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
1130 }
1131
1132 // Enabling this will cause captions to draw smoother, but slower:
1133 #define DOUBLE_BUFFER_CAPTION
1134
1135 /*
1136 * @implemented
1137 */
1138 BOOL WINAPI
1139 DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
1140 {
1141 BOOL Hook, Ret = FALSE;
1142
1143 LOADUSERAPIHOOK
1144
1145 Hook = BeginIfHookedUserApiHook();
1146
1147 /* Bypass SEH and go direct. */
1148 if (!Hook) return NtUserDrawCaption(hWnd, hDC, lprc, uFlags);
1149
1150 _SEH2_TRY
1151 {
1152 Ret = guah.DrawCaption(hWnd, hDC, lprc, uFlags);
1153 }
1154 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1155 {
1156 }
1157 _SEH2_END;
1158
1159 EndUserApiHook();
1160
1161 return Ret;
1162 }
1163
1164 /*
1165 * @implemented
1166 */
1167 BOOL
1168 WINAPI
1169 DrawCaptionTempW(
1170 HWND hWnd,
1171 HDC hDC,
1172 const RECT *rect,
1173 HFONT hFont,
1174 HICON hIcon,
1175 LPCWSTR str,
1176 UINT uFlags
1177 )
1178 {
1179 UNICODE_STRING Text = {0};
1180 RtlInitUnicodeString(&Text, str);
1181 return NtUserDrawCaptionTemp(hWnd, hDC, rect, hFont, hIcon, &Text, uFlags);
1182 }
1183
1184 /*
1185 * @implemented
1186 */
1187 BOOL
1188 WINAPI
1189 DrawCaptionTempA(
1190 HWND hwnd,
1191 HDC hdc,
1192 const RECT *rect,
1193 HFONT hFont,
1194 HICON hIcon,
1195 LPCSTR str,
1196 UINT uFlags
1197 )
1198 {
1199 LPWSTR strW;
1200 INT len;
1201 BOOL ret = FALSE;
1202
1203 if (!(uFlags & DC_TEXT) || !str)
1204 return DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, NULL, uFlags);
1205
1206 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
1207 if ((strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR))))
1208 {
1209 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len );
1210 ret = DrawCaptionTempW(hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
1211 HeapFree(GetProcessHeap(), 0, strW);
1212 }
1213 return ret;
1214 }
1215
1216 /***********************************************************************
1217 * NcGetInsideRect
1218 *
1219 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1220 * but without the borders (if any).
1221 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1222 */
1223 static void FASTCALL
1224 NcGetInsideRect(HWND Wnd, RECT *Rect)
1225 {
1226 DWORD Style;
1227 DWORD ExStyle;
1228
1229 GetWindowRect(Wnd, Rect);
1230 Rect->right = Rect->right - Rect->left;
1231 Rect->left = 0;
1232 Rect->bottom = Rect->bottom - Rect->top;
1233 Rect->top = 0;
1234
1235 Style = GetWindowLongPtrW(Wnd, GWL_STYLE);
1236 if (0 != (Style & WS_ICONIC))
1237 {
1238 return;
1239 }
1240
1241 /* Remove frame from rectangle */
1242 ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE);
1243 if (HAS_THICKFRAME(Style, ExStyle))
1244 {
1245 InflateRect(Rect, - GetSystemMetrics(SM_CXFRAME), - GetSystemMetrics(SM_CYFRAME));
1246 }
1247 else if (HAS_DLGFRAME(Style, ExStyle))
1248 {
1249 InflateRect(Rect, - GetSystemMetrics(SM_CXDLGFRAME), - GetSystemMetrics(SM_CYDLGFRAME));
1250 }
1251 else if (HAS_THINFRAME(Style, ExStyle))
1252 {
1253 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1254 }
1255
1256 /* We have additional border information if the window
1257 * is a child (but not an MDI child) */
1258 if (0 != (Style & WS_CHILD)
1259 && 0 == (ExStyle & WS_EX_MDICHILD))
1260 {
1261 if (0 != (ExStyle & WS_EX_CLIENTEDGE))
1262 {
1263 InflateRect(Rect, - GetSystemMetrics(SM_CXEDGE), - GetSystemMetrics(SM_CYEDGE));
1264 }
1265 if (0 != (ExStyle & WS_EX_STATICEDGE))
1266 {
1267 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1268 }
1269 }
1270 }
1271
1272 /***********************************************************************
1273 * NcGetSysPopupPos
1274 */
1275 void FASTCALL
1276 NcGetSysPopupPos(HWND Wnd, RECT *Rect)
1277 {
1278 RECT WindowRect;
1279
1280 if (IsIconic(Wnd))
1281 {
1282 GetWindowRect(Wnd, Rect);
1283 }
1284 else
1285 {
1286 NcGetInsideRect(Wnd, Rect);
1287 GetWindowRect(Wnd, &WindowRect);
1288 OffsetRect(Rect, WindowRect.left, WindowRect.top);
1289 if (0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_CHILD))
1290 {
1291 ClientToScreen(GetParent(Wnd), (POINT *) Rect);
1292 }
1293 Rect->right = Rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1294 Rect->bottom = Rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1295 }
1296 }