3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS User32
5 * PURPOSE: Static control
6 * FILE: lib/user32/controls/static.c
7 * PROGRAMER: Ge van Geldorp (ge@gse.nl)
8 * REVISION HISTORY: 2003/05/28 GvG Created
9 * NOTES: Adapted from Wine
13 #include "user32/regcontrol.h"
15 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style );
16 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style );
17 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style );
18 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style );
19 static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style );
20 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style );
21 //static LRESULT CALLBACK StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
22 static LRESULT CALLBACK StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
24 static COLORREF color_black, color_gray, color_white;
26 /* offsets for GetWindowLong for static private information */
27 #define HFONT_GWL_OFFSET 0
28 #define HICON_GWL_OFFSET (sizeof(HFONT))
29 #define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON))
31 typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
33 static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
35 STATIC_PaintTextfn, /* SS_LEFT */
36 STATIC_PaintTextfn, /* SS_CENTER */
37 STATIC_PaintTextfn, /* SS_RIGHT */
38 STATIC_PaintIconfn, /* SS_ICON */
39 STATIC_PaintRectfn, /* SS_BLACKRECT */
40 STATIC_PaintRectfn, /* SS_GRAYRECT */
41 STATIC_PaintRectfn, /* SS_WHITERECT */
42 STATIC_PaintRectfn, /* SS_BLACKFRAME */
43 STATIC_PaintRectfn, /* SS_GRAYFRAME */
44 STATIC_PaintRectfn, /* SS_WHITEFRAME */
45 NULL, /* SS_USERITEM */
46 STATIC_PaintTextfn, /* SS_SIMPLE */
47 STATIC_PaintTextfn, /* SS_LEFTNOWORDWRAP */
48 STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */
49 STATIC_PaintBitmapfn, /* SS_BITMAP */
50 NULL, /* SS_ENHMETAFILE */
51 STATIC_PaintEtchedfn, /* SS_ETCHEDHORIZ */
52 STATIC_PaintEtchedfn, /* SS_ETCHEDVERT */
53 STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */
57 /*********************************************************************
58 * static class descriptor
60 const struct builtin_class_descr STATIC_builtin_class =
63 CS_GLOBALCLASS | CS_DBLCLKS, /* style */
64 (WNDPROC) StaticWndProcW, /* procW */
65 STATIC_EXTRA_BYTES, /* extra */
66 (LPCWSTR) IDC_ARROW, /* cursor */ /* FIXME Wine uses IDC_ARROWA */
71 /***********************************************************************
74 * Set the icon for an SS_ICON control.
76 static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
80 CURSORICONINFO *info = hicon?(CURSORICONINFO *) GlobalLock16(HICON_16(hicon)):NULL;
82 if ((style & SS_TYPEMASK) != SS_ICON) return 0;
84 ERR("huh? hicon!=0, but info=0???\n");
87 prevIcon = (HICON)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hicon );
90 SetWindowPos( hwnd, 0, 0, 0, info->nWidth, info->nHeight,
91 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
92 GlobalUnlock16(HICON_16(hicon));
96 OutputDebugStringA("STATIC_SetIcon not implemented\n");
101 /***********************************************************************
104 * Set the bitmap for an SS_BITMAP control.
106 static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
110 if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
111 if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) {
112 OutputDebugStringA("huh? hBitmap!=0, but not bitmap\n");
115 hOldBitmap = (HBITMAP)SetWindowLongA( hwnd, HICON_GWL_OFFSET, (LONG)hBitmap );
119 GetObjectW(hBitmap, sizeof(bm), &bm);
120 SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight,
121 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
126 /***********************************************************************
129 * Load the icon for an SS_ICON control.
131 static HICON STATIC_LoadIconW( HWND hwnd, LPCWSTR name )
133 HINSTANCE hInstance = (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE );
134 HICON hicon = LoadIconW( hInstance, name );
135 if (!hicon) hicon = LoadIconW( 0, name );
139 /***********************************************************************
142 * Load the bitmap for an SS_BITMAP control.
144 static HBITMAP STATIC_LoadBitmapW( HWND hwnd, LPCWSTR name )
146 HINSTANCE hInstance = (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE );
147 HBITMAP hbitmap = LoadBitmapW( hInstance, name );
148 if (!hbitmap) /* Try OEM icon (FIXME: is this right?) */
149 hbitmap = LoadBitmapW( 0, name );
153 /***********************************************************************
156 * Try to immediately paint the control.
158 static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
160 LONG style = full_style & SS_TYPEMASK;
163 GetClientRect( hwnd, &rc );
164 if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
168 (staticPaintFunc[style])( hwnd, hdc, full_style );
169 ReleaseDC( hwnd, hdc );
173 /***********************************************************************
176 static LRESULT CALLBACK StaticWndProcW( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
179 LONG full_style = GetWindowLongA( hwnd, GWL_STYLE );
180 LONG style = full_style & SS_TYPEMASK;
182 if (!IsWindow( hwnd )) return 0;
186 if (style < 0L || style > SS_TYPEMASK)
188 OutputDebugStringA("Unknown style\n");
191 /* initialise colours */
192 color_black = GetSysColor(COLOR_3DDKSHADOW);
193 color_gray = GetSysColor(COLOR_3DSHADOW);
194 color_white = GetSysColor(COLOR_3DHILIGHT);
198 if (style == SS_ICON) {
201 * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
203 * We don't want to do this yet because DestroyIcon32 is broken. If the icon
204 * had already been loaded by the application the last thing we want to do is
205 * GlobalFree16 the handle.
209 else return DefWindowProcW(hwnd, uMsg, wParam, lParam);
214 BeginPaint(hwnd, &ps);
215 if (staticPaintFunc[style])
216 (staticPaintFunc[style])( hwnd, ps.hdc, full_style );
222 InvalidateRect(hwnd, NULL, TRUE);
225 case WM_SYSCOLORCHANGE:
226 color_black = GetSysColor(COLOR_3DDKSHADOW);
227 color_gray = GetSysColor(COLOR_3DSHADOW);
228 color_white = GetSysColor(COLOR_3DHILIGHT);
229 InvalidateRect(hwnd, NULL, TRUE);
233 if (full_style & SS_SUNKEN)
234 SetWindowLongA( hwnd, GWL_EXSTYLE,
235 GetWindowLongA( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
237 lParam = (LPARAM)(((LPCREATESTRUCTW)lParam)->lpszName);
244 hIcon = STATIC_LoadIconW(hwnd, (LPCWSTR)lParam);
245 /* FIXME : should we also return the previous hIcon here ??? */
246 STATIC_SetIcon(hwnd, hIcon, style);
252 hBitmap = STATIC_LoadBitmapW(hwnd, (LPCWSTR)lParam);
253 STATIC_SetBitmap(hwnd, hBitmap, style);
260 case SS_LEFTNOWORDWRAP:
264 lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
266 if (uMsg == WM_SETTEXT)
267 STATIC_TryPaintFcn( hwnd, full_style );
273 lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
275 if(uMsg == WM_SETTEXT)
276 InvalidateRect(hwnd, NULL, TRUE);
278 return 1; /* success. FIXME: check text length */
281 if ((style == SS_ICON) || (style == SS_BITMAP)) return 0;
282 SetWindowLongA( hwnd, HFONT_GWL_OFFSET, wParam );
284 InvalidateRect( hwnd, NULL, TRUE );
288 return GetWindowLongA( hwnd, HFONT_GWL_OFFSET );
291 if (full_style & SS_NOTIFY)
294 return HTTRANSPARENT;
300 if (! (full_style & SS_NOTIFY)) return 0;
301 SendMessageW(GetParent(hwnd), WM_COMMAND,
302 MAKEWPARAM((WORD) GetWindowLongW(hwnd, GWL_ID), STN_CLICKED), (LPARAM) hwnd);
305 case WM_LBUTTONDBLCLK:
306 if (! (full_style & SS_NOTIFY)) return 0;
307 SendMessageW(GetParent(hwnd), WM_COMMAND,
308 MAKEWPARAM((WORD) GetWindowLongW(hwnd, GWL_ID), STN_DBLCLK), (LPARAM) hwnd);
313 return GetWindowLongA( hwnd, HICON_GWL_OFFSET );
318 lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, style );
321 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, style );
324 OutputDebugStringA("STM_SETIMAGE: Unhandled type\n");
327 InvalidateRect( hwnd, NULL, TRUE );
331 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, style );
332 InvalidateRect( hwnd, NULL, TRUE );
336 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
341 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style )
344 LONG id = GetWindowLongA( hwnd, GWL_ID );
346 dis.CtlType = ODT_STATIC;
349 dis.itemAction = ODA_DRAWENTIRE;
354 GetClientRect( hwnd, &dis.rcItem );
356 SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
357 SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
360 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style )
368 HPEN ShadowPen, HighlightPen;
370 GetClientRect( hwnd, &rc);
372 switch (style & SS_TYPEMASK)
375 wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
379 wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
383 wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
387 wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP;
390 case SS_LEFTNOWORDWRAP:
391 wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER;
398 if (style & SS_NOPREFIX)
399 wFormat |= DT_NOPREFIX;
400 switch(style & SS_ELLIPSISMASK)
402 case SS_WORDELLIPSIS:
403 wFormat |= DT_WORD_ELLIPSIS | DT_SINGLELINE;
406 wFormat |= DT_END_ELLIPSIS;
407 wFormat &= ~DT_WORDBREAK;
409 case SS_PATHELLIPSIS:
410 wFormat |= DT_PATH_ELLIPSIS;
411 wFormat &= ~DT_WORDBREAK;
415 if ((hFont = (HFONT)GetWindowLongA( hwnd, HFONT_GWL_OFFSET ))) SelectObject( hdc, hFont );
417 if ((style & SS_NOPREFIX) || ((style & SS_TYPEMASK) != SS_SIMPLE))
419 hBrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
420 (WPARAM)hdc, (LPARAM)hwnd );
421 if (!hBrush) /* did the app forget to call defwindowproc ? */
422 hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC,
423 (WPARAM)hdc, (LPARAM)hwnd);
424 FillRect( hdc, &rc, hBrush );
426 if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
427 SetBkMode(hdc, TRANSPARENT);
429 if (style & SS_SUNKEN)
431 ShadowPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNSHADOW));
432 SelectObject(hdc, ShadowPen);
433 MoveToEx(hdc, 0, rc.bottom - 2, NULL);
435 LineTo(hdc, rc.right - 1, 0);
436 HighlightPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_BTNHIGHLIGHT));
437 SelectObject(hdc, HighlightPen);
438 LineTo(hdc, rc.right - 1, rc.bottom - 1);
439 LineTo(hdc, -1, rc.bottom - 1);
440 SelectObject(hdc, GetStockObject(WHITE_PEN));
441 DeleteObject(HighlightPen);
442 DeleteObject(ShadowPen);
449 if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return;
450 if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return;
451 SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text );
452 DrawTextW( hdc, text, -1, &rc, wFormat );
453 HeapFree( GetProcessHeap(), 0, text );
456 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style )
461 GetClientRect( hwnd, &rc);
463 switch (style & SS_TYPEMASK)
466 hBrush = CreateSolidBrush(color_black);
467 FillRect( hdc, &rc, hBrush );
470 hBrush = CreateSolidBrush(color_gray);
471 FillRect( hdc, &rc, hBrush );
474 hBrush = CreateSolidBrush(color_white);
475 FillRect( hdc, &rc, hBrush );
478 hBrush = CreateSolidBrush(color_black);
479 FrameRect( hdc, &rc, hBrush );
482 hBrush = CreateSolidBrush(color_gray);
483 FrameRect( hdc, &rc, hBrush );
486 hBrush = CreateSolidBrush(color_white);
487 FrameRect( hdc, &rc, hBrush );
492 DeleteObject( hBrush );
496 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
502 GetClientRect( hwnd, &rc );
503 hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
504 (WPARAM)hdc, (LPARAM)hwnd );
505 FillRect( hdc, &rc, hbrush );
506 if ((hIcon = (HICON)GetWindowLongA( hwnd, HICON_GWL_OFFSET )))
507 DrawIcon( hdc, rc.left, rc.top, hIcon );
510 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
515 HBITMAP hBitmap, oldbitmap;
517 GetClientRect( hwnd, &rc );
518 hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
519 (WPARAM)hdc, (LPARAM)hwnd );
520 FillRect( hdc, &rc, hbrush );
522 if ((hBitmap = (HBITMAP)GetWindowLongA( hwnd, HICON_GWL_OFFSET )))
527 if(GetObjectType(hBitmap) != OBJ_BITMAP) return;
528 if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
529 GetObjectW(hBitmap, sizeof(bm), &bm);
530 GetBitmapDimensionEx(hBitmap, &sz);
531 oldbitmap = SelectObject(hMemDC, hBitmap);
532 BitBlt(hdc, sz.cx, sz.cy, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,
534 SelectObject(hMemDC, oldbitmap);
540 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style )
544 GetClientRect( hwnd, &rc );
545 switch (style & SS_TYPEMASK)
548 #if 0 /* This is what seems logical */
549 DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM);
550 #else /* But this is what NT, Win2k and WinXP actually do */
551 DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP);
555 #if 0 /* This is what seems logical */
556 DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT);
557 #else /* But this is what NT, Win2k and WinXP actually do */
558 DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT);
562 DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);