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

Last change on this file since 161 was 161, checked in by achimha, 26 years ago

Incorporated complete DrawFrameControl code from WINE - should be fully functionaluitools.cpp

File size: 43.8 KB
Line 
1/* $Id: uitools.cpp,v 1.2 1999-06-23 16:36:56 achimha 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 */
9
10#include "winuser.h"
11#include "user32.h"
12
13static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
14 0xaaaa, 0x5555, 0xaaaa, 0x5555 };
15
16/* These tables are used in:
17 * UITOOLS_DrawDiagEdge()
18 * UITOOLS_DrawRectEdge()
19 */
20static const char LTInnerNormal[] = {
21 -1, -1, -1, -1,
22 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
23 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1,
24 -1, -1, -1, -1
25};
26
27static const char LTOuterNormal[] = {
28 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
29 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
30 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
31 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1
32};
33
34static const char RBInnerNormal[] = {
35 -1, -1, -1, -1,
36 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
37 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
38 -1, -1, -1, -1
39};
40
41static const char RBOuterNormal[] = {
42 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
43 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
44 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
45 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1
46};
47
48static const char LTInnerSoft[] = {
49 -1, -1, -1, -1,
50 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
51 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
52 -1, -1, -1, -1
53};
54
55static const char LTOuterSoft[] = {
56 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
57 COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
58 COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
59 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
60};
61
62#define RBInnerSoft RBInnerNormal /* These are the same */
63#define RBOuterSoft RBOuterNormal
64
65static const char LTRBOuterMono[] = {
66 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
67 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
68 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
69 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
70};
71
72static const char LTRBInnerMono[] = {
73 -1, -1, -1, -1,
74 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
75 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
76 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
77};
78
79static const char LTRBOuterFlat[] = {
80 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
81 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
82 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
83 COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
84};
85
86static const char LTRBInnerFlat[] = {
87 -1, -1, -1, -1,
88 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
89 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
90 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
91};
92
93/***********************************************************************
94 * UITOOLS_DrawDiagEdge
95 *
96 * Same as DrawEdge invoked with BF_DIAGONAL
97 *
98 * 03-Dec-1997: Changed by Bertho Stultiens
99 *
100 * See also comments with UITOOLS_DrawRectEdge()
101 */
102static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc,
103 UINT uType, UINT uFlags)
104{
105 POINT Points[4];
106 char InnerI, OuterI;
107 HPEN InnerPen, OuterPen;
108 POINT SavePoint;
109 HPEN SavePen;
110 int spx, spy;
111 int epx, epy;
112 int Width = rc->right - rc->left;
113 int Height= rc->bottom - rc->top;
114 int SmallDiam = Width > Height ? Height : Width;
115 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
116 || (uType & BDR_OUTER) == BDR_OUTER)
117 && !(uFlags & (BF_FLAT|BF_MONO)) );
118 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
119 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
120
121 /* Init some vars */
122 OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
123 SavePen = (HPEN)SelectObject(hdc, InnerPen);
124 spx = spy = epx = epy = 0; /* Satisfy the compiler... */
125
126 /* Determine the colors of the edges */
127 if(uFlags & BF_MONO)
128 {
129 InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
130 OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
131 }
132 else if(uFlags & BF_FLAT)
133 {
134 InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
135 OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
136 }
137 else if(uFlags & BF_SOFT)
138 {
139 if(uFlags & BF_BOTTOM)
140 {
141 InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
142 OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
143 }
144 else
145 {
146 InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
147 OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
148 }
149 }
150 else
151 {
152 if(uFlags & BF_BOTTOM)
153 {
154 InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
155 OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
156 }
157 else
158 {
159 InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
160 OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
161 }
162 }
163
164 if(InnerI != -1) InnerPen = GetSysColorPen(InnerI);
165 if(OuterI != -1) OuterPen = GetSysColorPen(OuterI);
166
167 MoveToEx(hdc, 0, 0, &SavePoint);
168
169 /* Don't ask me why, but this is what is visible... */
170 /* This must be possible to do much simpler, but I fail to */
171 /* see the logic in the MS implementation (sigh...). */
172 /* So, this might look a bit brute force here (and it is), but */
173 /* it gets the job done;) */
174
175 switch(uFlags & BF_RECT)
176 {
177 case 0:
178 case BF_LEFT:
179 case BF_BOTTOM:
180 case BF_BOTTOMLEFT:
181 /* Left bottom endpoint */
182 epx = rc->left-1;
183 spx = epx + SmallDiam;
184 epy = rc->bottom;
185 spy = epy - SmallDiam;
186 break;
187
188 case BF_TOPLEFT:
189 case BF_BOTTOMRIGHT:
190 /* Left top endpoint */
191 epx = rc->left-1;
192 spx = epx + SmallDiam;
193 epy = rc->top-1;
194 spy = epy + SmallDiam;
195 break;
196
197 case BF_TOP:
198 case BF_RIGHT:
199 case BF_TOPRIGHT:
200 case BF_RIGHT|BF_LEFT:
201 case BF_RIGHT|BF_LEFT|BF_TOP:
202 case BF_BOTTOM|BF_TOP:
203 case BF_BOTTOM|BF_TOP|BF_LEFT:
204 case BF_BOTTOMRIGHT|BF_LEFT:
205 case BF_BOTTOMRIGHT|BF_TOP:
206 case BF_RECT:
207 /* Right top endpoint */
208 spx = rc->left;
209 epx = spx + SmallDiam;
210 spy = rc->bottom-1;
211 epy = spy - SmallDiam;
212 break;
213 }
214
215 MoveToEx(hdc, spx, spy, NULL);
216 SelectObject(hdc, OuterPen);
217 LineTo(hdc, epx, epy);
218
219 SelectObject(hdc, InnerPen);
220
221 switch(uFlags & (BF_RECT|BF_DIAGONAL))
222 {
223 case BF_DIAGONAL_ENDBOTTOMLEFT:
224 case (BF_DIAGONAL|BF_BOTTOM):
225 case BF_DIAGONAL:
226 case (BF_DIAGONAL|BF_LEFT):
227 MoveToEx(hdc, spx-1, spy, NULL);
228 LineTo(hdc, epx, epy-1);
229 Points[0].x = spx-add;
230 Points[0].y = spy;
231 Points[1].x = rc->left;
232 Points[1].y = rc->top;
233 Points[2].x = epx+1;
234 Points[2].y = epy-1-add;
235 Points[3] = Points[2];
236 break;
237
238 case BF_DIAGONAL_ENDBOTTOMRIGHT:
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->bottom-1;
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|BF_BOTTOM|BF_RIGHT|BF_TOP):
251 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
252 case BF_DIAGONAL_ENDTOPRIGHT:
253 case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
254 MoveToEx(hdc, spx+1, spy, NULL);
255 LineTo(hdc, epx, epy+1);
256 Points[0].x = epx-1;
257 Points[0].y = epy+1+add;
258 Points[1].x = rc->right-1;
259 Points[1].y = rc->top+add;
260 Points[2].x = rc->right-1;
261 Points[2].y = rc->bottom-1;
262 Points[3].x = spx+add;
263 Points[3].y = spy;
264 break;
265
266 case BF_DIAGONAL_ENDTOPLEFT:
267 MoveToEx(hdc, spx, spy-1, NULL);
268 LineTo(hdc, epx+1, epy);
269 Points[0].x = epx+1+add;
270 Points[0].y = epy+1;
271 Points[1].x = rc->right-1;
272 Points[1].y = rc->top;
273 Points[2].x = rc->right-1;
274 Points[2].y = rc->bottom-1-add;
275 Points[3].x = spx;
276 Points[3].y = spy-add;
277 break;
278
279 case (BF_DIAGONAL|BF_TOP):
280 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
281 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
282 MoveToEx(hdc, spx+1, spy-1, NULL);
283 LineTo(hdc, epx, epy);
284 Points[0].x = epx-1;
285 Points[0].y = epy+1;
286 Points[1].x = rc->right-1;
287 Points[1].y = rc->top;
288 Points[2].x = rc->right-1;
289 Points[2].y = rc->bottom-1-add;
290 Points[3].x = spx+add;
291 Points[3].y = spy-add;
292 break;
293
294 case (BF_DIAGONAL|BF_RIGHT):
295 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
296 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
297 MoveToEx(hdc, spx, spy, NULL);
298 LineTo(hdc, epx-1, epy+1);
299 Points[0].x = spx;
300 Points[0].y = spy;
301 Points[1].x = rc->left;
302 Points[1].y = rc->top+add;
303 Points[2].x = epx-1-add;
304 Points[2].y = epy+1+add;
305 Points[3] = Points[2];
306 break;
307 }
308
309 /* Fill the interior if asked */
310 if((uFlags & BF_MIDDLE) && retval)
311 {
312 HBRUSH hbsave;
313 HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW
314 :COLOR_BTNFACE);
315 HPEN hpsave;
316 HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW
317 : COLOR_BTNFACE);
318 hbsave = (HBRUSH)SelectObject(hdc, hb);
319 hpsave = (HPEN)SelectObject(hdc, hp);
320 Polygon(hdc, Points, 4);
321 SelectObject(hdc, hbsave);
322 SelectObject(hdc, hpsave);
323 }
324
325 /* Adjust rectangle if asked */
326 if(uFlags & BF_ADJUST)
327 {
328 if(uFlags & BF_LEFT) rc->left += add;
329 if(uFlags & BF_RIGHT) rc->right -= add;
330 if(uFlags & BF_TOP) rc->top += add;
331 if(uFlags & BF_BOTTOM) rc->bottom -= add;
332 }
333
334 /* Cleanup */
335 SelectObject(hdc, SavePen);
336 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
337
338 return retval;
339}
340
341/***********************************************************************
342 * UITOOLS_DrawRectEdge
343 *
344 * Same as DrawEdge invoked without BF_DIAGONAL
345 *
346 * 23-Nov-1997: Changed by Bertho Stultiens
347 *
348 * Well, I started testing this and found out that there are a few things
349 * that weren't quite as win95. The following rewrite should reproduce
350 * win95 results completely.
351 * The colorselection is table-driven to avoid awfull if-statements.
352 * The table below show the color settings.
353 *
354 * Pen selection table for uFlags = 0
355 *
356 * uType | LTI | LTO | RBI | RBO
357 * ------+-------+-------+-------+-------
358 * 0000 | x | x | x | x
359 * 0001 | x | 22 | x | 21
360 * 0010 | x | 16 | x | 20
361 * 0011 | x | x | x | x
362 * ------+-------+-------+-------+-------
363 * 0100 | x | 20 | x | 16
364 * 0101 | 20 | 22 | 16 | 21
365 * 0110 | 20 | 16 | 16 | 20
366 * 0111 | x | x | x | x
367 * ------+-------+-------+-------+-------
368 * 1000 | x | 21 | x | 22
369 * 1001 | 21 | 22 | 22 | 21
370 * 1010 | 21 | 16 | 22 | 20
371 * 1011 | x | x | x | x
372 * ------+-------+-------+-------+-------
373 * 1100 | x | x | x | x
374 * 1101 | x | x (22)| x | x (21)
375 * 1110 | x | x (16)| x | x (20)
376 * 1111 | x | x | x | x
377 *
378 * Pen selection table for uFlags = BF_SOFT
379 *
380 * uType | LTI | LTO | RBI | RBO
381 * ------+-------+-------+-------+-------
382 * 0000 | x | x | x | x
383 * 0001 | x | 20 | x | 21
384 * 0010 | x | 21 | x | 20
385 * 0011 | x | x | x | x
386 * ------+-------+-------+-------+-------
387 * 0100 | x | 22 | x | 16
388 * 0101 | 22 | 20 | 16 | 21
389 * 0110 | 22 | 21 | 16 | 20
390 * 0111 | x | x | x | x
391 * ------+-------+-------+-------+-------
392 * 1000 | x | 16 | x | 22
393 * 1001 | 16 | 20 | 22 | 21
394 * 1010 | 16 | 21 | 22 | 20
395 * 1011 | x | x | x | x
396 * ------+-------+-------+-------+-------
397 * 1100 | x | x | x | x
398 * 1101 | x | x (20)| x | x (21)
399 * 1110 | x | x (21)| x | x (20)
400 * 1111 | x | x | x | x
401 *
402 * x = don't care; (n) = is what win95 actually uses
403 * LTI = left Top Inner line
404 * LTO = left Top Outer line
405 * RBI = Right Bottom Inner line
406 * RBO = Right Bottom Outer line
407 * 15 = COLOR_BTNFACE
408 * 16 = COLOR_BTNSHADOW
409 * 20 = COLOR_BTNHIGHLIGHT
410 * 21 = COLOR_3DDKSHADOW
411 * 22 = COLOR_3DLIGHT
412 */
413
414
415static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc,
416 UINT uType, UINT uFlags)
417{
418 char LTInnerI, LTOuterI;
419 char RBInnerI, RBOuterI;
420 HPEN LTInnerPen, LTOuterPen;
421 HPEN RBInnerPen, RBOuterPen;
422 RECT InnerRect = *rc;
423 POINT SavePoint;
424 HPEN SavePen;
425 int LBpenplus = 0;
426 int LTpenplus = 0;
427 int RTpenplus = 0;
428 int RBpenplus = 0;
429 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
430 || (uType & BDR_OUTER) == BDR_OUTER)
431 && !(uFlags & (BF_FLAT|BF_MONO)) );
432
433 /* Init some vars */
434 LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
435 SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
436
437 /* Determine the colors of the edges */
438 if(uFlags & BF_MONO)
439 {
440 LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
441 LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
442 }
443 else if(uFlags & BF_FLAT)
444 {
445 LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
446 LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
447 }
448 else if(uFlags & BF_SOFT)
449 {
450 LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
451 LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
452 RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
453 RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
454 }
455 else
456 {
457 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
458 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
459 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
460 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
461 }
462
463 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) LBpenplus = 1;
464 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) RTpenplus = 1;
465 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
466 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) LTpenplus = 1;
467
468 if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI);
469 if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI);
470 if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI);
471 if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI);
472
473 if((uFlags & BF_MIDDLE) && retval)
474 {
475 FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ?
476 COLOR_WINDOW : COLOR_BTNFACE));
477 }
478
479 MoveToEx(hdc, 0, 0, &SavePoint);
480
481 /* Draw the outer edge */
482 SelectObject(hdc, LTOuterPen);
483 if(uFlags & BF_TOP)
484 {
485 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
486 LineTo(hdc, InnerRect.right, InnerRect.top);
487 }
488 if(uFlags & BF_LEFT)
489 {
490 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
491 LineTo(hdc, InnerRect.left, InnerRect.bottom);
492 }
493 SelectObject(hdc, RBOuterPen);
494 if(uFlags & BF_BOTTOM)
495 {
496 MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
497 LineTo(hdc, InnerRect.left-1, InnerRect.bottom-1);
498 }
499 if(uFlags & BF_RIGHT)
500 {
501 MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
502 LineTo(hdc, InnerRect.right-1, InnerRect.top-1);
503 }
504
505 /* Draw the inner edge */
506 SelectObject(hdc, LTInnerPen);
507 if(uFlags & BF_TOP)
508 {
509 MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
510 LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
511 }
512 if(uFlags & BF_LEFT)
513 {
514 MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
515 LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
516 }
517 SelectObject(hdc, RBInnerPen);
518 if(uFlags & BF_BOTTOM)
519 {
520 MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL);
521 LineTo(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2);
522 }
523 if(uFlags & BF_RIGHT)
524 {
525 MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL);
526 LineTo(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus);
527 }
528
529 /* Adjust rectangle if asked */
530 if(uFlags & BF_ADJUST)
531 {
532 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
533 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
534 if(uFlags & BF_LEFT) rc->left += add;
535 if(uFlags & BF_RIGHT) rc->right -= add;
536 if(uFlags & BF_TOP) rc->top += add;
537 if(uFlags & BF_BOTTOM) rc->bottom -= add;
538 }
539
540 /* Cleanup */
541 SelectObject(hdc, SavePen);
542 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
543 return retval;
544}
545
546
547//**********************************************************************
548// DrawEdge (USER32.155)
549//
550BOOL WIN32API DrawEdge(HDC hdc, LPRECT rc, UINT edge, UINT flags)
551{
552
553 if(flags & BF_DIAGONAL)
554 return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags);
555 else
556 return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags);
557}
558
559/************************************************************************
560 * UITOOLS_MakeSquareRect
561 *
562 * Utility to create a square rectangle and returning the width
563 */
564static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
565{
566 int Width = src->right - src->left;
567 int Height = src->bottom - src->top;
568 int SmallDiam = Width > Height ? Height : Width;
569
570 *dst = *src;
571
572 /* Make it a square box */
573 if(Width < Height) /* SmallDiam == Width */
574 {
575 dst->top += (Height-Width)/2;
576 dst->bottom = dst->top + SmallDiam;
577 }
578 else if(Width > Height) /* SmallDiam == Height */
579 {
580 dst->left += (Width-Height)/2;
581 dst->right = dst->left + SmallDiam;
582 }
583
584 return SmallDiam;
585}
586
587
588/************************************************************************
589 * UITOOLS_DFC_ButtonPush
590 *
591 * Draw a push button coming from DrawFrameControl()
592 *
593 * Does a pretty good job in emulating MS behavior. Some quirks are
594 * however there because MS uses a TrueType font (Marlett) to draw
595 * the buttons.
596 */
597static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
598{
599 UINT edge;
600 RECT myr = *r;
601
602 if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
603 edge = EDGE_SUNKEN;
604 else
605 edge = EDGE_RAISED;
606
607 if(uFlags & DFCS_CHECKED)
608 {
609 if(uFlags & DFCS_MONO)
610 UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
611 else
612 UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
613
614 if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
615 {
616 HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55);
617 HBRUSH hbsave;
618 HBRUSH hb = CreatePatternBrush(hbm);
619
620 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
621 hbsave = (HBRUSH)SelectObject(dc, hb);
622 PatBlt(dc, myr.left, myr.top, myr.right-myr.left, myr.bottom-myr.top, 0x00FA0089);
623 SelectObject(dc, hbsave);
624 DeleteObject(hb);
625 DeleteObject(hbm);
626 }
627 else
628 {
629 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
630 }
631 }
632 else
633 {
634 if(uFlags & DFCS_MONO)
635 {
636 UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
637 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
638 }
639 else
640 {
641 UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE |BF_SOFT| BF_RECT);
642 }
643 }
644
645 /* Adjust rectangle if asked */
646 if(uFlags & DFCS_ADJUSTRECT)
647 {
648 r->left += 2;
649 r->right -= 2;
650 r->top += 2;
651 r->bottom -= 2;
652 }
653
654 return TRUE;
655}
656
657
658/************************************************************************
659 * UITOOLS_DFC_ButtonChcek
660 *
661 * Draw a check/3state button coming from DrawFrameControl()
662 *
663 * Does a pretty good job in emulating MS behavior. Some quirks are
664 * however there because MS uses a TrueType font (Marlett) to draw
665 * the buttons.
666 */
667#define DFC_CHECKPOINTSMAX 6
668
669static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags)
670{
671 RECT myr;
672 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
673 int BorderShrink = SmallDiam / 16;
674
675 if(BorderShrink < 1) BorderShrink = 1;
676
677 /* FIXME: The FillRect() sequence doesn't work for sizes less than */
678 /* 4 pixels in diameter. Not really a problem but it isn't M$'s */
679 /* 100% equivalent. */
680 if(uFlags & (DFCS_FLAT|DFCS_MONO))
681 {
682 FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOWFRAME));
683 myr.left += 2 * BorderShrink;
684 myr.right -= 2 * BorderShrink;
685 myr.top += 2 * BorderShrink;
686 myr.bottom -= 2 * BorderShrink;
687 }
688 else
689 {
690 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
691 myr.right -= BorderShrink;
692 myr.bottom -= BorderShrink;
693 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNSHADOW));
694 myr.left += BorderShrink;
695 myr.top += BorderShrink;
696 FillRect(dc, &myr, GetSysColorBrush(COLOR_3DLIGHT));
697 myr.right -= BorderShrink;
698 myr.bottom -= BorderShrink;
699 FillRect(dc, &myr, GetSysColorBrush(COLOR_3DDKSHADOW));
700 myr.left += BorderShrink;
701 myr.top += BorderShrink;
702 }
703
704 if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED))
705 {
706 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
707 }
708 else if(uFlags & DFCS_CHECKED)
709 {
710 if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
711 {
712 HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55);
713 HBRUSH hbsave;
714 HBRUSH hb = CreatePatternBrush(hbm);
715
716 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
717 hbsave = (HBRUSH)SelectObject(dc, hb);
718 PatBlt(dc, myr.left, myr.top, myr.right-myr.left, myr.bottom-myr.top, 0x00FA0089);
719 SelectObject(dc, hbsave);
720 DeleteObject(hb);
721 DeleteObject(hbm);
722 }
723 else
724 {
725 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
726 }
727 }
728 else
729 {
730 FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW));
731 }
732
733 if(uFlags & DFCS_CHECKED)
734 {
735 POINT CheckPoints[DFC_CHECKPOINTSMAX];
736 int i;
737 HBRUSH hbsave;
738 HPEN hpsave;
739
740 /* FIXME: This comes very close to M$'s checkmark, but not */
741 /* exactly... When small or large there is a few pixels */
742 /* shift. Not bad, but could be better :) */
743 UITOOLS_MakeSquareRect(r, &myr);
744 CheckPoints[0].x = myr.left + 253*SmallDiam/1000;
745 CheckPoints[0].y = myr.top + 345*SmallDiam/1000;
746 CheckPoints[1].x = myr.left + 409*SmallDiam/1000;
747 CheckPoints[1].y = CheckPoints[0].y + (CheckPoints[1].x-CheckPoints[0].x);
748 CheckPoints[2].x = myr.left + 690*SmallDiam/1000;
749 CheckPoints[2].y = CheckPoints[1].y - (CheckPoints[2].x-CheckPoints[1].x);
750 CheckPoints[3].x = CheckPoints[2].x;
751 CheckPoints[3].y = CheckPoints[2].y + 3*SmallDiam/16;
752 CheckPoints[4].x = CheckPoints[1].x;
753 CheckPoints[4].y = CheckPoints[1].y + 3*SmallDiam/16;
754 CheckPoints[5].x = CheckPoints[0].x;
755 CheckPoints[5].y = CheckPoints[0].y + 3*SmallDiam/16;
756
757 i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
758 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
759 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
760 Polygon(dc, CheckPoints, DFC_CHECKPOINTSMAX);
761 SelectObject(dc, hpsave);
762 SelectObject(dc, hbsave);
763 }
764 return TRUE;
765}
766
767
768/************************************************************************
769 * UITOOLS_DFC_ButtonRadio
770 *
771 * Draw a radio/radioimage/radiomask button coming from DrawFrameControl()
772 *
773 * Does a pretty good job in emulating MS behavior. Some quirks are
774 * however there because MS uses a TrueType font (Marlett) to draw
775 * the buttons.
776 */
777static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags)
778{
779 RECT myr;
780 int i;
781 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
782 int BorderShrink = SmallDiam / 16;
783 HPEN hpsave;
784 HBRUSH hbsave;
785 int xe, ye;
786 int xc, yc;
787
788 if(BorderShrink < 1) BorderShrink = 1;
789
790 if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE)
791 {
792 FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH));
793 }
794
795 xe = myr.left;
796 ye = myr.top + SmallDiam - SmallDiam/2;
797
798 xc = myr.left + SmallDiam - SmallDiam/2;
799 yc = myr.top + SmallDiam - SmallDiam/2;
800
801 /* Define bounding box */
802 i = 14*SmallDiam/16;
803 myr.left = xc - i+i/2;
804 myr.right = xc + i/2;
805 myr.top = yc - i+i/2;
806 myr.bottom = yc + i/2;
807
808 if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK)
809 {
810 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
811 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
812 SelectObject(dc, hbsave);
813 }
814 else
815 {
816 if(uFlags & (DFCS_FLAT|DFCS_MONO))
817 {
818 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME));
819 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME));
820 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
821 SelectObject(dc, hbsave);
822 SelectObject(dc, hpsave);
823 }
824 else
825 {
826 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
827 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
828 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
829
830 SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW));
831 SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW));
832 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
833
834 myr.left += BorderShrink;
835 myr.right -= BorderShrink;
836 myr.top += BorderShrink;
837 myr.bottom -= BorderShrink;
838
839 SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT));
840 SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT));
841 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
842
843 SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW));
844 SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW));
845 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
846 SelectObject(dc, hbsave);
847 SelectObject(dc, hpsave);
848 }
849
850 i = 10*SmallDiam/16;
851 myr.left = xc - i+i/2;
852 myr.right = xc + i/2;
853 myr.top = yc - i+i/2;
854 myr.bottom = yc + i/2;
855 i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
856 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
857 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
858 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
859 SelectObject(dc, hbsave);
860 SelectObject(dc, hpsave);
861 }
862
863 if(uFlags & DFCS_CHECKED)
864 {
865 i = 6*SmallDiam/16;
866 i = i < 1 ? 1 : i;
867 myr.left = xc - i+i/2;
868 myr.right = xc + i/2;
869 myr.top = yc - i+i/2;
870 myr.bottom = yc + i/2;
871
872 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
873 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
874 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
875 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
876 SelectObject(dc, hpsave);
877 SelectObject(dc, hbsave);
878 }
879
880 /* FIXME: M$ has a polygon in the center at relative points: */
881 /* 0.476, 0.476 (times SmallDiam, SmallDiam) */
882 /* 0.476, 0.525 */
883 /* 0.500, 0.500 */
884 /* 0.500, 0.499 */
885 /* when the button is unchecked. The reason for it is unknown. The */
886 /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */
887 /* least 3 times (it looks like a clip-region when you see it happen). */
888 /* I do not really see a reason why this should be implemented. If you */
889 /* have a good reason, let me know. Maybe this is a quirk in the Marlett */
890 /* font. */
891
892 return TRUE;
893}
894
895/***********************************************************************
896 * UITOOLS_DrawFrameButton
897 */
898static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
899{
900 switch(uState & 0xff)
901 {
902 case DFCS_BUTTONPUSH:
903 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
904
905 case DFCS_BUTTONCHECK:
906 case DFCS_BUTTON3STATE:
907 return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState);
908
909 case DFCS_BUTTONRADIOIMAGE:
910 case DFCS_BUTTONRADIOMASK:
911 case DFCS_BUTTONRADIO:
912 return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState);
913
914// default:
915// WARN("Invalid button state=0x%04x\n", uState);
916 }
917
918 return FALSE;
919}
920
921/***********************************************************************
922 * UITOOLS_DrawFrameCaption
923 *
924 * Draw caption buttons (win95), coming from DrawFrameControl()
925 */
926
927static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
928{
929 POINT Line1[10];
930 POINT Line2[10];
931 int Line1N;
932 int Line2N;
933 RECT myr;
934 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
935 int i;
936 HBRUSH hbsave;
937 HPEN hpsave;
938 HFONT hfsave, hf;
939 int xc = (myr.left+myr.right)/2;
940 int yc = (myr.top+myr.bottom)/2;
941 int edge, move;
942 char str[2] = "?";
943 UINT alignsave;
944 int bksave;
945 COLORREF clrsave;
946 SIZE size;
947
948 UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00);
949
950 switch(uFlags & 0xff)
951 {
952 case DFCS_CAPTIONCLOSE:
953 edge = 328*SmallDiam/1000;
954 move = 95*SmallDiam/1000;
955 Line1[0].x = Line2[0].x = Line1[1].x = Line2[1].x = xc - edge;
956 Line1[2].y = Line2[5].y = Line1[1].y = Line2[4].y = yc - edge;
957 Line1[3].x = Line2[3].x = Line1[4].x = Line2[4].x = xc + edge;
958 Line1[5].y = Line2[2].y = Line1[4].y = Line2[1].y = yc + edge;
959 Line1[2].x = Line2[2].x = Line1[1].x + move;
960 Line1[0].y = Line2[3].y = Line1[1].y + move;
961 Line1[5].x = Line2[5].x = Line1[4].x - move;
962 Line1[3].y = Line2[0].y = Line1[4].y - move;
963 Line1N = 6;
964 Line2N = 6;
965 break;
966
967 case DFCS_CAPTIONHELP:
968 /* This one breaks the flow */
969 /* FIXME: We need the Marlett font in order to get this right. */
970
971 hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
972 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
973 DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System");
974 alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT);
975 bksave = SetBkMode(dc, TRANSPARENT);
976 clrsave = GetTextColor(dc);
977 hfsave = (HFONT)SelectObject(dc, hf);
978 GetTextExtentPoint32A(dc, str, 1, &size);
979
980 if(uFlags & DFCS_INACTIVE)
981 {
982 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
983 TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1);
984 }
985 SetTextColor(dc, GetSysColor(uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
986 TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1);
987
988 SelectObject(dc, hfsave);
989 SetTextColor(dc, clrsave);
990 SetBkMode(dc, bksave);
991 SetTextAlign(dc, alignsave);
992 DeleteObject(hf);
993 return TRUE;
994
995 case DFCS_CAPTIONMIN:
996 Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+2;
997 Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
998 Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1;
999 Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750;
1000 Line1N = 4;
1001 Line2N = 0;
1002 break;
1003
1004 case DFCS_CAPTIONMAX:
1005 edge = 47*SmallDiam/750;
1006 Line1[0].x = Line1[5].x = myr.left + 57*SmallDiam/750+3;
1007 Line1[0].y = Line1[1].y = myr.top + 143*SmallDiam/750+1;
1008 Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750;
1009 Line1[5].y = Line1[4].y = Line1[0].y + 93*SmallDiam/750;
1010 Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750;
1011 Line1[3].x = Line1[4].x = Line1[1].x - edge;
1012
1013 Line2[0].x = Line2[5].x = Line1[0].x;
1014 Line2[3].x = Line2[4].x = Line1[1].x;
1015 Line2[1].x = Line2[2].x = Line1[0].x + edge;
1016 Line2[0].y = Line2[1].y = Line1[0].y;
1017 Line2[4].y = Line2[5].y = Line1[2].y;
1018 Line2[2].y = Line2[3].y = Line1[2].y - edge;
1019 Line1N = 6;
1020 Line2N = 6;
1021 break;
1022
1023 case DFCS_CAPTIONRESTORE:
1024 /* FIXME: this one looks bad at small sizes < 15x15 :( */
1025 edge = 47*SmallDiam/750;
1026 move = 420*SmallDiam/750;
1027 Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2;
1028 Line1[0].y = Line1[1].y = myr.top + 169*SmallDiam/750+1;
1029 Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750;
1030 Line1[7].x = Line1[8].x = Line1[0].x + edge;
1031 Line1[1].x = Line1[2].x = Line1[0].x + move;
1032 Line1[5].x = Line1[6].x = Line1[1].x - edge;
1033 Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750;
1034 Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750;
1035 Line1[4].y = Line1[5].y = Line1[2].y - edge;
1036 Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750;
1037
1038 Line2[1].x = Line2[2].x = Line1[3].x;
1039 Line2[7].x = Line2[8].x = Line2[1].x - edge;
1040 Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move;
1041 Line2[5].x = Line2[6].x = Line2[0].x + edge;
1042 Line2[0].y = Line2[1].y = Line1[9].y;
1043 Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750;
1044 Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750;
1045 Line2[6].y = Line2[7].y = Line2[2].y - edge;
1046 Line1N = 10;
1047 Line2N = 10;
1048 break;
1049
1050 default:
1051// WARN("Invalid caption; flags=0x%04x\n", uFlags);
1052 return FALSE;
1053 }
1054
1055 /* Here the drawing takes place */
1056 if(uFlags & DFCS_INACTIVE)
1057 {
1058 /* If we have an inactive button, then you see a shadow */
1059 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1060 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1061 Polygon(dc, Line1, Line1N);
1062 if(Line2N > 0)
1063 Polygon(dc, Line2, Line2N);
1064 SelectObject(dc, hpsave);
1065 SelectObject(dc, hbsave);
1066 }
1067
1068 /* Correct for the shadow shift */
1069 for(i = 0; i < Line1N; i++)
1070 {
1071 Line1[i].x--;
1072 Line1[i].y--;
1073 }
1074 for(i = 0; i < Line2N; i++)
1075 {
1076 Line2[i].x--;
1077 Line2[i].y--;
1078 }
1079
1080 /* Make the final picture */
1081 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
1082 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
1083 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
1084
1085 Polygon(dc, Line1, Line1N);
1086 if(Line2N > 0)
1087 Polygon(dc, Line2, Line2N);
1088 SelectObject(dc, hpsave);
1089 SelectObject(dc, hbsave);
1090
1091 return TRUE;
1092}
1093
1094
1095/************************************************************************
1096 * UITOOLS_DrawFrameScroll
1097 *
1098 * Draw a scroll-bar control coming from DrawFrameControl()
1099 */
1100static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
1101{
1102 POINT Line[4];
1103 RECT myr;
1104 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2;
1105 int i;
1106 HBRUSH hbsave, hb, hb2;
1107 HPEN hpsave, hp, hp2;
1108 int tri = 310*SmallDiam/1000;
1109 int d46, d93;
1110
1111 switch(uFlags & 0xff)
1112 {
1113 case DFCS_SCROLLCOMBOBOX:
1114 case DFCS_SCROLLDOWN:
1115 Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1116 Line[2].y = myr.top + 687*SmallDiam/1000 + 1;
1117 Line[0].x = Line[2].x - tri;
1118 Line[1].x = Line[2].x + tri;
1119 Line[0].y = Line[1].y = Line[2].y - tri;
1120 break;
1121
1122 case DFCS_SCROLLUP:
1123 Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1124 Line[2].y = myr.top + 313*SmallDiam/1000 + 1;
1125 Line[0].x = Line[2].x - tri;
1126 Line[1].x = Line[2].x + tri;
1127 Line[0].y = Line[1].y = Line[2].y + tri;
1128 break;
1129
1130 case DFCS_SCROLLLEFT:
1131 Line[2].x = myr.left + 313*SmallDiam/1000 + 1;
1132 Line[2].y = myr.top + 470*SmallDiam/1000 + 2;
1133 Line[0].y = Line[2].y - tri;
1134 Line[1].y = Line[2].y + tri;
1135 Line[0].x = Line[1].x = Line[2].x + tri;
1136 break;
1137
1138 case DFCS_SCROLLRIGHT:
1139 Line[2].x = myr.left + 687*SmallDiam/1000 + 1;
1140 Line[2].y = myr.top + 470*SmallDiam/1000 + 2;
1141 Line[0].y = Line[2].y - tri;
1142 Line[1].y = Line[2].y + tri;
1143 Line[0].x = Line[1].x = Line[2].x - tri;
1144 break;
1145
1146 case DFCS_SCROLLSIZEGRIP:
1147 /* This one breaks the flow... */
1148 UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0));
1149 hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN));
1150 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));
1151 if(uFlags & (DFCS_MONO|DFCS_FLAT))
1152 {
1153 hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME);
1154 hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME);
1155 }
1156 else
1157 {
1158 hp = GetSysColorPen(COLOR_BTNHIGHLIGHT);
1159 hp2 = GetSysColorPen(COLOR_BTNSHADOW);
1160 hb = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
1161 hb2 = GetSysColorBrush(COLOR_BTNSHADOW);
1162 }
1163 Line[0].x = Line[1].x = r->right-1;
1164 Line[2].y = Line[3].y = r->bottom-1;
1165 d46 = 46*SmallDiam/750;
1166 d93 = 93*SmallDiam/750;
1167
1168 i = 586*SmallDiam/750;
1169 Line[0].y = r->bottom - i - 1;
1170 Line[3].x = r->right - i - 1;
1171 Line[1].y = Line[0].y + d46;
1172 Line[2].x = Line[3].x + d46;
1173 SelectObject(dc, hb);
1174 SelectObject(dc, hp);
1175 Polygon(dc, Line, 4);
1176
1177 Line[1].y++; Line[2].x++;
1178 Line[0].y = Line[1].y + d93;
1179 Line[3].x = Line[2].x + d93;
1180 SelectObject(dc, hb2);
1181 SelectObject(dc, hp2);
1182 Polygon(dc, Line, 4);
1183
1184 i = 398*SmallDiam/750;
1185 Line[0].y = r->bottom - i - 1;
1186 Line[3].x = r->right - i - 1;
1187 Line[1].y = Line[0].y + d46;
1188 Line[2].x = Line[3].x + d46;
1189 SelectObject(dc, hb);
1190 SelectObject(dc, hp);
1191 Polygon(dc, Line, 4);
1192
1193 Line[1].y++; Line[2].x++;
1194 Line[0].y = Line[1].y + d93;
1195 Line[3].x = Line[2].x + d93;
1196 SelectObject(dc, hb2);
1197 SelectObject(dc, hp2);
1198 Polygon(dc, Line, 4);
1199
1200 i = 210*SmallDiam/750;
1201 Line[0].y = r->bottom - i - 1;
1202 Line[3].x = r->right - i - 1;
1203 Line[1].y = Line[0].y + d46;
1204 Line[2].x = Line[3].x + d46;
1205 SelectObject(dc, hb);
1206 SelectObject(dc, hp);
1207 Polygon(dc, Line, 4);
1208
1209 Line[1].y++; Line[2].x++;
1210 Line[0].y = Line[1].y + d93;
1211 Line[3].x = Line[2].x + d93;
1212 SelectObject(dc, hb2);
1213 SelectObject(dc, hp2);
1214 Polygon(dc, Line, 4);
1215
1216 SelectObject(dc, hpsave);
1217 SelectObject(dc, hbsave);
1218 return TRUE;
1219
1220 default:
1221// WARN("Invalid scroll; flags=0x%04x\n", uFlags);
1222 return FALSE;
1223 }
1224
1225 /* Here do the real scroll-bar controls end up */
1226 UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00);
1227
1228 if(uFlags & DFCS_INACTIVE)
1229 {
1230 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1231 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1232 Polygon(dc, Line, 3);
1233 SelectObject(dc, hpsave);
1234 SelectObject(dc, hbsave);
1235 }
1236
1237 for(i = 0; i < 3; i++)
1238 {
1239 Line[i].x--;
1240 Line[i].y--;
1241 }
1242
1243 i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
1244 hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
1245 hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
1246 Polygon(dc, Line, 3);
1247 SelectObject(dc, hpsave);
1248 SelectObject(dc, hbsave);
1249
1250 return TRUE;
1251}
1252
1253/************************************************************************
1254 * UITOOLS_DrawFrameMenu
1255 *
1256 * Draw a menu control coming from DrawFrameControl()
1257 */
1258static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
1259{
1260 POINT Points[6];
1261 RECT myr;
1262 int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
1263 int i;
1264 HBRUSH hbsave;
1265 HPEN hpsave;
1266 int xe, ye;
1267 int xc, yc;
1268 BOOL retval = TRUE;
1269
1270 /* Using black and white seems to be utterly wrong, but win95 doesn't */
1271 /* use anything else. I think I tried all sys-colors to change things */
1272 /* without luck. It seems as if this behavior is inherited from the */
1273 /* win31 DFC() implementation... (you remember, B/W menus). */
1274
1275 FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH));
1276
1277 hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
1278 hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN));
1279
1280 switch(uFlags & 0xff)
1281 {
1282 case DFCS_MENUARROW:
1283 i = 187*SmallDiam/750;
1284 Points[2].x = myr.left + 468*SmallDiam/750;
1285 Points[2].y = myr.top + 352*SmallDiam/750+1;
1286 Points[0].y = Points[2].y - i;
1287 Points[1].y = Points[2].y + i;
1288 Points[0].x = Points[1].x = Points[2].x - i;
1289 Polygon(dc, Points, 3);
1290 break;
1291
1292 case DFCS_MENUBULLET:
1293 xe = myr.left;
1294 ye = myr.top + SmallDiam - SmallDiam/2;
1295 xc = myr.left + SmallDiam - SmallDiam/2;
1296 yc = myr.top + SmallDiam - SmallDiam/2;
1297 i = 234*SmallDiam/750;
1298 i = i < 1 ? 1 : i;
1299 myr.left = xc - i+i/2;
1300 myr.right = xc + i/2;
1301 myr.top = yc - i+i/2;
1302 myr.bottom = yc + i/2;
1303 Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
1304 break;
1305
1306 case DFCS_MENUCHECK:
1307 Points[0].x = myr.left + 253*SmallDiam/1000;
1308 Points[0].y = myr.top + 445*SmallDiam/1000;
1309 Points[1].x = myr.left + 409*SmallDiam/1000;
1310 Points[1].y = Points[0].y + (Points[1].x-Points[0].x);
1311 Points[2].x = myr.left + 690*SmallDiam/1000;
1312 Points[2].y = Points[1].y - (Points[2].x-Points[1].x);
1313 Points[3].x = Points[2].x;
1314 Points[3].y = Points[2].y + 3*SmallDiam/16;
1315 Points[4].x = Points[1].x;
1316 Points[4].y = Points[1].y + 3*SmallDiam/16;
1317 Points[5].x = Points[0].x;
1318 Points[5].y = Points[0].y + 3*SmallDiam/16;
1319 Polygon(dc, Points, 6);
1320 break;
1321
1322 default:
1323// WARN("Invalid menu; flags=0x%04x\n", uFlags);
1324 retval = FALSE;
1325 break;
1326 }
1327
1328 SelectObject(dc, hpsave);
1329 SelectObject(dc, hbsave);
1330 return retval;
1331}
1332
1333/**********************************************************************
1334 * DrawFrameControl (USER32.158)
1335 */
1336BOOL WIN32API DrawFrameControl(HDC hdc, LPRECT rc, UINT uType,
1337 UINT uState )
1338{
1339 /* Win95 doesn't support drawing in other mapping modes */
1340 if(GetMapMode(hdc) != MM_TEXT)
1341 return FALSE;
1342
1343 switch(uType)
1344 {
1345 case DFC_BUTTON:
1346 return UITOOLS95_DrawFrameButton(hdc, rc, uState);
1347 case DFC_CAPTION:
1348 return UITOOLS95_DrawFrameCaption(hdc, rc, uState);
1349 case DFC_MENU:
1350 return UITOOLS95_DrawFrameMenu(hdc, rc, uState);
1351 case DFC_SCROLL:
1352 return UITOOLS95_DrawFrameScroll(hdc, rc, uState);
1353// default:
1354// WARN("(%x,%p,%d,%x), bad type!\n",
1355// hdc,rc,uType,uState );
1356 }
1357 return FALSE;
1358}
Note: See TracBrowser for help on using the repository browser.