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