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