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