3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
20 /* INCLUDES ******************************************************************/
26 /* DEFINES ******************************************************************/
28 #define HAS_DLGFRAME(style,exStyle) \
29 (((exStyle) & WS_EX_DLGMODALFRAME) || \
30 (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
32 #define HAS_THICKFRAME(style,exStyle) \
33 (((style) & WS_THICKFRAME) && \
34 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
36 #define HAS_THINFRAME(style) \
37 (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
39 #define HAS_BIGFRAME(style,exStyle) \
40 (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
41 ((exStyle) & WS_EX_DLGMODALFRAME))
43 /* FUNCTIONS *****************************************************************/
46 DrawFrameControl(HDC hDc, LPRECT Rect, UINT Type, UINT State)
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()).
54 void NC_GetInsideRect( HWND hwnd, RECT *rect )
58 GetWindowRect(hwnd, rect);
59 Style = GetWindowLong(hwnd, GWL_STYLE);
60 ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
62 rect->top = rect->left = 0;
63 rect->right = rect->right - rect->left;
64 rect->bottom = rect->bottom - rect->top;
66 /* if (wndPtr->dwStyle & WS_ICONIC) goto END; */
68 /* Remove frame from rectangle */
69 if (HAS_THICKFRAME(Style, ExStyle ))
71 InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
73 else if (HAS_DLGFRAME(Style, ExStyle ))
75 InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
77 else if (HAS_THINFRAME( Style ))
79 InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
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 ) )
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));
97 /* Draws the Win95 system icon. */
99 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
101 HICON hIcon = NC_IconForWindow( hwnd );
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);
114 /* Draws the Win95 close button. */
115 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
119 NC_GetInsideRect( hwnd, &rect );
121 /* A tool window has a smaller Close button */
122 if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
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);
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;
135 rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
136 rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
140 DrawFrameControl( hdc, &rect, DFC_CAPTION,
142 (down ? DFCS_PUSHED : 0) |
143 (bGrayed ? DFCS_INACTIVE : 0)) );
146 /* Draws the maximize button for Win95 style windows. */
147 static void NC_DrawMaxButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
150 UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
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;
159 if (down) flags |= DFCS_PUSHED;
160 if (bGrayed) flags |= DFCS_INACTIVE;
161 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
164 /* Draws the minimize button for Win95 style windows. */
165 static void NC_DrawMinButton95(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
168 UINT flags = DFCS_CAPTIONMIN;
169 DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
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;
180 if (down) flags |= DFCS_PUSHED;
181 if (bGrayed) flags |= DFCS_INACTIVE;
182 DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
185 /* Draw a window frame inside the given rectangle, and update the rectangle. */
186 static void NC_DrawFrame95(
195 /* Firstly the "thick" frame */
196 if (style & WS_THICKFRAME)
198 width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
199 height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
201 /* SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
202 COLOR_INACTIVEBORDER) ); */
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 );
213 InflateRect( rect, -width, -height );
216 /* Now the other bit of the frame */
217 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
218 (exStyle & WS_EX_DLGMODALFRAME))
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 */
224 /* SelectObject( hdc, GetSysColorBrush(
225 (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
227 (exStyle & WS_EX_STATICEDGE) ?
229 (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
232 COLOR_WINDOWFRAME)); */
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 );
244 InflateRect( rect, -width, -height );
248 static HICON NC_IconForWindow( HWND hwnd )
250 HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
251 if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
253 /* If there is no hIcon specified and this is a modal dialog,
254 * get the default one.
256 /* if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
257 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); */
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(
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 );
284 /* FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
285 COLOR_INACTIVECAPTION) ); */
287 if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
288 if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
289 r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
292 if (style & WS_SYSMENU)
296 /* Go get the sysmenu */
297 hSysMenu = GetSystemMenu(hwnd, FALSE);
298 state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
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;
305 if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
307 /* In win95 the two buttons are always there */
308 /* But if the menu item is not in the menu they're disabled*/
310 NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
311 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
313 NC_DrawMinButton95( hwnd, hdc, FALSE, (!(style & WS_MINIMIZEBOX)));
314 r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
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);
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 );
332 DrawTextA( hdc, buffer, -1, &r,
333 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
334 DeleteObject (SelectObject (hdc, hOldFont));
338 static void NC_DoNCPaint95(
341 BOOL suppress_menupaint)
344 RECT rfuzz, rect, rectClip;
346 DWORD Style, ExStyle;
348 RECT ClientRect, WindowRect;
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);
357 /* Flags = wndPtr->flags; */
359 /* if (Style & WS_MINIMIZE ||
360 !WIN_IsWindowDrawable(hwnd, 0)) return; */ /* Nothing to do */
362 active = TRUE /* Flags & WIN_NCACTIVATED */;
364 DPRINT("%04x %d\n", hwnd, active);
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?
373 if (!(hdc = GetDCEx(hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
374 ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0)))) return;
377 /* if (ExcludeVisRect(hdc, ClientRect.left-WindowRect.left,
378 ClientRect.top-WindowRect.top,
379 ClientRect.right-WindowRect.left,
380 ClientRect.bottom-WindowRect.top)
383 ReleaseDC(hwnd, hdc);
387 rect.top = rect.left = 0;
388 rect.right = WindowRect.right - WindowRect.left;
389 rect.bottom = WindowRect.bottom - WindowRect.top;
392 GetRgnBox(clip, &rectClip);
399 /* SelectObject(hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); */
401 /* if (HAS_STATICOUTERFRAME(Style, ExStyle)) {
402 DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
404 else if (HAS_BIGFRAME(Style, ExStyle)) {
405 DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
408 NC_DrawFrame95(hdc, &rect, active, Style, ExStyle);
410 if ((Style & WS_CAPTION) == WS_CAPTION)
413 if (ExStyle & WS_EX_TOOLWINDOW) {
414 r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
415 rect.top += GetSystemMetrics(SM_CYSMCAPTION);
418 r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
419 rect.top += GetSystemMetrics(SM_CYCAPTION);
421 if(!clip || IntersectRect(&rfuzz, &r, &rectClip))
422 NC_DrawCaption95 (hdc, &r, hwnd, Style,
429 r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
431 DPRINT("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
432 r.left, r.top, r.right, r.bottom);
434 rect.top += MENU_DrawMenuBar(hdc, &r, hwnd, suppress_menupaint) + 1;
437 DPRINT("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
438 rect.left, rect.top, rect.right, rect.bottom);
440 if (ExStyle & WS_EX_CLIENTEDGE)
441 DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
443 /* Draw the scroll-bars */
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);
450 /* Draw the "size-box" */
451 if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL))
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)); */
459 ReleaseDC(hwnd, hdc);
462 /* Handle a WM_NCPAINT message. Called from DefWindowProc(). */
463 LONG NC_HandleNCPaint(HWND hwnd , HRGN clip)
465 DWORD Style = GetWindowLongW(hwnd, GWL_STYLE);
467 if(Style & WS_VISIBLE)
469 /* if(Style & WS_MINIMIZE)
470 WINPOS_RedrawIconTitle(hwnd); */
471 /* else if (TWEAK_WineLook == WIN31_LOOK)
472 NC_DoNCPaint(hwnd, clip, FALSE); */
474 NC_DoNCPaint95(hwnd, clip, FALSE);