dbghelp: Brought dbghelp.h a bit closer to PSDK definitions.
[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_RIGHTJUST
33  *
34  *   Messages
35  *   - STM_SETIMAGE: IMAGE_CURSOR
36  */
37
38 #include <stdarg.h>
39
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wingdi.h"
43 #include "wine/winuser16.h"
44 #include "controls.h"
45 #include "user_private.h"
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(static);
49
50 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style );
51 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style );
52 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style );
53 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style );
54 static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style );
55 static void STATIC_PaintEnhMetafn( HWND hwnd, HDC hdc, DWORD style );
56 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style );
57 static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
58 static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
59
60 static COLORREF color_3dshadow, color_3ddkshadow, color_3dhighlight;
61
62 /* offsets for GetWindowLong for static private information */
63 #define HFONT_GWL_OFFSET    0
64 #define HICON_GWL_OFFSET    (sizeof(HFONT))
65 #define STATIC_EXTRA_BYTES  (HICON_GWL_OFFSET + sizeof(HICON))
66
67 typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
68
69 static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
70 {
71     STATIC_PaintTextfn,      /* SS_LEFT */
72     STATIC_PaintTextfn,      /* SS_CENTER */
73     STATIC_PaintTextfn,      /* SS_RIGHT */
74     STATIC_PaintIconfn,      /* SS_ICON */
75     STATIC_PaintRectfn,      /* SS_BLACKRECT */
76     STATIC_PaintRectfn,      /* SS_GRAYRECT */
77     STATIC_PaintRectfn,      /* SS_WHITERECT */
78     STATIC_PaintRectfn,      /* SS_BLACKFRAME */
79     STATIC_PaintRectfn,      /* SS_GRAYFRAME */
80     STATIC_PaintRectfn,      /* SS_WHITEFRAME */
81     NULL,                    /* SS_USERITEM */
82     STATIC_PaintTextfn,      /* SS_SIMPLE */
83     STATIC_PaintTextfn,      /* SS_LEFTNOWORDWRAP */
84     STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */
85     STATIC_PaintBitmapfn,    /* SS_BITMAP */
86     STATIC_PaintEnhMetafn,   /* SS_ENHMETAFILE */
87     STATIC_PaintEtchedfn,    /* SS_ETCHEDHORZ */
88     STATIC_PaintEtchedfn,    /* SS_ETCHEDVERT */
89     STATIC_PaintEtchedfn,    /* SS_ETCHEDFRAME */
90 };
91
92
93 /*********************************************************************
94  * static class descriptor
95  */
96 const struct builtin_class_descr STATIC_builtin_class =
97 {
98     "Static",            /* name */
99     CS_DBLCLKS | CS_PARENTDC, /* style  */
100     StaticWndProcA,      /* procA */
101     StaticWndProcW,      /* procW */
102     STATIC_EXTRA_BYTES,  /* extra */
103     IDC_ARROW,           /* cursor */
104     0                    /* brush */
105 };
106
107
108 /***********************************************************************
109  *           STATIC_SetIcon
110  *
111  * Set the icon for an SS_ICON control.
112  */
113 static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
114 {
115     HICON prevIcon;
116     CURSORICONINFO * info;
117     
118     if ((style & SS_TYPEMASK) != SS_ICON) return 0;
119     info = hicon?(CURSORICONINFO *) GlobalLock16(HICON_16(hicon)):NULL;
120     if (hicon && !info) {
121         WARN("hicon != 0, but info == 0\n");
122         return 0;
123     }
124     prevIcon = (HICON)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hicon );
125     if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
126     {
127         /* Windows currently doesn't implement SS_RIGHTJUST */
128         /*
129         if ((style & SS_RIGHTJUST) != 0)
130         {
131             RECT wr;
132             GetWindowRect(hwnd, &wr);
133             SetWindowPos( hwnd, 0, wr.right - info->nWidth, wr.bottom - info->nHeight,
134                           info->nWidth, info->nHeight, SWP_NOACTIVATE | SWP_NOZORDER );
135         }
136         else */
137         {
138             SetWindowPos( hwnd, 0, 0, 0, info->nWidth, info->nHeight,
139                           SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
140         }
141     }
142     if (info) GlobalUnlock16(HICON_16(hicon));
143     return prevIcon;
144 }
145
146 /***********************************************************************
147  *           STATIC_SetBitmap
148  *
149  * Set the bitmap for an SS_BITMAP control.
150  */
151 static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
152 {
153     HBITMAP hOldBitmap;
154
155     if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
156     if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) {
157         WARN("hBitmap != 0, but it's not a bitmap\n");
158         return 0;
159     }
160     hOldBitmap = (HBITMAP)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hBitmap );
161     if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
162     {
163         BITMAP bm;
164         GetObjectW(hBitmap, sizeof(bm), &bm);
165         /* Windows currently doesn't implement SS_RIGHTJUST */
166         /*
167         if ((style & SS_RIGHTJUST) != 0)
168         {
169             RECT wr;
170             GetWindowRect(hwnd, &wr);
171             SetWindowPos( hwnd, 0, wr.right - bm.bmWidth, wr.bottom - bm.bmHeight,
172                           bm.bmWidth, bm.bmHeight, SWP_NOACTIVATE | SWP_NOZORDER );
173         }
174         else */
175         {
176             SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight,
177                           SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
178         }
179         
180     }
181     return hOldBitmap;
182 }
183
184 /***********************************************************************
185  *           STATIC_SetEnhMetaFile
186  *
187  * Set the enhanced metafile for an SS_ENHMETAFILE control.
188  */
189 static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style )
190 {
191     if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0;
192     if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE) {
193         WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n");
194         return 0;
195     }
196     return (HENHMETAFILE)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hEnhMetaFile );
197 }
198
199 /***********************************************************************
200  *           STATIC_GetImage
201  *
202  * Gets the bitmap for an SS_BITMAP control, the icon/cursor for an
203  * SS_ICON control or the enhanced metafile for an SS_ENHMETAFILE control.
204  */
205 static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style )
206 {
207     switch(style & SS_TYPEMASK)
208     {
209         case SS_ICON:
210             if ((wParam != IMAGE_ICON) &&
211                 (wParam != IMAGE_CURSOR)) return NULL;
212             break;
213         case SS_BITMAP:
214             if (wParam != IMAGE_BITMAP) return NULL;
215             break;
216         case SS_ENHMETAFILE:
217             if (wParam != IMAGE_ENHMETAFILE) return NULL;
218             break;
219         default:
220             return NULL;
221     }
222     return (HANDLE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
223 }
224
225 /***********************************************************************
226  *           STATIC_LoadIconA
227  *
228  * Load the icon for an SS_ICON control.
229  */
230 static HICON STATIC_LoadIconA( HWND hwnd, LPCSTR name, DWORD style )
231 {
232     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
233     if ((style & SS_REALSIZEIMAGE) != 0)
234     {
235         return LoadImageA(hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED);
236     }
237     else
238     {
239         HICON hicon = LoadIconA( hInstance, name );
240         if (!hicon) hicon = LoadCursorA( hInstance, name );
241         if (!hicon) hicon = LoadIconA( 0, name );
242         /* Windows doesn't try to load a standard cursor,
243            probably because most IDs for standard cursors conflict
244            with the IDs for standard icons anyway */
245         return hicon;
246     }
247 }
248
249 /***********************************************************************
250  *           STATIC_LoadIconW
251  *
252  * Load the icon for an SS_ICON control.
253  */
254 static HICON STATIC_LoadIconW( HWND hwnd, LPCWSTR name, DWORD style )
255 {
256     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
257     if ((style & SS_REALSIZEIMAGE) != 0)
258     {
259         return LoadImageW(hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED);
260     }
261     else
262     {
263         HICON hicon = LoadIconW( hInstance, name );
264         if (!hicon) hicon = LoadCursorW( hInstance, name );
265         if (!hicon) hicon = LoadIconW( 0, name );
266         /* Windows doesn't try to load a standard cursor,
267            probably because most IDs for standard cursors conflict
268            with the IDs for standard icons anyway */
269         return hicon;
270     }
271 }
272
273 /***********************************************************************
274  *           STATIC_LoadBitmapA
275  *
276  * Load the bitmap for an SS_BITMAP control.
277  */
278 static HBITMAP STATIC_LoadBitmapA( HWND hwnd, LPCSTR name )
279 {
280     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
281     /* Windows doesn't try to load OEM Bitmaps (hInstance == NULL) */
282     return LoadBitmapA( hInstance, name );
283 }
284
285 /***********************************************************************
286  *           STATIC_LoadBitmapW
287  *
288  * Load the bitmap for an SS_BITMAP control.
289  */
290 static HBITMAP STATIC_LoadBitmapW( HWND hwnd, LPCWSTR name )
291 {
292     HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
293     /* Windows doesn't try to load OEM Bitmaps (hInstance == NULL) */
294     return LoadBitmapW( hInstance, name );
295 }
296
297 /***********************************************************************
298  *           STATIC_TryPaintFcn
299  *
300  * Try to immediately paint the control.
301  */
302 static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
303 {
304     LONG style = full_style & SS_TYPEMASK;
305     RECT rc;
306
307     GetClientRect( hwnd, &rc );
308     if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
309     {
310         HDC hdc;
311         hdc = GetDC( hwnd );
312         (staticPaintFunc[style])( hwnd, hdc, full_style );
313         ReleaseDC( hwnd, hdc );
314     }
315 }
316
317 static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc)
318 {
319     HBRUSH hBrush = (HBRUSH) SendMessageW( GetParent(hwnd),
320                     WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
321     if (!hBrush) /* did the app forget to call DefWindowProc ? */
322     {
323         /* FIXME: DefWindowProc should return different colors if a
324                   manifest is present */
325         hBrush = (HBRUSH)DefWindowProcW(GetParent(hwnd), WM_CTLCOLORSTATIC,
326                                         (WPARAM)hdc, (LPARAM)hwnd);
327     }
328     return hBrush;
329 }
330
331 static VOID STATIC_InitColours(void)
332 {
333     color_3ddkshadow  = GetSysColor(COLOR_3DDKSHADOW);
334     color_3dshadow    = GetSysColor(COLOR_3DSHADOW);
335     color_3dhighlight = GetSysColor(COLOR_3DHIGHLIGHT);
336 }
337
338 /***********************************************************************
339  *           hasTextStyle
340  *
341  * Tests if the control displays text.
342  */
343 static BOOL hasTextStyle( DWORD style )
344 {
345     switch(style & SS_TYPEMASK)
346     {
347         case SS_SIMPLE:
348         case SS_LEFT:
349         case SS_LEFTNOWORDWRAP:
350         case SS_CENTER:
351         case SS_RIGHT:
352         case SS_OWNERDRAW:
353             return TRUE;
354     }
355     
356     return FALSE;
357 }
358
359 /***********************************************************************
360  *           StaticWndProc_common
361  */
362 static LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam,
363                                      LPARAM lParam, BOOL unicode )
364 {
365     LRESULT lResult = 0;
366     LONG full_style = GetWindowLongW( hwnd, GWL_STYLE );
367     LONG style = full_style & SS_TYPEMASK;
368
369     switch (uMsg)
370     {
371     case WM_CREATE:
372         if (style < 0L || style > SS_TYPEMASK)
373         {
374             ERR("Unknown style 0x%02lx\n", style );
375             return -1;
376         }
377         STATIC_InitColours();
378         break;
379
380     case WM_NCDESTROY:
381         if (style == SS_ICON) {
382 /*
383  * FIXME
384  *           DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
385  *
386  * We don't want to do this yet because DestroyIcon32 is broken. If the icon
387  * had already been loaded by the application the last thing we want to do is
388  * GlobalFree16 the handle.
389  */
390             break;
391         }
392         else return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
393                               DefWindowProcA(hwnd, uMsg, wParam, lParam);
394
395     case WM_PRINTCLIENT:
396     case WM_PAINT:
397         {
398             PAINTSTRUCT ps;
399             HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
400             if (staticPaintFunc[style])
401                 (staticPaintFunc[style])( hwnd, hdc, full_style );
402             if (!wParam) EndPaint(hwnd, &ps);
403         }
404         break;
405
406     case WM_ENABLE:
407         STATIC_TryPaintFcn( hwnd, full_style );
408         if (full_style & SS_NOTIFY) {
409             if (wParam) {
410                 SendMessageW( GetParent(hwnd), WM_COMMAND,
411                               MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_ENABLE ), (LPARAM)hwnd);
412             }
413             else {
414                 SendMessageW( GetParent(hwnd), WM_COMMAND,
415                               MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DISABLE ), (LPARAM)hwnd);
416             }
417         }
418         break;
419
420     case WM_SYSCOLORCHANGE:
421         STATIC_InitColours();
422         STATIC_TryPaintFcn( hwnd, full_style );
423         break;
424
425     case WM_NCCREATE:
426         {
427             LPCSTR textA;
428             LPCWSTR textW;
429     
430             if (full_style & SS_SUNKEN)
431                 SetWindowLongW( hwnd, GWL_EXSTYLE,
432                                 GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
433
434             if(unicode)
435             {
436                 textA = NULL;
437                 textW = ((LPCREATESTRUCTW)lParam)->lpszName;
438             }
439             else
440             {
441                 textA = ((LPCREATESTRUCTA)lParam)->lpszName;
442                 textW = NULL;
443             }
444
445             switch (style) {
446             case SS_ICON:
447                 {
448                     HICON hIcon;
449                     if(unicode)
450                        hIcon = STATIC_LoadIconW(hwnd, textW, full_style);
451                     else
452                        hIcon = STATIC_LoadIconA(hwnd, textA, full_style);
453                     STATIC_SetIcon(hwnd, hIcon, full_style);
454                 }
455                 break;
456             case SS_BITMAP:
457                 {
458                     HBITMAP hBitmap;
459                     if(unicode)
460                         hBitmap = STATIC_LoadBitmapW(hwnd, textW);
461                     else
462                         hBitmap = STATIC_LoadBitmapA(hwnd, textA);
463                     STATIC_SetBitmap(hwnd, hBitmap, full_style);
464                 }
465                 break;
466             }
467             /* SS_ENHMETAFILE: Despite what MSDN says, Windows does not load
468                the enhanced metafile that was specified as the window text. */
469         }
470         return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
471                          DefWindowProcA(hwnd, uMsg, wParam, lParam);
472
473     case WM_SETTEXT:
474         if (hasTextStyle( full_style ))
475         {
476             if (HIWORD(lParam))
477             {
478                 if(unicode)
479                      lResult = DefWindowProcW( hwnd, uMsg, wParam, lParam );
480                 else
481                     lResult = DefWindowProcA( hwnd, uMsg, wParam, lParam );
482                 STATIC_TryPaintFcn( hwnd, full_style );
483             }
484         }
485         break;
486
487     case WM_SETFONT:
488         if (hasTextStyle( full_style ))
489         {
490             SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam );
491             if (LOWORD(lParam))
492                 STATIC_TryPaintFcn( hwnd, full_style );
493         }
494         break;
495
496     case WM_GETFONT:
497         return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET );
498
499     case WM_NCHITTEST:
500         if (full_style & SS_NOTIFY)
501            return HTCLIENT;
502         else
503            return HTTRANSPARENT;
504
505     case WM_GETDLGCODE:
506         return DLGC_STATIC;
507
508     case WM_LBUTTONDOWN:
509     case WM_NCLBUTTONDOWN:
510         if (full_style & SS_NOTIFY)
511             SendMessageW( GetParent(hwnd), WM_COMMAND,
512                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd);
513         return 0;
514
515     case WM_LBUTTONDBLCLK:
516     case WM_NCLBUTTONDBLCLK:
517         if (full_style & SS_NOTIFY)
518             SendMessageW( GetParent(hwnd), WM_COMMAND,
519                           MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd);
520         return 0;
521
522     case STM_GETIMAGE:
523         return (LRESULT)STATIC_GetImage( hwnd, wParam, full_style );
524     
525     case STM_GETICON16:
526     case STM_GETICON:
527         return (LRESULT)STATIC_GetImage( hwnd, IMAGE_ICON, full_style );
528
529     case STM_SETIMAGE:
530         switch(wParam) {
531         case IMAGE_BITMAP:
532             lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
533             break;
534         case IMAGE_CURSOR:
535             FIXME("STM_SETIMAGE: Unhandled type IMAGE_CURSOR\n");
536             break;
537         case IMAGE_ENHMETAFILE:
538             lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style );
539             break;
540         case IMAGE_ICON:
541             lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
542             break;
543         default:
544             FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam);
545             break;
546         }
547         STATIC_TryPaintFcn( hwnd, full_style );
548         break;
549
550     case STM_SETICON16:
551     case STM_SETICON:
552         lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
553         STATIC_TryPaintFcn( hwnd, full_style );
554         break;
555
556     default:
557         return unicode ? DefWindowProcW(hwnd, uMsg, wParam, lParam) :
558                          DefWindowProcA(hwnd, uMsg, wParam, lParam);
559     }
560     return lResult;
561 }
562
563 /***********************************************************************
564  *           StaticWndProcA
565  */
566 static LRESULT WINAPI StaticWndProcA( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
567 {
568     if (!IsWindow( hWnd )) return 0;
569     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, FALSE);
570 }
571
572 /***********************************************************************
573  *           StaticWndProcW
574  */
575 static LRESULT WINAPI StaticWndProcW( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
576 {
577     if (!IsWindow( hWnd )) return 0;
578     return StaticWndProc_common(hWnd, uMsg, wParam, lParam, TRUE);
579 }
580
581 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style )
582 {
583   DRAWITEMSTRUCT dis;
584   HFONT font, oldFont = NULL;
585   UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
586
587   dis.CtlType    = ODT_STATIC;
588   dis.CtlID      = id;
589   dis.itemID     = 0;
590   dis.itemAction = ODA_DRAWENTIRE;
591   dis.itemState  = IsWindowEnabled(hwnd) ? 0 : ODS_DISABLED;
592   dis.hwndItem   = hwnd;
593   dis.hDC        = hdc;
594   dis.itemData   = 0;
595   GetClientRect( hwnd, &dis.rcItem );
596
597   font = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET );
598   if (font) oldFont = SelectObject( hdc, font );
599   SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
600   SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
601   if (font) SelectObject( hdc, oldFont );
602 }
603
604 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style )
605 {
606     RECT rc;
607     HBRUSH hBrush;
608     HFONT hFont, hOldFont = NULL;
609     WORD wFormat;
610     INT len;
611     WCHAR *text;
612
613     GetClientRect( hwnd, &rc);
614
615     switch (style & SS_TYPEMASK)
616     {
617     case SS_LEFT:
618         wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
619         break;
620
621     case SS_CENTER:
622         wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
623         break;
624
625     case SS_RIGHT:
626         wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
627         break;
628
629     case SS_SIMPLE:
630         wFormat = DT_LEFT | DT_SINGLELINE;
631         break;
632
633     case SS_LEFTNOWORDWRAP:
634         wFormat = DT_LEFT | DT_EXPANDTABS;
635         break;
636
637     default:
638         return;
639     }
640
641     if (style & SS_NOPREFIX)
642         wFormat |= DT_NOPREFIX;
643     
644     if ((style & SS_TYPEMASK) != SS_SIMPLE)
645     {
646         if (style & SS_CENTERIMAGE)
647             wFormat |= DT_SINGLELINE | DT_VCENTER;
648         if (style & SS_EDITCONTROL)
649             wFormat |= DT_EDITCONTROL;
650         if (style & SS_ENDELLIPSIS)
651             wFormat |= DT_SINGLELINE | DT_END_ELLIPSIS;
652         if (style & SS_PATHELLIPSIS)
653             wFormat |= DT_SINGLELINE | DT_PATH_ELLIPSIS;
654         if (style & SS_WORDELLIPSIS)
655             wFormat |= DT_SINGLELINE | DT_WORD_ELLIPSIS;
656     }
657
658     if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET )))
659         hOldFont = (HFONT)SelectObject( hdc, hFont );
660
661     /* SS_SIMPLE controls: WM_CTLCOLORSTATIC is sent, but the returned
662                            brush is not used */
663     hBrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
664     
665     if ((style & SS_TYPEMASK) != SS_SIMPLE)
666     {
667         FillRect( hdc, &rc, hBrush );
668         if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
669     }
670
671     if (!(len = SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 ))) return;
672     if (!(text = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return;
673     SendMessageW( hwnd, WM_GETTEXT, len + 1, (LPARAM)text );
674     
675     if (((style & SS_TYPEMASK) == SS_SIMPLE) && (style & SS_NOPREFIX))
676     {
677         /* Windows uses the faster ExtTextOut() to draw the text and
678            to paint the whole client rectangle with the text background
679            color. Reference: "Static Controls" by Kyle Marsh, 1992 */
680         ExtTextOutW( hdc, rc.left, rc.top, ETO_CLIPPED | ETO_OPAQUE,
681                      &rc, text, len, NULL );
682     }
683     else
684     {
685         DrawTextW( hdc, text, -1, &rc, wFormat );
686     }
687     
688     HeapFree( GetProcessHeap(), 0, text );
689     
690     if (hFont)
691         SelectObject( hdc, hOldFont );
692 }
693
694 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style )
695 {
696     RECT rc;
697     HBRUSH hBrush;
698
699     GetClientRect( hwnd, &rc);
700
701     switch (style & SS_TYPEMASK)
702     {
703     case SS_BLACKRECT:
704         hBrush = CreateSolidBrush(color_3ddkshadow);
705         FillRect( hdc, &rc, hBrush );
706         break;
707     case SS_GRAYRECT:
708         hBrush = CreateSolidBrush(color_3dshadow);
709         FillRect( hdc, &rc, hBrush );
710         break;
711     case SS_WHITERECT:
712         hBrush = CreateSolidBrush(color_3dhighlight);
713         FillRect( hdc, &rc, hBrush );
714         break;
715     case SS_BLACKFRAME:
716         hBrush = CreateSolidBrush(color_3ddkshadow);
717         FrameRect( hdc, &rc, hBrush );
718         break;
719     case SS_GRAYFRAME:
720         hBrush = CreateSolidBrush(color_3dshadow);
721         FrameRect( hdc, &rc, hBrush );
722         break;
723     case SS_WHITEFRAME:
724         hBrush = CreateSolidBrush(color_3dhighlight);
725         FrameRect( hdc, &rc, hBrush );
726         break;
727     default:
728         return;
729     }
730     DeleteObject( hBrush );
731 }
732
733
734 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
735 {
736     RECT rc;
737     HBRUSH hbrush;
738     HICON hIcon;
739     INT x, y;
740
741     GetClientRect( hwnd, &rc );
742     hbrush = (HBRUSH)SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
743                                    (WPARAM)hdc, (LPARAM)hwnd );
744     FillRect( hdc, &rc, hbrush );
745     hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET );
746     if (style & SS_CENTERIMAGE)
747     {
748         CURSORICONINFO *info = hIcon ? (CURSORICONINFO *)GlobalLock16(HICON_16(hIcon)) : NULL;
749         x = (rc.right - rc.left)/2 - (info ? info->nWidth/2 : 0);
750         y = (rc.bottom - rc.top)/2 - (info ? info->nHeight/2 : 0);
751     }
752     else
753     {
754         x = rc.left;
755         y = rc.top;
756     }
757     if (hIcon)
758         DrawIcon( hdc, x, y, hIcon );
759 }
760
761 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
762 {
763     HDC hMemDC;
764     HBITMAP hBitmap, oldbitmap;
765
766     /* message is still sent, even if the returned brush is not used */
767     SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC,
768                                    (WPARAM)hdc, (LPARAM)hwnd );
769
770     if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )))
771     {
772         INT x, y;
773         BITMAP bm;
774
775         if(GetObjectType(hBitmap) != OBJ_BITMAP) return;
776         if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
777         GetObjectW(hBitmap, sizeof(bm), &bm);
778         oldbitmap = SelectObject(hMemDC, hBitmap);
779         if (style & SS_CENTERIMAGE)
780         {
781             RECT rcClient;
782             GetClientRect(hwnd, &rcClient);
783             x = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2;
784             y = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2;
785         }
786         else
787         {
788             x = 0;
789             y = 0;
790         }
791         BitBlt(hdc, x, y, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,
792                SRCCOPY);
793         SelectObject(hMemDC, oldbitmap);
794         DeleteDC(hMemDC);
795     }
796 }
797
798
799 static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, DWORD style )
800 {
801     HENHMETAFILE hEnhMetaFile;
802     RECT rc;
803     HBRUSH hbrush;
804     
805     GetClientRect(hwnd, &rc);
806     hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
807     FillRect(hdc, &rc, hbrush);
808     if ((hEnhMetaFile = (HENHMETAFILE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )))
809     {
810         /* The control's current font is not selected into the
811            device context! */
812         if (GetObjectType(hEnhMetaFile) == OBJ_ENHMETAFILE)
813             PlayEnhMetaFile(hdc, hEnhMetaFile, &rc);
814     }
815 }
816
817
818 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style )
819 {
820     RECT rc;
821
822     GetClientRect( hwnd, &rc );
823     switch (style & SS_TYPEMASK)
824     {
825         case SS_ETCHEDHORZ:
826             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM);
827             break;
828         case SS_ETCHEDVERT:
829             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT);
830             break;
831         case SS_ETCHEDFRAME:
832             DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
833             break;
834     }
835 }