Added a first-cut version of MapVirtualKeyExW() that has the same
[wine] / controls / static.c
1 /*
2  * Static control
3  *
4  * Copyright  David W. Metcalfe, 1993
5  *
6  */
7
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "win.h"
12 #include "cursoricon.h"
13 #include "static.h"
14 #include "heap.h"
15 #include "debugtools.h"
16 #include "tweak.h"
17
18 DEFAULT_DEBUG_CHANNEL(static);
19
20 static void STATIC_PaintOwnerDrawfn( WND *wndPtr, HDC hdc );
21 static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc );
22 static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc );
23 static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc );
24 static void STATIC_PaintBitmapfn( WND *wndPtr, HDC hdc );
25 static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc );
26
27 static COLORREF color_windowframe, color_background, color_window;
28
29
30 typedef void (*pfPaint)( WND *, HDC );
31
32 static pfPaint staticPaintFunc[SS_TYPEMASK+1] =
33 {
34     STATIC_PaintTextfn,      /* SS_LEFT */
35     STATIC_PaintTextfn,      /* SS_CENTER */
36     STATIC_PaintTextfn,      /* SS_RIGHT */
37     STATIC_PaintIconfn,      /* SS_ICON */
38     STATIC_PaintRectfn,      /* SS_BLACKRECT */
39     STATIC_PaintRectfn,      /* SS_GRAYRECT */
40     STATIC_PaintRectfn,      /* SS_WHITERECT */
41     STATIC_PaintRectfn,      /* SS_BLACKFRAME */
42     STATIC_PaintRectfn,      /* SS_GRAYFRAME */
43     STATIC_PaintRectfn,      /* SS_WHITEFRAME */
44     NULL,                    /* Not defined */
45     STATIC_PaintTextfn,      /* SS_SIMPLE */
46     STATIC_PaintTextfn,      /* SS_LEFTNOWORDWRAP */
47     STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */
48     STATIC_PaintBitmapfn,    /* SS_BITMAP */
49     NULL,                    /* SS_ENHMETAFILE */
50     STATIC_PaintEtchedfn,    /* SS_ETCHEDHORIZ */
51     STATIC_PaintEtchedfn,    /* SS_ETCHEDVERT */
52     STATIC_PaintEtchedfn,    /* SS_ETCHEDFRAME */
53 };
54
55
56 /***********************************************************************
57  *           STATIC_SetIcon
58  *
59  * Set the icon for an SS_ICON control.
60  */
61 static HICON16 STATIC_SetIcon( WND *wndPtr, HICON16 hicon )
62 {
63     HICON16 prevIcon;
64     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
65     CURSORICONINFO *info = hicon?(CURSORICONINFO *) GlobalLock16( hicon ):NULL;
66
67     if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_ICON) return 0;
68     if (hicon && !info) {
69         ERR("huh? hicon!=0, but info=0???\n");
70         return 0;
71     }
72     prevIcon = infoPtr->hIcon;
73     infoPtr->hIcon = hicon;
74     if (hicon)
75     {
76         SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, info->nWidth, info->nHeight,
77                         SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
78         GlobalUnlock16( hicon );
79     }
80     return prevIcon;
81 }
82
83 /***********************************************************************
84  *           STATIC_SetBitmap
85  *
86  * Set the bitmap for an SS_BITMAP control.
87  */
88 static HBITMAP16 STATIC_SetBitmap( WND *wndPtr, HBITMAP16 hBitmap )
89 {
90     HBITMAP16 hOldBitmap;
91     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
92
93     if ((wndPtr->dwStyle & SS_TYPEMASK) != SS_BITMAP) return 0;
94     if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP) {
95         ERR("huh? hBitmap!=0, but not bitmap\n");
96         return 0;
97     }
98     hOldBitmap = infoPtr->hIcon;
99     infoPtr->hIcon = hBitmap;
100     if (hBitmap)
101     {
102         BITMAP bm;
103         GetObjectA(hBitmap, sizeof(bm), &bm);
104         SetWindowPos( wndPtr->hwndSelf, 0, 0, 0, bm.bmWidth, bm.bmHeight,
105                       SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
106     }
107     return hOldBitmap;
108 }
109
110
111 /***********************************************************************
112  *           STATIC_LoadIcon
113  *
114  * Load the icon for an SS_ICON control.
115  */
116 static HICON STATIC_LoadIcon( WND *wndPtr, LPCSTR name )
117 {
118     HICON hicon = LoadIconA( wndPtr->hInstance, name );
119     if (!hicon) hicon = LoadIconA( 0, name );
120     return hicon;
121 }
122
123 /***********************************************************************
124  *           STATIC_LoadBitmap
125  *
126  * Load the bitmap for an SS_BITMAP control.
127  */
128 static HBITMAP STATIC_LoadBitmap( WND *wndPtr, LPCSTR name )
129 {
130     HBITMAP hbitmap = LoadBitmapA( wndPtr->hInstance, name );
131     if (!hbitmap)  /* Try OEM icon (FIXME: is this right?) */
132         hbitmap = LoadBitmapA( 0, name );
133     return hbitmap;
134 }
135
136
137 /***********************************************************************
138  *           StaticWndProc
139  */
140 LRESULT WINAPI StaticWndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
141                               LPARAM lParam )
142 {
143     LRESULT lResult = 0;
144     WND *wndPtr = WIN_FindWndPtr(hWnd);
145     LONG style = wndPtr->dwStyle & SS_TYPEMASK;
146     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
147
148     switch (uMsg)
149     {
150     case WM_NCCREATE: {
151         CREATESTRUCTA *cs = (CREATESTRUCTA *)lParam;
152
153         if ((TWEAK_WineLook > WIN31_LOOK) && (wndPtr->dwStyle & SS_SUNKEN))
154             wndPtr->dwExStyle |= WS_EX_STATICEDGE;
155
156         if (style == SS_ICON)
157         {
158             if (cs->lpszName)
159             {
160                 if (!HIWORD(cs->lpszName) || cs->lpszName[0])
161                     STATIC_SetIcon( wndPtr,
162                                 STATIC_LoadIcon( wndPtr, cs->lpszName ));
163             }
164             lResult = 1;
165             goto END;
166         }
167         if (style == SS_BITMAP)
168         {
169             if (cs->lpszName)
170                 STATIC_SetBitmap( wndPtr,
171                                 STATIC_LoadBitmap( wndPtr, cs->lpszName ));
172             WARN("style SS_BITMAP, dwStyle is 0x%08lx\n",
173                         wndPtr->dwStyle);
174             lResult = 1;
175             goto END;
176         }
177         if (!HIWORD(cs->lpszName) && (cs->lpszName))
178         {
179                 FIXME("windowName is 0x%04x, not doing DefWindowProc\n",
180                     LOWORD(cs->lpszName));
181                 lResult = 1;
182                 goto END;
183         }
184         lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
185         goto END;
186     }
187     case WM_CREATE:
188         if (style < 0L || style > SS_TYPEMASK)
189         {
190             ERR("Unknown style 0x%02lx\n", style );
191             lResult = -1L;
192             break;
193         }
194         /* initialise colours */
195         color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
196         color_background   = GetSysColor(COLOR_BACKGROUND);
197         color_window       = GetSysColor(COLOR_WINDOW);
198         break;
199
200     case WM_NCDESTROY:
201         if (style == SS_ICON) {
202 /*
203  * FIXME
204  *           DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
205  * 
206  * We don't want to do this yet because DestroyIcon32 is broken. If the icon
207  * had already been loaded by the application the last thing we want to do is
208  * GlobalFree16 the handle.
209  */
210         } else {
211             lResult = DefWindowProcA( hWnd, uMsg, wParam, lParam );
212         }
213         break;
214
215     case WM_PAINT:
216         {
217             PAINTSTRUCT ps;
218             BeginPaint( hWnd, &ps );
219             if (staticPaintFunc[style])
220                 (staticPaintFunc[style])( wndPtr, ps.hdc );
221             EndPaint( hWnd, &ps );
222         }
223         break;
224
225     case WM_ENABLE:
226         InvalidateRect( hWnd, NULL, FALSE );
227         break;
228
229     case WM_SYSCOLORCHANGE:
230         color_windowframe  = GetSysColor(COLOR_WINDOWFRAME);
231         color_background   = GetSysColor(COLOR_BACKGROUND);
232         color_window       = GetSysColor(COLOR_WINDOW);
233         InvalidateRect( hWnd, NULL, TRUE );
234         break;
235
236     case WM_SETTEXT:
237         if (style == SS_ICON)
238             /* FIXME : should we also return the previous hIcon here ??? */
239             STATIC_SetIcon( wndPtr, STATIC_LoadIcon( wndPtr, (LPCSTR)lParam ));
240         else if (style == SS_BITMAP) 
241             STATIC_SetBitmap(wndPtr,STATIC_LoadBitmap(wndPtr,(LPCSTR)lParam ));
242         else
243             DEFWND_SetTextA( wndPtr, (LPCSTR)lParam );
244         InvalidateRect( hWnd, NULL, FALSE );
245         lResult = 1; /* success. FIXME: check text length */
246         break;
247
248     case WM_SETFONT:
249         if (style == SS_ICON)
250         {
251             lResult = 0;
252             goto END;
253         }
254         if (style == SS_BITMAP)
255         {
256             lResult = 0;
257             goto END;
258         }
259         infoPtr->hFont = (HFONT16)wParam;
260         if (LOWORD(lParam))
261         {
262             InvalidateRect( hWnd, NULL, FALSE );
263             UpdateWindow( hWnd );
264         }
265         break;
266
267     case WM_GETFONT:
268         lResult = infoPtr->hFont;
269         goto END;
270
271     case WM_NCHITTEST:
272         if (wndPtr->dwStyle & SS_NOTIFY)
273            lResult = HTCLIENT;
274         else
275            lResult = HTTRANSPARENT;
276         goto END;
277
278     case WM_GETDLGCODE:
279         lResult = DLGC_STATIC;
280         goto END;
281
282     case STM_GETIMAGE:
283     case STM_GETICON16:
284     case STM_GETICON:
285         lResult = infoPtr->hIcon;
286         goto END;
287
288     case STM_SETIMAGE:
289         switch(wParam) {
290         case IMAGE_BITMAP:
291             lResult = STATIC_SetBitmap( wndPtr, (HBITMAP)lParam );
292             break;
293         case IMAGE_ICON:
294             lResult = STATIC_SetIcon( wndPtr, (HICON16)lParam );
295             break;
296         default:
297             FIXME("STM_SETIMAGE: Unhandled type %x\n", wParam);
298             break;
299         }
300         InvalidateRect( hWnd, NULL, FALSE );
301         UpdateWindow( hWnd );
302         break;
303
304     case STM_SETICON16:
305     case STM_SETICON:
306         lResult = STATIC_SetIcon( wndPtr, (HICON16)wParam );
307         InvalidateRect( hWnd, NULL, FALSE );
308         UpdateWindow( hWnd );
309         break;
310
311     default:
312         lResult = DefWindowProcA(hWnd, uMsg, wParam, lParam);
313         break;
314     }
315     
316 END:
317     WIN_ReleaseWndPtr(wndPtr);
318     return lResult;
319 }
320
321 static void STATIC_PaintOwnerDrawfn( WND *wndPtr, HDC hdc )
322 {
323   DRAWITEMSTRUCT dis;
324
325   dis.CtlType    = ODT_STATIC;
326   dis.CtlID      = wndPtr->wIDmenu;
327   dis.itemID     = 0;
328   dis.itemAction = ODA_DRAWENTIRE;
329   dis.itemState  = 0;
330   dis.hwndItem   = wndPtr->hwndSelf;
331   dis.hDC        = hdc;
332   dis.itemData   = 0;
333   GetClientRect( wndPtr->hwndSelf, &dis.rcItem );
334
335   SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC, 
336                 hdc, wndPtr->hwndSelf );    
337   SendMessageA( GetParent(wndPtr->hwndSelf), WM_DRAWITEM,
338                 wndPtr->wIDmenu, (LPARAM)&dis );
339 }
340
341 static void STATIC_PaintTextfn( WND *wndPtr, HDC hdc )
342 {
343     RECT rc;
344     HBRUSH hBrush;
345     WORD wFormat;
346
347     LONG style = wndPtr->dwStyle;
348     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
349
350     GetClientRect( wndPtr->hwndSelf, &rc);
351
352     switch (style & SS_TYPEMASK)
353     {
354     case SS_LEFT:
355         wFormat = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
356         break;
357
358     case SS_CENTER:
359         wFormat = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
360         break;
361
362     case SS_RIGHT:
363         wFormat = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK | DT_NOCLIP;
364         break;
365
366     case SS_SIMPLE:
367         wFormat = DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_NOCLIP;
368         break;
369
370     case SS_LEFTNOWORDWRAP:
371         wFormat = DT_LEFT | DT_EXPANDTABS | DT_VCENTER;
372         break;
373
374     default:
375         return;
376     }
377
378     if (style & SS_NOPREFIX)
379         wFormat |= DT_NOPREFIX;
380
381     if (infoPtr->hFont) SelectObject( hdc, infoPtr->hFont );
382
383     if ((style & SS_NOPREFIX) || ((style & SS_TYPEMASK) != SS_SIMPLE))
384     {
385         hBrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
386                              hdc, wndPtr->hwndSelf );
387         if (!hBrush) hBrush = GetStockObject(WHITE_BRUSH);
388         FillRect( hdc, &rc, hBrush );    
389     }
390     if (!IsWindowEnabled(wndPtr->hwndSelf))
391         SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
392
393     if (wndPtr->text) DrawTextW( hdc, wndPtr->text, -1, &rc, wFormat );
394 }
395
396 static void STATIC_PaintRectfn( WND *wndPtr, HDC hdc )
397 {
398     RECT rc;
399     HBRUSH hBrush;
400
401     GetClientRect( wndPtr->hwndSelf, &rc);
402     
403     switch (wndPtr->dwStyle & SS_TYPEMASK)
404     {
405     case SS_BLACKRECT:
406         hBrush = CreateSolidBrush(color_windowframe);
407         FillRect( hdc, &rc, hBrush );
408         break;
409     case SS_GRAYRECT:
410         hBrush = CreateSolidBrush(color_background);
411         FillRect( hdc, &rc, hBrush );
412         break;
413     case SS_WHITERECT:
414         hBrush = CreateSolidBrush(color_window);
415         FillRect( hdc, &rc, hBrush );
416         break;
417     case SS_BLACKFRAME:
418         hBrush = CreateSolidBrush(color_windowframe);
419         FrameRect( hdc, &rc, hBrush );
420         break;
421     case SS_GRAYFRAME:
422         hBrush = CreateSolidBrush(color_background);
423         FrameRect( hdc, &rc, hBrush );
424         break;
425     case SS_WHITEFRAME:
426         hBrush = CreateSolidBrush(color_window);
427         FrameRect( hdc, &rc, hBrush );
428         break;
429     default:
430         return;
431     }
432     DeleteObject( hBrush );
433 }
434
435
436 static void STATIC_PaintIconfn( WND *wndPtr, HDC hdc )
437 {
438     RECT rc;
439     HBRUSH hbrush;
440     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
441
442     GetClientRect( wndPtr->hwndSelf, &rc );
443     hbrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
444                              hdc, wndPtr->hwndSelf );
445     FillRect( hdc, &rc, hbrush );
446     if (infoPtr->hIcon) DrawIcon( hdc, rc.left, rc.top, infoPtr->hIcon );
447 }
448
449 static void STATIC_PaintBitmapfn(WND *wndPtr, HDC hdc )
450 {
451     RECT rc;
452     HBRUSH hbrush;
453     STATICINFO *infoPtr = (STATICINFO *)wndPtr->wExtra;
454     HDC hMemDC;
455     HBITMAP oldbitmap;
456
457     GetClientRect( wndPtr->hwndSelf, &rc );
458     hbrush = SendMessageA( GetParent(wndPtr->hwndSelf), WM_CTLCOLORSTATIC,
459                              hdc, wndPtr->hwndSelf );
460     FillRect( hdc, &rc, hbrush );
461
462     if (infoPtr->hIcon) {
463         BITMAP bm;
464         SIZE sz;
465
466         if(GetObjectType(infoPtr->hIcon) != OBJ_BITMAP)
467             return;
468         if (!(hMemDC = CreateCompatibleDC( hdc ))) return;
469         GetObjectA(infoPtr->hIcon, sizeof(bm), &bm);
470         GetBitmapDimensionEx(infoPtr->hIcon, &sz);
471         oldbitmap = SelectObject(hMemDC, infoPtr->hIcon);
472         BitBlt(hdc, sz.cx, sz.cy, bm.bmWidth, bm.bmHeight, hMemDC, 0, 0,
473                SRCCOPY);
474         SelectObject(hMemDC, oldbitmap);
475         DeleteDC(hMemDC);
476     }
477 }
478
479
480 static void STATIC_PaintEtchedfn( WND *wndPtr, HDC hdc )
481 {
482     RECT rc;
483
484     if (TWEAK_WineLook == WIN31_LOOK)
485         return;
486
487     GetClientRect( wndPtr->hwndSelf, &rc );
488     switch (wndPtr->dwStyle & SS_TYPEMASK)
489     {
490         case SS_ETCHEDHORZ:
491             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_TOP|BF_BOTTOM);
492             break;
493         case SS_ETCHEDVERT:
494             DrawEdge(hdc,&rc,EDGE_ETCHED,BF_LEFT|BF_RIGHT);
495             break;
496         case SS_ETCHEDFRAME:
497             DrawEdge (hdc, &rc, EDGE_ETCHED, BF_RECT);
498             break;
499     }
500 }
501