ntoskrnl.exe: Reimplement KeSetTimerEx() on top of thread pool.
[wine.git] / dlls / comctl32 / static.c
blobb3254e5761b32a6b8877a426e7781258606ae222
1 /*
2 * Static control
4 * Copyright David W. Metcalfe, 1993
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.
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.
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
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).
27 * TODO:
28 * - Animated cursors
31 #include <stdarg.h>
33 #include "windef.h"
34 #include "winbase.h"
35 #include "wingdi.h"
36 #include "winuser.h"
37 #include "commctrl.h"
39 #include "wine/heap.h"
40 #include "wine/debug.h"
42 #include "comctl32.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(static);
46 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style );
47 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style );
48 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style );
49 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style );
50 static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, DWORD style );
51 static void STATIC_PaintEnhMetafn( HWND hwnd, HDC hdc, DWORD style );
52 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style );
54 struct static_extra_info
56 HFONT hfont;
57 union
59 HICON hicon;
60 HBITMAP hbitmap;
61 HENHMETAFILE hemf;
62 } image;
63 BOOL image_has_alpha;
66 typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
68 static const pfPaint staticPaintFunc[SS_TYPEMASK+1] =
70 STATIC_PaintTextfn, /* SS_LEFT */
71 STATIC_PaintTextfn, /* SS_CENTER */
72 STATIC_PaintTextfn, /* SS_RIGHT */
73 STATIC_PaintIconfn, /* SS_ICON */
74 STATIC_PaintRectfn, /* SS_BLACKRECT */
75 STATIC_PaintRectfn, /* SS_GRAYRECT */
76 STATIC_PaintRectfn, /* SS_WHITERECT */
77 STATIC_PaintRectfn, /* SS_BLACKFRAME */
78 STATIC_PaintRectfn, /* SS_GRAYFRAME */
79 STATIC_PaintRectfn, /* SS_WHITEFRAME */
80 NULL, /* SS_USERITEM */
81 STATIC_PaintTextfn, /* SS_SIMPLE */
82 STATIC_PaintTextfn, /* SS_LEFTNOWORDWRAP */
83 STATIC_PaintOwnerDrawfn, /* SS_OWNERDRAW */
84 STATIC_PaintBitmapfn, /* SS_BITMAP */
85 STATIC_PaintEnhMetafn, /* SS_ENHMETAFILE */
86 STATIC_PaintEtchedfn, /* SS_ETCHEDHORZ */
87 STATIC_PaintEtchedfn, /* SS_ETCHEDVERT */
88 STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */
91 static struct static_extra_info *get_extra_ptr( HWND hwnd, BOOL force )
93 struct static_extra_info *extra = (struct static_extra_info *)GetWindowLongPtrW( hwnd, 0 );
94 if (!extra && force)
96 extra = heap_alloc_zero( sizeof(*extra) );
97 if (extra)
98 SetWindowLongPtrW( hwnd, 0, (ULONG_PTR)extra );
100 return extra;
103 static BOOL get_icon_size( HICON handle, SIZE *size )
105 ICONINFO info;
106 BITMAP bmp;
107 int ret;
109 if (!GetIconInfo(handle, &info))
110 return FALSE;
112 ret = GetObjectW(info.hbmColor, sizeof(bmp), &bmp);
113 if (ret)
115 size->cx = bmp.bmWidth;
116 size->cy = bmp.bmHeight;
119 DeleteObject(info.hbmMask);
120 DeleteObject(info.hbmColor);
122 return !!ret;
125 /***********************************************************************
126 * STATIC_SetIcon
128 * Set the icon for an SS_ICON control.
130 static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
132 HICON prevIcon;
133 SIZE size;
134 struct static_extra_info *extra;
136 if ((style & SS_TYPEMASK) != SS_ICON) return 0;
137 if (hicon && !get_icon_size( hicon, &size ))
139 WARN("hicon != 0, but invalid\n");
140 return 0;
143 extra = get_extra_ptr( hwnd, TRUE );
144 if (!extra) return 0;
146 prevIcon = extra->image.hicon;
147 extra->image.hicon = hicon;
148 if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
150 /* Windows currently doesn't implement SS_RIGHTJUST */
152 if ((style & SS_RIGHTJUST) != 0)
154 RECT wr;
155 GetWindowRect(hwnd, &wr);
156 SetWindowPos( hwnd, 0, wr.right - info->nWidth, wr.bottom - info->nHeight,
157 info->nWidth, info->nHeight, SWP_NOACTIVATE | SWP_NOZORDER );
159 else */
161 SetWindowPos( hwnd, 0, 0, 0, size.cx, size.cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
164 return prevIcon;
167 static HBITMAP create_alpha_bitmap( HBITMAP hbitmap )
169 BITMAP bm;
170 HBITMAP alpha;
171 BITMAPINFO info;
172 HDC hdc;
173 void *bits;
174 DWORD i;
175 BYTE *ptr;
176 BOOL has_alpha = FALSE;
178 GetObjectW( hbitmap, sizeof(bm), &bm );
179 if (bm.bmBitsPixel != 32) return 0;
181 if (!(hdc = CreateCompatibleDC( 0 ))) return 0;
183 info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
184 info.bmiHeader.biWidth = bm.bmWidth;
185 info.bmiHeader.biHeight = -bm.bmHeight;
186 info.bmiHeader.biPlanes = 1;
187 info.bmiHeader.biBitCount = 32;
188 info.bmiHeader.biCompression = BI_RGB;
189 info.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
190 info.bmiHeader.biXPelsPerMeter = 0;
191 info.bmiHeader.biYPelsPerMeter = 0;
192 info.bmiHeader.biClrUsed = 0;
193 info.bmiHeader.biClrImportant = 0;
194 if ((alpha = CreateDIBSection( hdc, &info, DIB_RGB_COLORS, &bits, NULL, 0 )))
196 GetDIBits( hdc, hbitmap, 0, bm.bmHeight, bits, &info, DIB_RGB_COLORS );
198 for (i = 0, ptr = bits; i < bm.bmWidth * bm.bmHeight; i++, ptr += 4)
199 if ((has_alpha = (ptr[3] != 0))) break;
201 if (!has_alpha)
203 DeleteObject( alpha );
204 alpha = 0;
208 DeleteDC( hdc );
210 return alpha;
213 /***********************************************************************
214 * STATIC_SetBitmap
216 * Set the bitmap for an SS_BITMAP control.
218 static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
220 HBITMAP hOldBitmap, alpha;
221 struct static_extra_info *extra;
223 if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
224 if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP)
226 WARN("hBitmap != 0, but it's not a bitmap\n");
227 return 0;
230 extra = get_extra_ptr( hwnd, TRUE );
231 if (!extra) return 0;
233 hOldBitmap = extra->image.hbitmap;
234 extra->image.hbitmap = hBitmap;
235 extra->image_has_alpha = FALSE;
237 if (hBitmap)
239 alpha = create_alpha_bitmap( hBitmap );
240 if (alpha)
242 extra->image.hbitmap = alpha;
243 extra->image_has_alpha = TRUE;
247 if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
249 BITMAP bm;
250 GetObjectW(hBitmap, sizeof(bm), &bm);
252 /* Windows currently doesn't implement SS_RIGHTJUST */
254 if ((style & SS_RIGHTJUST) != 0)
256 RECT wr;
257 GetWindowRect(hwnd, &wr);
258 SetWindowPos( hwnd, 0, wr.right - bm.bmWidth, wr.bottom - bm.bmHeight,
259 bm.bmWidth, bm.bmHeight, SWP_NOACTIVATE | SWP_NOZORDER );
261 else */
263 SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight,
264 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
267 return hOldBitmap;
270 /***********************************************************************
271 * STATIC_SetEnhMetaFile
273 * Set the enhanced metafile for an SS_ENHMETAFILE control.
275 static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style )
277 HENHMETAFILE old_hemf;
278 struct static_extra_info *extra;
280 if ((style & SS_TYPEMASK) != SS_ENHMETAFILE) return 0;
281 if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE)
283 WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n");
284 return 0;
287 extra = get_extra_ptr( hwnd, TRUE );
288 if (!extra) return 0;
290 old_hemf = extra->image.hemf;
291 extra->image.hemf = hEnhMetaFile;
293 return old_hemf;
296 /***********************************************************************
297 * STATIC_GetImage
299 * Gets the bitmap for an SS_BITMAP control, the icon/cursor for an
300 * SS_ICON control or the enhanced metafile for an SS_ENHMETAFILE control.
302 static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style )
304 struct static_extra_info *extra;
306 switch (style & SS_TYPEMASK)
308 case SS_ICON:
309 if ((wParam != IMAGE_ICON) &&
310 (wParam != IMAGE_CURSOR)) return NULL;
311 break;
312 case SS_BITMAP:
313 if (wParam != IMAGE_BITMAP) return NULL;
314 break;
315 case SS_ENHMETAFILE:
316 if (wParam != IMAGE_ENHMETAFILE) return NULL;
317 break;
318 default:
319 return NULL;
322 extra = get_extra_ptr( hwnd, FALSE );
323 return extra ? extra->image.hbitmap : 0;
326 static void STATIC_SetFont( HWND hwnd, HFONT hfont )
328 struct static_extra_info *extra = get_extra_ptr( hwnd, TRUE );
329 if (extra)
330 extra->hfont = hfont;
333 static HFONT STATIC_GetFont( HWND hwnd )
335 struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
336 return extra ? extra->hfont : 0;
339 /***********************************************************************
340 * STATIC_LoadIconW
342 * Load the icon for an SS_ICON control.
344 static HICON STATIC_LoadIconW( HINSTANCE hInstance, LPCWSTR name, DWORD style )
346 HICON hicon = 0;
348 if (hInstance && ((ULONG_PTR)hInstance >> 16))
350 if ((style & SS_REALSIZEIMAGE) != 0)
351 hicon = LoadImageW(hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED);
352 else
354 hicon = LoadIconW( hInstance, name );
355 if (!hicon) hicon = LoadCursorW( hInstance, name );
358 if (!hicon) hicon = LoadIconW( 0, name );
359 /* Windows doesn't try to load a standard cursor,
360 probably because most IDs for standard cursors conflict
361 with the IDs for standard icons anyway */
362 return hicon;
365 /***********************************************************************
366 * STATIC_TryPaintFcn
368 * Try to immediately paint the control.
370 static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
372 LONG style = full_style & SS_TYPEMASK;
373 RECT rc;
375 GetClientRect( hwnd, &rc );
376 if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
378 HDC hdc;
379 HRGN hrgn;
381 hdc = GetDC( hwnd );
382 hrgn = set_control_clipping( hdc, &rc );
383 (staticPaintFunc[style])( hwnd, hdc, full_style );
384 SelectClipRgn( hdc, hrgn );
385 if (hrgn) DeleteObject( hrgn );
386 ReleaseDC( hwnd, hdc );
390 static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc)
392 HBRUSH hBrush;
393 HWND parent = GetParent(hwnd);
395 if (!parent) parent = hwnd;
396 hBrush = (HBRUSH) SendMessageW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
397 if (!hBrush) /* did the app forget to call DefWindowProc ? */
399 /* FIXME: DefWindowProc should return different colors if a
400 manifest is present */
401 hBrush = (HBRUSH)DefWindowProcW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd);
403 return hBrush;
406 /***********************************************************************
407 * hasTextStyle
409 * Tests if the control displays text.
411 static BOOL hasTextStyle( DWORD style )
413 switch (style & SS_TYPEMASK)
415 case SS_SIMPLE:
416 case SS_LEFT:
417 case SS_LEFTNOWORDWRAP:
418 case SS_CENTER:
419 case SS_RIGHT:
420 case SS_OWNERDRAW:
421 return TRUE;
424 return FALSE;
427 static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
429 LRESULT lResult = 0;
430 LONG full_style = GetWindowLongW( hwnd, GWL_STYLE );
431 LONG style = full_style & SS_TYPEMASK;
433 if (!IsWindow( hwnd )) return 0;
435 switch (uMsg)
437 case WM_CREATE:
438 if (style < 0L || style > SS_TYPEMASK)
440 ERR("Unknown style 0x%02x\n", style );
441 return -1;
443 break;
445 case WM_NCDESTROY:
446 if (style == SS_ICON)
448 struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
449 if (extra)
451 if (extra->image_has_alpha)
452 DeleteObject( extra->image.hbitmap );
453 heap_free( extra );
456 * FIXME
457 * DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
459 * We don't want to do this yet because DestroyIcon32 is broken. If the icon
460 * had already been loaded by the application the last thing we want to do is
461 * GlobalFree16 the handle.
463 break;
465 else
466 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
468 case WM_ERASEBKGND:
469 /* do all painting in WM_PAINT like Windows does */
470 return 1;
472 case WM_PRINTCLIENT:
473 case WM_PAINT:
475 PAINTSTRUCT ps;
476 RECT rect;
477 HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
478 GetClientRect( hwnd, &rect );
479 if (staticPaintFunc[style])
481 HRGN hrgn = set_control_clipping( hdc, &rect );
482 (staticPaintFunc[style])( hwnd, hdc, full_style );
483 SelectClipRgn( hdc, hrgn );
484 if (hrgn) DeleteObject( hrgn );
486 if (!wParam) EndPaint(hwnd, &ps);
488 break;
490 case WM_ENABLE:
491 STATIC_TryPaintFcn( hwnd, full_style );
492 if (full_style & SS_NOTIFY)
494 if (wParam)
495 SendMessageW( GetParent(hwnd), WM_COMMAND,
496 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_ENABLE ), (LPARAM)hwnd);
497 else
498 SendMessageW( GetParent(hwnd), WM_COMMAND,
499 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DISABLE ), (LPARAM)hwnd);
501 break;
503 case WM_SYSCOLORCHANGE:
504 COMCTL32_RefreshSysColors();
505 STATIC_TryPaintFcn( hwnd, full_style );
506 break;
508 case WM_NCCREATE:
510 CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
512 if (full_style & SS_SUNKEN)
513 SetWindowLongW( hwnd, GWL_EXSTYLE,
514 GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
516 switch (style)
518 case SS_ICON:
520 HICON hIcon;
522 hIcon = STATIC_LoadIconW(cs->hInstance, cs->lpszName, full_style);
523 STATIC_SetIcon(hwnd, hIcon, full_style);
525 break;
526 case SS_BITMAP:
527 if ((ULONG_PTR)cs->hInstance >> 16)
529 HBITMAP hBitmap;
530 hBitmap = LoadBitmapW(cs->hInstance, cs->lpszName);
531 STATIC_SetBitmap(hwnd, hBitmap, full_style);
533 break;
535 /* SS_ENHMETAFILE: Despite what MSDN says, Windows does not load
536 the enhanced metafile that was specified as the window text. */
538 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
540 case WM_SETTEXT:
541 if (hasTextStyle( full_style ))
543 lResult = DefWindowProcW( hwnd, uMsg, wParam, lParam );
544 STATIC_TryPaintFcn( hwnd, full_style );
546 break;
548 case WM_SETFONT:
549 if (hasTextStyle( full_style ))
551 STATIC_SetFont( hwnd, (HFONT)wParam );
552 if (LOWORD(lParam))
553 RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN );
555 break;
557 case WM_GETFONT:
558 return (LRESULT)STATIC_GetFont( hwnd );
560 case WM_NCHITTEST:
561 if (full_style & SS_NOTIFY)
562 return HTCLIENT;
563 else
564 return HTTRANSPARENT;
566 case WM_GETDLGCODE:
567 return DLGC_STATIC;
569 case WM_LBUTTONDOWN:
570 case WM_NCLBUTTONDOWN:
571 if (full_style & SS_NOTIFY)
572 SendMessageW( GetParent(hwnd), WM_COMMAND,
573 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd);
574 return 0;
576 case WM_LBUTTONDBLCLK:
577 case WM_NCLBUTTONDBLCLK:
578 if (full_style & SS_NOTIFY)
579 SendMessageW( GetParent(hwnd), WM_COMMAND,
580 MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd);
581 return 0;
583 case STM_GETIMAGE:
584 return (LRESULT)STATIC_GetImage( hwnd, wParam, full_style );
586 case STM_GETICON:
587 return (LRESULT)STATIC_GetImage( hwnd, IMAGE_ICON, full_style );
589 case STM_SETIMAGE:
590 switch (wParam)
592 case IMAGE_BITMAP:
593 lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
594 break;
595 case IMAGE_ENHMETAFILE:
596 lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style );
597 break;
598 case IMAGE_ICON:
599 case IMAGE_CURSOR:
600 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
601 break;
602 default:
603 FIXME("STM_SETIMAGE: Unhandled type %lx\n", wParam);
604 break;
606 STATIC_TryPaintFcn( hwnd, full_style );
607 break;
609 case STM_SETICON:
610 lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
611 STATIC_TryPaintFcn( hwnd, full_style );
612 break;
614 default:
615 return DefWindowProcW(hwnd, uMsg, wParam, lParam);
617 return lResult;
620 static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, DWORD style )
622 DRAWITEMSTRUCT dis;
623 HFONT font, oldFont = NULL;
624 UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
626 dis.CtlType = ODT_STATIC;
627 dis.CtlID = id;
628 dis.itemID = 0;
629 dis.itemAction = ODA_DRAWENTIRE;
630 dis.itemState = IsWindowEnabled(hwnd) ? 0 : ODS_DISABLED;
631 dis.hwndItem = hwnd;
632 dis.hDC = hdc;
633 dis.itemData = 0;
634 GetClientRect( hwnd, &dis.rcItem );
636 font = STATIC_GetFont( hwnd );
637 if (font) oldFont = SelectObject( hdc, font );
638 SendMessageW( GetParent(hwnd), WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
639 SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
640 if (font) SelectObject( hdc, oldFont );
643 static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, DWORD style )
645 RECT rc;
646 HBRUSH hBrush;
647 HFONT hFont, hOldFont = NULL;
648 UINT format;
649 INT len, buf_size;
650 WCHAR *text;
652 GetClientRect( hwnd, &rc);
654 switch (style & SS_TYPEMASK)
656 case SS_LEFT:
657 format = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
658 break;
660 case SS_CENTER:
661 format = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
662 break;
664 case SS_RIGHT:
665 format = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
666 break;
668 case SS_SIMPLE:
669 format = DT_LEFT | DT_SINGLELINE;
670 break;
672 case SS_LEFTNOWORDWRAP:
673 format = DT_LEFT | DT_EXPANDTABS;
674 break;
676 default:
677 return;
680 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_RIGHT)
681 format = DT_RIGHT | (format & ~(DT_LEFT | DT_CENTER));
683 if (style & SS_NOPREFIX)
684 format |= DT_NOPREFIX;
686 if ((style & SS_TYPEMASK) != SS_SIMPLE)
688 if (style & SS_CENTERIMAGE)
689 format |= DT_SINGLELINE | DT_VCENTER;
690 if (style & SS_EDITCONTROL)
691 format |= DT_EDITCONTROL;
692 if (style & SS_ENDELLIPSIS)
693 format |= DT_SINGLELINE | DT_END_ELLIPSIS;
694 if (style & SS_PATHELLIPSIS)
695 format |= DT_SINGLELINE | DT_PATH_ELLIPSIS;
696 if (style & SS_WORDELLIPSIS)
697 format |= DT_SINGLELINE | DT_WORD_ELLIPSIS;
700 if ((hFont = STATIC_GetFont( hwnd )))
701 hOldFont = SelectObject( hdc, hFont );
703 /* SS_SIMPLE controls: WM_CTLCOLORSTATIC is sent, but the returned
704 brush is not used */
705 hBrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
707 if ((style & SS_TYPEMASK) != SS_SIMPLE)
709 FillRect( hdc, &rc, hBrush );
710 if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
713 buf_size = 256;
714 if (!(text = HeapAlloc( GetProcessHeap(), 0, buf_size * sizeof(WCHAR) )))
715 goto no_TextOut;
717 while ((len = InternalGetWindowText( hwnd, text, buf_size )) == buf_size - 1)
719 buf_size *= 2;
720 if (!(text = HeapReAlloc( GetProcessHeap(), 0, text, buf_size * sizeof(WCHAR) )))
721 goto no_TextOut;
724 if (!len) goto no_TextOut;
726 if (((style & SS_TYPEMASK) == SS_SIMPLE) && (style & SS_NOPREFIX))
728 /* Windows uses the faster ExtTextOut() to draw the text and
729 to paint the whole client rectangle with the text background
730 color. Reference: "Static Controls" by Kyle Marsh, 1992 */
731 ExtTextOutW( hdc, rc.left, rc.top, ETO_CLIPPED | ETO_OPAQUE,
732 &rc, text, len, NULL );
734 else
736 DrawTextW( hdc, text, -1, &rc, format );
739 no_TextOut:
740 HeapFree( GetProcessHeap(), 0, text );
742 if (hFont)
743 SelectObject( hdc, hOldFont );
746 static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, DWORD style )
748 RECT rc;
749 HBRUSH hBrush;
751 GetClientRect( hwnd, &rc);
753 /* FIXME: send WM_CTLCOLORSTATIC */
754 switch (style & SS_TYPEMASK)
756 case SS_BLACKRECT:
757 hBrush = CreateSolidBrush(comctl32_color.clr3dDkShadow);
758 FillRect( hdc, &rc, hBrush );
759 break;
760 case SS_GRAYRECT:
761 hBrush = CreateSolidBrush(comctl32_color.clr3dShadow);
762 FillRect( hdc, &rc, hBrush );
763 break;
764 case SS_WHITERECT:
765 hBrush = CreateSolidBrush(comctl32_color.clr3dHilight);
766 FillRect( hdc, &rc, hBrush );
767 break;
768 case SS_BLACKFRAME:
769 hBrush = CreateSolidBrush(comctl32_color.clr3dDkShadow);
770 FrameRect( hdc, &rc, hBrush );
771 break;
772 case SS_GRAYFRAME:
773 hBrush = CreateSolidBrush(comctl32_color.clr3dShadow);
774 FrameRect( hdc, &rc, hBrush );
775 break;
776 case SS_WHITEFRAME:
777 hBrush = CreateSolidBrush(comctl32_color.clr3dHilight);
778 FrameRect( hdc, &rc, hBrush );
779 break;
780 default:
781 return;
783 DeleteObject( hBrush );
787 static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, DWORD style )
789 RECT rc, iconRect;
790 HBRUSH hbrush;
791 HICON hIcon;
792 SIZE size;
794 GetClientRect( hwnd, &rc );
795 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
796 hIcon = STATIC_GetImage( hwnd, IMAGE_ICON, style );
797 if (!hIcon || !get_icon_size( hIcon, &size ))
799 FillRect(hdc, &rc, hbrush);
801 else
803 if (style & SS_CENTERIMAGE)
805 iconRect.left = (rc.right - rc.left) / 2 - size.cx / 2;
806 iconRect.top = (rc.bottom - rc.top) / 2 - size.cy / 2;
807 iconRect.right = iconRect.left + size.cx;
808 iconRect.bottom = iconRect.top + size.cy;
810 else
811 iconRect = rc;
812 FillRect( hdc, &rc, hbrush );
813 DrawIconEx( hdc, iconRect.left, iconRect.top, hIcon, iconRect.right - iconRect.left,
814 iconRect.bottom - iconRect.top, 0, NULL, DI_NORMAL );
818 static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
820 HDC hMemDC;
821 HBITMAP hBitmap, oldbitmap;
822 HBRUSH hbrush;
824 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
826 if ((hBitmap = STATIC_GetImage( hwnd, IMAGE_BITMAP, style ))
827 && (GetObjectType(hBitmap) == OBJ_BITMAP)
828 && (hMemDC = CreateCompatibleDC( hdc )))
830 BITMAP bm;
831 RECT rcClient;
832 LOGBRUSH brush;
833 BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
834 struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
836 GetObjectW(hBitmap, sizeof(bm), &bm);
837 oldbitmap = SelectObject(hMemDC, hBitmap);
839 /* Set the background color for monochrome bitmaps
840 to the color of the background brush */
841 if (GetObjectW( hbrush, sizeof(brush), &brush ))
843 if (brush.lbStyle == BS_SOLID)
844 SetBkColor(hdc, brush.lbColor);
846 GetClientRect(hwnd, &rcClient);
847 if (style & SS_CENTERIMAGE)
849 FillRect( hdc, &rcClient, hbrush );
850 rcClient.left = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2;
851 rcClient.top = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2;
852 rcClient.right = rcClient.left + bm.bmWidth;
853 rcClient.bottom = rcClient.top + bm.bmHeight;
856 if (extra->image_has_alpha)
857 GdiAlphaBlend(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
858 rcClient.bottom - rcClient.top, hMemDC,
859 0, 0, bm.bmWidth, bm.bmHeight, blend);
860 else
861 StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
862 rcClient.bottom - rcClient.top, hMemDC,
863 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
864 SelectObject(hMemDC, oldbitmap);
865 DeleteDC(hMemDC);
869 static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, DWORD style )
871 HENHMETAFILE hEnhMetaFile;
872 RECT rc;
873 HBRUSH hbrush;
875 GetClientRect(hwnd, &rc);
876 hbrush = STATIC_SendWmCtlColorStatic(hwnd, hdc);
877 FillRect(hdc, &rc, hbrush);
878 if ((hEnhMetaFile = STATIC_GetImage( hwnd, IMAGE_ENHMETAFILE, style )))
880 /* The control's current font is not selected into the
881 device context! */
882 if (GetObjectType(hEnhMetaFile) == OBJ_ENHMETAFILE)
883 PlayEnhMetaFile(hdc, hEnhMetaFile, &rc);
887 static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, DWORD style )
889 RECT rc;
891 /* FIXME: sometimes (not always) sends WM_CTLCOLORSTATIC */
892 GetClientRect( hwnd, &rc );
893 switch (style & SS_TYPEMASK)
895 case SS_ETCHEDHORZ:
896 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_TOP | BF_BOTTOM);
897 break;
898 case SS_ETCHEDVERT:
899 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_LEFT | BF_RIGHT);
900 break;
901 case SS_ETCHEDFRAME:
902 DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT);
903 break;
907 void STATIC_Register(void)
909 WNDCLASSW wndClass;
911 memset(&wndClass, 0, sizeof(wndClass));
912 wndClass.style = CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS;
913 wndClass.lpfnWndProc = STATIC_WindowProc;
914 wndClass.cbClsExtra = 0;
915 wndClass.cbWndExtra = sizeof(struct static_extra_info *);
916 wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
917 wndClass.hbrBackground = NULL;
918 wndClass.lpszClassName = WC_STATICW;
919 RegisterClassW(&wndClass);