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

Last change on this file since 1256 was 1256, checked in by sandervl, 26 years ago

MDI fix, extra message support etc

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