2 * winctrls.c: routines to self-manage the controls in a dialog
16 #define STATICHEIGHT 8
17 #define CHECKBOXHEIGHT 8
20 #define COMBOHEIGHT 12
21 #define PUSHBTNHEIGHT 14
22 #define PROGBARHEIGHT 14
24 void ctlposinit(struct ctlpos
*cp
, HWND hwnd
,
25 int leftborder
, int rightborder
, int topborder
)
29 cp
->font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
31 GetClientRect(hwnd
, &r
);
35 MapDialogRect(hwnd
, &r2
);
36 cp
->dlu4inpix
= r2
.right
;
37 cp
->width
= (r
.right
* 4) / (r2
.right
) - 2 * GAPBETWEEN
;
38 cp
->xoff
= leftborder
;
39 cp
->width
-= leftborder
+ rightborder
;
42 void doctl(struct ctlpos
*cp
, RECT r
,
43 char *wclass
, int wstyle
, int exstyle
, char *wtext
, int wid
)
47 * Note nonstandard use of RECT. This is deliberate: by
48 * transforming the width and height directly we arrange to
49 * have all supposedly same-sized controls really same-sized.
53 MapDialogRect(cp
->hwnd
, &r
);
55 ctl
= CreateWindowEx(exstyle
, wclass
, wtext
, wstyle
,
56 r
.left
, r
.top
, r
.right
, r
.bottom
,
57 cp
->hwnd
, (HMENU
) wid
, hinst
, NULL
);
58 SendMessage(ctl
, WM_SETFONT
, cp
->font
, MAKELPARAM(TRUE
, 0));
62 * A title bar across the top of a sub-dialog.
64 void bartitle(struct ctlpos
*cp
, char *name
, int id
)
71 r
.bottom
= STATICHEIGHT
;
72 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
73 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, name
, id
);
77 * Begin a grouping box, with or without a group title.
79 void beginbox(struct ctlpos
*cp
, char *name
, int idbox
)
81 cp
->boxystart
= cp
->ypos
;
83 cp
->boxystart
-= STATICHEIGHT
/ 2;
85 cp
->ypos
+= STATICHEIGHT
;
87 cp
->width
-= 2 * GAPXBOX
;
96 void endbox(struct ctlpos
*cp
)
100 cp
->width
+= 2 * GAPXBOX
;
101 cp
->ypos
+= GAPYBOX
- GAPBETWEEN
;
104 r
.top
= cp
->boxystart
;
105 r
.bottom
= cp
->ypos
- cp
->boxystart
;
106 doctl(cp
, r
, "BUTTON", BS_GROUPBOX
| WS_CHILD
| WS_VISIBLE
, 0,
107 cp
->boxtext ? cp
->boxtext
: "", cp
->boxid
);
112 * Some edit boxes. Each one has a static above it. The percentages
113 * of the horizontal space are provided.
115 void multiedit(struct ctlpos
*cp
, ...)
125 int staticid
, editid
, pcwidth
;
126 text
= va_arg(ap
, char *);
129 staticid
= va_arg(ap
, int);
130 editid
= va_arg(ap
, int);
131 pcwidth
= va_arg(ap
, int);
133 r
.left
= xpos
+ GAPBETWEEN
;
135 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
136 r
.right
= xpos
- r
.left
;
139 r
.bottom
= STATICHEIGHT
;
140 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
141 r
.top
= cp
->ypos
+ 8 + GAPWITHIN
;
142 r
.bottom
= EDITHEIGHT
;
144 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
145 WS_EX_CLIENTEDGE
, "", editid
);
148 cp
->ypos
+= 8 + GAPWITHIN
+ 12 + GAPBETWEEN
;
151 static void radioline_common(struct ctlpos
*cp
, int nacross
, va_list ap
)
160 btext
= va_arg(ap
, char *);
167 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
170 bid
= va_arg(ap
, int);
171 nextbtext
= va_arg(ap
, char *);
172 r
.left
= GAPBETWEEN
+ i
* (cp
->width
+ GAPBETWEEN
) / nacross
;
175 (i
+ 1) * (cp
->width
+ GAPBETWEEN
) / nacross
- r
.left
;
177 r
.right
= cp
->width
- r
.left
;
179 r
.bottom
= RADIOHEIGHT
;
180 doctl(cp
, r
, "BUTTON",
181 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
182 group
, 0, btext
, bid
);
187 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
191 * A set of radio buttons on the same line, with a static above
192 * them. `nacross' dictates how many parts the line is divided into
193 * (you might want this not to equal the number of buttons if you
194 * needed to line up some 2s and some 3s to look good in the same
197 * There's a bit of a hack in here to ensure that if nacross
198 * exceeds the actual number of buttons, the rightmost button
199 * really does get all the space right to the edge of the line, so
200 * you can do things like
202 * (*) Button1 (*) Button2 (*) ButtonWithReallyLongTitle
204 void radioline(struct ctlpos
*cp
, char *text
, int id
, int nacross
, ...)
212 r
.bottom
= STATICHEIGHT
;
213 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
214 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
215 va_start(ap
, nacross
);
216 radioline_common(cp
, nacross
, ap
);
221 * A set of radio buttons on the same line, without a static above
222 * them. Otherwise just like radioline.
224 void bareradioline(struct ctlpos
*cp
, int nacross
, ...)
228 va_start(ap
, nacross
);
229 radioline_common(cp
, nacross
, ap
);
234 * A set of radio buttons on multiple lines, with a static above
237 void radiobig(struct ctlpos
*cp
, char *text
, int id
, ...)
246 r
.bottom
= STATICHEIGHT
;
247 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
248 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
254 btext
= va_arg(ap
, char *);
257 bid
= va_arg(ap
, int);
261 r
.bottom
= STATICHEIGHT
;
262 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
263 doctl(cp
, r
, "BUTTON",
264 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
265 group
, 0, btext
, bid
);
269 cp
->ypos
+= GAPBETWEEN
- GAPWITHIN
;
273 * A single standalone checkbox.
275 void checkbox(struct ctlpos
*cp
, char *text
, int id
)
282 r
.bottom
= CHECKBOXHEIGHT
;
283 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
284 doctl(cp
, r
, "BUTTON",
285 BS_AUTOCHECKBOX
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
, 0,
290 * A single standalone static text control.
292 void statictext(struct ctlpos
*cp
, char *text
, int id
)
299 r
.bottom
= STATICHEIGHT
;
300 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
301 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
305 * A button on the right hand side, with a static to its left.
307 void staticbtn(struct ctlpos
*cp
, char *stext
, int sid
,
308 char *btext
, int bid
)
310 const int height
= (PUSHBTNHEIGHT
> STATICHEIGHT ?
311 PUSHBTNHEIGHT
: STATICHEIGHT
);
313 int lwid
, rwid
, rpos
;
315 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
316 lwid
= rpos
- 2 * GAPBETWEEN
;
317 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
320 r
.top
= cp
->ypos
+ (height
- STATICHEIGHT
) / 2;
322 r
.bottom
= STATICHEIGHT
;
323 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
326 r
.top
= cp
->ypos
+ (height
- PUSHBTNHEIGHT
) / 2;
328 r
.bottom
= PUSHBTNHEIGHT
;
329 doctl(cp
, r
, "BUTTON",
330 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
333 cp
->ypos
+= height
+ GAPBETWEEN
;
337 * An edit control on the right hand side, with a static to its left.
339 static void staticedit_internal(struct ctlpos
*cp
, char *stext
,
340 int sid
, int eid
, int percentedit
,
343 const int height
= (EDITHEIGHT
> STATICHEIGHT ?
344 EDITHEIGHT
: STATICHEIGHT
);
346 int lwid
, rwid
, rpos
;
349 GAPBETWEEN
+ (100 - percentedit
) * (cp
->width
+ GAPBETWEEN
) / 100;
350 lwid
= rpos
- 2 * GAPBETWEEN
;
351 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
354 r
.top
= cp
->ypos
+ (height
- STATICHEIGHT
) / 2;
356 r
.bottom
= STATICHEIGHT
;
357 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
360 r
.top
= cp
->ypos
+ (height
- EDITHEIGHT
) / 2;
362 r
.bottom
= EDITHEIGHT
;
364 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
| style
,
365 WS_EX_CLIENTEDGE
, "", eid
);
367 cp
->ypos
+= height
+ GAPBETWEEN
;
370 void staticedit(struct ctlpos
*cp
, char *stext
,
371 int sid
, int eid
, int percentedit
)
373 staticedit_internal(cp
, stext
, sid
, eid
, percentedit
, 0);
376 void staticpassedit(struct ctlpos
*cp
, char *stext
,
377 int sid
, int eid
, int percentedit
)
379 staticedit_internal(cp
, stext
, sid
, eid
, percentedit
, ES_PASSWORD
);
383 * A big multiline edit control with a static labelling it.
385 void bigeditctrl(struct ctlpos
*cp
, char *stext
,
386 int sid
, int eid
, int lines
)
393 r
.bottom
= STATICHEIGHT
;
394 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
395 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
400 r
.bottom
= EDITHEIGHT
+ (lines
- 1) * STATICHEIGHT
;
401 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
403 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| ES_MULTILINE
,
404 WS_EX_CLIENTEDGE
, "", eid
);
408 * A tab-control substitute when a real tab control is unavailable.
410 void ersatztab(struct ctlpos
*cp
, char *stext
, int sid
, int lid
, int s2id
)
412 const int height
= (COMBOHEIGHT
> STATICHEIGHT ?
413 COMBOHEIGHT
: STATICHEIGHT
);
415 int bigwid
, lwid
, rwid
, rpos
;
416 static const int BIGGAP
= 15;
417 static const int MEDGAP
= 3;
419 bigwid
= cp
->width
+ 2 * GAPBETWEEN
- 2 * BIGGAP
;
421 rpos
= BIGGAP
+ (bigwid
+ BIGGAP
) / 2;
422 lwid
= rpos
- 2 * BIGGAP
;
423 rwid
= bigwid
+ BIGGAP
- rpos
;
426 r
.top
= cp
->ypos
+ (height
- STATICHEIGHT
) / 2;
428 r
.bottom
= STATICHEIGHT
;
429 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
432 r
.top
= cp
->ypos
+ (height
- COMBOHEIGHT
) / 2;
434 r
.bottom
= COMBOHEIGHT
* 10;
435 doctl(cp
, r
, "COMBOBOX",
436 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
437 CBS_DROPDOWNLIST
| CBS_HASSTRINGS
, WS_EX_CLIENTEDGE
, "", lid
);
439 cp
->ypos
+= height
+ MEDGAP
+ GAPBETWEEN
;
445 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDHORZ
,
450 * A static line, followed by an edit control on the left hand side
451 * and a button on the right.
453 void editbutton(struct ctlpos
*cp
, char *stext
, int sid
,
454 int eid
, char *btext
, int bid
)
456 const int height
= (EDITHEIGHT
> PUSHBTNHEIGHT ?
457 EDITHEIGHT
: PUSHBTNHEIGHT
);
459 int lwid
, rwid
, rpos
;
464 r
.bottom
= STATICHEIGHT
;
465 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
466 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
468 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
469 lwid
= rpos
- 2 * GAPBETWEEN
;
470 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
473 r
.top
= cp
->ypos
+ (height
- EDITHEIGHT
) / 2;
475 r
.bottom
= EDITHEIGHT
;
477 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
478 WS_EX_CLIENTEDGE
, "", eid
);
481 r
.top
= cp
->ypos
+ (height
- PUSHBTNHEIGHT
) / 2;
483 r
.bottom
= PUSHBTNHEIGHT
;
484 doctl(cp
, r
, "BUTTON",
485 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
488 cp
->ypos
+= height
+ GAPBETWEEN
;
492 * Special control which was hard to describe generically: the
493 * session-saver assembly. A static; below that an edit box; below
494 * that a list box. To the right of the list box, a column of
497 void sesssaver(struct ctlpos
*cp
, char *text
,
498 int staticid
, int editid
, int listid
, ...)
502 int lwid
, rwid
, rpos
;
504 const int LISTDEFHEIGHT
= 66;
506 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
507 lwid
= rpos
- 2 * GAPBETWEEN
;
508 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
510 /* The static control. */
514 r
.bottom
= STATICHEIGHT
;
515 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
516 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
518 /* The edit control. */
522 r
.bottom
= EDITHEIGHT
;
523 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
525 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
526 WS_EX_CLIENTEDGE
, "", editid
);
529 * The buttons (we should hold off on the list box until we
530 * know how big the buttons are).
532 va_start(ap
, listid
);
535 char *btext
= va_arg(ap
, char *);
539 bid
= va_arg(ap
, int);
543 r
.bottom
= PUSHBTNHEIGHT
;
544 y
+= r
.bottom
+ GAPWITHIN
;
545 doctl(cp
, r
, "BUTTON",
546 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
550 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
553 if (y
< LISTDEFHEIGHT
)
559 cp
->ypos
+= y
+ GAPBETWEEN
;
560 doctl(cp
, r
, "LISTBOX",
561 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
|
562 LBS_NOTIFY
| LBS_HASSTRINGS
, WS_EX_CLIENTEDGE
, "", listid
);
566 * Another special control: the environment-variable setter. A
567 * static line first; then a pair of edit boxes with associated
568 * statics, and two buttons; then a list box.
570 void envsetter(struct ctlpos
*cp
, char *stext
, int sid
,
571 char *e1stext
, int e1sid
, int e1id
,
572 char *e2stext
, int e2sid
, int e2id
,
573 int listid
, char *b1text
, int b1id
, char *b2text
, int b2id
)
576 const int height
= (STATICHEIGHT
> EDITHEIGHT
578 PUSHBTNHEIGHT ? STATICHEIGHT
: EDITHEIGHT
>
579 PUSHBTNHEIGHT ? EDITHEIGHT
: PUSHBTNHEIGHT
);
580 const static int percents
[] = { 20, 35, 10, 25 };
581 int i
, j
, xpos
, percent
;
582 const int LISTHEIGHT
= 42;
584 /* The static control. */
588 r
.bottom
= STATICHEIGHT
;
589 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
590 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
592 /* The statics+edits+buttons. */
593 for (j
= 0; j
< 2; j
++) {
595 for (i
= 0; i
< 4; i
++) {
596 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
597 r
.left
= xpos
+ GAPBETWEEN
;
598 percent
+= percents
[i
];
599 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
600 r
.right
= xpos
- r
.left
;
602 r
.bottom
= (i
== 0 ? STATICHEIGHT
:
603 i
== 1 ? EDITHEIGHT
: PUSHBTNHEIGHT
);
604 r
.top
+= (height
- r
.bottom
) / 2;
606 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
607 j
== 0 ? e1stext
: e2stext
, j
== 0 ? e1sid
: e2sid
);
610 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
611 WS_EX_CLIENTEDGE
, "", j
== 0 ? e1id
: e2id
);
613 doctl(cp
, r
, "BUTTON",
614 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
615 0, j
== 0 ? b1text
: b2text
, j
== 0 ? b1id
: b2id
);
618 cp
->ypos
+= height
+ GAPWITHIN
;
625 r
.bottom
= LISTHEIGHT
;
626 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
627 doctl(cp
, r
, "LISTBOX",
628 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
629 | LBS_USETABSTOPS
, WS_EX_CLIENTEDGE
, "", listid
);
633 * Yet another special control: the character-class setter. A
634 * static, then a list, then a line containing a
635 * button-and-static-and-edit.
637 void charclass(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
638 char *btext
, int bid
, int eid
, char *s2text
, int s2id
)
641 const int height
= (STATICHEIGHT
> EDITHEIGHT
643 PUSHBTNHEIGHT ? STATICHEIGHT
: EDITHEIGHT
>
644 PUSHBTNHEIGHT ? EDITHEIGHT
: PUSHBTNHEIGHT
);
645 const static int percents
[] = { 30, 40, 30 };
646 int i
, xpos
, percent
;
647 const int LISTHEIGHT
= 66;
649 /* The static control. */
653 r
.bottom
= STATICHEIGHT
;
654 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
655 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
661 r
.bottom
= LISTHEIGHT
;
662 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
663 doctl(cp
, r
, "LISTBOX",
664 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
665 | LBS_USETABSTOPS
, WS_EX_CLIENTEDGE
, "", listid
);
667 /* The button+static+edit. */
669 for (i
= 0; i
< 3; i
++) {
670 r
.left
= xpos
+ GAPBETWEEN
;
671 percent
+= percents
[i
];
672 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
673 r
.right
= xpos
- r
.left
;
675 r
.bottom
= (i
== 0 ? PUSHBTNHEIGHT
:
676 i
== 1 ? STATICHEIGHT
: EDITHEIGHT
);
677 r
.top
+= (height
- r
.bottom
) / 2;
679 doctl(cp
, r
, "BUTTON",
680 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
683 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
687 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
688 WS_EX_CLIENTEDGE
, "", eid
);
691 cp
->ypos
+= height
+ GAPBETWEEN
;
695 * A special control (horrors!). The colour editor. A static line;
696 * then on the left, a list box, and on the right, a sequence of
697 * two-part statics followed by a button.
699 void colouredit(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
700 char *btext
, int bid
, ...)
705 int lwid
, rwid
, rpos
;
706 const int LISTHEIGHT
= 66;
708 /* The static control. */
712 r
.bottom
= STATICHEIGHT
;
713 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
714 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
716 rpos
= GAPBETWEEN
+ 2 * (cp
->width
+ GAPBETWEEN
) / 3;
717 lwid
= rpos
- 2 * GAPBETWEEN
;
718 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
724 r
.bottom
= LISTHEIGHT
;
725 doctl(cp
, r
, "LISTBOX",
726 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
727 | LBS_USETABSTOPS
| LBS_NOTIFY
, WS_EX_CLIENTEDGE
, "", listid
);
735 ltext
= va_arg(ap
, char *);
738 lid
= va_arg(ap
, int);
739 rid
= va_arg(ap
, int);
741 r
.bottom
= STATICHEIGHT
;
742 y
+= r
.bottom
+ GAPWITHIN
;
745 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, ltext
, lid
);
746 r
.left
= rpos
+ r
.right
;
747 r
.right
= rwid
- r
.right
;
748 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_RIGHT
, 0, "",
754 r
.top
= y
+ 2 * GAPWITHIN
;
755 r
.bottom
= PUSHBTNHEIGHT
;
758 doctl(cp
, r
, "BUTTON",
759 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
762 cp
->ypos
+= LISTHEIGHT
+ GAPBETWEEN
;
766 * A progress bar (from Common Controls). We like our progress bars
767 * to be smooth and unbroken, without those ugly divisions; some
768 * older compilers may not support that, but that's life.
770 void progressbar(struct ctlpos
*cp
, int id
)
777 r
.bottom
= PROGBARHEIGHT
;
778 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
780 doctl(cp
, r
, PROGRESS_CLASS
, WS_CHILD
| WS_VISIBLE
784 , WS_EX_CLIENTEDGE
, "", id
);
788 * Another special control: the forwarding options setter. First a
789 * list box; next a static header line, introducing a pair of edit
790 * boxes with associated statics, another button, and a radio
793 void fwdsetter(struct ctlpos
*cp
, int listid
, char *stext
, int sid
,
794 char *e1stext
, int e1sid
, int e1id
,
795 char *e2stext
, int e2sid
, int e2id
,
796 char *btext
, int bid
)
799 const int height
= (STATICHEIGHT
> EDITHEIGHT
801 PUSHBTNHEIGHT ? STATICHEIGHT
: EDITHEIGHT
>
802 PUSHBTNHEIGHT ? EDITHEIGHT
: PUSHBTNHEIGHT
);
803 const static int percents
[] = { 25, 35, 15, 25 };
804 int i
, j
, xpos
, percent
;
805 const int LISTHEIGHT
= 42;
811 r
.bottom
= LISTHEIGHT
;
812 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
813 doctl(cp
, r
, "LISTBOX",
814 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
815 | LBS_USETABSTOPS
, WS_EX_CLIENTEDGE
, "", listid
);
817 /* The static control. */
821 r
.bottom
= STATICHEIGHT
;
822 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
823 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
825 /* The statics+edits+buttons. */
826 for (j
= 0; j
< 2; j
++) {
828 for (i
= 0; i
< (j ?
2 : 4); i
++) {
829 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
830 r
.left
= xpos
+ GAPBETWEEN
;
831 percent
+= percents
[i
];
832 if (j
==1 && i
==1) percent
= 100;
833 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
834 r
.right
= xpos
- r
.left
;
836 r
.bottom
= (i
== 0 ? STATICHEIGHT
:
837 i
== 1 ? EDITHEIGHT
: PUSHBTNHEIGHT
);
838 r
.top
+= (height
- r
.bottom
) / 2;
840 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
841 j
== 0 ? e1stext
: e2stext
, j
== 0 ? e1sid
: e2sid
);
844 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
845 WS_EX_CLIENTEDGE
, "", j
== 0 ? e1id
: e2id
);
847 doctl(cp
, r
, "BUTTON",
848 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
852 cp
->ypos
+= height
+ GAPWITHIN
;