Hack around broken state management so InstallShield works.
[wine] / dlls / user / static.c
1 /*
2  * Static control
3  *
4  * Copyright  David W. Metcalfe, 1993
5  *
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.
10  *
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.
15  *
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
19  *
20  * NOTES
21  *
22  * This code was audited for completeness against the documented features
23  * of Comctl32.dll version 6.0 on Oct. 4, 2004, by Dimitrie O. Paun.
24  * 
25  * Unless otherwise noted, we believe this code to be complete, as per
26  * the specification mentioned above.
27  * If you discover missing features, or bugs, please note them below.
28  * 
29  * TODO:
30  *
31  *   Styles
32  *   - SS_EDITCONTROL
33  *   - SS_ENDELLIPSIS
34  *   - SS_ENHMETAFILE
35  *   - SS_PATHELLIPSIS
36  *   - SS_REALSIZECONTROL
37  *   - SS_REALSIZEIMAGE
38  *   - SS_RIGHTJUST
39  *   - SS_WORDELLIPSIS
40  *
41  *   Notifications
42  *   - STN_DISABLE
43  *   - STN_ENABLE
44  *
45  *   Messages
46  *   - STM_SETIMAGE: IMAGE_CURSOR, IMAGE_ENHMETAFILE
47  */
48
49 #include <stdarg.h>
50
51 #include "windef.h"
52 #include "winbase.h"
53 #include "wingdi.h"
54 #include "wine/winuser16.h"
55 #include "controls.h"
56 #include "user_private.h"
57 #include "wine/debug.h"
58
59 WINE_DEFAULT_DEBUG_CHANNEL(static);
60
61 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style );
62 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style );
63 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style );
64 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style );
65 static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style );
66 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style );
67 static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
68 static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
69
70 static COLORREF color_3dshadow, color_3ddkshadow, color_3dhighlight;
71
72 /* offsets for GetWindowLong for static private information */
73 #define HFONT_GWL_OFFSET    0
74 #define HICON_GWL_OFFSET    (sizeof(HFONT))
75 #define STATIC_EXTRA_BYTES  (HICON_GWL_OFFSET + sizeof(HICON))
76
77 typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
78
79 static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
80 {
81     STATIC_PaintTextfn,      /* SS_LEFT */
82     STATIC_PaintTextfn,      /* SS_CENTER */
83     STATIC_PaintTextfn,      /* SS_RIGHT */
84     STATIC_PaintIconfn,      /* SS_ICON */
85     STATIC_PaintRectfn,      /* SS_BLACKRECT */
86     STATIC_PaintRectfn,      /* SS_GRAYRECT */
87     STATIC_PaintRectfn,      /* SS_WHITERECT */
88     STATIC_PaintRectfn,      /* SS_BLACKFRAME */
89     STATIC_PaintRectfn,      /* SS_GRAYFRAME */
90     STATIC_PaintRectfn,      /* SS_WHITEFRAME */
91     NULL,                    /* SS_USERITEM */
92     STATIC_PaintTextfn,      /* SS_SIMPLE */
93     STATIC_PaintTextfn,      /* SS_LEFTNOWORDWRAP */
94     STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */
95     STATIC_PaintBitmapfn,    /* SS_BITMAP */
96     NULL,                    /* SS_ENHMETAFILE */
97     STATIC_PaintEtchedfn,    /* SS_ETCHEDHORZ */
98     STATIC_PaintEtchedfn,    /* SS_ETCHEDVERT */
99     STATIC_PaintEtchedfn,    /* SS_ETCHEDFRAME */
100 };
101
102
103 /*********************************************************************
104  * static class descriptor
105  */
106 const struct builtin_class_descr STATIC_builtin_class =
107 {
108     "Static",            /* name */
109     CS_DBLCLKS | CS_PARENTDC, /* style  */
110     StaticWndProcA,      /* procA */
111     StaticWndProcW,      /* procW */
112     STATIC_EXTRA_BYTES,  /* extra */
113     IDC_ARROW,           /* cursor */
114     0                    /* brush */
115 };
116
117
118 /***********************************************************************
119  *           STATIC_SetIcon
120  *
121  * Set the icon for an SS_ICON control.
122  */
123 static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
124 {
125     HICON prevIcon;
126     CURSORICONINFO *info = hicon?(CURSORICONINFO *) GlobalLock16(HICON_16(hicon)):NULL;
127
128     if ((style & SS_TYPEMASK) != SS_ICON) return 0;
129     if (hicon && !info) {
130         ERR("huh? hicon!=0, but info=0???\n");
131         return 0;
132     }
133     prevIcon = (HICON)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hicon );
134     if (hicon && !(style & SS_CENTERIMAGE))
135     {
136         SetWindowPos( hwnd, 0, 0, 0, info->nWidth, info->nHeight,
137                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
138         GlobalUnlock16(HICON_16(hicon));
139     }
140     return prevIcon;
141 }
142
143 /***********************************************************************
144  *           STATIC_SetBitmap
145  *
146  * Set the bitmap for an SS_BITMAP control.
147  */
148 static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
149 {
150     HBITMAP hOldBitmap;
151
152     if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
153     if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) {
154         ERR("huh? hBitmap!=0, but not bitmap\n");
155         return 0;
156     }
157     hOldBitmap = (HBITMAP)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hBitmap );
158     if (hBitmap && !(style & SS_CENTERIMAGE))
159     {
160         BITMAP bm;
161         GetObjectW(hBitmap, sizeof(bm), &bm);
162         SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight,
163                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
164     }
165     return hOldBitmap;
166 }
167
168 /***********************************************************************
169  *           STATIC_LoadIconA
170  *
171  * Load the icon for an SS_ICON control.
172  */
173 static HICON STATIC_LoadIconA( HWND hwnd, LPCSTR name )
174 {
175     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
176     HICON hicon = LoadIconA( hInstance, name );
177     if (!hicon) hicon = LoadIconA( 0, name );
178     return hicon;
179 }
180
181 /***********************************************************************
182  *           STATIC_LoadIconW
183  *
184  * Load the icon for an SS_ICON control.
185  */
186 static HICON STATIC_LoadIconW( HWND hwnd, LPCWSTR name )
187 {
188     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
189     HICON hicon = LoadIconW( hInstance, name );
190     if (!hicon) hicon = LoadIconW( 0, name );
191     return hicon;
192 }
193
194 /***********************************************************************
195  *           STATIC_LoadBitmapA
196  *
197  * Load the bitmap for an SS_BITMAP control.
198  */
199 static HBITMAP STATIC_LoadBitmapA( HWND hwnd, LPCSTR name )
200 {
201     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
202     HBITMAP hbitmap = LoadBitmapA( hInstance, name );
203     if (!hbitmap)  /* Try OEM icon (FIXME: is this right?) */
204         hbitmap = LoadBitmapA( 0, name );
205     return hbitmap;
206 }
207
208 /***********************************************************************
209  *           STATIC_LoadBitmapW
210  *
211  * Load the bitmap for an SS_BITMAP control.
212  */
213 static HBITMAP STATIC_LoadBitmapW( HWND hwnd, LPCWSTR name )
214 {
215     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
216     HBITMAP hbitmap = LoadBitmapW( hInstance, name );
217     if (!hbitmap)  /* Try OEM icon (FIXME: is this right?) */
218         hbitmap = LoadBitmapW( 0, name );
219     return hbitmap;
220 }
221
222 /***********************************************************************
223  *           STATIC_TryPaintFcn
224  *
225  * Try to immediately paint the control.
226  */
227 static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
228 {
229     LONG style = full_style & SS_TYPEMASK;
230     RECT rc;
231
232     GetClientRect( hwnd, &rc );
233     if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
234     {
235         HDC hdc;
236         hdc = GetDC( hwnd );
237         (staticPaintFunc[style])( hwnd, hdc, full_style );
238         ReleaseDC( hwnd, hdc );
239     }
240 }
241
242 static VOID STATIC_InitColours(void)
243 {
244     color_3ddkshadow  = GetSysColor(COLOR_3DDKSHADOW);
245     color_3dshadow    = GetSysColor(COLOR_3DSHADOW);
246     color_3dhighlight = GetSysColor(COLOR_3DHIGHLIGHT);
247 }
248
249 /***********************************************************************
250  *           StaticWndProc_common
251  */
252 static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam,
253                                      LPARAM lParam, BOOL unicode )
254 {
255     LRESULT lResult = 0;
256     LONG full_style = GetWindowLongW( hwnd, GWL_STYLE );
257     LONG style = full_style & SS_TYPEMASK;
258
259     switch (uMsg)
260     {
261     case WM_CREATE:
262         if (style < 0L || style > SS_TYPEMASK)
263         {
264             ERR("Unknown style 0x%02lx\n", style );
265             return -1;
266         }
267         STATIC_InitColours();
268         break;
269
270     case WM_NCDESTROY:
271         if (style == SS_ICON) {
272 /*
273  * FIXME
274  *           DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
275  *
276  * We don't want to do this yet because DestroyIcon32 is broken. If the icon
277  * had already been loaded by the application the last thing we want to do is
278  * GlobalFree16 the handle.
279  */
280             break;
281         }
282         else return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
283                               DefWindowProcA(hwnd, uMsg, wParam, lParam);
284
285     case WM_PAINT:
286         {
287             PAINTSTRUCT ps;
288             HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
289             if (staticPaintFunc[style])
290                 (staticPaintFunc[style])( hwnd, hdc, full_style );
291             if (!wParam) EndPaint(hwnd, &ps);
292         }
293         break;
294
295     case WM_ENABLE:
296         InvalidateRect(hwnd, NULL, TRUE);
297         break;
298
299     case WM_SYSCOLORCHANGE:
300         STATIC_InitColours();
301         InvalidateRect(hwnd, NULL, TRUE);
302         break;
303
304     case WM_NCCREATE:
305         if (full_style & SS_SUNKEN)
306             SetWindowLongW( hwnd, GWL_EXSTYLE,
307                             GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
308
309         if(unicode)
310             lParam = (LPARAM)(((LPCREATESTRUCTW)lParam)->lpszName);
311         else
312             lParam = (LPARAM)(((LPCREATESTRUCTA)lParam)->lpszName);
313         /* fall through */
314     case WM_SETTEXT:
315         switch (style) {
316         case SS_ICON:
317         {
318             HICON hIcon;
319             if(unicode)
320                 hIcon = STATIC_LoadIconW(hwnd, (LPCWSTR)lParam);
321             else
322                 hIcon = STATIC_LoadIconA(hwnd, (LPCSTR)lParam);
323             /* FIXME : should we also return the previous hIcon here ??? */
324             STATIC_SetIcon(hwnd, hIcon, full_style);
325             break;
326         }
327         case SS_BITMAP:
328         {
329             HBITMAP hBitmap;
330             if(unicode)
331                 hBitmap = STATIC_LoadBitmapW(hwnd, (LPCWSTR)lParam);
332             else
333                 hBitmap = STATIC_LoadBitmapA(hwnd, (LPCSTR)lParam);
334             STATIC_SetBitmap(hwnd, hBitmap, full_style);
335             break;
336         }
337         case SS_LEFT:
338         case SS_CENTER:
339         case SS_RIGHT:
340         case SS_SIMPLE:
341         case SS_LEFTNOWORDWRAP:
342         {
343             if (HIWORD(lParam))
344             {
345                 if(unicode)
346                     lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
347                 else
348                     lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
349             }
350             if (uMsg == WM_SETTEXT)
351                 STATIC_TryPaintFcn( hwnd, full_style );
352             break;
353         }
354         default:
355             if (HIWORD(lParam))
356             {
357                 if(unicode)
358                     lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
359                 else
360                     lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
361             }
362             if(uMsg == WM_SETTEXT)
363                 InvalidateRect(hwnd, NULL, TRUE);
364         }
365         return 1; /* success. FIXME: check text length */
366
367     case WM_SETFONT:
368         if ((style == SS_ICON) || (style == SS_BITMAP)) return 0;
369         SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam );
370         if (LOWORD(lParam))
371             InvalidateRect( hwnd, NULL, TRUE );
372         break;
373
374     case WM_GETFONT:
375         return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET );
376
377     case WM_NCHITTEST:
378         if (full_style & SS_NOTIFY)
379            return HTCLIENT;
380         else
381            return HTTRANSPARENT;
382
383     case WM_GETDLGCODE:
384         return DLGC_STATIC;
385
386     case WM_LBUTTONDOWN:
387     case WM_NCLBUTTONDOWN:
388         if (full_style & SS_NOTIFY)
389             SendMessageW( GetParent(hwnd), WM_COMMAND,
390                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd);
391         return 0;
392
393     case WM_LBUTTONDBLCLK:
394     case WM_NCLBUTTONDBLCLK:
395         if (full_style & SS_NOTIFY)
396             SendMessageW( GetParent(hwnd), WM_COMMAND,
397                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd);
398         return 0;
399
400     case STM_GETIMAGE:
401     case STM_GETICON16:
402     case STM_GETICON:
403         return GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
404
405     case STM_SETIMAGE:
406         switch(wParam) {
407         case IMAGE_BITMAP:
408             lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
409             break;
410         case IMAGE_CURSOR:
411             FIXME("STM_SETIMAGE: Unhandled type IMAGE_CURSOR\n");
412             break;
413         case IMAGE_ENHMETAFILE:
414             FIXME("STM_SETIMAGE: Unhandled type IMAGE_ENHMETAFILE\n");
415             break;
416         case IMAGE_ICON:
417             lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
418             break;
419         default:
420             FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam);
421             break;
422         }
423         InvalidateRect( hwnd, NULL, TRUE );
424         break;
425
426     case STM_SETICON16:
427     case STM_SETICON:
428         lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
429         InvalidateRect( hwnd, NULL, TRUE );
430         break;
431
432     default:
433         return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
434                          DefWindowProcA(hwnd, uMsg, wParam, lParam);
435     }
436     return lResult;
437 }
438
439 /***********************************************************************
440  *           StaticWndProcA
441  */
442 static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
443 {
444     if (!IsWindow( hWnd )) return 0;
445     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, FALSE);
446 }
447
448 /***********************************************************************
449  *           StaticWndProcW
450  */
451 static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
452 {
453     if (!IsWindow( hWnd )) return 0;
454     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, TRUE);
455 }
456
457 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style )
458 {
459   DRAWITEMSTRUCT dis;
460   UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
461
462   dis.CtlType    = ODT_STATIC;
463   dis.CtlID      = id;
464   dis.itemID     = 0;
465   dis.itemAction = ODA_DRAWENTIRE;
466   dis.itemState  = 0;
467   dis.hwndItem   = hwnd;
468   dis.hDC        = hdc;
469   dis.itemData   = 0;
470   GetClientRect( hwnd, &dis.rcItem );
471
472   SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
473   SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
474 }
475
476 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style )
477 {
478     RECT rc;
479     HBRUSH hBrush;
480     HFONT hFont;
481     WORD wFormat;
482     INT len;
483     WCHAR *text;
484
485     GetClientRect( hwnd, &rc);
486
487     switch (style & SS_TYPEMASK)
488     {
489     case SS_LEFT:
490         wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
491         break;
492
493     case SS_CENTER:
494         wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
495         break;
496
497     case SS_RIGHT:
498         wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
499         break;
500
501     case SS_SIMPLE:
502         wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
503         break;
504
505     case SS_LEFTNOWORDWRAP:
506         wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER;
507         break;
508
509     default:
510         return;
511     }
512
513     if (style & SS_NOPREFIX)
514         wFormat |= DT_NOPREFIX;
515     if (style & SS_CENTERIMAGE)
516         wFormat |= DT_VCENTER;
517
518     if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ))) SelectObject( hdc, hFont );
519
520     if ((style & SS_NOPREFIX) || ((style & SS_TYPEMASK) != SS_SIMPLE))
521     {
522         hBrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
523                                        (WPARAM)hdc, (LPARAM)hwnd );
524         if (!hBrush) /* did the app forget to call defwindowproc ? */
525             hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC,
526                                             (WPARAM)hdc, (LPARAM)hwnd);
527         FillRect( hdc, &rc, hBrush );
528     }
529     if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
530
531     if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return;
532     if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return;
533     SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text );
534     DrawTextW( hdc, text, -1, &rc, wFormat );
535     HeapFree( GetProcessHeap(), 0, text );
536 }
537
538 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style )
539 {
540     RECT rc;
541     HBRUSH hBrush;
542
543     GetClientRect( hwnd, &rc);
544
545     switch (style & SS_TYPEMASK)
546     {
547     case SS_BLACKRECT:
548         hBrush = CreateSolidBrush(color_3ddkshadow);
549         FillRect( hdc, &rc, hBrush );
550         break;
551     case SS_GRAYRECT:
552         hBrush = CreateSolidBrush(color_3dshadow);
553         FillRect( hdc, &rc, hBrush );
554         break;
555     case SS_WHITERECT:
556         hBrush = CreateSolidBrush(color_3dhighlight);
557         FillRect( hdc, &rc, hBrush );
558         break;
559     case SS_BLACKFRAME:
560         hBrush = CreateSolidBrush(color_3ddkshadow);
561         FrameRect( hdc, &rc, hBrush );
562         break;
563     case SS_GRAYFRAME:
564         hBrush = CreateSolidBrush(color_3dshadow);
565         FrameRect( hdc, &rc, hBrush );
566         break;
567     case SS_WHITEFRAME:
568         hBrush = CreateSolidBrush(color_3dhighlight);
569         FrameRect( hdc, &rc, hBrush );
570         break;
571     default:
572         return;
573     }
574     DeleteObject( hBrush );
575 }
576
577
578 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
579 {
580     RECT rc;
581     HBRUSH hbrush;
582     HICON hIcon;
583     INT x, y;
584
585     GetClientRect( hwnd, &rc );
586     hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
587                                    (WPARAM)hdc, (LPARAM)hwnd );
588     FillRect( hdc, &rc, hbrush );
589     hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
590     if (style & SS_CENTERIMAGE)
591     {
592         CURSORICONINFO *info = hIcon ? (CURSORICONINFO *)GlobalLock16(HICON_16(hIcon)) : NULL;
593         x = (rc.right - rc.left)/2 - (info ? info->nWidth/2 : 0);
594         y = (rc.bottom - rc.top)/2 - (info ? info->nHeight/2 : 0);
595     }
596     else
597     {
598         x = rc.left;
599         y = rc.top;
600     }
601     if (hIcon)
602         DrawIcon( hdc, x, y, hIcon );
603 }
604
605 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
606 {
607     HDC hMemDC;
608     HBITMAP hBitmap, oldbitmap;
609
610     /* message is still sent, even if the returned brush is not used */
611     SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
612                                    (WPARAM)hdc, (LPARAM)hwnd );
613
614     if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )))
615     {
616         INT x, y;
617         BITMAP bm;
618
619         if(GetObjectType(hBitmap) != OBJ_BITMAP) return;
620         if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
621         GetObjectW(hBitmap, sizeof(bm), &bm);
622         oldbitmap = SelectObject(hMemDC, hBitmap);
623         if (style & SS_CENTERIMAGE)
624         {
625             RECT rcClient;
626             GetClientRect(hwnd, &rcClient);
627             x = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2;
628             y = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2;
629         }
630         else
631         {
632             x = 0;
633             y = 0;
634         }
635         BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,
636                SRCCOPY);
637         SelectObject(hMemDC, oldbitmap);
638         DeleteDC(hMemDC);
639     }
640 }
641
642
643 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style )
644 {
645     RECT rc;
646
647     GetClientRect( hwnd, &rc );
648     switch (style & SS_TYPEMASK)
649     {
650         case SS_ETCHEDHORZ:
651             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM);
652             break;
653         case SS_ETCHEDVERT:
654             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT);
655             break;
656         case SS_ETCHEDFRAME:
657             DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
658             break;
659     }
660 }