Fix message tests to run cleanly on Windows XP SP1.
[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_PRINTCLIENT:
286     case WM_PAINT:
287         {
288             PAINTSTRUCT ps;
289             HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
290             if (staticPaintFunc[style])
291                 (staticPaintFunc[style])( hwnd, hdc, full_style );
292             if (!wParam) EndPaint(hwnd, &ps);
293         }
294         break;
295
296     case WM_ENABLE:
297         InvalidateRect(hwnd, NULL, TRUE);
298         break;
299
300     case WM_SYSCOLORCHANGE:
301         STATIC_InitColours();
302         InvalidateRect(hwnd, NULL, TRUE);
303         break;
304
305     case WM_NCCREATE:
306         if (full_style & SS_SUNKEN)
307             SetWindowLongW( hwnd, GWL_EXSTYLE,
308                             GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
309
310         if(unicode)
311             lParam = (LPARAM)(((LPCREATESTRUCTW)lParam)->lpszName);
312         else
313             lParam = (LPARAM)(((LPCREATESTRUCTA)lParam)->lpszName);
314         /* fall through */
315     case WM_SETTEXT:
316         switch (style) {
317         case SS_ICON:
318         {
319             HICON hIcon;
320             if(unicode)
321                 hIcon = STATIC_LoadIconW(hwnd, (LPCWSTR)lParam);
322             else
323                 hIcon = STATIC_LoadIconA(hwnd, (LPCSTR)lParam);
324             /* FIXME : should we also return the previous hIcon here ??? */
325             STATIC_SetIcon(hwnd, hIcon, full_style);
326             break;
327         }
328         case SS_BITMAP:
329         {
330             HBITMAP hBitmap;
331             if(unicode)
332                 hBitmap = STATIC_LoadBitmapW(hwnd, (LPCWSTR)lParam);
333             else
334                 hBitmap = STATIC_LoadBitmapA(hwnd, (LPCSTR)lParam);
335             STATIC_SetBitmap(hwnd, hBitmap, full_style);
336             break;
337         }
338         case SS_LEFT:
339         case SS_CENTER:
340         case SS_RIGHT:
341         case SS_SIMPLE:
342         case SS_LEFTNOWORDWRAP:
343         {
344             if (HIWORD(lParam))
345             {
346                 if(unicode)
347                     lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
348                 else
349                     lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
350             }
351             if (uMsg == WM_SETTEXT)
352                 STATIC_TryPaintFcn( hwnd, full_style );
353             break;
354         }
355         default:
356             if (HIWORD(lParam))
357             {
358                 if(unicode)
359                     lResult = DefWindowProcW( hwnd, WM_SETTEXT, wParam, lParam );
360                 else
361                     lResult = DefWindowProcA( hwnd, WM_SETTEXT, wParam, lParam );
362             }
363             if(uMsg == WM_SETTEXT)
364                 InvalidateRect(hwnd, NULL, TRUE);
365         }
366         return 1; /* success. FIXME: check text length */
367
368     case WM_SETFONT:
369         if ((style == SS_ICON) || (style == SS_BITMAP)) return 0;
370         SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam );
371         if (LOWORD(lParam))
372             InvalidateRect( hwnd, NULL, TRUE );
373         break;
374
375     case WM_GETFONT:
376         return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET );
377
378     case WM_NCHITTEST:
379         if (full_style & SS_NOTIFY)
380            return HTCLIENT;
381         else
382            return HTTRANSPARENT;
383
384     case WM_GETDLGCODE:
385         return DLGC_STATIC;
386
387     case WM_LBUTTONDOWN:
388     case WM_NCLBUTTONDOWN:
389         if (full_style & SS_NOTIFY)
390             SendMessageW( GetParent(hwnd), WM_COMMAND,
391                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd);
392         return 0;
393
394     case WM_LBUTTONDBLCLK:
395     case WM_NCLBUTTONDBLCLK:
396         if (full_style & SS_NOTIFY)
397             SendMessageW( GetParent(hwnd), WM_COMMAND,
398                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd);
399         return 0;
400
401     case STM_GETIMAGE:
402     case STM_GETICON16:
403     case STM_GETICON:
404         return GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
405
406     case STM_SETIMAGE:
407         switch(wParam) {
408         case IMAGE_BITMAP:
409             lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
410             break;
411         case IMAGE_CURSOR:
412             FIXME("STM_SETIMAGE: Unhandled type IMAGE_CURSOR\n");
413             break;
414         case IMAGE_ENHMETAFILE:
415             FIXME("STM_SETIMAGE: Unhandled type IMAGE_ENHMETAFILE\n");
416             break;
417         case IMAGE_ICON:
418             lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
419             break;
420         default:
421             FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam);
422             break;
423         }
424         InvalidateRect( hwnd, NULL, TRUE );
425         break;
426
427     case STM_SETICON16:
428     case STM_SETICON:
429         lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
430         InvalidateRect( hwnd, NULL, TRUE );
431         break;
432
433     default:
434         return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
435                          DefWindowProcA(hwnd, uMsg, wParam, lParam);
436     }
437     return lResult;
438 }
439
440 /***********************************************************************
441  *           StaticWndProcA
442  */
443 static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
444 {
445     if (!IsWindow( hWnd )) return 0;
446     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, FALSE);
447 }
448
449 /***********************************************************************
450  *           StaticWndProcW
451  */
452 static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
453 {
454     if (!IsWindow( hWnd )) return 0;
455     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, TRUE);
456 }
457
458 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style )
459 {
460   DRAWITEMSTRUCT dis;
461   UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
462
463   dis.CtlType    = ODT_STATIC;
464   dis.CtlID      = id;
465   dis.itemID     = 0;
466   dis.itemAction = ODA_DRAWENTIRE;
467   dis.itemState  = 0;
468   dis.hwndItem   = hwnd;
469   dis.hDC        = hdc;
470   dis.itemData   = 0;
471   GetClientRect( hwnd, &dis.rcItem );
472
473   SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
474   SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
475 }
476
477 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style )
478 {
479     RECT rc;
480     HBRUSH hBrush;
481     HFONT hFont;
482     WORD wFormat;
483     INT len;
484     WCHAR *text;
485
486     GetClientRect( hwnd, &rc);
487
488     switch (style & SS_TYPEMASK)
489     {
490     case SS_LEFT:
491         wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
492         break;
493
494     case SS_CENTER:
495         wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
496         break;
497
498     case SS_RIGHT:
499         wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
500         break;
501
502     case SS_SIMPLE:
503         wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER;
504         break;
505
506     case SS_LEFTNOWORDWRAP:
507         wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER;
508         break;
509
510     default:
511         return;
512     }
513
514     if (style & SS_NOPREFIX)
515         wFormat |= DT_NOPREFIX;
516     if (style & SS_CENTERIMAGE)
517         wFormat |= DT_VCENTER;
518
519     if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ))) SelectObject( hdc, hFont );
520
521     if ((style & SS_NOPREFIX) || ((style & SS_TYPEMASK) != SS_SIMPLE))
522     {
523         hBrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
524                                        (WPARAM)hdc, (LPARAM)hwnd );
525         if (!hBrush) /* did the app forget to call defwindowproc ? */
526             hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC,
527                                             (WPARAM)hdc, (LPARAM)hwnd);
528         FillRect( hdc, &rc, hBrush );
529     }
530     if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
531
532     if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return;
533     if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return;
534     SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text );
535     DrawTextW( hdc, text, -1, &rc, wFormat );
536     HeapFree( GetProcessHeap(), 0, text );
537 }
538
539 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style )
540 {
541     RECT rc;
542     HBRUSH hBrush;
543
544     GetClientRect( hwnd, &rc);
545
546     switch (style & SS_TYPEMASK)
547     {
548     case SS_BLACKRECT:
549         hBrush = CreateSolidBrush(color_3ddkshadow);
550         FillRect( hdc, &rc, hBrush );
551         break;
552     case SS_GRAYRECT:
553         hBrush = CreateSolidBrush(color_3dshadow);
554         FillRect( hdc, &rc, hBrush );
555         break;
556     case SS_WHITERECT:
557         hBrush = CreateSolidBrush(color_3dhighlight);
558         FillRect( hdc, &rc, hBrush );
559         break;
560     case SS_BLACKFRAME:
561         hBrush = CreateSolidBrush(color_3ddkshadow);
562         FrameRect( hdc, &rc, hBrush );
563         break;
564     case SS_GRAYFRAME:
565         hBrush = CreateSolidBrush(color_3dshadow);
566         FrameRect( hdc, &rc, hBrush );
567         break;
568     case SS_WHITEFRAME:
569         hBrush = CreateSolidBrush(color_3dhighlight);
570         FrameRect( hdc, &rc, hBrush );
571         break;
572     default:
573         return;
574     }
575     DeleteObject( hBrush );
576 }
577
578
579 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
580 {
581     RECT rc;
582     HBRUSH hbrush;
583     HICON hIcon;
584     INT x, y;
585
586     GetClientRect( hwnd, &rc );
587     hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
588                                    (WPARAM)hdc, (LPARAM)hwnd );
589     FillRect( hdc, &rc, hbrush );
590     hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
591     if (style & SS_CENTERIMAGE)
592     {
593         CURSORICONINFO *info = hIcon ? (CURSORICONINFO *)GlobalLock16(HICON_16(hIcon)) : NULL;
594         x = (rc.right - rc.left)/2 - (info ? info->nWidth/2 : 0);
595         y = (rc.bottom - rc.top)/2 - (info ? info->nHeight/2 : 0);
596     }
597     else
598     {
599         x = rc.left;
600         y = rc.top;
601     }
602     if (hIcon)
603         DrawIcon( hdc, x, y, hIcon );
604 }
605
606 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
607 {
608     HDC hMemDC;
609     HBITMAP hBitmap, oldbitmap;
610
611     /* message is still sent, even if the returned brush is not used */
612     SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
613                                    (WPARAM)hdc, (LPARAM)hwnd );
614
615     if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )))
616     {
617         INT x, y;
618         BITMAP bm;
619
620         if(GetObjectType(hBitmap) != OBJ_BITMAP) return;
621         if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
622         GetObjectW(hBitmap, sizeof(bm), &bm);
623         oldbitmap = SelectObject(hMemDC, hBitmap);
624         if (style & SS_CENTERIMAGE)
625         {
626             RECT rcClient;
627             GetClientRect(hwnd, &rcClient);
628             x = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2;
629             y = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2;
630         }
631         else
632         {
633             x = 0;
634             y = 0;
635         }
636         BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,
637                SRCCOPY);
638         SelectObject(hMemDC, oldbitmap);
639         DeleteDC(hMemDC);
640     }
641 }
642
643
644 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style )
645 {
646     RECT rc;
647
648     GetClientRect( hwnd, &rc );
649     switch (style & SS_TYPEMASK)
650     {
651         case SS_ETCHEDHORZ:
652             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM);
653             break;
654         case SS_ETCHEDVERT:
655             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT);
656             break;
657         case SS_ETCHEDFRAME:
658             DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
659             break;
660     }
661 }