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