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
26 #include "wine/winuser16.h"
28 #include "cursoricon.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(static);
35 static void STATIC_PaintOwnerDrawfn( HWND hwnd
, HDC hdc
, DWORD style
);
36 static void STATIC_PaintTextfn( HWND hwnd
, HDC hdc
, DWORD style
);
37 static void STATIC_PaintRectfn( HWND hwnd
, HDC hdc
, DWORD style
);
38 static void STATIC_PaintIconfn( HWND hwnd
, HDC hdc
, DWORD style
);
39 static void STATIC_PaintBitmapfn( HWND hwnd
, HDC hdc
, DWORD style
);
40 static void STATIC_PaintEtchedfn( HWND hwnd
, HDC hdc
, DWORD style
);
41 static LRESULT WINAPI
StaticWndProcA( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
42 static LRESULT WINAPI
StaticWndProcW( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
44 static COLORREF color_windowframe
, color_background
, color_window
;
46 /* offsets for GetWindowLong for static private information */
47 #define HFONT_GWL_OFFSET 0
48 #define HICON_GWL_OFFSET (sizeof(HFONT))
49 #define STATIC_EXTRA_BYTES (HICON_GWL_OFFSET + sizeof(HICON))
51 typedef void (*pfPaint
)( HWND hwnd
, HDC hdc
, DWORD style
);
53 static pfPaint staticPaintFunc
[SS_TYPEMASK
+1] =
55 STATIC_PaintTextfn
, /* SS_LEFT */
56 STATIC_PaintTextfn
, /* SS_CENTER */
57 STATIC_PaintTextfn
, /* SS_RIGHT */
58 STATIC_PaintIconfn
, /* SS_ICON */
59 STATIC_PaintRectfn
, /* SS_BLACKRECT */
60 STATIC_PaintRectfn
, /* SS_GRAYRECT */
61 STATIC_PaintRectfn
, /* SS_WHITERECT */
62 STATIC_PaintRectfn
, /* SS_BLACKFRAME */
63 STATIC_PaintRectfn
, /* SS_GRAYFRAME */
64 STATIC_PaintRectfn
, /* SS_WHITEFRAME */
65 NULL
, /* SS_USERITEM */
66 STATIC_PaintTextfn
, /* SS_SIMPLE */
67 STATIC_PaintTextfn
, /* SS_LEFTNOWORDWRAP */
68 STATIC_PaintOwnerDrawfn
, /* SS_OWNERDRAW */
69 STATIC_PaintBitmapfn
, /* SS_BITMAP */
70 NULL
, /* SS_ENHMETAFILE */
71 STATIC_PaintEtchedfn
, /* SS_ETCHEDHORIZ */
72 STATIC_PaintEtchedfn
, /* SS_ETCHEDVERT */
73 STATIC_PaintEtchedfn
, /* SS_ETCHEDFRAME */
77 /*********************************************************************
78 * static class descriptor
80 const struct builtin_class_descr STATIC_builtin_class
=
83 CS_DBLCLKS
| CS_PARENTDC
, /* style */
84 StaticWndProcA
, /* procA */
85 StaticWndProcW
, /* procW */
86 STATIC_EXTRA_BYTES
, /* extra */
87 IDC_ARROW
, /* cursor */
92 /***********************************************************************
95 * Set the icon for an SS_ICON control.
97 static HICON
STATIC_SetIcon( HWND hwnd
, HICON hicon
, DWORD style
)
100 CURSORICONINFO
*info
= hicon
?(CURSORICONINFO
*) GlobalLock16(HICON_16(hicon
)):NULL
;
102 if ((style
& SS_TYPEMASK
) != SS_ICON
) return 0;
103 if (hicon
&& !info
) {
104 ERR("huh? hicon!=0, but info=0???\n");
107 prevIcon
= (HICON
)SetWindowLongPtrW( hwnd
, HICON_GWL_OFFSET
, (LONG_PTR
)hicon
);
110 SetWindowPos( hwnd
, 0, 0, 0, info
->nWidth
, info
->nHeight
,
111 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
112 GlobalUnlock16(HICON_16(hicon
));
117 /***********************************************************************
120 * Set the bitmap for an SS_BITMAP control.
122 static HBITMAP
STATIC_SetBitmap( HWND hwnd
, HBITMAP hBitmap
, DWORD style
)
126 if ((style
& SS_TYPEMASK
) != SS_BITMAP
) return 0;
127 if (hBitmap
&& GetObjectType(hBitmap
) != OBJ_BITMAP
) {
128 ERR("huh? hBitmap!=0, but not bitmap\n");
131 hOldBitmap
= (HBITMAP
)SetWindowLongPtrA( hwnd
, HICON_GWL_OFFSET
, (LONG_PTR
)hBitmap
);
135 GetObjectW(hBitmap
, sizeof(bm
), &bm
);
136 SetWindowPos( hwnd
, 0, 0, 0, bm
.bmWidth
, bm
.bmHeight
,
137 SWP_NOACTIVATE
| SWP_NOMOVE
| SWP_NOZORDER
);
142 /***********************************************************************
145 * Load the icon for an SS_ICON control.
147 static HICON
STATIC_LoadIconA( HWND hwnd
, LPCSTR name
)
149 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtrW( hwnd
, GWLP_HINSTANCE
);
150 HICON hicon
= LoadIconA( hInstance
, name
);
151 if (!hicon
) hicon
= LoadIconA( 0, name
);
155 /***********************************************************************
158 * Load the icon for an SS_ICON control.
160 static HICON
STATIC_LoadIconW( HWND hwnd
, LPCWSTR name
)
162 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtrW( hwnd
, GWLP_HINSTANCE
);
163 HICON hicon
= LoadIconW( hInstance
, name
);
164 if (!hicon
) hicon
= LoadIconW( 0, name
);
168 /***********************************************************************
171 * Load the bitmap for an SS_BITMAP control.
173 static HBITMAP
STATIC_LoadBitmapA( HWND hwnd
, LPCSTR name
)
175 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtrW( hwnd
, GWLP_HINSTANCE
);
176 HBITMAP hbitmap
= LoadBitmapA( hInstance
, name
);
177 if (!hbitmap
) /* Try OEM icon (FIXME: is this right?) */
178 hbitmap
= LoadBitmapA( 0, name
);
182 /***********************************************************************
185 * Load the bitmap for an SS_BITMAP control.
187 static HBITMAP
STATIC_LoadBitmapW( HWND hwnd
, LPCWSTR name
)
189 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLongPtrW( hwnd
, GWLP_HINSTANCE
);
190 HBITMAP hbitmap
= LoadBitmapW( hInstance
, name
);
191 if (!hbitmap
) /* Try OEM icon (FIXME: is this right?) */
192 hbitmap
= LoadBitmapW( 0, name
);
196 /***********************************************************************
199 * Try to immediately paint the control.
201 static VOID
STATIC_TryPaintFcn(HWND hwnd
, LONG full_style
)
203 LONG style
= full_style
& SS_TYPEMASK
;
206 GetClientRect( hwnd
, &rc
);
207 if (!IsRectEmpty(&rc
) && IsWindowVisible(hwnd
) && staticPaintFunc
[style
])
211 (staticPaintFunc
[style
])( hwnd
, hdc
, full_style
);
212 ReleaseDC( hwnd
, hdc
);
216 /***********************************************************************
217 * StaticWndProc_common
219 static LRESULT
StaticWndProc_common( HWND hwnd
, UINT uMsg
, WPARAM wParam
,
220 LPARAM lParam
, BOOL unicode
)
223 LONG full_style
= GetWindowLongA( hwnd
, GWL_STYLE
);
224 LONG style
= full_style
& SS_TYPEMASK
;
229 if (style
< 0L || style
> SS_TYPEMASK
)
231 ERR("Unknown style 0x%02lx\n", style
);
234 /* initialise colours */
235 color_windowframe
= GetSysColor(COLOR_WINDOWFRAME
);
236 color_background
= GetSysColor(COLOR_BACKGROUND
);
237 color_window
= GetSysColor(COLOR_WINDOW
);
241 if (style
== SS_ICON
) {
244 * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
246 * We don't want to do this yet because DestroyIcon32 is broken. If the icon
247 * had already been loaded by the application the last thing we want to do is
248 * GlobalFree16 the handle.
252 else return unicode
? DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
) :
253 DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
258 HDC hdc
= wParam
? (HDC
)wParam
: BeginPaint(hwnd
, &ps
);
259 if (staticPaintFunc
[style
])
260 (staticPaintFunc
[style
])( hwnd
, hdc
, full_style
);
261 if (!wParam
) EndPaint(hwnd
, &ps
);
266 InvalidateRect(hwnd
, NULL
, TRUE
);
269 case WM_SYSCOLORCHANGE
:
270 color_windowframe
= GetSysColor(COLOR_WINDOWFRAME
);
271 color_background
= GetSysColor(COLOR_BACKGROUND
);
272 color_window
= GetSysColor(COLOR_WINDOW
);
273 InvalidateRect(hwnd
, NULL
, TRUE
);
277 if (full_style
& SS_SUNKEN
)
278 SetWindowLongA( hwnd
, GWL_EXSTYLE
,
279 GetWindowLongA( hwnd
, GWL_EXSTYLE
) | WS_EX_STATICEDGE
);
282 lParam
= (LPARAM
)(((LPCREATESTRUCTW
)lParam
)->lpszName
);
284 lParam
= (LPARAM
)(((LPCREATESTRUCTA
)lParam
)->lpszName
);
292 hIcon
= STATIC_LoadIconW(hwnd
, (LPCWSTR
)lParam
);
294 hIcon
= STATIC_LoadIconA(hwnd
, (LPCSTR
)lParam
);
295 /* FIXME : should we also return the previous hIcon here ??? */
296 STATIC_SetIcon(hwnd
, hIcon
, style
);
303 hBitmap
= STATIC_LoadBitmapW(hwnd
, (LPCWSTR
)lParam
);
305 hBitmap
= STATIC_LoadBitmapA(hwnd
, (LPCSTR
)lParam
);
306 STATIC_SetBitmap(hwnd
, hBitmap
, style
);
313 case SS_LEFTNOWORDWRAP
:
318 lResult
= DefWindowProcW( hwnd
, WM_SETTEXT
, wParam
, lParam
);
320 lResult
= DefWindowProcA( hwnd
, WM_SETTEXT
, wParam
, lParam
);
322 if (uMsg
== WM_SETTEXT
)
323 STATIC_TryPaintFcn( hwnd
, full_style
);
330 lResult
= DefWindowProcW( hwnd
, WM_SETTEXT
, wParam
, lParam
);
332 lResult
= DefWindowProcA( hwnd
, WM_SETTEXT
, wParam
, lParam
);
334 if(uMsg
== WM_SETTEXT
)
335 InvalidateRect(hwnd
, NULL
, TRUE
);
337 return 1; /* success. FIXME: check text length */
340 if ((style
== SS_ICON
) || (style
== SS_BITMAP
)) return 0;
341 SetWindowLongPtrW( hwnd
, HFONT_GWL_OFFSET
, wParam
);
343 InvalidateRect( hwnd
, NULL
, TRUE
);
347 return GetWindowLongPtrW( hwnd
, HFONT_GWL_OFFSET
);
350 if (full_style
& SS_NOTIFY
)
353 return HTTRANSPARENT
;
359 case WM_NCLBUTTONDOWN
:
360 if (full_style
& SS_NOTIFY
)
361 SendMessageW( GetParent(hwnd
), WM_COMMAND
,
362 MAKEWPARAM( GetWindowLongPtrW(hwnd
,GWLP_ID
), STN_CLICKED
), (LPARAM
)hwnd
);
365 case WM_LBUTTONDBLCLK
:
366 case WM_NCLBUTTONDBLCLK
:
367 if (full_style
& SS_NOTIFY
)
368 SendMessageW( GetParent(hwnd
), WM_COMMAND
,
369 MAKEWPARAM( GetWindowLongPtrW(hwnd
,GWLP_ID
), STN_DBLCLK
), (LPARAM
)hwnd
);
375 return GetWindowLongPtrW( hwnd
, HICON_GWL_OFFSET
);
380 lResult
= (LRESULT
)STATIC_SetBitmap( hwnd
, (HBITMAP
)lParam
, style
);
383 lResult
= (LRESULT
)STATIC_SetIcon( hwnd
, (HICON
)lParam
, style
);
386 FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam
);
389 InvalidateRect( hwnd
, NULL
, TRUE
);
394 lResult
= (LRESULT
)STATIC_SetIcon( hwnd
, (HICON
)wParam
, style
);
395 InvalidateRect( hwnd
, NULL
, TRUE
);
399 return unicode
? DefWindowProcW(hwnd
, uMsg
, wParam
, lParam
) :
400 DefWindowProcA(hwnd
, uMsg
, wParam
, lParam
);
405 /***********************************************************************
408 static LRESULT WINAPI
StaticWndProcA( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
410 if (!IsWindow( hWnd
)) return 0;
411 return StaticWndProc_common(hWnd
, uMsg
, wParam
, lParam
, FALSE
);
414 /***********************************************************************
417 static LRESULT WINAPI
StaticWndProcW( HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
419 if (!IsWindow( hWnd
)) return 0;
420 return StaticWndProc_common(hWnd
, uMsg
, wParam
, lParam
, TRUE
);
423 static void STATIC_PaintOwnerDrawfn( HWND hwnd
, HDC hdc
, DWORD style
)
426 UINT id
= (UINT
)GetWindowLongPtrW( hwnd
, GWLP_ID
);
428 dis
.CtlType
= ODT_STATIC
;
431 dis
.itemAction
= ODA_DRAWENTIRE
;
436 GetClientRect( hwnd
, &dis
.rcItem
);
438 SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
, (WPARAM
)hdc
, (LPARAM
)hwnd
);
439 SendMessageW( GetParent(hwnd
), WM_DRAWITEM
, id
, (LPARAM
)&dis
);
442 static void STATIC_PaintTextfn( HWND hwnd
, HDC hdc
, DWORD style
)
451 GetClientRect( hwnd
, &rc
);
453 switch (style
& SS_TYPEMASK
)
456 wFormat
= DT_LEFT
| DT_EXPANDTABS
| DT_WORDBREAK
;
460 wFormat
= DT_CENTER
| DT_EXPANDTABS
| DT_WORDBREAK
;
464 wFormat
= DT_RIGHT
| DT_EXPANDTABS
| DT_WORDBREAK
;
468 wFormat
= DT_LEFT
| DT_SINGLELINE
| DT_VCENTER
;
471 case SS_LEFTNOWORDWRAP
:
472 wFormat
= DT_LEFT
| DT_EXPANDTABS
| DT_VCENTER
;
479 if (style
& SS_NOPREFIX
)
480 wFormat
|= DT_NOPREFIX
;
482 if ((hFont
= (HFONT
)GetWindowLongPtrW( hwnd
, HFONT_GWL_OFFSET
))) SelectObject( hdc
, hFont
);
484 if ((style
& SS_NOPREFIX
) || ((style
& SS_TYPEMASK
) != SS_SIMPLE
))
486 hBrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
487 (WPARAM
)hdc
, (LPARAM
)hwnd
);
488 if (!hBrush
) /* did the app forget to call defwindowproc ? */
489 hBrush
= (HBRUSH
)DefWindowProcW(GetParent(hwnd
), WM_CTLCOLORSTATIC
,
490 (WPARAM
)hdc
, (LPARAM
)hwnd
);
491 FillRect( hdc
, &rc
, hBrush
);
493 if (!IsWindowEnabled(hwnd
)) SetTextColor(hdc
, GetSysColor(COLOR_GRAYTEXT
));
495 if (!(len
= SendMessageW( hwnd
, WM_GETTEXTLENGTH
, 0, 0 ))) return;
496 if (!(text
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
) ))) return;
497 SendMessageW( hwnd
, WM_GETTEXT
, len
+ 1, (LPARAM
)text
);
498 DrawTextW( hdc
, text
, -1, &rc
, wFormat
);
499 HeapFree( GetProcessHeap(), 0, text
);
502 static void STATIC_PaintRectfn( HWND hwnd
, HDC hdc
, DWORD style
)
507 GetClientRect( hwnd
, &rc
);
509 switch (style
& SS_TYPEMASK
)
512 hBrush
= CreateSolidBrush(color_windowframe
);
513 FillRect( hdc
, &rc
, hBrush
);
516 hBrush
= CreateSolidBrush(color_background
);
517 FillRect( hdc
, &rc
, hBrush
);
520 hBrush
= CreateSolidBrush(color_window
);
521 FillRect( hdc
, &rc
, hBrush
);
524 hBrush
= CreateSolidBrush(color_windowframe
);
525 FrameRect( hdc
, &rc
, hBrush
);
528 hBrush
= CreateSolidBrush(color_background
);
529 FrameRect( hdc
, &rc
, hBrush
);
532 hBrush
= CreateSolidBrush(color_window
);
533 FrameRect( hdc
, &rc
, hBrush
);
538 DeleteObject( hBrush
);
542 static void STATIC_PaintIconfn( HWND hwnd
, HDC hdc
, DWORD style
)
548 GetClientRect( hwnd
, &rc
);
549 hbrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
550 (WPARAM
)hdc
, (LPARAM
)hwnd
);
551 FillRect( hdc
, &rc
, hbrush
);
552 if ((hIcon
= (HICON
)GetWindowLongPtrW( hwnd
, HICON_GWL_OFFSET
)))
553 DrawIcon( hdc
, rc
.left
, rc
.top
, hIcon
);
556 static void STATIC_PaintBitmapfn(HWND hwnd
, HDC hdc
, DWORD style
)
559 HBITMAP hBitmap
, oldbitmap
;
561 /* message is still sent, even if the returned brush is not used */
562 SendMessageW( GetParent(hwnd
), WM_CTLCOLORSTATIC
,
563 (WPARAM
)hdc
, (LPARAM
)hwnd
);
565 if ((hBitmap
= (HBITMAP
)GetWindowLongPtrW( hwnd
, HICON_GWL_OFFSET
)))
569 if(GetObjectType(hBitmap
) != OBJ_BITMAP
) return;
570 if (!(hMemDC
= CreateCompatibleDC( hdc
))) return;
571 GetObjectW(hBitmap
, sizeof(bm
), &bm
);
572 oldbitmap
= SelectObject(hMemDC
, hBitmap
);
573 BitBlt(hdc
, 0, 0, bm
.bmWidth
, bm
.bmHeight
, hMemDC
, 0, 0,
575 SelectObject(hMemDC
, oldbitmap
);
581 static void STATIC_PaintEtchedfn( HWND hwnd
, HDC hdc
, DWORD style
)
585 GetClientRect( hwnd
, &rc
);
586 switch (style
& SS_TYPEMASK
)
589 DrawEdge(hdc
,&rc
,EDGE_ETCHED
,BF_TOP
|BF_BOTTOM
);
592 DrawEdge(hdc
,&rc
,EDGE_ETCHED
,BF_LEFT
|BF_RIGHT
);
595 DrawEdge (hdc
, &rc
, EDGE_ETCHED
, BF_RECT
);