4 * Copyright David W. Metcalfe, 1993
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/winuser16.h"
25 #include "cursoricon.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(static);
32 static void STATIC_PaintOwnerDrawfn( HWND hwnd
, HDC hdc
, DWORD style
);
33 static void STATIC_PaintTextfn( HWND hwnd
, HDC hdc
, DWORD style
);
34 static void STATIC_PaintRectfn( HWND hwnd
, HDC hdc
, DWORD style
);
35 static void STATIC_PaintIconfn( HWND hwnd
, HDC hdc
, DWORD style
);
36 static void STATIC_PaintBitmapfn( HWND hwnd
, HDC hdc
, DWORD style
);
37 static void STATIC_PaintEtchedfn( HWND hwnd
, HDC hdc
, DWORD style
);
38 static LRESULT WINAPI
StaticWndProcA( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
39 static LRESULT WINAPI
StaticWndProcW( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
41 static COLORREF color_windowframe
, color_background
, color_window
;
43 /* offsets for GetWindowLong for static private information */
44 #define HFONT_GWL_OFFSET 0
45 #define HICON_GWL_OFFSET (sizeof(HFONT))
46 #define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON))
48 typedef void (*pfPaint
)( HWND hwnd
, HDC hdc
, DWORD style
);
50 static pfPaint staticPaintFunc
[SS_TYPEMASK
+1] =
52 STATIC_PaintTextfn
, /* SS_LEFT */
53 STATIC_PaintTextfn
, /* SS_CENTER */
54 STATIC_PaintTextfn
, /* SS_RIGHT */
55 STATIC_PaintIconfn
, /* SS_ICON */
56 STATIC_PaintRectfn
, /* SS_BLACKRECT */
57 STATIC_PaintRectfn
, /* SS_GRAYRECT */
58 STATIC_PaintRectfn
, /* SS_WHITERECT */
59 STATIC_PaintRectfn
, /* SS_BLACKFRAME */
60 STATIC_PaintRectfn
, /* SS_GRAYFRAME */
61 STATIC_PaintRectfn
, /* SS_WHITEFRAME */
62 NULL
, /* SS_USERITEM */
63 STATIC_PaintTextfn
, /* SS_SIMPLE */
64 STATIC_PaintTextfn
, /* SS_LEFTNOWORDWRAP */
65 STATIC_PaintOwnerDrawfn
, /* SS_OWNERDRAW */
66 STATIC_PaintBitmapfn
, /* SS_BITMAP */
67 NULL
, /* SS_ENHMETAFILE */
68 STATIC_PaintEtchedfn
, /* SS_ETCHEDHORIZ */
69 STATIC_PaintEtchedfn
, /* SS_ETCHEDVERT */
70 STATIC_PaintEtchedfn
, /* SS_ETCHEDFRAME */
74 /*********************************************************************
75 * static class descriptor
77 const struct builtin_class_descr STATIC_builtin_class
=
80 CS_GLOBALCLASS
| CS_DBLCLKS
| CS_PARENTDC
, /* style */
81 StaticWndProcA
, /* procA */
82 StaticWndProcW
, /* procW */
83 STATIC_EXTRA_BYTES
, /* extra */
84 IDC_ARROWA
, /* cursor */
89 /***********************************************************************
92 * Set the icon for an SS_ICON control.
94 static HICON
STATIC_SetIcon( HWND hwnd
, HICON hicon
, DWORD style
)
97 CURSORICONINFO
*info
= hicon
?(CURSORICONINFO
*) GlobalLock16(HICON_16(hicon
)):NULL
;
99 if ((style
& SS_TYPEMASK
) != SS_ICON
) return 0;
100 if (hicon
&& !info
) {
101 ERR("huh? hicon!=0, but info=0???\n");
104 prevIcon
= (HICON
)SetWindowLongA( hwnd
, HICON_GWL_OFFSET
, (LONG
)hicon
);
107 SetWindowPos( hwnd
, 0, 0, 0, info
->nWidth
, info
->nHeight
,
108 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
109 GlobalUnlock16(HICON_16(hicon
));
114 /***********************************************************************
117 * Set the bitmap for an SS_BITMAP control.
119 static HBITMAP
STATIC_SetBitmap( HWND hwnd
, HBITMAP hBitmap
, DWORD style
)
123 if ((style
& SS_TYPEMASK
) != SS_BITMAP
) return 0;
124 if (hBitmap
&& GetObjectType(hBitmap
) != OBJ_BITMAP
) {
125 ERR("huh? hBitmap!=0, but not bitmap\n");
128 hOldBitmap
= (HBITMAP
)SetWindowLongA( hwnd
, HICON_GWL_OFFSET
, (LONG
)hBitmap
);
132 GetObjectW(hBitmap
, sizeof(bm
), &bm
);
133 SetWindowPos( hwnd
, 0, 0, 0, bm
.bmWidth
, bm
.bmHeight
,
134 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
139 /***********************************************************************
142 * Load the icon for an SS_ICON control.
144 static HICON
STATIC_LoadIconA( HWND hwnd
, LPCSTR name
)
146 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongA( hwnd
, GWL_HINSTANCE
);
147 HICON hicon
= LoadIconA( hInstance
, name
);
148 if (!hicon
) hicon
= LoadIconA( 0, name
);
152 /***********************************************************************
155 * Load the icon for an SS_ICON control.
157 static HICON
STATIC_LoadIconW( HWND hwnd
, LPCWSTR name
)
159 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongA( hwnd
, GWL_HINSTANCE
);
160 HICON hicon
= LoadIconW( hInstance
, name
);
161 if (!hicon
) hicon
= LoadIconW( 0, name
);
165 /***********************************************************************
168 * Load the bitmap for an SS_BITMAP control.
170 static HBITMAP
STATIC_LoadBitmapA( HWND hwnd
, LPCSTR name
)
172 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongA( hwnd
, GWL_HINSTANCE
);
173 HBITMAP hbitmap
= LoadBitmapA( hInstance
, name
);
174 if (!hbitmap
) /* Try OEM icon (FIXME: is this right?) */
175 hbitmap
= LoadBitmapA( 0, name
);
179 /***********************************************************************
182 * Load the bitmap for an SS_BITMAP control.
184 static HBITMAP
STATIC_LoadBitmapW( HWND hwnd
, LPCWSTR name
)
186 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongA( hwnd
, GWL_HINSTANCE
);
187 HBITMAP hbitmap
= LoadBitmapW( hInstance
, name
);
188 if (!hbitmap
) /* Try OEM icon (FIXME: is this right?) */
189 hbitmap
= LoadBitmapW( 0, name
);
193 /***********************************************************************
196 * Try to immediately paint the control.
198 static VOID
STATIC_TryPaintFcn(HWND hwnd
, LONG full_style
)
200 LONG style
= full_style
& SS_TYPEMASK
;
203 GetClientRect( hwnd
, &rc
);
204 if (!IsRectEmpty(&rc
) && IsWindowVisible(hwnd
) && staticPaintFunc
[style
])
208 (staticPaintFunc
[style
])( hwnd
, hdc
, full_style
);
209 ReleaseDC( hwnd
, hdc
);
213 /***********************************************************************
214 * StaticWndProc_common
216 static LRESULT
StaticWndProc_common( HWND hwnd
, UINT uMsg
, WPARAM wParam
,
217 LPARAM lParam
, BOOL unicode
)
220 LONG full_style
= GetWindowLongA( hwnd
, GWL_STYLE
);
221 LONG style
= full_style
& SS_TYPEMASK
;
226 if (style
< 0L || style
> SS_TYPEMASK
)
228 ERR("Unknown style 0x%02lx\n", style
);
231 /* initialise colours */
232 color_windowframe
= GetSysColor(COLOR_WINDOWFRAME
);
233 color_background
= GetSysColor(COLOR_BACKGROUND
);
234 color_window
= GetSysColor(COLOR_WINDOW
);
238 if (style
== SS_ICON
) {
241 * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
243 * We don't want to do this yet because DestroyIcon32 is broken. If the icon
244 * had already been loaded by the application the last thing we want to do is
245 * GlobalFree16 the handle.
249 else return unicode
? DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
) :
250 DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
255 BeginPaint(hwnd
, &ps
);
256 if (staticPaintFunc
[style
])
257 (staticPaintFunc
[style
])( hwnd
, ps
.hdc
, full_style
);
263 InvalidateRect(hwnd
, NULL
, TRUE
);
266 case WM_SYSCOLORCHANGE
:
267 color_windowframe
= GetSysColor(COLOR_WINDOWFRAME
);
268 color_background
= GetSysColor(COLOR_BACKGROUND
);
269 color_window
= GetSysColor(COLOR_WINDOW
);
270 InvalidateRect(hwnd
, NULL
, TRUE
);
274 if ((TWEAK_WineLook
> WIN31_LOOK
) && (full_style
& SS_SUNKEN
))
275 SetWindowLongA( hwnd
, GWL_EXSTYLE
,
276 GetWindowLongA( hwnd
, GWL_EXSTYLE
) | WS_EX_STATICEDGE
);
279 lParam
= (LPARAM
)(((LPCREATESTRUCTW
)lParam
)->lpszName
);
281 lParam
= (LPARAM
)(((LPCREATESTRUCTA
)lParam
)->lpszName
);
289 hIcon
= STATIC_LoadIconW(hwnd
, (LPCWSTR
)lParam
);
291 hIcon
= STATIC_LoadIconA(hwnd
, (LPCSTR
)lParam
);
292 /* FIXME : should we also return the previous hIcon here ??? */
293 STATIC_SetIcon(hwnd
, hIcon
, style
);
300 hBitmap
= STATIC_LoadBitmapW(hwnd
, (LPCWSTR
)lParam
);
302 hBitmap
= STATIC_LoadBitmapA(hwnd
, (LPCSTR
)lParam
);
303 STATIC_SetBitmap(hwnd
, hBitmap
, style
);
310 case SS_LEFTNOWORDWRAP
:
315 lResult
= DefWindowProcW( hwnd
, WM_SETTEXT
, wParam
, lParam
);
317 lResult
= DefWindowProcA( hwnd
, WM_SETTEXT
, wParam
, lParam
);
319 if (uMsg
== WM_SETTEXT
)
320 STATIC_TryPaintFcn( hwnd
, full_style
);
327 lResult
= DefWindowProcW( hwnd
, WM_SETTEXT
, wParam
, lParam
);
329 lResult
= DefWindowProcA( hwnd
, WM_SETTEXT
, wParam
, lParam
);
331 if(uMsg
== WM_SETTEXT
)
332 InvalidateRect(hwnd
, NULL
, TRUE
);
334 return 1; /* success. FIXME: check text length */
337 if ((style
== SS_ICON
) || (style
== SS_BITMAP
)) return 0;
338 SetWindowLongA( hwnd
, HFONT_GWL_OFFSET
, wParam
);
340 InvalidateRect( hwnd
, NULL
, TRUE
);
344 return GetWindowLongA( hwnd
, HFONT_GWL_OFFSET
);
347 if (full_style
& SS_NOTIFY
)
350 return HTTRANSPARENT
;
358 return GetWindowLongA( hwnd
, HICON_GWL_OFFSET
);
363 lResult
= (LRESULT
)STATIC_SetBitmap( hwnd
, (HBITMAP
)lParam
, style
);
366 lResult
= (LRESULT
)STATIC_SetIcon( hwnd
, (HICON
)lParam
, style
);
369 FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam
);
372 InvalidateRect( hwnd
, NULL
, TRUE
);
377 lResult
= (LRESULT
)STATIC_SetIcon( hwnd
, (HICON
)wParam
, style
);
378 InvalidateRect( hwnd
, NULL
, TRUE
);
382 return unicode
? DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
) :
383 DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
388 /***********************************************************************
391 static LRESULT WINAPI
StaticWndProcA( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
393 if (!IsWindow( hWnd
)) return 0;
394 return StaticWndProc_common(hWnd
, uMsg
, wParam
, lParam
, FALSE
);
397 /***********************************************************************
400 static LRESULT WINAPI
StaticWndProcW( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
402 if (!IsWindow( hWnd
)) return 0;
403 return StaticWndProc_common(hWnd
, uMsg
, wParam
, lParam
, TRUE
);
406 static void STATIC_PaintOwnerDrawfn( HWND hwnd
, HDC hdc
, DWORD style
)
409 LONG id
= GetWindowLongA( hwnd
, GWL_ID
);
411 dis
.CtlType
= ODT_STATIC
;
414 dis
.itemAction
= ODA_DRAWENTIRE
;
419 GetClientRect( hwnd
, &dis
.rcItem
);
421 SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
, (WPARAM
)hdc
, (LPARAM
)hwnd
);
422 SendMessageW( GetParent(hwnd
), WM_DRAWITEM
, id
, (LPARAM
)&dis
);
425 static void STATIC_PaintTextfn( HWND hwnd
, HDC hdc
, DWORD style
)
434 GetClientRect( hwnd
, &rc
);
436 switch (style
& SS_TYPEMASK
)
439 wFormat
= DT_LEFT
| DT_EXPANDTABS
| DT_WORDBREAK
| DT_NOCLIP
;
443 wFormat
= DT_CENTER
| DT_EXPANDTABS
| DT_WORDBREAK
| DT_NOCLIP
;
447 wFormat
= DT_RIGHT
| DT_EXPANDTABS
| DT_WORDBREAK
| DT_NOCLIP
;
451 wFormat
= DT_LEFT
| DT_SINGLELINE
| DT_VCENTER
| DT_NOCLIP
;
454 case SS_LEFTNOWORDWRAP
:
455 wFormat
= DT_LEFT
| DT_EXPANDTABS
| DT_VCENTER
;
462 if (style
& SS_NOPREFIX
)
463 wFormat
|= DT_NOPREFIX
;
465 if ((hFont
= (HFONT
)GetWindowLongA( hwnd
, HFONT_GWL_OFFSET
))) SelectObject( hdc
, hFont
);
467 if ((style
& SS_NOPREFIX
) || ((style
& SS_TYPEMASK
) != SS_SIMPLE
))
469 hBrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
470 (WPARAM
)hdc
, (LPARAM
)hwnd
);
471 if (!hBrush
) /* did the app forget to call defwindowproc ? */
472 hBrush
= (HBRUSH
)DefWindowProcW(GetParent(hwnd
), WM_CTLCOLORSTATIC
,
473 (WPARAM
)hdc
, (LPARAM
)hwnd
);
474 FillRect( hdc
, &rc
, hBrush
);
476 if (!IsWindowEnabled(hwnd
)) SetTextColor(hdc
, GetSysColor(COLOR_GRAYTEXT
));
478 if (!(len
= SendMessageW( hwnd
, WM_GETTEXTLENGTH
, 0, 0 ))) return;
479 if (!(text
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return;
480 SendMessageW( hwnd
, WM_GETTEXT
, len
+ 1, (LPARAM
)text
);
481 DrawTextW( hdc
, text
, -1, &rc
, wFormat
);
482 HeapFree( GetProcessHeap(), 0, text
);
485 static void STATIC_PaintRectfn( HWND hwnd
, HDC hdc
, DWORD style
)
490 GetClientRect( hwnd
, &rc
);
492 switch (style
& SS_TYPEMASK
)
495 hBrush
= CreateSolidBrush(color_windowframe
);
496 FillRect( hdc
, &rc
, hBrush
);
499 hBrush
= CreateSolidBrush(color_background
);
500 FillRect( hdc
, &rc
, hBrush
);
503 hBrush
= CreateSolidBrush(color_window
);
504 FillRect( hdc
, &rc
, hBrush
);
507 hBrush
= CreateSolidBrush(color_windowframe
);
508 FrameRect( hdc
, &rc
, hBrush
);
511 hBrush
= CreateSolidBrush(color_background
);
512 FrameRect( hdc
, &rc
, hBrush
);
515 hBrush
= CreateSolidBrush(color_window
);
516 FrameRect( hdc
, &rc
, hBrush
);
521 DeleteObject( hBrush
);
525 static void STATIC_PaintIconfn( HWND hwnd
, HDC hdc
, DWORD style
)
531 GetClientRect( hwnd
, &rc
);
532 hbrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
533 (WPARAM
)hdc
, (LPARAM
)hwnd
);
534 FillRect( hdc
, &rc
, hbrush
);
535 if ((hIcon
= (HICON
)GetWindowLongA( hwnd
, HICON_GWL_OFFSET
)))
536 DrawIcon( hdc
, rc
.left
, rc
.top
, hIcon
);
539 static void STATIC_PaintBitmapfn(HWND hwnd
, HDC hdc
, DWORD style
)
544 HBITMAP hBitmap
, oldbitmap
;
546 GetClientRect( hwnd
, &rc
);
547 hbrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
548 (WPARAM
)hdc
, (LPARAM
)hwnd
);
549 FillRect( hdc
, &rc
, hbrush
);
551 if ((hBitmap
= (HBITMAP
)GetWindowLongA( hwnd
, HICON_GWL_OFFSET
)))
556 if(GetObjectType(hBitmap
) != OBJ_BITMAP
) return;
557 if (!(hMemDC
= CreateCompatibleDC( hdc
))) return;
558 GetObjectW(hBitmap
, sizeof(bm
), &bm
);
559 GetBitmapDimensionEx(hBitmap
, &sz
);
560 oldbitmap
= SelectObject(hMemDC
, hBitmap
);
561 BitBlt(hdc
, sz
.cx
, sz
.cy
, bm
.bmWidth
, bm
.bmHeight
, hMemDC
, 0, 0,
563 SelectObject(hMemDC
, oldbitmap
);
569 static void STATIC_PaintEtchedfn( HWND hwnd
, HDC hdc
, DWORD style
)
573 if (TWEAK_WineLook
== WIN31_LOOK
)
576 GetClientRect( hwnd
, &rc
);
577 switch (style
& SS_TYPEMASK
)
580 DrawEdge(hdc
,&rc
,EDGE_ETCHED
,BF_TOP
|BF_BOTTOM
);
583 DrawEdge(hdc
,&rc
,EDGE_ETCHED
,BF_LEFT
|BF_RIGHT
);
586 DrawEdge (hdc
, &rc
, EDGE_ETCHED
, BF_RECT
);