Implement system menus
[reactos.git] / reactos / lib / 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 /*
26 * Define this to get the code working on ReactOS. It should be removed later.
27 */
28 /*
29 Already defined in makefile now.
30 #define __REACTOS__
31 */
32
33 /*
34 * Use w32api headers
35 */
36 /*
37 #define __USE_W32API
38 #define _WIN32_WINNT 0x0501
39 */
40
41 #include <windows.h>
42 #include <windowsx.h>
43 #include <string.h>
44 #include <menu.h>
45 #include <winpos.h>
46 #include <user32/wininternal.h>
47 #include <user32.h>
48
49 #define NDEBUG
50 #include <debug.h>
51
52 #define HAS_DLGFRAME(Style, ExStyle) \
53 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
54 (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))
55
56 #define HAS_THICKFRAME(Style, ExStyle) \
57 (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
58 (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))
59
60 #define HAS_THINFRAME(Style, ExStyle) \
61 (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))
62
63 #define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
64 ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE)) || \
65 ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
66 (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
67 (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))
68 /*
69 * FIXME: This should be moved to a header
70 */
71 VOID
72 IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar);
73 DWORD
74 IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging);
75 HPEN STDCALL
76 GetSysColorPen(int nIndex);
77
78 extern ATOM AtomInternalPos;
79
80 /* PRIVATE FUNCTIONS **********************************************************/
81
82 BOOL
83 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
84 {
85 if (Style & WS_MINIMIZE)
86 return TRUE;
87 if (ExStyle & WS_EX_DLGMODALFRAME)
88 return TRUE;
89 if (ExStyle & WS_EX_STATICEDGE)
90 return FALSE;
91 if (Style & WS_THICKFRAME)
92 return TRUE;
93 Style &= WS_CAPTION;
94 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
95 return TRUE;
96 return FALSE;
97 }
98
99 VOID
100 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
101 {
102 DWORD Border = 0;
103
104 if (UserHasWindowEdge(Style, ExStyle))
105 Border += 2;
106 else if (ExStyle & WS_EX_STATICEDGE)
107 Border += 1;
108 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
109 Border += 2;
110 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
111 Border ++;
112 Size->cx = Size->cy = Border;
113 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
114 {
115 Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
116 Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
117 }
118 Size->cx *= GetSystemMetrics(SM_CXBORDER);
119 Size->cy *= GetSystemMetrics(SM_CYBORDER);
120 }
121
122 BOOL
123 UserHasMenu(HWND hWnd, ULONG Style)
124 {
125 return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
126 }
127
128 HICON
129 UserGetWindowIcon(HWND hwnd)
130 {
131 HICON Ret = 0;
132
133 SendMessageTimeoutW(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&Ret);
134 if (!Ret)
135 SendMessageTimeoutW(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&Ret);
136 if (!Ret)
137 SendMessageTimeoutW(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&Ret);
138 if (!Ret)
139 Ret = (HICON)GetClassLongW(hwnd, GCL_HICONSM);
140 if (!Ret)
141 Ret = (HICON)GetClassLongW(hwnd, GCL_HICON);
142 if (!Ret)
143 SendMessageTimeoutW(hwnd, WM_QUERYDRAGICON, 0, 0, 0, 1000, (LPDWORD)&Ret);
144 if (!Ret)
145 Ret = LoadIconW(0, IDI_APPLICATION);
146
147 return Ret;
148 }
149
150 BOOL
151 UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect)
152 {
153 HICON WindowIcon;
154
155 if((WindowIcon = UserGetWindowIcon(hWnd)))
156 {
157 return DrawIconEx(hDC, Rect->left + 2, Rect->top + 2, WindowIcon,
158 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
159 0, NULL, DI_NORMAL);
160 }
161 return FALSE;
162 }
163
164 /*
165 * FIXME:
166 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
167 * wasting precious CPU cycles) every time
168 * - Center the buttons verticaly in the rect
169 */
170 VOID
171 UserDrawCaptionButton(LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hDC, BOOL bDown, ULONG Type)
172 {
173 RECT TempRect;
174
175 if (!(Style & WS_SYSMENU))
176 {
177 return;
178 }
179
180 TempRect = *Rect;
181
182 switch (Type)
183 {
184 case DFCS_CAPTIONMIN:
185 {
186 if (ExStyle & WS_EX_TOOLWINDOW)
187 return; /* ToolWindows don't have min/max buttons */
188
189 if (Style & WS_SYSMENU)
190 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
191 if (Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
192 TempRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
193 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
194 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
195 TempRect.top += 2;
196 TempRect.right -= 1;
197
198 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
199 ((Style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN) |
200 (bDown ? DFCS_PUSHED : 0) |
201 ((Style & WS_MINIMIZEBOX) ? 0 : DFCS_INACTIVE));
202 break;
203 }
204 case DFCS_CAPTIONMAX:
205 {
206 if (ExStyle & WS_EX_TOOLWINDOW)
207 return; /* ToolWindows don't have min/max buttons */
208
209 if (Style & WS_SYSMENU)
210 TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
211 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
212 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
213 TempRect.top += 2;
214 TempRect.right -= 1;
215
216 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
217 ((Style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
218 (bDown ? DFCS_PUSHED : 0) |
219 ((Style & WS_MAXIMIZEBOX) ? 0 : DFCS_INACTIVE));
220 break;
221 }
222 case DFCS_CAPTIONCLOSE:
223 {
224 /* FIXME: A tool window has a smaller Close button */
225
226 if (ExStyle & WS_EX_TOOLWINDOW)
227 {
228 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSMSIZE);
229 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMSIZE) - 2;
230 }
231 else
232 {
233 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE);
234 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
235 }
236 TempRect.top += 2;
237 TempRect.right -= 2;
238
239 DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
240 (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
241 ((Style & WS_SYSMENU) ? 0 : DFCS_INACTIVE)));
242 break;
243 }
244 }
245 }
246
247 VOID
248 UserDrawCaptionButtonWnd(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
249 {
250 RECT WindowRect;
251 SIZE WindowBorder;
252 DWORD Style, ExStyle;
253
254 GetWindowRect(hWnd, &WindowRect);
255 WindowRect.right -= WindowRect.left;
256 WindowRect.bottom -= WindowRect.top;
257 WindowRect.left = WindowRect.top = 0;
258 Style = GetWindowLongW(hWnd, GWL_STYLE);
259 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
260 UserGetWindowBorders(Style, ExStyle, &WindowBorder, FALSE);
261 InflateRect(&WindowRect, -WindowBorder.cx, -WindowBorder.cy);
262 UserDrawCaptionButton(&WindowRect, Style, ExStyle, hDC, bDown, Type);
263 }
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)
272 {
273 HDC hDC;
274 BOOL Active;
275 DWORD Style, ExStyle;
276 HWND Parent;
277 RECT ClientRect, WindowRect, CurrentRect, TempRect;
278
279 if (!IsWindowVisible(hWnd))
280 return 0;
281
282 Style = GetWindowLongW(hWnd, GWL_STYLE);
283
284 hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | 0x10000);
285 if (hDC == 0)
286 {
287 return 0;
288 }
289
290 Parent = GetParent(hWnd);
291 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
292 if (ExStyle & WS_EX_MDICHILD)
293 {
294 Active = IsChild(GetForegroundWindow(), hWnd);
295 if (Active)
296 Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));
297 }
298 else
299 {
300 Active = (GetForegroundWindow() == hWnd);
301 }
302 GetWindowRect(hWnd, &WindowRect);
303 GetClientRect(hWnd, &ClientRect);
304
305 CurrentRect.top = CurrentRect.left = 0;
306 CurrentRect.right = WindowRect.right - WindowRect.left;
307 CurrentRect.bottom = WindowRect.bottom - WindowRect.top;
308
309 /* Draw outer edge */
310 if (UserHasWindowEdge(Style, ExStyle))
311 {
312 DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);
313 } else
314 if (ExStyle & WS_EX_STATICEDGE)
315 {
316 DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
317 }
318
319 /* Firstly the "thick" frame */
320 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
321 {
322 DWORD Width =
323 (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
324 GetSystemMetrics(SM_CXBORDER);
325 DWORD Height =
326 (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
327 GetSystemMetrics(SM_CYBORDER);
328
329 SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :
330 COLOR_INACTIVEBORDER));
331
332 /* Draw frame */
333 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
334 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
335 #ifdef __REACTOS__
336 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
337 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
338 #else
339 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
340 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
341 #endif
342
343 InflateRect(&CurrentRect, -Width, -Height);
344 }
345
346 /* Now the other bit of the frame */
347 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
348 {
349 DWORD Width = GetSystemMetrics(SM_CXBORDER);
350 DWORD Height = GetSystemMetrics(SM_CYBORDER);
351
352 SelectObject(hDC, GetSysColorBrush(
353 (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
354 (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
355 (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
356 COLOR_WINDOWFRAME));
357
358 /* Draw frame */
359 PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
360 PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
361 #ifdef __REACTOS__
362 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
363 PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
364 #else
365 PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
366 PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
367 #endif
368
369 InflateRect(&CurrentRect, -Width, -Height);
370 }
371
372 /* Draw caption */
373 if ((Style & WS_CAPTION) == WS_CAPTION)
374 {
375 DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;
376 HPEN PreviousPen;
377 BOOL Gradient = FALSE;
378
379 if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)
380 {
381 CaptionFlags |= DC_GRADIENT;
382 }
383
384 TempRect = CurrentRect;
385
386 if (Active)
387 {
388 CaptionFlags |= DC_ACTIVE;
389 }
390
391 if (ExStyle & WS_EX_TOOLWINDOW)
392 {
393 CaptionFlags |= DC_SMALLCAP;
394 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1;
395 CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);
396 }
397 else
398 {
399 TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;
400 CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);
401 }
402
403 DrawCaption(hWnd, hDC, &TempRect, CaptionFlags);
404
405 /* Draw buttons */
406 if (Style & WS_SYSMENU)
407 {
408 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);
409 if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))
410 {
411 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);
412 UserDrawCaptionButton(&TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);
413 }
414 }
415 if(!(Style & WS_MINIMIZE))
416 {
417 /* Line under caption */
418 PreviousPen = SelectObject(hDC, GetSysColorPen(
419 ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |
420 WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
421 COLOR_WINDOWFRAME : COLOR_3DFACE));
422 MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);
423 LineTo(hDC, TempRect.right, TempRect.bottom);
424 SelectObject(hDC, PreviousPen);
425 }
426 }
427
428 if(!(Style & WS_MINIMIZE))
429 {
430 HMENU menu = GetMenu(hWnd);
431 /* Draw menu bar */
432 if (menu && !(Style & WS_CHILD))
433 {
434 TempRect = CurrentRect;
435 TempRect.bottom = TempRect.top + (UINT)NtUserSetMenuBarHeight(menu, 0);
436 CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, TRUE);
437 }
438
439 if (ExStyle & WS_EX_CLIENTEDGE)
440 {
441 DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
442 }
443
444 /* Draw the scrollbars */
445 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
446 (CurrentRect.bottom - CurrentRect.top) > GetSystemMetrics(SM_CYHSCROLL))
447 {
448 RECT ParentClientRect;
449
450 TempRect = CurrentRect;
451 if (ExStyle & WS_EX_LEFTSCROLLBAR)
452 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
453 else
454 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
455 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
456 FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_SCROLLBAR));
457 /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
458 if(Parent)
459 GetClientRect(Parent, &ParentClientRect);
460 if (HASSIZEGRIP(Style, ExStyle, GetWindowLongW(Parent, GWL_STYLE), WindowRect, ParentClientRect))
461 {
462 DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
463 }
464 IntDrawScrollBar(hWnd, hDC, SB_VERT);
465 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
466 }
467 else
468 {
469 if (Style & WS_VSCROLL)
470 IntDrawScrollBar(hWnd, hDC, SB_VERT);
471 else if (Style & WS_HSCROLL)
472 IntDrawScrollBar(hWnd, hDC, SB_HORZ);
473 }
474 }
475
476 ReleaseDC(hWnd, hDC);
477
478 return 0;
479 }
480
481 LRESULT
482 DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect)
483 {
484 LRESULT Result = 0;
485 DWORD Style = GetClassLongW(hWnd, GCL_STYLE);
486 DWORD ExStyle;
487 SIZE WindowBorders;
488 RECT OrigRect = *Rect;
489
490 if (CalcSizeStruct)
491 {
492 if (Style & CS_VREDRAW)
493 {
494 Result |= WVR_VREDRAW;
495 }
496 if (Style & CS_HREDRAW)
497 {
498 Result |= WVR_HREDRAW;
499 }
500 Result |= WVR_VALIDRECTS;
501 }
502
503 Style = GetWindowLongW(hWnd, GWL_STYLE);
504 ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
505
506 if (!(Style & WS_MINIMIZE))
507 {
508 ULONG menuheight;
509 HMENU menu = GetMenu(hWnd);
510
511 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
512 InflateRect(Rect, -WindowBorders.cx, -WindowBorders.cy);
513 if ((Style & WS_CAPTION) == WS_CAPTION)
514 {
515 if (ExStyle & WS_EX_TOOLWINDOW)
516 Rect->top += GetSystemMetrics(SM_CYSMCAPTION);
517 else
518 Rect->top += GetSystemMetrics(SM_CYCAPTION);
519 }
520
521 if (menu && !(Style & WS_CHILD))
522 {
523 HDC hDC = GetWindowDC(hWnd);
524 if(hDC)
525 {
526 RECT CliRect = *Rect;
527 CliRect.bottom -= OrigRect.top;
528 CliRect.right -= OrigRect.left;
529 CliRect.left -= OrigRect.left;
530 CliRect.top -= OrigRect.top;
531 menuheight = (ULONG)MenuDrawMenuBar(hDC, &CliRect, hWnd, FALSE);
532 ReleaseDC(hWnd, hDC);
533 Rect->top += max(menuheight, GetSystemMetrics(SM_CYMENU));
534 }
535 }
536
537 if (ExStyle & WS_EX_CLIENTEDGE)
538 {
539 InflateRect(Rect, -2 * GetSystemMetrics(SM_CXBORDER),
540 -2 * GetSystemMetrics(SM_CYBORDER));
541 }
542
543 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
544 (Rect->bottom - Rect->top) > GetSystemMetrics(SM_CYHSCROLL))
545 {
546 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
547 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
548 else
549 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
550 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
551 }
552 else
553 {
554 if (Style & WS_VSCROLL)
555 {
556 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
557 Rect->left += GetSystemMetrics(SM_CXVSCROLL);
558 else
559 Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
560 }
561 else if (Style & WS_HSCROLL)
562 Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
563 }
564 if (Rect->top > Rect->bottom)
565 Rect->bottom = Rect->top;
566 if (Rect->left > Rect->right)
567 Rect->right = Rect->left;
568 }
569 else
570 {
571 Rect->right = Rect->left;
572 Rect->bottom = Rect->top;
573 }
574
575 return Result;
576 }
577
578 LRESULT
579 DefWndNCActivate(HWND hWnd, WPARAM wParam)
580 {
581 DefWndNCPaint(hWnd, (HRGN)1);
582 return TRUE;
583 }
584
585 /*
586 * FIXME:
587 * - Check the scrollbar handling
588 */
589 LRESULT
590 DefWndNCHitTest(HWND hWnd, POINT Point)
591 {
592 RECT WindowRect, ClientRect, OrigWndRect;
593 POINT ClientPoint;
594 SIZE WindowBorders;
595 ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
596 ULONG ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
597
598 GetWindowRect(hWnd, &WindowRect);
599 if (!PtInRect(&WindowRect, Point))
600 {
601 return HTNOWHERE;
602 }
603 OrigWndRect = WindowRect;
604
605 if (UserHasWindowEdge(Style, ExStyle))
606 {
607 DWORD XSize, YSize;
608
609 UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
610 InflateRect(&WindowRect, -WindowBorders.cx, -WindowBorders.cy);
611 XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
612 YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
613 if (!PtInRect(&WindowRect, Point))
614 {
615 BOOL ThickFrame;
616
617 ThickFrame = (Style & WS_THICKFRAME);
618 if (Point.y < WindowRect.top)
619 {
620 if(Style & WS_MINIMIZE)
621 return HTCAPTION;
622 if(!ThickFrame)
623 return HTBORDER;
624 if (Point.x < (WindowRect.left + XSize))
625 return HTTOPLEFT;
626 if (Point.x >= (WindowRect.right - XSize))
627 return HTTOPRIGHT;
628 return HTTOP;
629 }
630 if (Point.y >= WindowRect.bottom)
631 {
632 if(Style & WS_MINIMIZE)
633 return HTCAPTION;
634 if(!ThickFrame)
635 return HTBORDER;
636 if (Point.x < (WindowRect.left + XSize))
637 return HTBOTTOMLEFT;
638 if (Point.x >= (WindowRect.right - XSize))
639 return HTBOTTOMRIGHT;
640 return HTBOTTOM;
641 }
642 if (Point.x < WindowRect.left)
643 {
644 if(Style & WS_MINIMIZE)
645 return HTCAPTION;
646 if(!ThickFrame)
647 return HTBORDER;
648 if (Point.y < (WindowRect.top + YSize))
649 return HTTOPLEFT;
650 if (Point.y >= (WindowRect.bottom - YSize))
651 return HTBOTTOMLEFT;
652 return HTLEFT;
653 }
654 if (Point.x >= WindowRect.right)
655 {
656 if(Style & WS_MINIMIZE)
657 return HTCAPTION;
658 if(!ThickFrame)
659 return HTBORDER;
660 if (Point.y < (WindowRect.top + YSize))
661 return HTTOPRIGHT;
662 if (Point.y >= (WindowRect.bottom - YSize))
663 return HTBOTTOMRIGHT;
664 return HTRIGHT;
665 }
666 }
667 }
668 else
669 {
670 if (ExStyle & WS_EX_STATICEDGE)
671 InflateRect(&WindowRect,
672 -GetSystemMetrics(SM_CXBORDER),
673 -GetSystemMetrics(SM_CYBORDER));
674 if (!PtInRect(&WindowRect, Point))
675 return HTBORDER;
676 }
677
678 if ((Style & WS_CAPTION) == WS_CAPTION)
679 {
680 if (ExStyle & WS_EX_TOOLWINDOW)
681 WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
682 else
683 WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
684 if (!PtInRect(&WindowRect, Point))
685 {
686 if (Style & WS_SYSMENU)
687 {
688 if (ExStyle & WS_EX_TOOLWINDOW)
689 {
690 WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE);
691 }
692 else
693 {
694 WindowRect.left += GetSystemMetrics(SM_CXSIZE);
695 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
696 }
697 }
698 if (Point.x <= WindowRect.left)
699 return HTSYSMENU;
700 if (WindowRect.right <= Point.x)
701 return HTCLOSE;
702 if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
703 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
704 if (Point.x >= WindowRect.right)
705 return HTMAXBUTTON;
706 if (Style & WS_MINIMIZEBOX)
707 WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
708 if (Point.x >= WindowRect.right)
709 return HTMINBUTTON;
710 return HTCAPTION;
711 }
712 }
713
714 if(!(Style & WS_MINIMIZE))
715 {
716 HMENU menu;
717
718 ClientPoint = Point;
719 ScreenToClient(hWnd, &ClientPoint);
720 GetClientRect(hWnd, &ClientRect);
721
722 if (PtInRect(&ClientRect, ClientPoint))
723 {
724 return HTCLIENT;
725 }
726
727 if ((menu = GetMenu(hWnd)) && !(Style & WS_CHILD))
728 {
729 if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
730 return HTMENU;
731 }
732
733 if (ExStyle & WS_EX_CLIENTEDGE)
734 {
735 InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
736 -2 * GetSystemMetrics(SM_CYBORDER));
737 }
738
739 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
740 (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
741 {
742 RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
743 HWND Parent = GetParent(hWnd);
744
745 TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
746 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
747 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
748 else
749 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
750 if (PtInRect(&TempRect, Point))
751 return HTVSCROLL;
752
753 TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
754 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
755 TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
756 else
757 TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
758 if (PtInRect(&TempRect2, Point))
759 return HTHSCROLL;
760
761 TempRect.top = TempRect2.top;
762 TempRect.bottom = TempRect2.bottom;
763 if(Parent)
764 GetClientRect(Parent, &ParentRect);
765 if (PtInRect(&TempRect, Point) && HASSIZEGRIP(Style, ExStyle,
766 GetWindowLongW(Parent, GWL_STYLE), OrigWndRect, ParentRect))
767 {
768 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
769 return HTBOTTOMLEFT;
770 else
771 return HTBOTTOMRIGHT;
772 }
773 }
774 else
775 {
776 if (Style & WS_VSCROLL)
777 {
778 RECT TempRect = WindowRect;
779
780 if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
781 TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
782 else
783 TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
784 if (PtInRect(&TempRect, Point))
785 return HTVSCROLL;
786 } else
787 if (Style & WS_HSCROLL)
788 {
789 RECT TempRect = WindowRect;
790 TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
791 if (PtInRect(&TempRect, Point))
792 return HTHSCROLL;
793 }
794 }
795 }
796
797 return HTNOWHERE;
798 }
799
800 VOID
801 DefWndDoButton(HWND hWnd, WPARAM wParam)
802 {
803 MSG Msg;
804 BOOL InBtn, HasBtn = FALSE;
805 ULONG Btn, Style;
806 WPARAM SCMsg, CurBtn = wParam, OrigBtn = wParam;
807 HDC WindowDC;
808
809 Style = GetWindowLongW(hWnd, GWL_STYLE);
810 switch(wParam)
811 {
812 case HTCLOSE:
813 Btn = DFCS_CAPTIONCLOSE;
814 SCMsg = SC_CLOSE;
815 HasBtn = (Style & WS_SYSMENU);
816 break;
817 case HTMINBUTTON:
818 Btn = DFCS_CAPTIONMIN;
819 SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
820 HasBtn = (Style & WS_MINIMIZEBOX);
821 break;
822 case HTMAXBUTTON:
823 Btn = DFCS_CAPTIONMAX;
824 SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
825 HasBtn = (Style & WS_MAXIMIZEBOX);
826 break;
827 default:
828 return;
829 }
830
831 InBtn = HasBtn;
832
833 SetCapture(hWnd);
834
835 if(HasBtn)
836 {
837 WindowDC = GetWindowDC(hWnd);
838 UserDrawCaptionButtonWnd(hWnd, WindowDC, HasBtn , Btn);
839 }
840
841 for(;;)
842 {
843 GetMessageW(&Msg, 0, 0, 0);
844 switch(Msg.message)
845 {
846 case WM_NCLBUTTONUP:
847 case WM_LBUTTONUP:
848 if(InBtn)
849 goto done;
850 else
851 {
852 ReleaseCapture();
853 if (HasBtn)
854 ReleaseDC(hWnd, WindowDC);
855 return;
856 }
857 case WM_NCMOUSEMOVE:
858 case WM_MOUSEMOVE:
859 if(HasBtn)
860 {
861 CurBtn = DefWndNCHitTest(hWnd, Msg.pt);
862 if(InBtn != (CurBtn == OrigBtn))
863 {
864 UserDrawCaptionButtonWnd( hWnd, WindowDC, (CurBtn == OrigBtn) , Btn);
865 }
866 InBtn = CurBtn == OrigBtn;
867 }
868 break;
869 }
870 }
871
872 done:
873 UserDrawCaptionButtonWnd( hWnd, WindowDC, FALSE , Btn);
874 ReleaseDC(hWnd, WindowDC);
875 ReleaseCapture();
876 SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, 0);
877 return;
878 }
879
880
881 LRESULT
882 DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
883 {
884 switch (wParam)
885 {
886 case HTCAPTION:
887 {
888 HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
889 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
890 {
891 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
892 }
893 break;
894 }
895 case HTSYSMENU:
896 {
897 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
898 {
899 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
900 lParam);
901 }
902 break;
903 }
904 case HTMENU:
905 {
906 SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
907 break;
908 }
909 case HTHSCROLL:
910 {
911 SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
912 break;
913 }
914 case HTVSCROLL:
915 {
916 SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
917 break;
918 }
919 case HTMINBUTTON:
920 case HTMAXBUTTON:
921 case HTCLOSE:
922 {
923 DefWndDoButton(hWnd, wParam);
924 break;
925 }
926 case HTLEFT:
927 case HTRIGHT:
928 case HTTOP:
929 case HTBOTTOM:
930 case HTTOPLEFT:
931 case HTTOPRIGHT:
932 case HTBOTTOMLEFT:
933 case HTBOTTOMRIGHT:
934 {
935 HWND Parent;
936
937 if(wParam == HTBOTTOMRIGHT && (Parent = GetParent(hWnd)) &&
938 (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) &&
939 !(GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD) &&
940 !(GetWindowLongW(Parent, GWL_STYLE) & WS_MAXIMIZE))
941 {
942 SendMessageW(Parent, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
943 break;
944 }
945 SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
946 break;
947 }
948 }
949 return(0);
950 }
951
952
953 LRESULT
954 DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
955 {
956 ULONG Style;
957
958 Style = GetWindowLongW(hWnd, GWL_STYLE);
959 switch(wParam)
960 {
961 case HTCAPTION:
962 {
963 /* Maximize/Restore the window */
964 if((Style & WS_CAPTION) && (Style & WS_MAXIMIZEBOX))
965 {
966 SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
967 }
968 break;
969 }
970 case HTSYSMENU:
971 {
972 SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
973 break;
974 }
975 default:
976 return DefWndNCLButtonDown(hWnd, wParam, lParam);
977 }
978 return(0);
979 }
980
981 VOID
982 DefWndTrackScrollBar(HWND hWnd, WPARAM wParam, POINT Point)
983 {
984 INT ScrollBar;
985
986 if ((wParam & 0xfff0) == SC_HSCROLL)
987 {
988 if ((wParam & 0x0f) != HTHSCROLL)
989 return;
990 ScrollBar = SB_HORZ;
991 }
992 else
993 {
994 if ((wParam & 0x0f) != HTVSCROLL)
995 return;
996 ScrollBar = SB_VERT;
997 }
998
999 /* FIXME */
1000 }
1001
1002 /* PUBLIC FUNCTIONS ***********************************************************/
1003
1004 /*
1005 * @implemented
1006 */
1007 BOOL STDCALL
1008 AdjustWindowRectEx(LPRECT lpRect,
1009 DWORD dwStyle,
1010 BOOL bMenu,
1011 DWORD dwExStyle)
1012 {
1013 SIZE BorderSize;
1014
1015 if (bMenu)
1016 {
1017 lpRect->top -= GetSystemMetrics(SM_CYMENU);
1018 }
1019 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1020 {
1021 if (dwExStyle & WS_EX_TOOLWINDOW)
1022 lpRect->top -= GetSystemMetrics(SM_CYSMCAPTION);
1023 else
1024 lpRect->top -= GetSystemMetrics(SM_CYCAPTION);
1025 }
1026 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
1027 InflateRect(
1028 lpRect,
1029 BorderSize.cx,
1030 BorderSize.cy);
1031
1032 return TRUE;
1033 }
1034
1035
1036 /*
1037 * @implemented
1038 */
1039 BOOL STDCALL
1040 AdjustWindowRect(LPRECT lpRect,
1041 DWORD dwStyle,
1042 BOOL bMenu)
1043 {
1044 return AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0);
1045 }
1046
1047 // Enabling this will cause captions to draw smoother, but slower:
1048 #define DOUBLE_BUFFER_CAPTION
1049
1050 /*
1051 * @implemented
1052 */
1053 BOOL WINAPI
1054 DrawCaption(HWND hWnd, HDC hDC, LPCRECT lprc, UINT uFlags)
1055 {
1056 NONCLIENTMETRICSW nclm;
1057 BOOL result = FALSE;
1058 RECT r = *lprc;
1059 UINT VCenter = 0, Padding = 0, Height;
1060 ULONG Style;
1061 WCHAR buffer[256];
1062 HFONT hFont = NULL;
1063 HFONT hOldFont = NULL;
1064 HBRUSH OldBrush = NULL;
1065 HDC MemDC = NULL;
1066 int ButtonWidth;
1067 COLORREF OldTextColor;
1068
1069 #ifdef DOUBLE_BUFFER_CAPTION
1070 HBITMAP MemBMP = NULL, OldBMP = NULL;
1071
1072 MemDC = CreateCompatibleDC(hDC);
1073 if (! MemDC) goto cleanup;
1074 MemBMP = CreateCompatibleBitmap(hDC, lprc->right - lprc->left, lprc->bottom - lprc->top);
1075 if (! MemBMP) goto cleanup;
1076 OldBMP = SelectObject(MemDC, MemBMP);
1077 if (! OldBMP) goto cleanup;
1078 #else
1079 MemDC = hDC;
1080
1081 OffsetViewportOrgEx(MemDC, lprc->left, lprc->top, NULL);
1082 #endif
1083
1084 Style = GetWindowLongW(hWnd, GWL_STYLE);
1085
1086 /* Windows behaves like this */
1087 Height = GetSystemMetrics(SM_CYCAPTION) - 1;
1088
1089 VCenter = (lprc->bottom - lprc->top) / 2;
1090 Padding = VCenter - (Height / 2);
1091
1092 r.left = Padding;
1093 r.right = r.left + (lprc->right - lprc->left);
1094 r.top = Padding;
1095 r.bottom = r.top + (Height / 2);
1096
1097 // Draw the caption background
1098 if (uFlags & DC_INBUTTON)
1099 {
1100 OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_BTNFACE : COLOR_BTNSHADOW) );
1101 if (! OldBrush) goto cleanup;
1102 if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
1103 }
1104 else
1105 {
1106 if (uFlags & DC_GRADIENT)
1107 {
1108 static GRADIENT_RECT gcap = {0, 1};
1109 TRIVERTEX vert[2];
1110 COLORREF Colors[2];
1111 LONG xx;
1112
1113 r.right = (lprc->right - lprc->left);
1114 if (uFlags & DC_SMALLCAP)
1115 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE) - 2;
1116 else
1117 ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
1118
1119 if (Style & WS_SYSMENU)
1120 {
1121 r.right -= 3 + ButtonWidth;
1122 if (! (uFlags & DC_SMALLCAP))
1123 {
1124 if(Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
1125 r.right -= 2 + 2 * ButtonWidth;
1126 else
1127 r.right -= 2;
1128 r.right -= 2;
1129 }
1130 }
1131
1132 Colors[0] = GetSysColor((uFlags & DC_ACTIVE) ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
1133 Colors[1] = GetSysColor((uFlags & DC_ACTIVE) ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION);
1134
1135 if ((uFlags & DC_ICON) && (Style & WS_SYSMENU) && !(uFlags & DC_SMALLCAP))
1136 {
1137 OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
1138 if (!OldBrush) goto cleanup;
1139 xx = GetSystemMetrics(SM_CXSIZE) + Padding;
1140 /* draw icon background */
1141 PatBlt(MemDC, 0, 0, xx, lprc->bottom - lprc->top, PATCOPY);
1142 // For some reason the icon isn't centered correctly...
1143 r.top --;
1144 UserDrawSysMenuButton(hWnd, MemDC, &r);
1145 r.top ++;
1146 r.left += xx;
1147 }
1148
1149 vert[0].x = r.left;
1150 vert[0].y = 0;
1151 vert[0].Red = GetRValue(Colors[0]) << 8;
1152 vert[0].Green = GetGValue(Colors[0]) << 8;
1153 vert[0].Blue = GetBValue(Colors[0]) << 8;
1154 vert[0].Alpha = 0;
1155
1156 vert[1].x = r.right;
1157 vert[1].y = lprc->bottom - lprc->top;
1158 vert[1].Red = GetRValue(Colors[1]) << 8;
1159 vert[1].Green = GetGValue(Colors[1]) << 8;
1160 vert[1].Blue = GetBValue(Colors[1]) << 8;
1161 vert[1].Alpha = 0;
1162
1163 GdiGradientFill(MemDC, vert, 2, &gcap, 1, GRADIENT_FILL_RECT_H);
1164
1165 if(OldBrush)
1166 {
1167 SelectObject(MemDC, OldBrush);
1168 OldBrush = NULL;
1169 }
1170 xx = lprc->right - lprc->left - r.right;
1171 if(xx > 0)
1172 {
1173 OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_GRADIENTACTIVECAPTION : COLOR_GRADIENTINACTIVECAPTION));
1174 if (!OldBrush) goto cleanup;
1175 PatBlt(MemDC, r.right, 0, xx, lprc->bottom - lprc->top, PATCOPY);
1176 }
1177 }
1178 else
1179 {
1180 OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1181 if (! OldBrush) goto cleanup;
1182 if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
1183 }
1184 }
1185
1186 if ((uFlags & DC_ICON) && !(uFlags & DC_GRADIENT) && (Style & WS_SYSMENU) && !(uFlags & DC_SMALLCAP))
1187 {
1188 // For some reason the icon isn't centered correctly...
1189 r.top --;
1190 UserDrawSysMenuButton(hWnd, MemDC, &r);
1191 r.top ++;
1192 }
1193 r.top ++;
1194 r.left += 2;
1195
1196 r.bottom = r.top + Height;
1197
1198 if ((uFlags & DC_TEXT) && (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) )))
1199 {
1200 if(!(uFlags & DC_GRADIENT))
1201 {
1202 if (!(uFlags & DC_SMALLCAP) && ((uFlags & DC_ICON) || (uFlags & DC_INBUTTON)))
1203 r.left += GetSystemMetrics(SM_CXSIZE) + Padding;
1204
1205 r.right = (lprc->right - lprc->left);
1206 if (uFlags & DC_SMALLCAP)
1207 ButtonWidth = GetSystemMetrics(SM_CXSMSIZE) - 2;
1208 else
1209 ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
1210
1211 if (Style & WS_SYSMENU)
1212 {
1213 r.right -= 3 + ButtonWidth;
1214 if (! (uFlags & DC_SMALLCAP))
1215 {
1216 if(Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
1217 r.right -= 2 + 2 * ButtonWidth;
1218 else
1219 r.right -= 2;
1220 r.right -= 2;
1221 }
1222 }
1223 }
1224
1225 nclm.cbSize = sizeof(nclm);
1226 if (! SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &nclm, 0)) goto cleanup;
1227
1228 SetBkMode( MemDC, TRANSPARENT );
1229 if (uFlags & DC_SMALLCAP)
1230 hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
1231 else
1232 hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
1233
1234 if (! hFont) goto cleanup;
1235
1236 hOldFont = SelectObject(MemDC, hFont);
1237 if (! hOldFont) goto cleanup;
1238
1239 if (uFlags & DC_INBUTTON)
1240 OldTextColor = SetTextColor(MemDC, GetSysColor(uFlags & DC_ACTIVE ? COLOR_BTNTEXT : COLOR_GRAYTEXT));
1241 else
1242 OldTextColor = SetTextColor(MemDC, GetSysColor(uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT));
1243
1244 DrawTextW(MemDC, buffer, wcslen(buffer), &r, DT_VCENTER | DT_END_ELLIPSIS);
1245
1246 SetTextColor(MemDC, OldTextColor);
1247 }
1248
1249 #if 0
1250 if (uFlags & DC_BUTTONS)
1251 {
1252 // Windows XP draws the caption buttons with DC_BUTTONS
1253 // r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1254 // UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
1255 // r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
1256 // UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
1257 // UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
1258 }
1259 #endif
1260
1261 #ifdef DOUBLE_BUFFER_CAPTION
1262 if (! BitBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
1263 MemDC, 0, 0, SRCCOPY)) goto cleanup;
1264 #endif
1265
1266 result = TRUE;
1267
1268 cleanup :
1269 if (MemDC)
1270 {
1271 if (OldBrush) SelectObject(MemDC, OldBrush);
1272 if (hOldFont) SelectObject(MemDC, hOldFont);
1273 if (hFont) DeleteObject(hFont);
1274 #ifdef DOUBLE_BUFFER_CAPTION
1275 if (OldBMP) SelectObject(MemDC, OldBMP);
1276 if (MemBMP) DeleteObject(MemBMP);
1277 DeleteDC(MemDC);
1278 #else
1279 OffsetViewportOrgEx(MemDC, -lprc->left, -lprc->top, NULL);
1280 #endif
1281 }
1282
1283 return result;
1284 }
1285
1286
1287 /*
1288 * @unimplemented
1289 */
1290 BOOL
1291 STDCALL
1292 DrawCaptionTempW(
1293 HWND hwnd,
1294 HDC hdc,
1295 const RECT *rect,
1296 HFONT hFont,
1297 HICON hIcon,
1298 LPCWSTR str,
1299 UINT uFlags
1300 )
1301 {
1302 UNIMPLEMENTED;
1303 return FALSE;
1304 }
1305
1306 /*
1307 * @unimplemented
1308 */
1309 BOOL
1310 STDCALL
1311 DrawCaptionTempA(
1312 HWND hwnd,
1313 HDC hdc,
1314 const RECT *rect,
1315 HFONT hFont,
1316 HICON hIcon,
1317 LPCSTR str,
1318 UINT uFlags
1319 )
1320 {
1321 UNIMPLEMENTED;
1322 return FALSE;
1323 }
1324
1325 /***********************************************************************
1326 * NcGetInsideRect
1327 *
1328 * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
1329 * but without the borders (if any).
1330 * The rectangle is in window coordinates (for drawing with GetWindowDC()).
1331 */
1332 static void FASTCALL
1333 NcGetInsideRect(HWND Wnd, RECT *Rect)
1334 {
1335 DWORD Style;
1336 DWORD ExStyle;
1337
1338 GetWindowRect(Wnd, Rect);
1339 Rect->right = Rect->right - Rect->left;
1340 Rect->left = 0;
1341 Rect->bottom = Rect->bottom - Rect->top;
1342 Rect->top = 0;
1343
1344 Style = GetWindowLongW(Wnd, GWL_STYLE);
1345 if (0 != (Style & WS_ICONIC))
1346 {
1347 return;
1348 }
1349
1350 /* Remove frame from rectangle */
1351 ExStyle = GetWindowLongW(Wnd, GWL_EXSTYLE);
1352 if (HAS_THICKFRAME(Style, ExStyle))
1353 {
1354 InflateRect(Rect, - GetSystemMetrics(SM_CXFRAME), - GetSystemMetrics(SM_CYFRAME));
1355 }
1356 else if (HAS_DLGFRAME(Style, ExStyle))
1357 {
1358 InflateRect(Rect, - GetSystemMetrics(SM_CXDLGFRAME), - GetSystemMetrics(SM_CYDLGFRAME));
1359 }
1360 else if (HAS_THINFRAME(Style, ExStyle))
1361 {
1362 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1363 }
1364
1365 /* We have additional border information if the window
1366 * is a child (but not an MDI child) */
1367 if (0 != (Style & WS_CHILD)
1368 && 0 == (ExStyle & WS_EX_MDICHILD))
1369 {
1370 if (0 != (ExStyle & WS_EX_CLIENTEDGE))
1371 {
1372 InflateRect(Rect, - GetSystemMetrics(SM_CXEDGE), - GetSystemMetrics(SM_CYEDGE));
1373 }
1374 if (0 != (ExStyle & WS_EX_STATICEDGE))
1375 {
1376 InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
1377 }
1378 }
1379 }
1380
1381 /***********************************************************************
1382 * NcGetSysPopupPos
1383 */
1384 void FASTCALL
1385 NcGetSysPopupPos(HWND Wnd, RECT *Rect)
1386 {
1387 RECT WindowRect;
1388
1389 if (IsIconic(Wnd))
1390 {
1391 GetWindowRect(Wnd, Rect);
1392 }
1393 else
1394 {
1395 NcGetInsideRect(Wnd, Rect);
1396 GetWindowRect(Wnd, &WindowRect);
1397 OffsetRect(Rect, WindowRect.left, WindowRect.top);
1398 if (0 != (GetWindowLongW(Wnd, GWL_STYLE) & WS_CHILD))
1399 {
1400 ClientToScreen(GetParent(Wnd), (POINT *) Rect);
1401 }
1402 Rect->right = Rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1403 Rect->bottom = Rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1404 }
1405 }