Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comctl32_v6/static.c
5968 views
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 <stdarg.h>
32
#include <stdlib.h>
33
34
#include "windef.h"
35
#include "winbase.h"
36
#include "wingdi.h"
37
#include "winuser.h"
38
#include "commctrl.h"
39
40
#include "wine/debug.h"
41
42
#include "comctl32.h"
43
44
WINE_DEFAULT_DEBUG_CHANNEL(static);
45
46
static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
47
static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
48
static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
49
static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
50
static void STATIC_PaintBitmapfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
51
static void STATIC_PaintEnhMetafn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
52
static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
53
54
struct static_extra_info
55
{
56
HFONT hfont;
57
union
58
{
59
HICON hicon;
60
HBITMAP hbitmap;
61
HENHMETAFILE hemf;
62
} image;
63
BOOL image_has_alpha;
64
};
65
66
typedef void (*pfPaint)( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style );
67
68
static const pfPaint staticPaintFunc[SS_TYPEMASK+1] =
69
{
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
NULL, /* SS_ETCHEDHORZ */
87
NULL, /* SS_ETCHEDVERT */
88
STATIC_PaintEtchedfn, /* SS_ETCHEDFRAME */
89
};
90
91
static struct static_extra_info *get_extra_ptr( HWND hwnd, BOOL force )
92
{
93
struct static_extra_info *extra = (struct static_extra_info *)GetWindowLongPtrW( hwnd, 0 );
94
if (!extra && force)
95
{
96
extra = Alloc( sizeof(*extra) );
97
if (extra)
98
SetWindowLongPtrW( hwnd, 0, (ULONG_PTR)extra );
99
}
100
return extra;
101
}
102
103
static BOOL get_icon_size( HICON handle, SIZE *size )
104
{
105
ICONINFO info;
106
BITMAP bmp;
107
int ret;
108
109
if (!GetIconInfo(handle, &info))
110
return FALSE;
111
112
ret = GetObjectW(info.hbmColor, sizeof(bmp), &bmp);
113
if (ret)
114
{
115
size->cx = bmp.bmWidth;
116
size->cy = bmp.bmHeight;
117
}
118
119
DeleteObject(info.hbmMask);
120
DeleteObject(info.hbmColor);
121
122
return !!ret;
123
}
124
125
/***********************************************************************
126
* STATIC_SetIcon
127
*
128
* Set the icon for an SS_ICON control.
129
*/
130
static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
131
{
132
HICON prevIcon;
133
SIZE size;
134
struct static_extra_info *extra;
135
136
if (hicon && !get_icon_size( hicon, &size ))
137
{
138
WARN("hicon != 0, but invalid\n");
139
return 0;
140
}
141
142
extra = get_extra_ptr( hwnd, TRUE );
143
if (!extra) return 0;
144
145
prevIcon = extra->image.hicon;
146
extra->image.hicon = hicon;
147
if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
148
{
149
/* Windows currently doesn't implement SS_RIGHTJUST */
150
/*
151
if ((style & SS_RIGHTJUST) != 0)
152
{
153
RECT wr;
154
GetWindowRect(hwnd, &wr);
155
SetWindowPos( hwnd, 0, wr.right - info->nWidth, wr.bottom - info->nHeight,
156
info->nWidth, info->nHeight, SWP_NOACTIVATE | SWP_NOZORDER );
157
}
158
else */
159
{
160
SetWindowPos( hwnd, 0, 0, 0, size.cx, size.cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
161
}
162
}
163
return prevIcon;
164
}
165
166
static HBITMAP create_alpha_bitmap( HBITMAP hbitmap )
167
{
168
BITMAP bm;
169
HBITMAP alpha;
170
BITMAPINFO info;
171
HDC hdc;
172
void *bits;
173
DWORD i;
174
BYTE *ptr;
175
BOOL has_alpha = FALSE;
176
177
GetObjectW( hbitmap, sizeof(bm), &bm );
178
if (bm.bmBitsPixel != 32) return 0;
179
180
if (!(hdc = CreateCompatibleDC( 0 ))) return 0;
181
182
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
183
info.bmiHeader.biWidth = bm.bmWidth;
184
info.bmiHeader.biHeight = -bm.bmHeight;
185
info.bmiHeader.biPlanes = 1;
186
info.bmiHeader.biBitCount = 32;
187
info.bmiHeader.biCompression = BI_RGB;
188
info.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
189
info.bmiHeader.biXPelsPerMeter = 0;
190
info.bmiHeader.biYPelsPerMeter = 0;
191
info.bmiHeader.biClrUsed = 0;
192
info.bmiHeader.biClrImportant = 0;
193
if ((alpha = CreateDIBSection( hdc, &info, DIB_RGB_COLORS, &bits, NULL, 0 )))
194
{
195
GetDIBits( hdc, hbitmap, 0, bm.bmHeight, bits, &info, DIB_RGB_COLORS );
196
197
for (i = 0, ptr = bits; i < bm.bmWidth * bm.bmHeight; i++, ptr += 4)
198
if ((has_alpha = (ptr[3] != 0))) break;
199
200
if (!has_alpha)
201
{
202
DeleteObject( alpha );
203
alpha = 0;
204
}
205
else
206
{
207
/* pre-multiply by alpha */
208
for (i = 0, ptr = bits; i < bm.bmWidth * bm.bmHeight; i++, ptr += 4)
209
{
210
unsigned int alpha = ptr[3];
211
ptr[0] = (ptr[0] * alpha + 127) / 255;
212
ptr[1] = (ptr[1] * alpha + 127) / 255;
213
ptr[2] = (ptr[2] * alpha + 127) / 255;
214
}
215
}
216
}
217
218
DeleteDC( hdc );
219
220
return alpha;
221
}
222
223
/***********************************************************************
224
* STATIC_SetBitmap
225
*
226
* Set the bitmap for an SS_BITMAP control.
227
*/
228
static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
229
{
230
HBITMAP hOldBitmap, alpha;
231
struct static_extra_info *extra;
232
233
if (hBitmap && GetObjectType(hBitmap) != OBJ_BITMAP)
234
{
235
WARN("hBitmap != 0, but it's not a bitmap\n");
236
return 0;
237
}
238
239
extra = get_extra_ptr( hwnd, TRUE );
240
if (!extra) return 0;
241
242
hOldBitmap = extra->image.hbitmap;
243
extra->image.hbitmap = hBitmap;
244
extra->image_has_alpha = FALSE;
245
246
if (hBitmap)
247
{
248
alpha = create_alpha_bitmap( hBitmap );
249
if (alpha)
250
{
251
extra->image.hbitmap = alpha;
252
extra->image_has_alpha = TRUE;
253
}
254
}
255
256
if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
257
{
258
BITMAP bm;
259
GetObjectW(hBitmap, sizeof(bm), &bm);
260
261
/* Windows currently doesn't implement SS_RIGHTJUST */
262
/*
263
if ((style & SS_RIGHTJUST) != 0)
264
{
265
RECT wr;
266
GetWindowRect(hwnd, &wr);
267
SetWindowPos( hwnd, 0, wr.right - bm.bmWidth, wr.bottom - bm.bmHeight,
268
bm.bmWidth, bm.bmHeight, SWP_NOACTIVATE | SWP_NOZORDER );
269
}
270
else */
271
{
272
SetWindowPos( hwnd, 0, 0, 0, bm.bmWidth, bm.bmHeight,
273
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER );
274
}
275
}
276
return hOldBitmap;
277
}
278
279
/***********************************************************************
280
* STATIC_SetEnhMetaFile
281
*
282
* Set the enhanced metafile for an SS_ENHMETAFILE control.
283
*/
284
static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, DWORD style )
285
{
286
HENHMETAFILE old_hemf;
287
struct static_extra_info *extra;
288
289
if (hEnhMetaFile && GetObjectType(hEnhMetaFile) != OBJ_ENHMETAFILE)
290
{
291
WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n");
292
return 0;
293
}
294
295
extra = get_extra_ptr( hwnd, TRUE );
296
if (!extra) return 0;
297
298
old_hemf = extra->image.hemf;
299
extra->image.hemf = hEnhMetaFile;
300
301
return old_hemf;
302
}
303
304
/***********************************************************************
305
* STATIC_GetImage
306
*
307
* Gets the bitmap for an SS_BITMAP control, the icon/cursor for an
308
* SS_ICON control or the enhanced metafile for an SS_ENHMETAFILE control.
309
*/
310
static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style )
311
{
312
struct static_extra_info *extra;
313
314
switch (style & SS_TYPEMASK)
315
{
316
case SS_ICON:
317
if ((wParam != IMAGE_ICON) &&
318
(wParam != IMAGE_CURSOR)) return NULL;
319
break;
320
case SS_BITMAP:
321
if (wParam != IMAGE_BITMAP) return NULL;
322
break;
323
case SS_ENHMETAFILE:
324
if (wParam != IMAGE_ENHMETAFILE) return NULL;
325
break;
326
default:
327
return NULL;
328
}
329
330
extra = get_extra_ptr( hwnd, FALSE );
331
return extra ? extra->image.hbitmap : 0;
332
}
333
334
static void STATIC_SetFont( HWND hwnd, HFONT hfont )
335
{
336
struct static_extra_info *extra = get_extra_ptr( hwnd, TRUE );
337
if (extra)
338
extra->hfont = hfont;
339
}
340
341
static HFONT STATIC_GetFont( HWND hwnd )
342
{
343
struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
344
return extra ? extra->hfont : 0;
345
}
346
347
/***********************************************************************
348
* STATIC_LoadIconW
349
*
350
* Load the icon for an SS_ICON control.
351
*/
352
static HICON STATIC_LoadIconW( HINSTANCE hInstance, LPCWSTR name, DWORD style )
353
{
354
HICON hicon = 0;
355
356
if (hInstance && ((ULONG_PTR)hInstance >> 16))
357
{
358
if ((style & SS_REALSIZEIMAGE) != 0)
359
hicon = LoadImageW(hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED);
360
else
361
{
362
hicon = LoadIconW( hInstance, name );
363
if (!hicon) hicon = LoadCursorW( hInstance, name );
364
}
365
}
366
if (!hicon) hicon = LoadIconW( 0, name );
367
/* Windows doesn't try to load a standard cursor,
368
probably because most IDs for standard cursors conflict
369
with the IDs for standard icons anyway */
370
return hicon;
371
}
372
373
static HBRUSH STATIC_SendWmCtlColorStatic(HWND hwnd, HDC hdc)
374
{
375
HBRUSH hBrush;
376
HWND parent = GetParent(hwnd);
377
378
if (!parent) parent = hwnd;
379
hBrush = (HBRUSH) SendMessageW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd );
380
if (!hBrush) /* did the app forget to call DefWindowProc ? */
381
{
382
/* FIXME: DefWindowProc should return different colors if a
383
manifest is present */
384
hBrush = (HBRUSH)DefWindowProcW( parent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hwnd);
385
}
386
return hBrush;
387
}
388
389
/***********************************************************************
390
* STATIC_TryPaintFcn
391
*
392
* Try to immediately paint the control.
393
*/
394
static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
395
{
396
if (IsWindowVisible(hwnd))
397
{
398
RECT rc;
399
HDC hdc;
400
HRGN hrgn;
401
HBRUSH hbrush;
402
LONG style = full_style & SS_TYPEMASK;
403
404
GetClientRect( hwnd, &rc );
405
hdc = GetDC( hwnd );
406
hrgn = set_control_clipping( hdc, &rc );
407
hbrush = STATIC_SendWmCtlColorStatic( hwnd, hdc );
408
if (staticPaintFunc[style])
409
(staticPaintFunc[style])( hwnd, hdc, hbrush, full_style );
410
SelectClipRgn( hdc, hrgn );
411
if (hrgn) DeleteObject( hrgn );
412
ReleaseDC( hwnd, hdc );
413
}
414
}
415
416
/***********************************************************************
417
* hasTextStyle
418
*
419
* Tests if the control displays text.
420
*/
421
static BOOL hasTextStyle( DWORD style )
422
{
423
switch (style & SS_TYPEMASK)
424
{
425
case SS_SIMPLE:
426
case SS_LEFT:
427
case SS_LEFTNOWORDWRAP:
428
case SS_CENTER:
429
case SS_RIGHT:
430
case SS_OWNERDRAW:
431
return TRUE;
432
}
433
434
return FALSE;
435
}
436
437
static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
438
{
439
const WCHAR *window_name;
440
LRESULT lResult = 0;
441
LONG full_style = GetWindowLongW( hwnd, GWL_STYLE );
442
LONG style = full_style & SS_TYPEMASK;
443
444
if (!IsWindow( hwnd )) return 0;
445
446
switch (uMsg)
447
{
448
case WM_CREATE:
449
{
450
HWND parent;
451
452
if (style < 0L || style > SS_TYPEMASK)
453
{
454
ERR("Unknown style %#lx\n", style );
455
return -1;
456
}
457
458
parent = GetParent( hwnd );
459
if (parent)
460
EnableThemeDialogTexture( parent, ETDT_ENABLE );
461
break;
462
}
463
464
case WM_NCDESTROY:
465
if (style == SS_ICON)
466
{
467
struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
468
if (extra)
469
{
470
if (extra->image_has_alpha)
471
DeleteObject( extra->image.hbitmap );
472
Free( extra );
473
}
474
/*
475
* FIXME
476
* DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
477
*
478
* We don't want to do this yet because DestroyIcon32 is broken. If the icon
479
* had already been loaded by the application the last thing we want to do is
480
* GlobalFree16 the handle.
481
*/
482
break;
483
}
484
else
485
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
486
487
case WM_ERASEBKGND:
488
/* do all painting in WM_PAINT like Windows does */
489
return 1;
490
491
case WM_PRINTCLIENT:
492
case WM_PAINT:
493
{
494
PAINTSTRUCT ps;
495
RECT rect;
496
HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
497
HRGN hrgn;
498
HBRUSH hbrush;
499
500
GetClientRect( hwnd, &rect );
501
hrgn = set_control_clipping( hdc, &rect );
502
hbrush = STATIC_SendWmCtlColorStatic( hwnd, hdc );
503
if (staticPaintFunc[style])
504
(staticPaintFunc[style])( hwnd, hdc, hbrush, full_style );
505
SelectClipRgn( hdc, hrgn );
506
if (hrgn) DeleteObject( hrgn );
507
if (!wParam) EndPaint(hwnd, &ps);
508
}
509
break;
510
511
case WM_ENABLE:
512
STATIC_TryPaintFcn( hwnd, full_style );
513
if (full_style & SS_NOTIFY)
514
{
515
if (wParam)
516
SendMessageW( GetParent(hwnd), WM_COMMAND,
517
MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_ENABLE ), (LPARAM)hwnd);
518
else
519
SendMessageW( GetParent(hwnd), WM_COMMAND,
520
MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DISABLE ), (LPARAM)hwnd);
521
}
522
break;
523
524
case WM_SYSCOLORCHANGE:
525
COMCTL32_RefreshSysColors();
526
STATIC_TryPaintFcn( hwnd, full_style );
527
break;
528
529
case WM_THEMECHANGED:
530
return COMCTL32_ThemeChanged( hwnd, NULL, TRUE, TRUE );
531
532
case WM_NCCREATE:
533
{
534
CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam;
535
536
if (full_style & SS_SUNKEN || style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT)
537
SetWindowLongW( hwnd, GWL_EXSTYLE,
538
GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE );
539
540
if (style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT) {
541
RECT rc;
542
GetClientRect(hwnd, &rc);
543
if (style == SS_ETCHEDHORZ)
544
rc.bottom = rc.top;
545
else
546
rc.right = rc.left;
547
AdjustWindowRectEx(&rc, full_style, FALSE, GetWindowLongW(hwnd, GWL_EXSTYLE));
548
SetWindowPos(hwnd, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
549
}
550
551
if (cs->lpszName && cs->lpszName[0] == 0xffff)
552
window_name = MAKEINTRESOURCEW(cs->lpszName[1]);
553
else
554
window_name = cs->lpszName;
555
556
switch (style)
557
{
558
case SS_ICON:
559
{
560
HICON hIcon;
561
562
hIcon = STATIC_LoadIconW(cs->hInstance, window_name, full_style);
563
STATIC_SetIcon(hwnd, hIcon, full_style);
564
}
565
break;
566
case SS_BITMAP:
567
if ((ULONG_PTR)cs->hInstance >> 16)
568
{
569
HBITMAP hBitmap;
570
hBitmap = LoadBitmapW(cs->hInstance, window_name);
571
STATIC_SetBitmap(hwnd, hBitmap, full_style);
572
}
573
break;
574
}
575
/* SS_ENHMETAFILE: Despite what MSDN says, Windows does not load
576
the enhanced metafile that was specified as the window text. */
577
}
578
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
579
580
case WM_SETTEXT:
581
if (hasTextStyle( full_style ))
582
{
583
lResult = DefWindowProcW( hwnd, uMsg, wParam, lParam );
584
STATIC_TryPaintFcn( hwnd, full_style );
585
}
586
break;
587
588
case WM_GETOBJECT:
589
if ((LONG)lParam == OBJID_QUERYCLASSNAMEIDX)
590
return 0x10003;
591
break;
592
593
case WM_SETFONT:
594
if (hasTextStyle( full_style ))
595
{
596
STATIC_SetFont( hwnd, (HFONT)wParam );
597
if (LOWORD(lParam))
598
RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN );
599
}
600
break;
601
602
case WM_GETFONT:
603
return (LRESULT)STATIC_GetFont( hwnd );
604
605
case WM_NCHITTEST:
606
if (full_style & SS_NOTIFY)
607
return HTCLIENT;
608
else
609
return HTTRANSPARENT;
610
611
case WM_GETDLGCODE:
612
return DLGC_STATIC;
613
614
case WM_LBUTTONDOWN:
615
case WM_NCLBUTTONDOWN:
616
if (full_style & SS_NOTIFY)
617
SendMessageW( GetParent(hwnd), WM_COMMAND,
618
MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_CLICKED ), (LPARAM)hwnd);
619
return 0;
620
621
case WM_LBUTTONDBLCLK:
622
case WM_NCLBUTTONDBLCLK:
623
if (full_style & SS_NOTIFY)
624
SendMessageW( GetParent(hwnd), WM_COMMAND,
625
MAKEWPARAM( GetWindowLongPtrW(hwnd,GWLP_ID), STN_DBLCLK ), (LPARAM)hwnd);
626
return 0;
627
628
case STM_GETIMAGE:
629
return (LRESULT)STATIC_GetImage( hwnd, wParam, full_style );
630
631
case STM_GETICON:
632
return (LRESULT)STATIC_GetImage( hwnd, IMAGE_ICON, full_style );
633
634
case STM_SETIMAGE:
635
switch (wParam)
636
{
637
case IMAGE_BITMAP:
638
if (style != SS_BITMAP) return 0;
639
lResult = (LRESULT)STATIC_SetBitmap( hwnd, (HBITMAP)lParam, full_style );
640
break;
641
case IMAGE_ENHMETAFILE:
642
if (style != SS_ENHMETAFILE) return 0;
643
lResult = (LRESULT)STATIC_SetEnhMetaFile( hwnd, (HENHMETAFILE)lParam, full_style );
644
break;
645
case IMAGE_ICON:
646
case IMAGE_CURSOR:
647
if (style != SS_ICON) return 0;
648
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)lParam, full_style );
649
break;
650
default:
651
FIXME("STM_SETIMAGE: Unhandled type %Ix\n", wParam);
652
break;
653
}
654
STATIC_TryPaintFcn( hwnd, full_style );
655
break;
656
657
case STM_SETICON:
658
if (style != SS_ICON) return 0;
659
lResult = (LRESULT)STATIC_SetIcon( hwnd, (HICON)wParam, full_style );
660
STATIC_TryPaintFcn( hwnd, full_style );
661
break;
662
663
default:
664
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
665
}
666
return lResult;
667
}
668
669
static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
670
{
671
DRAWITEMSTRUCT dis;
672
HFONT font, oldFont = NULL;
673
UINT id = (UINT)GetWindowLongPtrW( hwnd, GWLP_ID );
674
675
dis.CtlType = ODT_STATIC;
676
dis.CtlID = id;
677
dis.itemID = 0;
678
dis.itemAction = ODA_DRAWENTIRE;
679
dis.itemState = IsWindowEnabled(hwnd) ? 0 : ODS_DISABLED;
680
dis.hwndItem = hwnd;
681
dis.hDC = hdc;
682
dis.itemData = 0;
683
GetClientRect( hwnd, &dis.rcItem );
684
685
font = STATIC_GetFont( hwnd );
686
if (font) oldFont = SelectObject( hdc, font );
687
SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
688
if (font) SelectObject( hdc, oldFont );
689
}
690
691
static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
692
{
693
RECT rc;
694
HFONT hFont, hOldFont = NULL;
695
UINT format;
696
INT len, buf_size;
697
WCHAR *text;
698
699
GetClientRect( hwnd, &rc);
700
701
switch (style & SS_TYPEMASK)
702
{
703
case SS_LEFT:
704
format = DT_LEFT | DT_EXPANDTABS | DT_WORDBREAK;
705
break;
706
707
case SS_CENTER:
708
format = DT_CENTER | DT_EXPANDTABS | DT_WORDBREAK;
709
break;
710
711
case SS_RIGHT:
712
format = DT_RIGHT | DT_EXPANDTABS | DT_WORDBREAK;
713
break;
714
715
case SS_SIMPLE:
716
format = DT_LEFT | DT_SINGLELINE;
717
break;
718
719
case SS_LEFTNOWORDWRAP:
720
format = DT_LEFT | DT_EXPANDTABS;
721
break;
722
723
default:
724
return;
725
}
726
727
if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_RIGHT)
728
format = DT_RIGHT | (format & ~(DT_LEFT | DT_CENTER));
729
730
if (style & SS_NOPREFIX)
731
format |= DT_NOPREFIX;
732
733
if ((style & SS_TYPEMASK) != SS_SIMPLE)
734
{
735
if (style & SS_CENTERIMAGE)
736
format |= DT_SINGLELINE | DT_VCENTER;
737
if (style & SS_EDITCONTROL)
738
format |= DT_EDITCONTROL;
739
if (style & SS_ENDELLIPSIS)
740
format |= DT_SINGLELINE | DT_END_ELLIPSIS;
741
if (style & SS_PATHELLIPSIS)
742
format |= DT_SINGLELINE | DT_PATH_ELLIPSIS;
743
if (style & SS_WORDELLIPSIS)
744
format |= DT_SINGLELINE | DT_WORD_ELLIPSIS;
745
}
746
747
if ((hFont = STATIC_GetFont( hwnd )))
748
hOldFont = SelectObject( hdc, hFont );
749
750
if ((style & SS_TYPEMASK) != SS_SIMPLE)
751
{
752
FillRect( hdc, &rc, hbrush );
753
if (!IsWindowEnabled(hwnd)) SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
754
}
755
756
buf_size = 256;
757
if (!(text = Alloc( buf_size * sizeof(WCHAR) )))
758
goto no_TextOut;
759
760
while ((len = InternalGetWindowText( hwnd, text, buf_size )) == buf_size - 1)
761
{
762
buf_size *= 2;
763
if (!(text = ReAlloc( text, buf_size * sizeof(WCHAR) )))
764
goto no_TextOut;
765
}
766
767
if (!len) goto no_TextOut;
768
769
if (((style & SS_TYPEMASK) == SS_SIMPLE) && (style & SS_NOPREFIX))
770
{
771
/* Windows uses the faster ExtTextOut() to draw the text and
772
to paint the whole client rectangle with the text background
773
color. Reference: "Static Controls" by Kyle Marsh, 1992 */
774
ExtTextOutW( hdc, rc.left, rc.top, ETO_CLIPPED | ETO_OPAQUE,
775
&rc, text, len, NULL );
776
}
777
else
778
{
779
DrawTextW( hdc, text, -1, &rc, format );
780
}
781
782
no_TextOut:
783
Free( text );
784
785
if (hFont)
786
SelectObject( hdc, hOldFont );
787
}
788
789
static void STATIC_PaintRectfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
790
{
791
RECT rc;
792
793
GetClientRect( hwnd, &rc);
794
795
switch (style & SS_TYPEMASK)
796
{
797
case SS_BLACKRECT:
798
hbrush = CreateSolidBrush(comctl32_color.clr3dDkShadow);
799
FillRect( hdc, &rc, hbrush );
800
break;
801
case SS_GRAYRECT:
802
hbrush = CreateSolidBrush(comctl32_color.clr3dShadow);
803
FillRect( hdc, &rc, hbrush );
804
break;
805
case SS_WHITERECT:
806
hbrush = CreateSolidBrush(comctl32_color.clr3dHilight);
807
FillRect( hdc, &rc, hbrush );
808
break;
809
case SS_BLACKFRAME:
810
hbrush = CreateSolidBrush(comctl32_color.clr3dDkShadow);
811
FrameRect( hdc, &rc, hbrush );
812
break;
813
case SS_GRAYFRAME:
814
hbrush = CreateSolidBrush(comctl32_color.clr3dShadow);
815
FrameRect( hdc, &rc, hbrush );
816
break;
817
case SS_WHITEFRAME:
818
hbrush = CreateSolidBrush(comctl32_color.clr3dHilight);
819
FrameRect( hdc, &rc, hbrush );
820
break;
821
default:
822
return;
823
}
824
DeleteObject( hbrush );
825
}
826
827
828
static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
829
{
830
RECT rc, iconRect;
831
HICON hIcon;
832
SIZE size;
833
834
GetClientRect( hwnd, &rc );
835
hIcon = STATIC_GetImage( hwnd, IMAGE_ICON, style );
836
if (!hIcon || !get_icon_size( hIcon, &size ))
837
{
838
FillRect(hdc, &rc, hbrush);
839
}
840
else
841
{
842
if (style & SS_CENTERIMAGE)
843
{
844
iconRect.left = (rc.right - rc.left) / 2 - size.cx / 2;
845
iconRect.top = (rc.bottom - rc.top) / 2 - size.cy / 2;
846
iconRect.right = iconRect.left + size.cx;
847
iconRect.bottom = iconRect.top + size.cy;
848
}
849
else
850
iconRect = rc;
851
FillRect( hdc, &rc, hbrush );
852
DrawIconEx( hdc, iconRect.left, iconRect.top, hIcon, iconRect.right - iconRect.left,
853
iconRect.bottom - iconRect.top, 0, NULL, DI_NORMAL );
854
}
855
}
856
857
static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
858
{
859
HDC hMemDC;
860
HBITMAP hBitmap, oldbitmap;
861
RECT rcClient;
862
863
GetClientRect( hwnd, &rcClient );
864
FillRect( hdc, &rcClient, hbrush );
865
866
if ((hBitmap = STATIC_GetImage( hwnd, IMAGE_BITMAP, style ))
867
&& (GetObjectType(hBitmap) == OBJ_BITMAP)
868
&& (hMemDC = CreateCompatibleDC( hdc )))
869
{
870
BITMAP bm;
871
LOGBRUSH brush;
872
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
873
struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
874
875
GetObjectW(hBitmap, sizeof(bm), &bm);
876
oldbitmap = SelectObject(hMemDC, hBitmap);
877
878
/* Set the background color for monochrome bitmaps
879
to the color of the background brush */
880
if (GetObjectW( hbrush, sizeof(brush), &brush ))
881
{
882
if (brush.lbStyle == BS_SOLID)
883
SetBkColor(hdc, brush.lbColor);
884
}
885
if (style & SS_CENTERIMAGE)
886
{
887
rcClient.left = (rcClient.right - rcClient.left)/2 - bm.bmWidth/2;
888
rcClient.top = (rcClient.bottom - rcClient.top)/2 - bm.bmHeight/2;
889
rcClient.right = rcClient.left + bm.bmWidth;
890
rcClient.bottom = rcClient.top + bm.bmHeight;
891
}
892
893
if (extra->image_has_alpha)
894
GdiAlphaBlend(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
895
rcClient.bottom - rcClient.top, hMemDC,
896
0, 0, bm.bmWidth, bm.bmHeight, blend);
897
else
898
StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
899
rcClient.bottom - rcClient.top, hMemDC,
900
0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
901
SelectObject(hMemDC, oldbitmap);
902
DeleteDC(hMemDC);
903
}
904
}
905
906
static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
907
{
908
HENHMETAFILE hEnhMetaFile;
909
RECT rc;
910
911
GetClientRect(hwnd, &rc);
912
FillRect(hdc, &rc, hbrush);
913
if ((hEnhMetaFile = STATIC_GetImage( hwnd, IMAGE_ENHMETAFILE, style )))
914
{
915
/* The control's current font is not selected into the
916
device context! */
917
if (GetObjectType(hEnhMetaFile) == OBJ_ENHMETAFILE)
918
PlayEnhMetaFile(hdc, hEnhMetaFile, &rc);
919
}
920
}
921
922
static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style )
923
{
924
RECT rc;
925
926
GetClientRect( hwnd, &rc );
927
DrawEdge(hdc, &rc, EDGE_ETCHED, BF_RECT);
928
}
929
930
void STATIC_Register(void)
931
{
932
WNDCLASSW wndClass;
933
934
memset(&wndClass, 0, sizeof(wndClass));
935
wndClass.style = CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS;
936
wndClass.lpfnWndProc = STATIC_WindowProc;
937
wndClass.cbClsExtra = 0;
938
wndClass.cbWndExtra = sizeof(struct static_extra_info *);
939
wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
940
wndClass.hbrBackground = NULL;
941
wndClass.lpszClassName = WC_STATICW;
942
RegisterClassW(&wndClass);
943
}
944
945