source: trunk/src/user32/uitools.cpp@ 1229

Last change on this file since 1229 was 1229, checked in by cbratschi, 26 years ago

merged with WINE, button: gray text for radio/checkbox, more to do

File size: 67.9 KB
Line 
1/* $Id: uitools.cpp,v 1.11 1999-10-09 16:28:25 cbratschi Exp $ */
2/*
3 * User Interface Functions
4 *
5 * Copyright 1997 Dimitrie O. Paun
6 * Copyright 1997 Bertho A. Stultiens
7 * Copyright 1999 Achim Hasenmueller
8 * Copyright 1999 Christoph Bratschi
9 * Copyright 1999 Rene Pronk
10 *
11 * WINE version: 990923
12 */
13
14#include "winuser.h"
15#include "user32.h"
16
17static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
18 0xaaaa, 0x5555, 0xaaaa, 0x5555 };
19
20/* These tables are used in:
21 * UITOOLS_DrawDiagEdge()
22 * UITOOLS_DrawRectEdge()
23 */
24static const char LTInnerNormal[] = {
25 -1, -1, -1, -1,
26 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
27 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1,
28 -1, -1, -1, -1
29};
30
31static const char LTOuterNormal[] = {
32 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
33 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
34 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
35 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1
36};
37
38static const char RBInnerNormal[] = {
39 -1, -1, -1, -1,
40 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
41 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
42 -1, -1, -1, -1
43};
44
45static const char RBOuterNormal[] = {
46 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
47 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
48 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
49 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1
50};
51
52static const char LTInnerSoft[] = {
53 -1, -1, -1, -1,
54 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
55 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
56 -1, -1, -1, -1
57};
58
59static const char LTOuterSoft[] = {
60 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
61 COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
62 COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
63 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
64};
65
66#define RBInnerSoft RBInnerNormal /* These are the same */
67#define RBOuterSoft RBOuterNormal
68
69static const char LTRBOuterMono[] = {
70 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
71 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
72 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
73 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
74};
75
76static const char LTRBInnerMono[] = {
77 -1, -1, -1, -1,
78 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
79 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
80 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
81};
82
83static const char LTRBOuterFlat[] = {
84 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
85 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
86 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
87 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
88};
89
90static const char LTRBInnerFlat[] = {
91 -1, -1, -1, -1,
92 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
93 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
94 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
95};
96
97/***********************************************************************
98 * UITOOLS_DrawDiagEdge
99 *
100 * Same as DrawEdge invoked with BF_DIAGONAL
101 *
102 * 03-Dec-1997: Changed by Bertho Stultiens
103 *
104 * See also comments with UITOOLS_DrawRectEdge()
105 */
106static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc,
107 UINT uType, UINT uFlags)
108{
109 POINT Points[4];
110 char InnerI, OuterI;
111 HPEN InnerPen, OuterPen;
112 POINT SavePoint;
113 HPEN SavePen;
114 int spx, spy;
115 int epx, epy;
116 int Width = rc->right - rc->left;
117 int Height= rc->bottom - rc->top;
118 int SmallDiam = Width > Height ? Height : Width;
119 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
120 || (uType & BDR_OUTER) == BDR_OUTER)
121 && !(uFlags & (BF_FLAT|BF_MONO)) );
122 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
123 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
124
125 if (IsRectEmpty(rc)) return retval; //nothing to do
126
127 /* Init some vars */
128 OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
129 SavePen = (HPEN)SelectObject(hdc, InnerPen);
130 spx = spy = epx = epy = 0; /* Satisfy the compiler... */
131
132 /* Determine the colors of the edges */
133 if(uFlags & BF_MONO)
134 {
135 InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
136 OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
137 }
138 else if(uFlags & BF_FLAT)
139 {
140 InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
141 OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
142 }
143 else if(uFlags & BF_SOFT)
144 {
145 if(uFlags & BF_BOTTOM)
146 {
147 InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
148 OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
149 }
150 else
151 {
152 InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
153 OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
154 }
155 }
156 else
157 {
158 if(uFlags & BF_BOTTOM)
159 {
160 InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
161 OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
162 }
163 else
164 {
165 InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
166 OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
167 }
168 }
169
170 if(InnerI != -1) InnerPen = GetSysColorPen(InnerI);
171 if(OuterI != -1) OuterPen = GetSysColorPen(OuterI);
172
173 MoveToEx(hdc, 0, 0, &SavePoint);
174
175 /* Don't ask me why, but this is what is visible... */
176 /* This must be possible to do much simpler, but I fail to */
177 /* see the logic in the MS implementation (sigh...). */
178 /* So, this might look a bit brute force here (and it is), but */
179 /* it gets the job done;) */
180
181 switch(uFlags & BF_RECT)
182 {
183 case 0:
184 case BF_LEFT:
185 case BF_BOTTOM:
186 case BF_BOTTOMLEFT:
187 /* Left bottom endpoint */
188 epx = rc->left-1;
189 spx = epx + SmallDiam;
190 epy = rc->bottom;
191 spy = epy - SmallDiam;
192 epx++;
193 epy--;
194 break;
195
196 case BF_TOPLEFT:
197 case BF_BOTTOMRIGHT:
198 /* Left top endpoint */
199 epx = rc->left-1;
200 spx = epx + SmallDiam;
201 epy = rc->top-1;
202 spy = epy + SmallDiam;
203 epx++;
204 epy++;
205 break;
206
207 case BF_TOP:
208 case BF_RIGHT:
209 case BF_TOPRIGHT:
210 case BF_RIGHT|BF_LEFT:
211 case BF_RIGHT|BF_LEFT|BF_TOP:
212 case BF_BOTTOM|BF_TOP:
213 case BF_BOTTOM|BF_TOP|BF_LEFT:
214 case BF_BOTTOMRIGHT|BF_LEFT:
215 case BF_BOTTOMRIGHT|BF_TOP:
216 case BF_RECT:
217 /* Right top endpoint */
218 spx = rc->left;
219 epx = spx + SmallDiam;
220 spy = rc->bottom-1;
221 epy = spy - SmallDiam;
222 epx--;
223 epy++;
224 break;
225 }
226
227 MoveToEx(hdc, spx, spy, NULL);
228 SelectObject(hdc, OuterPen);
229 LineTo(hdc, epx, epy);
230
231 SelectObject(hdc, InnerPen);
232
233 switch(uFlags & (BF_RECT|BF_DIAGONAL))
234 {
235 case BF_DIAGONAL_ENDBOTTOMLEFT:
236 case (BF_DIAGONAL|BF_BOTTOM):
237 case BF_DIAGONAL:
238 case (BF_DIAGONAL|BF_LEFT):
239 MoveToEx(hdc, spx-1, spy, NULL);
240 LineTo(hdc, epx, epy-1);
241 Points[0].x = spx-add;
242 Points[0].y = spy;
243 Points[1].x = rc->left;
244 Points[1].y = rc->top;
245 Points[2].x = epx+1;
246 Points[2].y = epy-1-add;
247 Points[3] = Points[2];
248 break;
249
250 case BF_DIAGONAL_ENDBOTTOMRIGHT:
251 MoveToEx(hdc, spx-1, spy, NULL);
252 LineTo(hdc, epx, epy+1);
253 Points[0].x = spx-add;
254 Points[0].y = spy;
255 Points[1].x = rc->left;
256 Points[1].y = rc->bottom-1;
257 Points[2].x = epx+1;
258 Points[2].y = epy+1+add;
259 Points[3] = Points[2];
260 break;
261
262 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
263 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
264 case BF_DIAGONAL_ENDTOPRIGHT:
265 case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
266 MoveToEx(hdc, spx+1, spy, NULL);
267 LineTo(hdc, epx, epy+1);
268 Points[0].x = epx-1;
269 Points[0].y = epy+1+add;
270 Points[1].x = rc->right-1;
271 Points[1].y = rc->top+add;
272 Points[2].x = rc->right-1;
273 Points[2].y = rc->bottom-1;
274 Points[3].x = spx+add;
275 Points[3].y = spy;
276 break;
277
278 case BF_DIAGONAL_ENDTOPLEFT:
279 MoveToEx(hdc, spx, spy-1, NULL);
280 LineTo(hdc, epx+1, epy);
281 Points[0].x = epx+1+add;
282 Points[0].y = epy+1;
283 Points[1].x = rc->right-1;
284 Points[1].y = rc->top;
285 Points[2].x = rc->right-1;
286 Points[2].y = rc->bottom-1-add;
287 Points[3].x = spx;
288 Points[3].y = spy-add;
289 break;
290
291 case (BF_DIAGONAL|BF_TOP):
292 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
293 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
294 MoveToEx(hdc, spx+1, spy-1, NULL);
295 LineTo(hdc, epx, epy);
296 Points[0].x = epx-1;
297 Points[0].y = epy+1;
298 Points[1].x = rc->right-1;
299 Points[1].y = rc->top;
300 Points[2].x = rc->right-1;
301 Points[2].y = rc->bottom-1-add;
302 Points[3].x = spx+add;
303 Points[3].y = spy-add;
304 break;
305
306 case (BF_DIAGONAL|BF_RIGHT):
307 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
308 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
309 MoveToEx(hdc, spx, spy, NULL);
310 LineTo(hdc, epx-1, epy+1);
311 Points[0].x = spx;
312 Points[0].y = spy;
313 Points[1].x = rc->left;
314 Points[1].y = rc->top+add;
315 Points[2].x = epx-1-add;
316 Points[2].y = epy+1+add;
317 Points[3] = Points[2];
318 break;
319 }
320
321 /* Fill the interior if asked */
322 if((uFlags & BF_MIDDLE) && retval)
323 {
324 HBRUSH hbsave;
325 HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW
326 :COLOR_BTNFACE);
327 HPEN hpsave;
328 HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW
329 : COLOR_BTNFACE);
330 hbsave = (HBRUSH)SelectObject(hdc, hb);
331 hpsave = (HPEN)SelectObject(hdc, hp);
332 Polygon(hdc, Points, 4);
333 SelectObject(hdc, hbsave);
334 SelectObject(hdc, hpsave);
335 }
336
337 /* Adjust rectangle if asked */
338 if(uFlags & BF_ADJUST)
339 {
340 if(uFlags & BF_LEFT) rc->left += add;
341 if(uFlags & BF_RIGHT) rc->right -= add;
342 if(uFlags & BF_TOP) rc->top += add;
343 if(uFlags & BF_BOTTOM) rc->bottom -= add;
344 }
345
346 /* Cleanup */
347 SelectObject(hdc, SavePen);
348 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
349
350 return retval;
351}
352
353/***********************************************************************
354 * UITOOLS_DrawRectEdge
355 *
356 * Same as DrawEdge invoked without BF_DIAGONAL
357 *
358 * 23-Nov-1997: Changed by Bertho Stultiens
359 * 25-June-1999: Changed by Christoph Bratschi
360 *
361 * Attention: only draw in the rect's range!
362 * left to right-1
363 * top to bottom-1
364 *
365 * Well, I started testing this and found out that there are a few things
366 * that weren't quite as win95. The following rewrite should reproduce
367 * win95 results completely.
368 * The colorselection is table-driven to avoid awfull if-statements.
369 * The table below show the color settings.
370 *
371 * Pen selection table for uFlags = 0
372 *
373 * uType | LTI | LTO | RBI | RBO
374 * ------+-------+-------+-------+-------
375 * 0000 | x | x | x | x
376 * 0001 | x | 22 | x | 21
377 * 0010 | x | 16 | x | 20
378 * 0011 | x | x | x | x
379 * ------+-------+-------+-------+-------
380 * 0100 | x | 20 | x | 16
381 * 0101 | 20 | 22 | 16 | 21
382 * 0110 | 20 | 16 | 16 | 20
383 * 0111 | x | x | x | x
384 * ------+-------+-------+-------+-------
385 * 1000 | x | 21 | x | 22
386 * 1001 | 21 | 22 | 22 | 21
387 * 1010 | 21 | 16 | 22 | 20
388 * 1011 | x | x | x | x
389 * ------+-------+-------+-------+-------
390 * 1100 | x | x | x | x
391 * 1101 | x | x (22)| x | x (21)
392 * 1110 | x | x (16)| x | x (20)
393 * 1111 | x | x | x | x
394 *
395 * Pen selection table for uFlags = BF_SOFT
396 *
397 * uType | LTI | LTO | RBI | RBO
398 * ------+-------+-------+-------+-------
399 * 0000 | x | x | x | x
400 * 0001 | x | 20 | x | 21
401 * 0010 | x | 21 | x | 20
402 * 0011 | x | x | x | x
403 * ------+-------+-------+-------+-------
404 * 0100 | x | 22 | x | 16
405 * 0101 | 22 | 20 | 16 | 21
406 * 0110 | 22 | 21 | 16 | 20
407 * 0111 | x | x | x | x
408 * ------+-------+-------+-------+-------
409 * 1000 | x | 16 | x | 22
410 * 1001 | 16 | 20 | 22 | 21
411 * 1010 | 16 | 21 | 22 | 20
412 * 1011 | x | x | x | x
413 * ------+-------+-------+-------+-------
414 * 1100 | x | x | x | x
415 * 1101 | x | x (20)| x | x (21)
416 * 1110 | x | x (21)| x | x (20)
417 * 1111 | x | x | x | x
418 *
419 * x = don't care; (n) = is what win95 actually uses
420 * LTI = left Top Inner line
421 * LTO = left Top Outer line
422 * RBI = Right Bottom Inner line
423 * RBO = Right Bottom Outer line
424 * 15 = COLOR_BTNFACE
425 * 16 = COLOR_BTNSHADOW
426 * 20 = COLOR_BTNHIGHLIGHT
427 * 21 = COLOR_3DDKSHADOW
428 * 22 = COLOR_3DLIGHT
429 */
430
431
432static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc,
433 UINT uType, UINT uFlags)
434{
435 char LTInnerI, LTOuterI;
436 char RBInnerI, RBOuterI;
437 HPEN LTInnerPen, LTOuterPen;
438 HPEN RBInnerPen, RBOuterPen;
439 RECT InnerRect = *rc;
440 POINT SavePoint;
441 HPEN SavePen;
442 int LBpenplus = 0;
443 int LTpenplus = 0;
444 int RTpenplus = 0;
445 int RBpenplus = 0;
446 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
447 || (uType & BDR_OUTER) == BDR_OUTER)
448 && !(uFlags & (BF_FLAT|BF_MONO)) );
449
450 if (IsRectEmpty(rc)) return retval; //nothing to do
451
452 /* Init some vars */
453 LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
454 SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
455
456 /* Determine the colors of the edges */
457 if(uFlags & BF_MONO)
458 {
459 LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
460 LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
461 }
462 else if(uFlags & BF_FLAT)
463 {
464 LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
465 LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
466
467 /* Bertho Stultiens states above that this function exactly matches win95
468 * In win98 BF_FLAT rectangels have an inner border same color as the
469 * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
470 * I don't know I go with Bertho and just sets it for win98 until proven
471 * otherwise.
472 * Dennis Björklund, 10 June, 99
473 */
474 if(LTInnerI != -1 )
475 LTInnerI = RBInnerI = COLOR_BTNFACE;
476 }
477 else if(uFlags & BF_SOFT)
478 {
479 LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
480 LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
481 RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
482 RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
483 }
484 else
485 {
486 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
487 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
488 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
489 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
490 }
491
492 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) LBpenplus = 1;
493 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) RTpenplus = 1;
494 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
495 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) LTpenplus = 1;
496
497 if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI);
498 if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI);
499 if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI);
500 if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI);
501
502 MoveToEx(hdc, 0, 0, &SavePoint);
503
504 /* Draw the outer edge */
505 SelectObject(hdc, LTOuterPen);
506 if(uFlags & BF_TOP)
507 {
508 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
509 LineTo(hdc, InnerRect.right-1, InnerRect.top);
510 }
511 if(uFlags & BF_LEFT)
512 {
513 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
514 LineTo(hdc, InnerRect.left, InnerRect.bottom-1);
515 }
516
517 SelectObject(hdc, RBOuterPen);
518 if(uFlags & BF_BOTTOM)
519 {
520 MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
521 LineTo(hdc, InnerRect.left, InnerRect.bottom-1);
522 }
523 if(uFlags & BF_RIGHT)
524 {
525 MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
526 LineTo(hdc, InnerRect.right-1, InnerRect.top);
527 }
528
529 /* Draw the inner edge */
530 SelectObject(hdc, LTInnerPen);
531 if(uFlags & BF_TOP)
532 {
533 MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
534 LineTo(hdc, InnerRect.right-RTpenplus-1, InnerRect.top+1);
535 }
536 if(uFlags & BF_LEFT)
537 {
538 MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
539 LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus-1);
540 }
541 SelectObject(hdc, RBInnerPen);
542 if(uFlags & BF_BOTTOM)
543 {
544 MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL);
545 LineTo(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2);
546 }
547 if(uFlags & BF_RIGHT)
548 {
549 MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL);
550 LineTo(hdc, InnerRect.right-2, InnerRect.top+RTpenplus);
551 }
552
553 if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
554 {
555 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
556 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
557
558 if(uFlags & BF_LEFT) InnerRect.left += add;
559 if(uFlags & BF_RIGHT) InnerRect.right -= add;
560 if(uFlags & BF_TOP) InnerRect.top += add;
561 if(uFlags & BF_BOTTOM) InnerRect.bottom -= add;
562
563 if((uFlags & BF_MIDDLE) && retval)
564 {
565 FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ?
566 COLOR_WINDOW : COLOR_BTNFACE));
567 }
568
569 if(uFlags & BF_ADJUST)
570 *rc = InnerRect;
571 }
572
573 /* Cleanup */
574 SelectObject(hdc, SavePen);
575 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
576 return retval;
577}
578
579
580//**********************************************************************
581// DrawEdge (USER32.155)
582//
583BOOL WIN32API DrawEdge(HDC hdc, LPRECT rc, UINT edge, UINT flags)
584{
585
586 if (flags & BF_DIAGONAL)
587 return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags);
588 else
589 return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags);
590}
591
592/************************************************************************
593 * UITOOLS_MakeSquareRect
594 *
595 * Utility to create a square rectangle and returning the width
596 */
597static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
598{
599 int Width = src->right - src->left;
600 int Height = src->bottom - src->top;
601 int SmallDiam = Width > Height ? Height : Width;
602
603 *dst = *src;
604
605 /* Make it a square box */
606 if(Width < Height) /* SmallDiam == Width */
607 {
608 dst->top += (Height-Width)/2;
609 dst->bottom = dst->top + SmallDiam;
610 }
611 else if(Width > Height) /* SmallDiam == Height */
612 {
613 dst->left += (Width-Height)/2;
614 dst->right = dst->left + SmallDiam;
615 }
616
617 return SmallDiam;
618}
619
620
621static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
622{
623 if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
624 {
625 HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55);
626 HBRUSH hbsave;
627 HBRUSH hb = CreatePatternBrush(hbm);
628 COLORREF bg;
629
630 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
631 bg = SetBkColor(dc, RGB(255, 255, 255));
632 hbsave = (HBRUSH)SelectObject(dc, hb);
633 PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
634 SelectObject(dc, hbsave);
635 SetBkColor(dc, bg);
636 DeleteObject(hb);
637 DeleteObject(hbm);
638 }
639 else
640 {
641 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
642 }
643}
644
645/************************************************************************
646 * UITOOLS_DFC_ButtonPush
647 *
648 * Draw a push button coming from DrawFrameControl()
649 *
650 * Does a pretty good job in emulating MS behavior. Some quirks are
651 * however there because MS uses a TrueType font (Marlett) to draw
652 * the buttons.
653 */
654static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
655{
656 UINT edge;
657 RECT myr = *r;
658
659 if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
660 edge = EDGE_SUNKEN;
661 else
662 edge = EDGE_RAISED;
663
664 if(uFlags & DFCS_CHECKED)
665 {
666 if(uFlags & DFCS_MONO)
667 UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
668 else
669 UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
670
671 UITOOLS_DrawCheckedRect( dc, &myr );
672 }
673 else
674 {
675 if(uFlags & DFCS_MONO)
676 {
677 UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
678 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
679 }
680 else
681 {
682 UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE |BF_SOFT| BF_RECT);
683 }
684 }
685
686 /* Adjust rectangle if asked */
687 if(uFlags & DFCS_ADJUSTRECT)
688 {
689 r->left += 2;
690 r->right -= 2;
691 r->top += 2;
692 r->bottom -= 2;
693 }
694
695 return TRUE;
696}
697
698
699/************************************************************************
700 * UITOOLS_DFC_ButtonCheck
701 *
702 * Draw a check/3state button coming from DrawFrameControl()
703 *
704 * Does a pretty good job in emulating MS behavior. Some quirks are
705 * however there because MS uses a TrueType font (Marlett) to draw
706 * the buttons.
707 */
708#define DFC_CHECKPOINTSMAX 6
709
710static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags)
711{
712 RECT myr;
713 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
714 UINT flags = BF_RECT | BF_ADJUST;
715
716 if(uFlags & DFCS_FLAT) flags |= BF_FLAT;
717 else if(uFlags & DFCS_MONO) flags |= BF_MONO;
718
719 UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags );
720
721 if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED))
722 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
723 else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) )
724 UITOOLS_DrawCheckedRect( dc, &myr );
725 else
726 {
727 FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW));
728 }
729
730 if(uFlags & DFCS_CHECKED)
731 {
732 POINT CheckPoints[DFC_CHECKPOINTSMAX];
733 int i;
734 HBRUSH hbsave;
735 HPEN hpsave;
736
737 /* FIXME: This comes very close to M$'s checkmark, but not */
738 /* exactly... When small or large there is a few pixels */
739 /* shift. Not bad, but could be better :) */
740 UITOOLS_MakeSquareRect(r, &myr);
741 CheckPoints[0].x = myr.left + 253*SmallDiam/1000;
742 CheckPoints[0].y = myr.top + 345*SmallDiam/1000;
743 CheckPoints[1].x = myr.left + 409*SmallDiam/1000;
744 CheckPoints[1].y = CheckPoints[0].y + (CheckPoints[1].x-CheckPoints[0].x);
745 CheckPoints[2].x = myr.left + 690*SmallDiam/1000;
746 CheckPoints[2].y = CheckPoints[1].y - (CheckPoints[2].x-CheckPoints[1].x);
747 CheckPoints[3].x = CheckPoints[2].x;
748 CheckPoints[3].y = CheckPoints[2].y + 3*SmallDiam/16;
749 CheckPoints[4].x = CheckPoints[1].x;
750 CheckPoints[4].y = CheckPoints[1].y + 3*SmallDiam/16;
751 CheckPoints[5].x = CheckPoints[0].x;
752 CheckPoints[5].y = CheckPoints[0].y + 3*SmallDiam/16;
753
754 i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
755 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
756 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
757 Polygon(dc, CheckPoints, DFC_CHECKPOINTSMAX);
758 SelectObject(dc, hpsave);
759 SelectObject(dc, hbsave);
760 }
761 return TRUE;
762}
763
764
765/************************************************************************
766 * UITOOLS_DFC_ButtonRadio
767 *
768 * Draw a radio/radioimage/radiomask button coming from DrawFrameControl()
769 *
770 * Does a pretty good job in emulating MS behavior. Some quirks are
771 * however there because MS uses a TrueType font (Marlett) to draw
772 * the buttons.
773 */
774static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags)
775{
776 RECT myr;
777 int i;
778 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
779 int BorderShrink = SmallDiam / 16;
780 HPEN hpsave;
781 HBRUSH hbsave;
782 int xe, ye;
783 int xc, yc;
784
785 if(BorderShrink < 1) BorderShrink = 1;
786
787 if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE)
788 {
789 FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH));
790 }
791
792 xe = myr.left;
793 ye = myr.top + SmallDiam - SmallDiam/2;
794
795 xc = myr.left + SmallDiam - SmallDiam/2;
796 yc = myr.top + SmallDiam - SmallDiam/2;
797
798 /* Define bounding box */
799 i = 14*SmallDiam/16;
800 myr.left = xc - i+i/2;
801 myr.right = xc + i/2;
802 myr.top = yc - i+i/2;
803 myr.bottom = yc + i/2;
804
805 if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK)
806 {
807 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
808 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
809 SelectObject(dc, hbsave);
810 }
811 else
812 {
813 if(uFlags & (DFCS_FLAT|DFCS_MONO))
814 {
815 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME));
816 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME));
817 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
818 SelectObject(dc, hbsave);
819 SelectObject(dc, hpsave);
820 }
821 else
822 {
823 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
824 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
825 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
826
827 SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW));
828 SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW));
829 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
830
831 myr.left += BorderShrink;
832 myr.right -= BorderShrink;
833 myr.top += BorderShrink;
834 myr.bottom -= BorderShrink;
835
836 SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT));
837 SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT));
838 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
839
840 SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW));
841 SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW));
842 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
843 SelectObject(dc, hbsave);
844 SelectObject(dc, hpsave);
845 }
846
847 i = 10*SmallDiam/16;
848 myr.left = xc - i+i/2;
849 myr.right = xc + i/2;
850 myr.top = yc - i+i/2;
851 myr.bottom = yc + i/2;
852 i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
853 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
854 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
855 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
856 SelectObject(dc, hbsave);
857 SelectObject(dc, hpsave);
858 }
859
860 if(uFlags & DFCS_CHECKED)
861 {
862 i = 6*SmallDiam/16;
863 i = i < 1 ? 1 : i;
864 myr.left = xc - i+i/2;
865 myr.right = xc + i/2;
866 myr.top = yc - i+i/2;
867 myr.bottom = yc + i/2;
868
869 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
870 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
871 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
872 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
873 SelectObject(dc, hpsave);
874 SelectObject(dc, hbsave);
875 }
876
877 /* FIXME: M$ has a polygon in the center at relative points: */
878 /* 0.476, 0.476 (times SmallDiam, SmallDiam) */
879 /* 0.476, 0.525 */
880 /* 0.500, 0.500 */
881 /* 0.500, 0.499 */
882 /* when the button is unchecked. The reason for it is unknown. The */
883 /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */
884 /* least 3 times (it looks like a clip-region when you see it happen). */
885 /* I do not really see a reason why this should be implemented. If you */
886 /* have a good reason, let me know. Maybe this is a quirk in the Marlett */
887 /* font. */
888
889 return TRUE;
890}
891
892/***********************************************************************
893 * UITOOLS_DrawFrameButton
894 */
895static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
896{
897 switch(uState & 0xff)
898 {
899 case DFCS_BUTTONPUSH:
900 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
901
902 case DFCS_BUTTONCHECK:
903 case DFCS_BUTTON3STATE:
904 return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState);
905
906 case DFCS_BUTTONRADIOIMAGE:
907 case DFCS_BUTTONRADIOMASK:
908 case DFCS_BUTTONRADIO:
909 return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState);
910
911// default:
912// WARN("Invalid button state=0x%04x\n", uState);
913 }
914
915 return FALSE;
916}
917
918/***********************************************************************
919 * UITOOLS_DrawFrameCaption
920 *
921 * Draw caption buttons (win95), coming from DrawFrameControl()
922 */
923
924static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
925{
926 POINT Line1[10];
927 POINT Line2[10];
928 int Line1N;
929 int Line2N;
930 RECT myr;
931 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
932 int i;
933 HBRUSH hbsave;
934 HPEN hpsave;
935 HFONT hfsave, hf;
936 int xc = (myr.left+myr.right)/2;
937 int yc = (myr.top+myr.bottom)/2;
938 int edge, move;
939 char str[2] = "?";
940 UINT alignsave;
941 int bksave;
942 COLORREF clrsave;
943 SIZE size;
944
945 UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00);
946
947 switch(uFlags & 0xff)
948 {
949 case DFCS_CAPTIONCLOSE:
950 edge = 328*SmallDiam/1000;
951 move = 95*SmallDiam/1000;
952 Line1[0].x = Line2[0].x = Line1[1].x = Line2[1].x = xc - edge;
953 Line1[2].y = Line2[5].y = Line1[1].y = Line2[4].y = yc - edge;
954 Line1[3].x = Line2[3].x = Line1[4].x = Line2[4].x = xc + edge;
955 Line1[5].y = Line2[2].y = Line1[4].y = Line2[1].y = yc + edge;
956 Line1[2].x = Line2[2].x = Line1[1].x + move;
957 Line1[0].y = Line2[3].y = Line1[1].y + move;
958 Line1[5].x = Line2[5].x = Line1[4].x - move;
959 Line1[3].y = Line2[0].y = Line1[4].y - move;
960 Line1N = 6;
961 Line2N = 6;
962 break;
963
964 case DFCS_CAPTIONHELP:
965 /* This one breaks the flow */
966 /* FIXME: We need the Marlett font in order to get this right. */
967
968 hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
969 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
970 DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System");
971 alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT);
972 bksave = SetBkMode(dc, TRANSPARENT);
973 clrsave = GetTextColor(dc);
974 hfsave = (HFONT)SelectObject(dc, hf);
975 GetTextExtentPoint32A(dc, str, 1, &size);
976
977 if(uFlags & DFCS_INACTIVE)
978 {
979 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
980 TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1);
981 }
982 SetTextColor(dc, GetSysColor(uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
983 TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1);
984
985 SelectObject(dc, hfsave);
986 SetTextColor(dc, clrsave);
987 SetBkMode(dc, bksave);
988 SetTextAlign(dc, alignsave);
989 DeleteObject(hf);
990 return TRUE;
991
992 case DFCS_CAPTIONMIN:
993 Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+2;
994 Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
995 Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1;
996 Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750;
997 Line1N = 4;
998 Line2N = 0;
999 break;
1000
1001 case DFCS_CAPTIONMAX:
1002 edge = 47*SmallDiam/750;
1003 Line1[0].x = Line1[5].x = myr.left + 57*SmallDiam/750+3;
1004 Line1[0].y = Line1[1].y = myr.top + 143*SmallDiam/750+1;
1005 Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750;
1006 Line1[5].y = Line1[4].y = Line1[0].y + 93*SmallDiam/750;
1007 Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750;
1008 Line1[3].x = Line1[4].x = Line1[1].x - edge;
1009
1010 Line2[0].x = Line2[5].x = Line1[0].x;
1011 Line2[3].x = Line2[4].x = Line1[1].x;
1012 Line2[1].x = Line2[2].x = Line1[0].x + edge;
1013 Line2[0].y = Line2[1].y = Line1[0].y;
1014 Line2[4].y = Line2[5].y = Line1[2].y;
1015 Line2[2].y = Line2[3].y = Line1[2].y - edge;
1016 Line1N = 6;
1017 Line2N = 6;
1018 break;
1019
1020 case DFCS_CAPTIONRESTORE:
1021 /* FIXME: this one looks bad at small sizes < 15x15 :( */
1022 edge = 47*SmallDiam/750;
1023 move = 420*SmallDiam/750;
1024 Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2;
1025 Line1[0].y = Line1[1].y = myr.top + 169*SmallDiam/750+1;
1026 Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750;
1027 Line1[7].x = Line1[8].x = Line1[0].x + edge;
1028 Line1[1].x = Line1[2].x = Line1[0].x + move;
1029 Line1[5].x = Line1[6].x = Line1[1].x - edge;
1030 Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750;
1031 Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750;
1032 Line1[4].y = Line1[5].y = Line1[2].y - edge;
1033 Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750;
1034
1035 Line2[1].x = Line2[2].x = Line1[3].x;
1036 Line2[7].x = Line2[8].x = Line2[1].x - edge;
1037 Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move;
1038 Line2[5].x = Line2[6].x = Line2[0].x + edge;
1039 Line2[0].y = Line2[1].y = Line1[9].y;
1040 Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750;
1041 Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750;
1042 Line2[6].y = Line2[7].y = Line2[2].y - edge;
1043 Line1N = 10;
1044 Line2N = 10;
1045 break;
1046
1047 default:
1048// WARN("Invalid caption; flags=0x%04x\n", uFlags);
1049 return FALSE;
1050 }
1051
1052 /* Here the drawing takes place */
1053 if(uFlags & DFCS_INACTIVE)
1054 {
1055 /* If we have an inactive button, then you see a shadow */
1056 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1057 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1058 Polygon(dc, Line1, Line1N);
1059 if(Line2N > 0)
1060 Polygon(dc, Line2, Line2N);
1061 SelectObject(dc, hpsave);
1062 SelectObject(dc, hbsave);
1063 }
1064
1065 /* Correct for the shadow shift */
1066 for(i = 0; i < Line1N; i++)
1067 {
1068 Line1[i].x--;
1069 Line1[i].y--;
1070 }
1071 for(i = 0; i < Line2N; i++)
1072 {
1073 Line2[i].x--;
1074 Line2[i].y--;
1075 }
1076
1077 /* Make the final picture */
1078 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
1079 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
1080 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
1081
1082 Polygon(dc, Line1, Line1N);
1083 if(Line2N > 0)
1084 Polygon(dc, Line2, Line2N);
1085 SelectObject(dc, hpsave);
1086 SelectObject(dc, hbsave);
1087
1088 return TRUE;
1089}
1090
1091
1092/************************************************************************
1093 * UITOOLS_DrawFrameScroll
1094 *
1095 * Draw a scroll-bar control coming from DrawFrameControl()
1096 */
1097static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
1098{
1099 POINT Line[4];
1100 RECT myr;
1101 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2;
1102 int i;
1103 HBRUSH hbsave, hb, hb2;
1104 HPEN hpsave, hp, hp2;
1105 int tri = 290*SmallDiam/1000 -1;
1106 int d46, d93;
1107
1108 /*
1109 * This fixes a problem with really tiny "scroll" buttons. In particular
1110 * with the updown control.
1111 * Making sure that the arrow is as least 3 pixels wide (or high).
1112 */
1113 if (tri == 0)
1114 tri = 1;
1115
1116 switch(uFlags & 0xff)
1117 {
1118 case DFCS_SCROLLCOMBOBOX:
1119 case DFCS_SCROLLDOWN:
1120 Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1121 Line[2].y = myr.top + 687*SmallDiam/1000 + 1;
1122 Line[0].x = Line[2].x - tri;
1123 Line[1].x = Line[2].x + tri;
1124 Line[0].y = Line[1].y = Line[2].y - tri;
1125 break;
1126
1127 case DFCS_SCROLLUP:
1128 Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1129 Line[2].y = myr.bottom - 687*SmallDiam/1000 + 1;
1130 Line[0].x = Line[2].x - tri;
1131 Line[1].x = Line[2].x + tri;
1132 Line[0].y = Line[1].y = Line[2].y + tri;
1133 break;
1134
1135 case DFCS_SCROLLLEFT:
1136 Line[2].x = myr.right - 687*SmallDiam/1000 + 1;
1137 Line[2].y = myr.top + 470*SmallDiam/1000 + 2;
1138 Line[0].y = Line[2].y - tri;
1139 Line[1].y = Line[2].y + tri;
1140 Line[0].x = Line[1].x = Line[2].x + tri;
1141 break;
1142
1143 case DFCS_SCROLLRIGHT:
1144 Line[2].x = myr.left + 687*SmallDiam/1000 + 1;
1145 Line[2].y = myr.top + 470*SmallDiam/1000 + 2;
1146 Line[0].y = Line[2].y - tri;
1147 Line[1].y = Line[2].y + tri;
1148 Line[0].x = Line[1].x = Line[2].x - tri;
1149 break;
1150
1151 case DFCS_SCROLLSIZEGRIP:
1152 /* This one breaks the flow... */
1153 UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0));
1154 hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN));
1155 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));
1156 if(uFlags & (DFCS_MONO|DFCS_FLAT))
1157 {
1158 hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME);
1159 hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME);
1160 }
1161 else
1162 {
1163 hp = GetSysColorPen(COLOR_BTNHIGHLIGHT);
1164 hp2 = GetSysColorPen(COLOR_BTNSHADOW);
1165 hb = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
1166 hb2 = GetSysColorBrush(COLOR_BTNSHADOW);
1167 }
1168 Line[0].x = Line[1].x = r->right-1;
1169 Line[2].y = Line[3].y = r->bottom-1;
1170 d46 = 46*SmallDiam/750;
1171 d93 = 93*SmallDiam/750;
1172
1173 i = 586*SmallDiam/750;
1174 Line[0].y = r->bottom - i - 1;
1175 Line[3].x = r->right - i - 1;
1176 Line[1].y = Line[0].y + d46;
1177 Line[2].x = Line[3].x + d46;
1178 SelectObject(dc, hb);
1179 SelectObject(dc, hp);
1180 Polygon(dc, Line, 4);
1181
1182 Line[1].y++; Line[2].x++;
1183 Line[0].y = Line[1].y + d93;
1184 Line[3].x = Line[2].x + d93;
1185 SelectObject(dc, hb2);
1186 SelectObject(dc, hp2);
1187 Polygon(dc, Line, 4);
1188
1189 i = 398*SmallDiam/750;
1190 Line[0].y = r->bottom - i - 1;
1191 Line[3].x = r->right - i - 1;
1192 Line[1].y = Line[0].y + d46;
1193 Line[2].x = Line[3].x + d46;
1194 SelectObject(dc, hb);
1195 SelectObject(dc, hp);
1196 Polygon(dc, Line, 4);
1197
1198 Line[1].y++; Line[2].x++;
1199 Line[0].y = Line[1].y + d93;
1200 Line[3].x = Line[2].x + d93;
1201 SelectObject(dc, hb2);
1202 SelectObject(dc, hp2);
1203 Polygon(dc, Line, 4);
1204
1205 i = 210*SmallDiam/750;
1206 Line[0].y = r->bottom - i - 1;
1207 Line[3].x = r->right - i - 1;
1208 Line[1].y = Line[0].y + d46;
1209 Line[2].x = Line[3].x + d46;
1210 SelectObject(dc, hb);
1211 SelectObject(dc, hp);
1212 Polygon(dc, Line, 4);
1213
1214 Line[1].y++; Line[2].x++;
1215 Line[0].y = Line[1].y + d93;
1216 Line[3].x = Line[2].x + d93;
1217 SelectObject(dc, hb2);
1218 SelectObject(dc, hp2);
1219 Polygon(dc, Line, 4);
1220
1221 SelectObject(dc, hpsave);
1222 SelectObject(dc, hbsave);
1223 return TRUE;
1224
1225 default:
1226// WARN("Invalid scroll; flags=0x%04x\n", uFlags);
1227 return FALSE;
1228 }
1229
1230 /* Here do the real scroll-bar controls end up */
1231 if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) )
1232 /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */
1233 /* want for the normal scroll-arrow button. */
1234 UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT);
1235 else
1236 UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) );
1237
1238 if(uFlags & DFCS_INACTIVE)
1239 {
1240 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1241 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1242 Polygon(dc, Line, 3);
1243 SelectObject(dc, hpsave);
1244 SelectObject(dc, hbsave);
1245 }
1246
1247 if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) )
1248 for(i = 0; i < 3; i++)
1249 {
1250 Line[i].x--;
1251 Line[i].y--;
1252 }
1253
1254 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
1255 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
1256 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
1257 Polygon(dc, Line, 3);
1258 SelectObject(dc, hpsave);
1259 SelectObject(dc, hbsave);
1260
1261 return TRUE;
1262}
1263
1264/************************************************************************
1265 * UITOOLS_DrawFrameMenu
1266 *
1267 * Draw a menu control coming from DrawFrameControl()
1268 */
1269static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
1270{
1271 POINT Points[6];
1272 RECT myr;
1273 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
1274 int i;
1275 HBRUSH hbsave;
1276 HPEN hpsave;
1277 int xe, ye;
1278 int xc, yc;
1279 BOOL retval = TRUE;
1280
1281 /* Using black and white seems to be utterly wrong, but win95 doesn't */
1282 /* use anything else. I think I tried all sys-colors to change things */
1283 /* without luck. It seems as if this behavior is inherited from the */
1284 /* win31 DFC() implementation... (you remember, B/W menus). */
1285
1286 FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH));
1287
1288 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
1289 hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN));
1290
1291 switch(uFlags & 0xff)
1292 {
1293 case DFCS_MENUARROW:
1294 i = 187*SmallDiam/750;
1295 Points[2].x = myr.left + 468*SmallDiam/750;
1296 Points[2].y = myr.top + 352*SmallDiam/750+1;
1297 Points[0].y = Points[2].y - i;
1298 Points[1].y = Points[2].y + i;
1299 Points[0].x = Points[1].x = Points[2].x - i;
1300 Polygon(dc, Points, 3);
1301 break;
1302
1303 case DFCS_MENUBULLET:
1304 xe = myr.left;
1305 ye = myr.top + SmallDiam - SmallDiam/2;
1306 xc = myr.left + SmallDiam - SmallDiam/2;
1307 yc = myr.top + SmallDiam - SmallDiam/2;
1308 i = 234*SmallDiam/750;
1309 i = i < 1 ? 1 : i;
1310 myr.left = xc - i+i/2;
1311 myr.right = xc + i/2;
1312 myr.top = yc - i+i/2;
1313 myr.bottom = yc + i/2;
1314 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
1315 break;
1316
1317 case DFCS_MENUCHECK:
1318 Points[0].x = myr.left + 253*SmallDiam/1000;
1319 Points[0].y = myr.top + 445*SmallDiam/1000;
1320 Points[1].x = myr.left + 409*SmallDiam/1000;
1321 Points[1].y = Points[0].y + (Points[1].x-Points[0].x);
1322 Points[2].x = myr.left + 690*SmallDiam/1000;
1323 Points[2].y = Points[1].y - (Points[2].x-Points[1].x);
1324 Points[3].x = Points[2].x;
1325 Points[3].y = Points[2].y + 3*SmallDiam/16;
1326 Points[4].x = Points[1].x;
1327 Points[4].y = Points[1].y + 3*SmallDiam/16;
1328 Points[5].x = Points[0].x;
1329 Points[5].y = Points[0].y + 3*SmallDiam/16;
1330 Polygon(dc, Points, 6);
1331 break;
1332
1333 default:
1334// WARN("Invalid menu; flags=0x%04x\n", uFlags);
1335 retval = FALSE;
1336 break;
1337 }
1338
1339 SelectObject(dc, hpsave);
1340 SelectObject(dc, hbsave);
1341 return retval;
1342}
1343
1344/**********************************************************************
1345 * DrawFrameControl (USER32.158)
1346 */
1347BOOL WIN32API DrawFrameControl(HDC hdc, LPRECT rc, UINT uType,
1348 UINT uState )
1349{
1350 /* Win95 doesn't support drawing in other mapping modes */
1351 if(GetMapMode(hdc) != MM_TEXT)
1352 return FALSE;
1353
1354 switch(uType)
1355 {
1356 case DFC_BUTTON:
1357 return UITOOLS95_DrawFrameButton(hdc, rc, uState);
1358 case DFC_CAPTION:
1359 return UITOOLS95_DrawFrameCaption(hdc, rc, uState);
1360 case DFC_MENU:
1361 return UITOOLS95_DrawFrameMenu(hdc, rc, uState);
1362 case DFC_SCROLL:
1363 return UITOOLS95_DrawFrameScroll(hdc, rc, uState);
1364// default:
1365// WARN("(%x,%p,%d,%x), bad type!\n",
1366// hdc,rc,uType,uState );
1367 }
1368 return FALSE;
1369}
1370
1371
1372/*****************************************************************************
1373 * Name : int WIN32API DrawTextExA
1374 * Purpose : The DrawTextEx function draw the text in the rectangle
1375 * Parameters:
1376 * Variables :
1377 * Result : If the function succeeds, the return value is the height of the
1378 * text, otherwise zero.
1379 * Remark : TODO: Returned number of characters is always the entire string
1380 * since there is no way to know the real answer this way.
1381 * Status : PARTIALLY IMPLEMENTED AND TESTED
1382 *
1383 * Author : Rene Pronk [Thu, 1999/07/29 15:03]
1384 * Christoph Bratschi: implemented DT_END_ELLIPSIS (Header control)
1385 *****************************************************************************/
1386
1387int WIN32API DrawTextExA (HDC hdc, LPCSTR lpchText, int cchText, LPRECT lprc,
1388 UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) {
1389
1390 int result;
1391 UINT oldDTFormat;
1392
1393 dprintf(("USER32:DrawTextExA (%08xh,%s,%08xh,%08xh,%08xh,%08xh).\n",
1394 hdc, lpchText, cchText, lprc, dwDTFormat, lpDTParams));
1395
1396 if (lpDTParams != NULL) {
1397 // 'create' margins
1398 lprc->left += lpDTParams->iLeftMargin;
1399 lprc->right -= lpDTParams->iRightMargin;
1400
1401 // just assume all the text has been drawn
1402 if (cchText != -1)
1403 lpDTParams->uiLengthDrawn = cchText;
1404 else {
1405 // determine string length
1406 int size = 0;
1407 while ((BYTE) *(lpchText + size) != 0)
1408 size ++;
1409 lpDTParams->uiLengthDrawn = size;
1410 }
1411 }
1412
1413 oldDTFormat = dwDTFormat & ~(DT_END_ELLIPSIS | DT_PATH_ELLIPSIS | DT_MODIFYSTRING | DT_EXPANDTABS);
1414 if (dwDTFormat & DT_END_ELLIPSIS && lpchText && (cchText != 0))
1415 {
1416 int textWidth,width;
1417 RECT rect;
1418
1419 if (cchText == -1) cchText = lstrlenA(lpchText);
1420 SetRectEmpty(&rect);
1421 DrawTextA(hdc,lpchText,cchText,&rect,oldDTFormat | DT_CALCRECT);
1422 width = lprc->right-lprc->left;
1423 textWidth = rect.right-rect.left;
1424 if (textWidth > width && width > 0)
1425 {
1426 char* newText;
1427 int endWidth,newTextLen;
1428
1429 DrawTextA(hdc,"...",3,&rect,DT_CALCRECT | DT_SINGLELINE | DT_LEFT);
1430 endWidth = rect.right-rect.left;
1431 newText = (char*)malloc(cchText+3);
1432 lstrcpyA(newText,lpchText);
1433 newTextLen = cchText+1;
1434 do
1435 {
1436 newTextLen--;
1437 DrawTextA(hdc,newText,newTextLen,&rect,oldDTFormat | DT_CALCRECT);
1438 textWidth = rect.right-rect.left;
1439 } while (textWidth+endWidth > width && newTextLen > 1);
1440
1441 lstrcpyA(&newText[newTextLen],"...");
1442 result = DrawTextA(hdc,newText,-1,lprc,oldDTFormat);;
1443
1444 if (dwDTFormat & DT_MODIFYSTRING) lstrcpynA((LPSTR)lpchText,newText,cchText);
1445 free(newText);
1446 } else result = DrawTextA(hdc,lpchText,cchText,lprc,oldDTFormat);
1447 } else
1448 result = DrawTextA (hdc, lpchText, cchText, lprc, oldDTFormat);
1449
1450 if (lpDTParams != NULL) {
1451 // don't forget to restore the margins
1452 lprc->left -= lpDTParams->iLeftMargin;
1453 lprc->right += lpDTParams->iRightMargin;
1454 }
1455
1456 return result;
1457}
1458
1459
1460
1461/*****************************************************************************
1462 * Name : int WIN32API DrawTextExW
1463 * Purpose : The DrawTextEx function draw the text in the rectangle
1464 * Parameters:
1465 * Variables :
1466 * Result : If the function succeeds, the return value is the height of the
1467 * text, otherwise zero.
1468 * Remark : TODO: Returned number of characters is always the entire string
1469 * since there is no way to know the real answer this way.
1470 * Status : PARTIALLY IMPLEMENTED AND TESTED
1471 *
1472 * Author : Rene Pronk [Thu, 1999/07/29 15:03]
1473 *****************************************************************************/
1474
1475int WIN32API DrawTextExW (HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc,
1476 UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) {
1477
1478 char *astring = UnicodeToAsciiString((LPWSTR)lpchText);
1479 int rc;
1480
1481 dprintf(("USER32:DrawTextExW (%08xh,%s,%08xh,%08xh,%08xh,%08xh).\n",
1482 hdc, astring, cchText, lprc, dwDTFormat, lpDTParams));
1483
1484 rc = DrawTextExA (hdc, astring, cchText, lprc, dwDTFormat, lpDTParams);
1485 if (dwDTFormat & DT_MODIFYSTRING) AsciiToUnicode(astring,lpchText);
1486 FreeAsciiString(astring);
1487 return(rc);
1488}
1489
1490
1491/******************************************************************************
1492 *
1493 * This function is used by Paint_DrawState which is inturn used by both
1494 * DrawStateA and DrawStateW. The code is directly borrowed from Wine.
1495 *
1496 ******************************************************************************/
1497
1498static BOOL Paint_DrawStateJam(HDC hdc, UINT opcode,
1499 DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
1500 LPRECT rc, UINT dtflags, BOOL unicode)
1501{
1502 HDC memdc;
1503 HBITMAP hbmsave;
1504 BOOL retval;
1505 INT cx = rc->right - rc->left;
1506 INT cy = rc->bottom - rc->top;
1507
1508 switch(opcode)
1509 {
1510 case DST_TEXT:
1511 case DST_PREFIXTEXT:
1512 if(unicode)
1513 return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags);
1514 else
1515 return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags);
1516
1517 case DST_ICON:
1518 return DrawIcon(hdc, rc->left, rc->top, (HICON)lp);
1519
1520 case DST_BITMAP:
1521 memdc = CreateCompatibleDC(hdc);
1522 if(!memdc) return FALSE;
1523 hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp);
1524 if(!hbmsave)
1525 {
1526 DeleteDC(memdc);
1527 return FALSE;
1528 }
1529 retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY);
1530 SelectObject(memdc, hbmsave);
1531 DeleteDC(memdc);
1532 return retval;
1533
1534 case DST_COMPLEX:
1535 if(func)
1536 return func(hdc, lp, wp, cx, cy);
1537 else
1538 return FALSE;
1539 }
1540 return FALSE;
1541}
1542
1543
1544/******************************************************************************
1545 *
1546 * This function is used by both DrawStateA and DrawStateW. The code is directly
1547 * borrowed from Wine
1548 *
1549 ******************************************************************************/
1550BOOL Paint_DrawState (HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
1551 INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode)
1552{
1553 HBITMAP hbm, hbmsave;
1554 HFONT hfsave;
1555 HBRUSH hbsave;
1556 HDC memdc;
1557 RECT rc;
1558 UINT dtflags = DT_NOCLIP;
1559 COLORREF fg, bg;
1560 UINT opcode = flags & 0xf;
1561 INT len = wp;
1562 BOOL retval, tmp;
1563
1564 if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */
1565 {
1566 if(unicode)
1567 len = lstrlenW((LPWSTR)lp);
1568 else
1569 len = lstrlenA((LPSTR)lp);
1570 }
1571
1572 /* Find out what size the image has if not given by caller */
1573 if(!cx || !cy)
1574 {
1575 SIZE s;
1576 BITMAP bmp;
1577
1578 switch(opcode)
1579 {
1580 case DST_TEXT:
1581 case DST_PREFIXTEXT:
1582 if(unicode)
1583 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s);
1584 else
1585 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s);
1586 if(!retval) return FALSE;
1587 break;
1588
1589 case DST_ICON:
1590 /* Just assume the icon has the size given by GetSystemMetrics. This should be
1591 valid since both CreateIcon and LoadIcon can't create icons with different
1592 sizes. I wouldn't how else to get the size of the icon. RP
1593 */
1594 s.cx = GetSystemMetrics (SM_CXICON);
1595 s.cy = GetSystemMetrics (SM_CYICON);
1596 break;
1597
1598 case DST_BITMAP:
1599 retval = GetObjectA ((HBITMAP) lp, sizeof (BITMAP), &bmp);
1600 if(retval == 0) return FALSE;
1601 s.cx = bmp.bmWidth;
1602 s.cy = bmp.bmHeight;
1603 break;
1604
1605 case DST_COMPLEX: /* cx and cy must be set in this mode */
1606 return FALSE;
1607 }
1608
1609 if(!cx) cx = s.cx;
1610 if(!cy) cy = s.cy;
1611 }
1612
1613 rc.left = x;
1614 rc.top = y;
1615 rc.right = x + cx;
1616 rc.bottom = y + cy;
1617
1618 if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */
1619 dtflags |= DT_RIGHT;
1620 if(opcode == DST_TEXT)
1621 dtflags |= DT_NOPREFIX;
1622
1623 /* For DSS_NORMAL we just jam in the image and return */
1624 if((flags & 0x7ff0) == DSS_NORMAL)
1625 {
1626 return Paint_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode);
1627 }
1628
1629 /* For all other states we need to convert the image to B/W in a local bitmap */
1630 /* before it is displayed */
1631 fg = SetTextColor(hdc, RGB(0, 0, 0));
1632 bg = SetBkColor(hdc, RGB(255, 255, 255));
1633 hbm = (HBITMAP)NULL; hbmsave = (HBITMAP)NULL;
1634 memdc = (HDC)NULL; hbsave = (HBRUSH)NULL;
1635 retval = FALSE; /* assume failure */
1636
1637 /* From here on we must use "goto cleanup" when something goes wrong */
1638 hbm = CreateBitmap(cx, cy, 1, 1, NULL);
1639 if(!hbm) goto cleanup;
1640 memdc = CreateCompatibleDC(hdc);
1641 if(!memdc) goto cleanup;
1642 hbmsave = (HBITMAP)SelectObject(memdc, hbm);
1643 if(!hbmsave) goto cleanup;
1644 rc.left = rc.top = 0;
1645 rc.right = cx;
1646 rc.bottom = cy;
1647 if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup;
1648 SetBkColor(memdc, RGB(255, 255, 255));
1649 SetTextColor(memdc, RGB(0, 0, 0));
1650 hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
1651 if(!hfsave && (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)) goto cleanup;
1652 tmp = Paint_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode);
1653 if(hfsave) SelectObject(memdc, hfsave);
1654 if(!tmp) goto cleanup;
1655
1656 /* These states cause the image to be dithered */
1657 if(flags & (DSS_UNION|DSS_DISABLED))
1658 {
1659 WORD wPattern55AA[] = { 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa, 0x5555, 0xaaaa };
1660 HBITMAP hPattern55AABitmap = CreateBitmap( 8, 8, 1, 1, wPattern55AA );
1661 HBRUSH hPattern55AABrush = CreatePatternBrush(hPattern55AABitmap);
1662
1663 hbsave = (HBRUSH)SelectObject(memdc, hPattern55AABrush);
1664 if(!hbsave) goto cleanup;
1665 tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089);
1666 if(hbsave) SelectObject(memdc, hbsave);
1667 if(!tmp) goto cleanup;
1668 }
1669
1670 hbsave = (HBRUSH)SelectObject(hdc, hbr ? hbr : GetStockObject(WHITE_BRUSH));
1671 if(!hbsave) goto cleanup;
1672
1673 if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
1674
1675 /* DSS_DEFAULT makes the image boldface */
1676 if(flags & DSS_DEFAULT)
1677 {
1678 if(!BitBlt(hdc, x+1, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
1679 }
1680
1681 retval = TRUE; /* We succeeded */
1682
1683cleanup:
1684 SetTextColor(hdc, fg);
1685 SetBkColor(hdc, bg);
1686
1687 if(hbsave) SelectObject(hdc, hbsave);
1688 if(hbmsave) SelectObject(memdc, hbmsave);
1689 if(hbm) DeleteObject(hbm);
1690 if(memdc) DeleteDC(memdc);
1691
1692 return retval;
1693}
1694
1695
1696
1697/*****************************************************************************
1698 * Name : BOOL WIN32API DrawStateA
1699 * Purpose : Draws a bitmap, icon, text or complex object in one of the following
1700 * states: normal, disabled, union or mono
1701 * Parameters:
1702 * Variables :
1703 * Result : If the function succeeds, the return value is a handle of the
1704 * window station associated with the calling process.
1705 * If the function fails, the return value is NULL. This can occur
1706 * if the calling process is not an application written for Windows
1707 * NT. To get extended error information, call GetLastError.
1708 * Remark : Disabled doesn't look like the Windows implementation, but it does
1709 * look disabled.
1710 * Status : PARTIALLY IMPLEMENTED
1711 *
1712 * Author : Rene Pronk [Sun, 1999/07/25 21:27]
1713 *****************************************************************************/
1714
1715BOOL WIN32API DrawStateA(HDC hdc, HBRUSH hbc, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
1716 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
1717{
1718 dprintf(("USER32:DrawStateA (%08xh,%08xh,%08xh,%08xh,%08xh,%d,%d,%d,%d,%08x).\n",
1719 hdc, hbc, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags));
1720
1721 return Paint_DrawState (hdc, hbc, lpOutputFunc, lData, wData, x, y ,cx, cy, fuFlags, FALSE);
1722}
1723
1724
1725
1726/*****************************************************************************
1727 * Name : BOOL WIN32API DrawStateW
1728 * Purpose : Draws a bitmap, icon, text or complex object in one of the following
1729 * states: normal, disabled, union or mono
1730 * Parameters:
1731 * Variables :
1732 * Result : If the function succeeds, the return value is a handle of the
1733 * window station associated with the calling process.
1734 * If the function fails, the return value is NULL. This can occur
1735 * if the calling process is not an application written for Windows
1736 * NT. To get extended error information, call GetLastError.
1737 * Remark : Disabled doesn't look like the Windows implementation, but it does
1738 * look disabled.
1739 * Status : PARTIALLY IMPLEMENTED
1740 *
1741 * Author : Rene Pronk [Sun, 1999/07/25 21:27]
1742 *****************************************************************************/
1743
1744BOOL WIN32API DrawStateW(HDC hdc, HBRUSH hbc, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
1745 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
1746{
1747 dprintf(("USER32:DrawStateW (%08xh,%08xh,%08xh,%08xh,%08xh,%d,%d,%d,%d,%08x).\n",
1748 hdc, hbc, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags));
1749
1750 return Paint_DrawState (hdc, hbc, lpOutputFunc, lData, wData, x, y ,cx, cy, fuFlags, TRUE);
1751}
1752//******************************************************************************
1753//******************************************************************************
1754BOOL WIN32API DrawFocusRect( HDC arg1, const RECT * arg2)
1755{
1756#ifdef DEBUG
1757 WriteLog("USER32: DrawFocusRect\n");
1758#endif
1759 return O32_DrawFocusRect(arg1, arg2);
1760}
1761//******************************************************************************
1762//******************************************************************************
1763BOOL WIN32API DrawIcon( HDC arg1, int arg2, int arg3, HICON arg4)
1764{
1765#ifdef DEBUG
1766 WriteLog("USER32: DrawIcon\n");
1767#endif
1768 return O32_DrawIcon(arg1, arg2, arg3, arg4);
1769}
1770//******************************************************************************
1771//******************************************************************************
1772BOOL WIN32API DrawIconEx(HDC hdc, int xLeft, int xRight, HICON hIcon,
1773 int cxWidth, int cyWidth, UINT istepIfAniCur,
1774 HBRUSH hbrFlickerFreeDraw, UINT diFlags)
1775{
1776#ifdef DEBUG
1777 WriteLog("USER32: DrawIcon, partially implemented\n");
1778#endif
1779 return O32_DrawIcon(hdc, xLeft, xRight, hIcon);
1780}
1781//******************************************************************************
1782//******************************************************************************
1783BOOL WIN32API DrawMenuBar( HWND arg1)
1784{
1785#ifdef DEBUG
1786 WriteLog("USER32: DrawMenuBar\n");
1787#endif
1788 return O32_DrawMenuBar(arg1);
1789}
1790//******************************************************************************
1791//******************************************************************************
1792int WIN32API DrawTextW( HDC arg1, LPCWSTR arg2, int arg3, PRECT arg4, UINT arg5)
1793{
1794 char *astring = UnicodeToAsciiString((LPWSTR)arg2);
1795 int rc;
1796
1797#ifdef DEBUG
1798 WriteLog("USER32: DrawTextW %s\n", astring);
1799#endif
1800 rc = O32_DrawText(arg1, astring, arg3, arg4, arg5);
1801 FreeAsciiString(astring);
1802 return(rc);
1803}
1804//******************************************************************************
1805//******************************************************************************
1806int WIN32API DrawTextA(HDC arg1, LPCSTR arg2, int arg3, PRECT arg4, UINT arg5)
1807{
1808#ifdef DEBUG
1809 WriteLog("USER32: DrawTextA %s", arg2);
1810#endif
1811 return O32_DrawText(arg1, arg2, arg3, arg4, arg5);
1812}
1813/*****************************************************************************
1814 * Name : BOOL WIN32API DrawAnimatedRects
1815 * Purpose : The DrawAnimatedRects function draws a wire-frame rectangle
1816 * and animates it to indicate the opening of an icon or the
1817 * minimizing or maximizing of a window.
1818 * Parameters: HWND hwnd handle of clipping window
1819 * int idAni type of animation
1820 * CONST RECT * lprcFrom address of rectangle coordinates (minimized)
1821 * CONST RECT * lprcTo address of rectangle coordinates (restored)
1822 * Variables :
1823 * Result : If the function succeeds, the return value is TRUE.
1824 * If the function fails, the return value is FALSE.
1825 * Remark :
1826 * Status : UNTESTED STUB
1827 *
1828 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1829 *****************************************************************************/
1830
1831BOOL WIN32API DrawAnimatedRects(HWND hwnd,
1832 int idAni,
1833 CONST RECT *lprcFrom,
1834 CONST RECT *lprcTo)
1835{
1836 dprintf(("USER32:DrawAnimatedRects (%08xh,%u,%08xh,%08x) not implemented.\n",
1837 hwnd,
1838 idAni,
1839 lprcFrom,
1840 lprcTo));
1841
1842 return (TRUE);
1843}
1844
1845
1846/*****************************************************************************
1847 * Name : VOID WIN32API DrawCaption
1848 * Purpose : The DrawCaption function draws a window caption.
1849 * Parameters: HDC hdc handle of device context
1850 * LPRECT lprc address of bounding rectangle coordinates
1851 * HFONT hfont handle of font for caption
1852 * HICON hicon handle of icon in caption
1853 * LPSTR lpszText address of caption string
1854 * WORD wFlags drawing options
1855 * Variables :
1856 * Result :
1857 * Remark :
1858 * Status : UNTESTED STUB
1859 *
1860 * Author : Patrick Haller [Thu, 1998/02/26 11:55]
1861 *****************************************************************************/
1862
1863BOOL WIN32API DrawCaption (HWND hwnd,
1864 HDC hdc,
1865 const RECT *lprc,
1866 UINT wFlags)
1867{
1868 dprintf(("USER32:DrawCaption (%08xh,%08xh,%08xh,%08xh) not implemented.\n",
1869 hwnd,
1870 hdc,
1871 lprc,
1872 wFlags));
1873
1874 return FALSE;
1875}
1876/***********************************************************************
1877 * DrawCaptionTemp32A [USER32.599]
1878 *
1879 * PARAMS
1880 *
1881 * RETURNS
1882 * Success:
1883 * Failure:
1884 */
1885
1886BOOL WIN32API DrawCaptionTempA(HWND hwnd,
1887 HDC hdc,
1888 const RECT *rect,
1889 HFONT hFont,
1890 HICON hIcon,
1891 LPCSTR str,
1892 UINT uFlags)
1893{
1894 RECT rc = *rect;
1895
1896 dprintf(("USER32: DrawCaptionTempA(%08xh,%08xh,%08xh,%08xh,%08xh,%08xh,%08xh)\n",
1897 hwnd,
1898 hdc,
1899 rect,
1900 hFont,
1901 hIcon,
1902 str,
1903 uFlags));
1904
1905 /* drawing background */
1906 if (uFlags & DC_INBUTTON)
1907 {
1908 O32_FillRect (hdc,
1909 &rc,
1910 GetSysColorBrush (COLOR_3DFACE));
1911
1912 if (uFlags & DC_ACTIVE)
1913 {
1914 HBRUSH hbr = O32_SelectObject (hdc,
1915 GetSysColorBrush (COLOR_ACTIVECAPTION));
1916 O32_PatBlt (hdc,
1917 rc.left,
1918 rc.top,
1919 rc.right - rc.left,
1920 rc.bottom - rc.top,
1921 0xFA0089);
1922
1923 O32_SelectObject (hdc,
1924 hbr);
1925 }
1926 }
1927 else
1928 {
1929 O32_FillRect (hdc,
1930 &rc,
1931 GetSysColorBrush ((uFlags & DC_ACTIVE) ?
1932 COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
1933 }
1934
1935
1936 /* drawing icon */
1937 if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP))
1938 {
1939 POINT pt;
1940
1941 pt.x = rc.left + 2;
1942 pt.y = (rc.bottom + rc.top - O32_GetSystemMetrics(SM_CYSMICON)) / 2;
1943
1944 if (hIcon)
1945 {
1946 DrawIconEx (hdc,
1947 pt.x,
1948 pt.y,
1949 hIcon,
1950 O32_GetSystemMetrics(SM_CXSMICON),
1951 O32_GetSystemMetrics(SM_CYSMICON),
1952 0,
1953 0,
1954 DI_NORMAL);
1955 }
1956 else
1957 {
1958 /* @@@PH 1999/06/08 not ported yet, just don't draw any icon
1959 WND *wndPtr = WIN_FindWndPtr(hwnd);
1960 HICON hAppIcon = 0;
1961
1962 if (wndPtr->class->hIconSm)
1963 hAppIcon = wndPtr->class->hIconSm;
1964 else
1965 if (wndPtr->class->hIcon)
1966 hAppIcon = wndPtr->class->hIcon;
1967
1968 DrawIconEx (hdc,
1969 pt.x,
1970 pt.y,
1971 hAppIcon,
1972 GetSystemMetrics(SM_CXSMICON),
1973 GetSystemMetrics(SM_CYSMICON),
1974 0,
1975 0,
1976 DI_NORMAL);
1977
1978 WIN_ReleaseWndPtr(wndPtr);
1979 */
1980 }
1981
1982 rc.left += (rc.bottom - rc.top);
1983 }
1984
1985 /* drawing text */
1986 if (uFlags & DC_TEXT)
1987 {
1988 HFONT hOldFont;
1989
1990 if (uFlags & DC_INBUTTON)
1991 O32_SetTextColor (hdc,
1992 O32_GetSysColor (COLOR_BTNTEXT));
1993 else
1994 if (uFlags & DC_ACTIVE)
1995 O32_SetTextColor (hdc,
1996 O32_GetSysColor (COLOR_CAPTIONTEXT));
1997 else
1998 O32_SetTextColor (hdc,
1999 O32_GetSysColor (COLOR_INACTIVECAPTIONTEXT));
2000
2001 O32_SetBkMode (hdc,
2002 TRANSPARENT);
2003
2004 if (hFont)
2005 hOldFont = O32_SelectObject (hdc,
2006 hFont);
2007 else
2008 {
2009 NONCLIENTMETRICSA nclm;
2010 HFONT hNewFont;
2011
2012 nclm.cbSize = sizeof(NONCLIENTMETRICSA);
2013 O32_SystemParametersInfo (SPI_GETNONCLIENTMETRICS,
2014 0,
2015 &nclm,
2016 0);
2017 hNewFont = O32_CreateFontIndirect ((uFlags & DC_SMALLCAP) ?
2018 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
2019 hOldFont = O32_SelectObject (hdc,
2020 hNewFont);
2021 }
2022
2023 if (str)
2024 O32_DrawText (hdc,
2025 str,
2026 -1,
2027 &rc,
2028 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
2029 else
2030 {
2031 CHAR szText[128];
2032 INT nLen;
2033
2034 nLen = O32_GetWindowText (hwnd,
2035 szText,
2036 128);
2037
2038 O32_DrawText (hdc,
2039 szText,
2040 nLen,
2041 &rc,
2042 DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
2043 }
2044
2045 if (hFont)
2046 O32_SelectObject (hdc,
2047 hOldFont);
2048 else
2049 O32_DeleteObject (O32_SelectObject (hdc,
2050 hOldFont));
2051 }
2052
2053 /* drawing focus ??? */
2054 if (uFlags & 0x2000)
2055 {
2056 dprintf(("USER32: DrawCaptionTempA undocumented flag (0x2000)!\n"));
2057 }
2058
2059 return 0;
2060}
2061
2062
2063/***********************************************************************
2064 * DrawCaptionTemp32W [USER32.602]
2065 *
2066 * PARAMS
2067 *
2068 * RETURNS
2069 * Success:
2070 * Failure:
2071 */
2072
2073BOOL WIN32API DrawCaptionTempW (HWND hwnd,
2074 HDC hdc,
2075 const RECT *rect,
2076 HFONT hFont,
2077 HICON hIcon,
2078 LPCWSTR str,
2079 UINT uFlags)
2080{
2081 LPSTR strAscii = UnicodeToAsciiString((LPWSTR)str);
2082
2083 BOOL res = DrawCaptionTempA (hwnd,
2084 hdc,
2085 rect,
2086 hFont,
2087 hIcon,
2088 strAscii,
2089 uFlags);
2090
2091 FreeAsciiString(strAscii);
2092
2093 return res;
2094}
2095
2096//******************************************************************************
2097//******************************************************************************
Note: See TracBrowser for help on using the repository browser.