update for HEAD-2003050101
[reactos.git] / lib / user32 / windows / nonclient.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #if 0
20 /* INCLUDES ******************************************************************/
21
22 #include <windows.h>
23 #include <user32.h>
24 #include <debug.h>
25
26 /* DEFINES ******************************************************************/
27
28 #define HAS_DLGFRAME(style,exStyle) \
29     (((exStyle) & WS_EX_DLGMODALFRAME) || \
30      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
31
32 #define HAS_THICKFRAME(style,exStyle) \
33     (((style) & WS_THICKFRAME) && \
34      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
35
36 #define HAS_THINFRAME(style) \
37     (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
38
39 #define HAS_BIGFRAME(style,exStyle) \
40     (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
41      ((exStyle) & WS_EX_DLGMODALFRAME))
42
43 /* FUNCTIONS *****************************************************************/
44
45 WINBOOL STDCALL
46 DrawFrameControl(HDC hDc, LPRECT Rect, UINT Type, UINT State)
47 {
48 }
49
50 /* Get the 'inside' rectangle of a window, i.e. the whole window rectangle
51  * but without the borders (if any).
52  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
53  */
54 void NC_GetInsideRect( HWND hwnd, RECT *rect )
55 {
56     DWORD Style, ExStyle;
57
58     GetWindowRect(hwnd, rect);
59     Style = GetWindowLong(hwnd, GWL_STYLE);
60     ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
61
62     rect->top    = rect->left = 0;
63     rect->right  = rect->right - rect->left;
64     rect->bottom = rect->bottom - rect->top;
65
66 /*    if (wndPtr->dwStyle & WS_ICONIC) goto END; */
67
68     /* Remove frame from rectangle */
69     if (HAS_THICKFRAME(Style, ExStyle ))
70     {
71         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
72     }
73     else if (HAS_DLGFRAME(Style, ExStyle ))
74     {
75         InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
76     }
77     else if (HAS_THINFRAME( Style ))
78     {
79         InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
80     }
81
82     /* We have additional border information if the window
83      * is a child (but not an MDI child) */
84     if ( (Style & WS_CHILD)  &&
85          ( (ExStyle & WS_EX_MDICHILD) == 0 ) )
86     {
87         if (ExStyle & WS_EX_CLIENTEDGE)
88             InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
89         if (ExStyle & WS_EX_STATICEDGE)
90             InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
91     }
92
93 END:
94     return;
95 }
96
97 /*  Draws the Win95 system icon. */
98 BOOL
99 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
100 {
101     HICON hIcon = NC_IconForWindow( hwnd );
102
103     if (hIcon)
104     {
105         RECT rect;
106         NC_GetInsideRect( hwnd, &rect );
107         DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
108                     GetSystemMetrics(SM_CXSMICON),
109                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
110     }
111     return (hIcon != 0);
112 }
113
114 /* Draws the Win95 close button. */
115 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
116 {
117     RECT rect;
118
119     NC_GetInsideRect( hwnd, &rect );
120
121     /* A tool window has a smaller Close button */
122     if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
123     {
124         INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE   */
125         INT iBmpWidth = 11;  /* it uses 11x11 for  the close button in tool window */
126         INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
127
128         rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
129         rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
130         rect.bottom = rect.top + iBmpHeight;
131         rect.right = rect.left + iBmpWidth;
132     }
133     else
134     {
135         rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
136         rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
137         rect.top += 2;
138         rect.right -= 2;
139     }
140     DrawFrameControl( hdc, &rect, DFC_CAPTION,
141                       (DFCS_CAPTIONCLOSE |
142                        (down ? DFCS_PUSHED : 0) |
143                        (bGrayed ? DFCS_INACTIVE : 0)) );
144 }
145
146 /*  Draws the maximize button for Win95 style windows. */
147 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
148 {
149     RECT rect;
150     UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
151
152     NC_GetInsideRect( hwnd, &rect );
153     if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
154         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
155     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
156     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
157     rect.top += 2;
158     rect.right -= 2;
159     if (down) flags |= DFCS_PUSHED;
160     if (bGrayed) flags |= DFCS_INACTIVE;
161     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
162 }
163
164 /*  Draws the minimize button for Win95 style windows. */
165 static void  NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
166 {
167     RECT rect;
168     UINT flags = DFCS_CAPTIONMIN;
169     DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
170
171     NC_GetInsideRect( hwnd, &rect );
172     if (style & WS_SYSMENU)
173         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
174     if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
175         rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
176     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
177     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
178     rect.top += 2;
179     rect.right -= 2;
180     if (down) flags |= DFCS_PUSHED;
181     if (bGrayed) flags |= DFCS_INACTIVE;
182     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
183 }
184
185 /* Draw a window frame inside the given rectangle, and update the rectangle. */
186 static void  NC_DrawFrame95(
187     HDC  hdc,
188     RECT  *rect,
189     BOOL  active,
190     DWORD style,
191     DWORD exStyle)
192 {
193     INT width, height;
194
195     /* Firstly the "thick" frame */
196     if (style & WS_THICKFRAME)
197     {
198         width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
199         height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
200
201 /*        SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
202                       COLOR_INACTIVEBORDER) ); */
203         /* Draw frame */
204         PatBlt( hdc, rect->left, rect->top,
205                   rect->right - rect->left, height, PATCOPY );
206         PatBlt( hdc, rect->left, rect->top,
207                   width, rect->bottom - rect->top, PATCOPY );
208         PatBlt( hdc, rect->left, rect->bottom - 1,
209                   rect->right - rect->left, -height, PATCOPY );
210         PatBlt( hdc, rect->right - 1, rect->top,
211                   -width, rect->bottom - rect->top, PATCOPY );
212
213         InflateRect( rect, -width, -height );
214     }
215
216     /* Now the other bit of the frame */
217     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
218         (exStyle & WS_EX_DLGMODALFRAME))
219     {
220         width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
221         height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
222         /* This should give a value of 1 that should also work for a border */
223
224 /*        SelectObject( hdc, GetSysColorBrush(
225                       (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
226                           COLOR_3DFACE :
227                       (exStyle & WS_EX_STATICEDGE) ?
228                           COLOR_WINDOWFRAME :
229                       (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
230                           COLOR_3DFACE :
231                             // else
232                           COLOR_WINDOWFRAME)); */
233
234         /* Draw frame */
235         PatBlt( hdc, rect->left, rect->top,
236                   rect->right - rect->left, height, PATCOPY );
237         PatBlt( hdc, rect->left, rect->top,
238                   width, rect->bottom - rect->top, PATCOPY );
239         PatBlt( hdc, rect->left, rect->bottom - 1,
240                   rect->right - rect->left, -height, PATCOPY );
241         PatBlt( hdc, rect->right - 1, rect->top,
242                   -width, rect->bottom - rect->top, PATCOPY );
243
244         InflateRect( rect, -width, -height );
245     }
246 }
247
248 static HICON NC_IconForWindow( HWND hwnd )
249 {
250     HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
251     if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
252
253     /* If there is no hIcon specified and this is a modal dialog,
254      * get the default one.
255      */
256 /*    if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
257         hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); */
258     return hIcon;
259 }
260
261 /* Draw the window caption for Win95 style windows. The correct pen for the window frame must be selected in the DC. */
262 static void  NC_DrawCaption95(
263     HDC  hdc,
264     RECT *rect,
265     HWND hwnd,
266     DWORD  style,
267     DWORD  exStyle,
268     BOOL active )
269 {
270     RECT  r = *rect;
271     char    buffer[256];
272     HPEN  hPrevPen;
273     HMENU hSysMenu;
274
275 /*    hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
276                      ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
277                                  WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
278                       COLOR_WINDOWFRAME : COLOR_3DFACE) ); */
279     MoveToEx( hdc, r.left, r.bottom - 1, NULL );
280     LineTo( hdc, r.right, r.bottom - 1 );
281     SelectObject( hdc, hPrevPen );
282     r.bottom--;
283
284 /*    FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
285                                             COLOR_INACTIVECAPTION) ); */
286
287     if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
288         if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
289             r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
290     }
291
292     if (style & WS_SYSMENU)
293     {
294         UINT state;
295
296         /* Go get the sysmenu */
297         hSysMenu = GetSystemMenu(hwnd, FALSE);
298         state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
299
300         /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
301         NC_DrawCloseButton95 (hwnd, hdc, FALSE,
302                               ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
303         r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
304
305         if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
306         {
307             /* In win95 the two buttons are always there */
308             /* But if the menu item is not in the menu they're disabled*/
309
310             NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
311             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
312
313             NC_DrawMinButton95( hwnd, hdc, FALSE,  (!(style & WS_MINIMIZEBOX)));
314             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
315         }
316     }
317
318     if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
319         NONCLIENTMETRICS nclm;
320         HFONT hFont, hOldFont;
321         nclm.cbSize = sizeof(NONCLIENTMETRICS);
322         SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
323         if (exStyle & WS_EX_TOOLWINDOW)
324             hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
325         else
326             hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
327         hOldFont = SelectObject (hdc, hFont);
328 /*      if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
329         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) ); */
330         SetBkMode( hdc, TRANSPARENT );
331         r.left += 2;
332         DrawTextA( hdc, buffer, -1, &r,
333                      DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
334         DeleteObject (SelectObject (hdc, hOldFont));
335     }
336 }
337
338 static void  NC_DoNCPaint95(
339     HWND  hwnd,
340     HRGN  clip,
341     BOOL  suppress_menupaint)
342 {
343     HDC hdc;
344     RECT rfuzz, rect, rectClip;
345     BOOL active;
346     DWORD Style, ExStyle;
347     WORD Flags;
348     RECT ClientRect, WindowRect;
349     int has_menu;
350
351     /* FIXME: Determine has_menu */
352     Style = GetWindowLong(hwnd, GWL_STYLE);
353     ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
354     GetWindowRect(hwnd, &WindowRect);
355     GetClientRect(hwnd, &ClientRect);
356
357 /* Flags = wndPtr->flags; */
358
359 /*    if (Style & WS_MINIMIZE ||
360          !WIN_IsWindowDrawable(hwnd, 0)) return; */ /* Nothing to do */
361
362     active  = TRUE /* Flags & WIN_NCACTIVATED */;
363
364     DPRINT("%04x %d\n", hwnd, active);
365
366     /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
367        the call to GetDCEx implying that it is allowed not to use it either.
368        However, the suggested GetDCEx(   , DCX_WINDOW | DCX_INTERSECTRGN)
369        will cause clipRgn to be deleted after ReleaseDC().
370        Now, how is the "system" supposed to tell what happened?
371      */
372
373     if (!(hdc = GetDCEx(hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
374                               ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0)))) return;
375
376
377 /*    if (ExcludeVisRect(hdc, ClientRect.left-WindowRect.left,
378                        ClientRect.top-WindowRect.top,
379                        ClientRect.right-WindowRect.left,
380                        ClientRect.bottom-WindowRect.top)
381         == NULLREGION)
382     {
383         ReleaseDC(hwnd, hdc);
384         return;
385     } */
386
387     rect.top = rect.left = 0;
388     rect.right  = WindowRect.right - WindowRect.left;
389     rect.bottom = WindowRect.bottom - WindowRect.top;
390
391     if(clip > 1)
392         GetRgnBox(clip, &rectClip);
393     else
394     {
395         clip = 0;
396         rectClip = rect;
397     }
398
399 /*    SelectObject(hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); */
400
401 /*    if (HAS_STATICOUTERFRAME(Style, ExStyle)) {
402         DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
403     }
404     else if (HAS_BIGFRAME(Style, ExStyle)) {
405         DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
406     } */
407
408     NC_DrawFrame95(hdc, &rect, active, Style, ExStyle);
409 /*
410     if ((Style & WS_CAPTION) == WS_CAPTION)
411     {
412         RECT  r = rect;
413         if (ExStyle & WS_EX_TOOLWINDOW) {
414             r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
415             rect.top += GetSystemMetrics(SM_CYSMCAPTION);
416         }
417         else {
418             r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
419             rect.top += GetSystemMetrics(SM_CYCAPTION);
420         }
421         if(!clip || IntersectRect(&rfuzz, &r, &rectClip))
422             NC_DrawCaption95 (hdc, &r, hwnd, Style,
423                               ExStyle, active);
424     }
425 */
426 /*    if (has_menu)
427     {
428         RECT r = rect;
429         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
430
431         DPRINT("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
432               r.left, r.top, r.right, r.bottom);
433
434         rect.top += MENU_DrawMenuBar(hdc, &r, hwnd, suppress_menupaint) + 1;
435     }
436 */
437     DPRINT("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
438           rect.left, rect.top, rect.right, rect.bottom);
439
440     if (ExStyle & WS_EX_CLIENTEDGE)
441         DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
442
443     /* Draw the scroll-bars */
444 /*
445     if (Style & WS_VSCROLL)
446         SCROLL_DrawScrollBar(hwnd, hdc, SB_VERT, TRUE, TRUE);
447     if (Style & WS_HSCROLL)
448         SCROLL_DrawScrollBar(hwnd, hdc, SB_HORZ, TRUE, TRUE);
449 */
450     /* Draw the "size-box" */
451     if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL))
452     {
453         RECT r = rect;
454         r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
455         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
456 /*        FillRect(hdc, &r,  GetSysColorBrush(COLOR_SCROLLBAR)); */
457     }
458
459     ReleaseDC(hwnd, hdc);
460 }
461
462 /* Handle a WM_NCPAINT message. Called from DefWindowProc(). */
463 LONG NC_HandleNCPaint(HWND hwnd , HRGN clip)
464 {
465     DWORD Style = GetWindowLongW(hwnd, GWL_STYLE);
466
467     if(Style & WS_VISIBLE)
468     {
469 /*      if(Style & WS_MINIMIZE)
470             WINPOS_RedrawIconTitle(hwnd); */
471 /*      else if (TWEAK_WineLook == WIN31_LOOK)
472             NC_DoNCPaint(hwnd, clip, FALSE); */
473 /*      else */
474             NC_DoNCPaint95(hwnd, clip, FALSE);
475     }
476     return 0;
477 }
478 #endif