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
) {
28 cp
->font
= SendMessage(hwnd
, WM_GETFONT
, 0, 0);
30 GetClientRect(hwnd
, &r
);
34 MapDialogRect(hwnd
, &r2
);
35 cp
->dlu4inpix
= r2
.right
;
36 cp
->width
= (r
.right
* 4) / (r2
.right
) - 2*GAPBETWEEN
;
37 cp
->xoff
= leftborder
;
38 cp
->width
-= leftborder
+ rightborder
;
41 void doctl(struct ctlpos
*cp
, RECT r
,
42 char *wclass
, int wstyle
, int exstyle
,
43 char *wtext
, int wid
) {
46 * Note nonstandard use of RECT. This is deliberate: by
47 * transforming the width and height directly we arrange to
48 * have all supposedly same-sized controls really same-sized.
52 MapDialogRect(cp
->hwnd
, &r
);
54 ctl
= CreateWindowEx(exstyle
, wclass
, wtext
, wstyle
,
55 r
.left
, r
.top
, r
.right
, r
.bottom
,
56 cp
->hwnd
, (HMENU
)wid
, hinst
, NULL
);
57 SendMessage(ctl
, WM_SETFONT
, cp
->font
, MAKELPARAM(TRUE
, 0));
61 * A title bar across the top of a sub-dialog.
63 void bartitle(struct ctlpos
*cp
, char *name
, int id
) {
66 r
.left
= GAPBETWEEN
; r
.right
= cp
->width
;
67 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
68 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
69 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, name
, id
);
73 * Begin a grouping box, with or without a group title.
75 void beginbox(struct ctlpos
*cp
, char *name
, int idbox
) {
76 cp
->boxystart
= cp
->ypos
;
78 cp
->boxystart
-= STATICHEIGHT
/2;
80 cp
->ypos
+= STATICHEIGHT
;
82 cp
->width
-= 2*GAPXBOX
;
91 void endbox(struct ctlpos
*cp
) {
94 cp
->width
+= 2*GAPXBOX
;
95 cp
->ypos
+= GAPYBOX
- GAPBETWEEN
;
96 r
.left
= GAPBETWEEN
; r
.right
= cp
->width
;
97 r
.top
= cp
->boxystart
; r
.bottom
= cp
->ypos
- cp
->boxystart
;
98 doctl(cp
, r
, "BUTTON", BS_GROUPBOX
| WS_CHILD
| WS_VISIBLE
, 0,
99 cp
->boxtext ? cp
->boxtext
: "", cp
->boxid
);
104 * Some edit boxes. Each one has a static above it. The percentages
105 * of the horizontal space are provided.
107 void multiedit(struct ctlpos
*cp
, ...) {
116 int staticid
, editid
, pcwidth
;
117 text
= va_arg(ap
, char *);
120 staticid
= va_arg(ap
, int);
121 editid
= va_arg(ap
, int);
122 pcwidth
= va_arg(ap
, int);
124 r
.left
= xpos
+ GAPBETWEEN
;
126 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
127 r
.right
= xpos
- r
.left
;
129 r
.top
= cp
->ypos
; r
.bottom
= STATICHEIGHT
;
130 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
132 r
.top
= cp
->ypos
+ 8 + GAPWITHIN
; r
.bottom
= EDITHEIGHT
;
134 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
139 cp
->ypos
+= 8+GAPWITHIN
+12+GAPBETWEEN
;
143 * A set of radio buttons on the same line, with a static above
144 * them. `nacross' dictates how many parts the line is divided into
145 * (you might want this not to equal the number of buttons if you
146 * needed to line up some 2s and some 3s to look good in the same
149 void radioline(struct ctlpos
*cp
,
150 char *text
, int id
, int nacross
, ...) {
156 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
157 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
158 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
159 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
160 va_start(ap
, nacross
);
166 btext
= va_arg(ap
, char *);
169 bid
= va_arg(ap
, int);
170 r
.left
= GAPBETWEEN
+ i
* (cp
->width
+GAPBETWEEN
)/nacross
;
171 r
.right
= (i
+1) * (cp
->width
+GAPBETWEEN
)/nacross
- r
.left
;
172 r
.top
= cp
->ypos
; r
.bottom
= RADIOHEIGHT
;
173 doctl(cp
, r
, "BUTTON",
174 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
181 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
185 * A set of radio buttons on multiple lines, with a static above
188 void radiobig(struct ctlpos
*cp
, char *text
, int id
, ...) {
193 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
194 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
195 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
196 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
202 btext
= va_arg(ap
, char *);
205 bid
= va_arg(ap
, int);
206 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
207 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
208 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
209 doctl(cp
, r
, "BUTTON",
210 BS_AUTORADIOBUTTON
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| group
,
216 cp
->ypos
+= GAPBETWEEN
- GAPWITHIN
;
220 * A single standalone checkbox.
222 void checkbox(struct ctlpos
*cp
, char *text
, int id
) {
225 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
226 r
.right
= cp
->width
; r
.bottom
= CHECKBOXHEIGHT
;
227 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
228 doctl(cp
, r
, "BUTTON",
229 BS_AUTOCHECKBOX
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
, 0,
234 * A single standalone static text control.
236 void statictext(struct ctlpos
*cp
, char *text
, int id
) {
239 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
240 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
241 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
242 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, id
);
246 * A button on the right hand side, with a static to its left.
248 void staticbtn(struct ctlpos
*cp
, char *stext
, int sid
,
249 char *btext
, int bid
) {
250 const int height
= (PUSHBTNHEIGHT
> STATICHEIGHT ?
251 PUSHBTNHEIGHT
: STATICHEIGHT
);
253 int lwid
, rwid
, rpos
;
255 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
256 lwid
= rpos
- 2*GAPBETWEEN
;
257 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
259 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
260 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
261 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
263 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
264 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
265 doctl(cp
, r
, "BUTTON",
266 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
270 cp
->ypos
+= height
+ GAPBETWEEN
;
274 * An edit control on the right hand side, with a static to its left.
276 static void staticedit_internal(struct ctlpos
*cp
, char *stext
,
277 int sid
, int eid
, int percentedit
,
279 const int height
= (EDITHEIGHT
> STATICHEIGHT ?
280 EDITHEIGHT
: STATICHEIGHT
);
282 int lwid
, rwid
, rpos
;
284 rpos
= GAPBETWEEN
+ (100-percentedit
) * (cp
->width
+ GAPBETWEEN
) / 100;
285 lwid
= rpos
- 2*GAPBETWEEN
;
286 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
288 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
289 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
290 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
292 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
293 r
.right
= rwid
; r
.bottom
= EDITHEIGHT
;
295 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
| style
,
299 cp
->ypos
+= height
+ GAPBETWEEN
;
302 void staticedit(struct ctlpos
*cp
, char *stext
,
303 int sid
, int eid
, int percentedit
) {
304 staticedit_internal(cp
, stext
, sid
, eid
, percentedit
, 0);
307 void staticpassedit(struct ctlpos
*cp
, char *stext
,
308 int sid
, int eid
, int percentedit
) {
309 staticedit_internal(cp
, stext
, sid
, eid
, percentedit
, ES_PASSWORD
);
313 * A big multiline edit control with a static labelling it.
315 void bigeditctrl(struct ctlpos
*cp
, char *stext
,
316 int sid
, int eid
, int lines
) {
319 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
320 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
321 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
322 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
324 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
325 r
.right
= cp
->width
; r
.bottom
= EDITHEIGHT
+ (lines
-1) * STATICHEIGHT
;
326 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
328 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| ES_MULTILINE
,
334 * A tab-control substitute when a real tab control is unavailable.
336 void ersatztab(struct ctlpos
*cp
, char *stext
, int sid
,
338 const int height
= (COMBOHEIGHT
> STATICHEIGHT ?
339 COMBOHEIGHT
: STATICHEIGHT
);
341 int bigwid
, lwid
, rwid
, rpos
;
342 static const int BIGGAP
= 15;
343 static const int MEDGAP
= 3;
345 bigwid
= cp
->width
+ 2*GAPBETWEEN
- 2*BIGGAP
;
347 rpos
= BIGGAP
+ (bigwid
+ BIGGAP
) / 2;
348 lwid
= rpos
- 2*BIGGAP
;
349 rwid
= bigwid
+ BIGGAP
- rpos
;
351 r
.left
= BIGGAP
; r
.top
= cp
->ypos
+ (height
-STATICHEIGHT
)/2;
352 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
353 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
355 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-COMBOHEIGHT
)/2;
356 r
.right
= rwid
; r
.bottom
= COMBOHEIGHT
*10;
357 doctl(cp
, r
, "COMBOBOX",
358 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
|
359 CBS_DROPDOWNLIST
| CBS_HASSTRINGS
,
363 cp
->ypos
+= height
+ MEDGAP
+ GAPBETWEEN
;
365 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
366 r
.right
= cp
->width
; r
.bottom
= 2;
367 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_ETCHEDHORZ
,
372 * A static line, followed by an edit control on the left hand side
373 * and a button on the right.
375 void editbutton(struct ctlpos
*cp
, char *stext
, int sid
,
376 int eid
, char *btext
, int bid
) {
377 const int height
= (EDITHEIGHT
> PUSHBTNHEIGHT ?
378 EDITHEIGHT
: PUSHBTNHEIGHT
);
380 int lwid
, rwid
, rpos
;
382 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
383 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
384 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
385 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
387 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
388 lwid
= rpos
- 2*GAPBETWEEN
;
389 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
391 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
+ (height
-EDITHEIGHT
)/2;
392 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
394 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
398 r
.left
= rpos
; r
.top
= cp
->ypos
+ (height
-PUSHBTNHEIGHT
)/2;
399 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
400 doctl(cp
, r
, "BUTTON",
401 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
405 cp
->ypos
+= height
+ GAPBETWEEN
;
409 * Special control which was hard to describe generically: the
410 * session-saver assembly. A static; below that an edit box; below
411 * that a list box. To the right of the list box, a column of
414 void sesssaver(struct ctlpos
*cp
, char *text
,
415 int staticid
, int editid
, int listid
, ...) {
418 int lwid
, rwid
, rpos
;
420 const int LISTDEFHEIGHT
= 66;
422 rpos
= GAPBETWEEN
+ 3 * (cp
->width
+ GAPBETWEEN
) / 4;
423 lwid
= rpos
- 2*GAPBETWEEN
;
424 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
426 /* The static control. */
427 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
428 r
.right
= lwid
; r
.bottom
= STATICHEIGHT
;
429 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
430 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, text
, staticid
);
432 /* The edit control. */
433 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
434 r
.right
= lwid
; r
.bottom
= EDITHEIGHT
;
435 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
437 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
442 * The buttons (we should hold off on the list box until we
443 * know how big the buttons are).
445 va_start(ap
, listid
);
448 char *btext
= va_arg(ap
, char *);
451 bid
= va_arg(ap
, int);
452 r
.left
= rpos
; r
.top
= y
;
453 r
.right
= rwid
; r
.bottom
= PUSHBTNHEIGHT
;
454 y
+= r
.bottom
+ GAPWITHIN
;
455 doctl(cp
, r
, "BUTTON",
456 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
461 /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
464 if (y
< LISTDEFHEIGHT
) y
= LISTDEFHEIGHT
;
465 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
466 r
.right
= lwid
; r
.bottom
= y
;
467 cp
->ypos
+= y
+ GAPBETWEEN
;
468 doctl(cp
, r
, "LISTBOX",
469 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
|
470 LBS_NOTIFY
| LBS_HASSTRINGS
,
476 * Another special control: the environment-variable setter. A
477 * static line first; then a pair of edit boxes with associated
478 * statics, and two buttons; then a list box.
480 void envsetter(struct ctlpos
*cp
, char *stext
, int sid
,
481 char *e1stext
, int e1sid
, int e1id
,
482 char *e2stext
, int e2sid
, int e2id
,
484 char *b1text
, int b1id
, char *b2text
, int b2id
) {
486 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
488 EDITHEIGHT
> PUSHBTNHEIGHT ?
489 EDITHEIGHT
: PUSHBTNHEIGHT
);
490 const static int percents
[] = { 20, 35, 10, 25 };
491 int i
, j
, xpos
, percent
;
492 const int LISTHEIGHT
= 42;
494 /* The static control. */
495 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
496 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
497 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
498 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
500 /* The statics+edits+buttons. */
501 for (j
= 0; j
< 2; j
++) {
503 for (i
= 0; i
< 4; i
++) {
504 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
505 r
.left
= xpos
+ GAPBETWEEN
;
506 percent
+= percents
[i
];
507 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
508 r
.right
= xpos
- r
.left
;
510 r
.bottom
= (i
==0 ? STATICHEIGHT
:
513 r
.top
+= (height
-r
.bottom
)/2;
515 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0,
516 j
==0 ? e1stext
: e2stext
, j
==0 ? e1sid
: e2sid
);
519 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
521 "", j
==0 ? e1id
: e2id
);
523 doctl(cp
, r
, "BUTTON",
524 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
526 j
==0 ? b1text
: b2text
, j
==0 ? b1id
: b2id
);
529 cp
->ypos
+= height
+ GAPWITHIN
;
533 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
534 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
535 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
536 doctl(cp
, r
, "LISTBOX",
537 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
544 * Yet another special control: the character-class setter. A
545 * static, then a list, then a line containing a
546 * button-and-static-and-edit.
548 void charclass(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
549 char *btext
, int bid
, int eid
, char *s2text
, int s2id
) {
551 const int height
= (STATICHEIGHT
> EDITHEIGHT
&& STATICHEIGHT
> PUSHBTNHEIGHT ?
553 EDITHEIGHT
> PUSHBTNHEIGHT ?
554 EDITHEIGHT
: PUSHBTNHEIGHT
);
555 const static int percents
[] = { 30, 40, 30 };
556 int i
, xpos
, percent
;
557 const int LISTHEIGHT
= 66;
559 /* The static control. */
560 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
561 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
562 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
563 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
566 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
567 r
.right
= cp
->width
; r
.bottom
= LISTHEIGHT
;
568 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
569 doctl(cp
, r
, "LISTBOX",
570 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
575 /* The button+static+edit. */
577 for (i
= 0; i
< 3; i
++) {
578 r
.left
= xpos
+ GAPBETWEEN
;
579 percent
+= percents
[i
];
580 xpos
= (cp
->width
+ GAPBETWEEN
) * percent
/ 100;
581 r
.right
= xpos
- r
.left
;
583 r
.bottom
= (i
==0 ? PUSHBTNHEIGHT
:
584 i
==1 ? STATICHEIGHT
:
586 r
.top
+= (height
-r
.bottom
)/2;
588 doctl(cp
, r
, "BUTTON",
589 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
592 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
596 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| ES_AUTOHSCROLL
,
597 WS_EX_CLIENTEDGE
, "", eid
);
600 cp
->ypos
+= height
+ GAPBETWEEN
;
604 * A special control (horrors!). The colour editor. A static line;
605 * then on the left, a list box, and on the right, a sequence of
606 * two-part statics followed by a button.
608 void colouredit(struct ctlpos
*cp
, char *stext
, int sid
, int listid
,
609 char *btext
, int bid
, ...) {
613 int lwid
, rwid
, rpos
;
614 const int LISTHEIGHT
= 66;
616 /* The static control. */
617 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
618 r
.right
= cp
->width
; r
.bottom
= STATICHEIGHT
;
619 cp
->ypos
+= r
.bottom
+ GAPWITHIN
;
620 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, stext
, sid
);
622 rpos
= GAPBETWEEN
+ 2 * (cp
->width
+ GAPBETWEEN
) / 3;
623 lwid
= rpos
- 2*GAPBETWEEN
;
624 rwid
= cp
->width
+ GAPBETWEEN
- rpos
;
627 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
628 r
.right
= lwid
; r
.bottom
= LISTHEIGHT
;
629 doctl(cp
, r
, "LISTBOX",
630 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_VSCROLL
| LBS_HASSTRINGS
|
631 LBS_USETABSTOPS
| LBS_NOTIFY
,
641 ltext
= va_arg(ap
, char *);
643 lid
= va_arg(ap
, int);
644 rid
= va_arg(ap
, int);
645 r
.top
= y
; r
.bottom
= STATICHEIGHT
;
646 y
+= r
.bottom
+ GAPWITHIN
;
647 r
.left
= rpos
; r
.right
= rwid
/2;
648 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
, 0, ltext
, lid
);
649 r
.left
= rpos
+ r
.right
; r
.right
= rwid
- r
.right
;
650 doctl(cp
, r
, "STATIC", WS_CHILD
| WS_VISIBLE
| SS_RIGHT
, 0, "", rid
);
655 r
.top
= y
+ 2*GAPWITHIN
; r
.bottom
= PUSHBTNHEIGHT
;
656 r
.left
= rpos
; r
.right
= rwid
;
657 doctl(cp
, r
, "BUTTON",
658 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| BS_PUSHBUTTON
,
661 cp
->ypos
+= LISTHEIGHT
+ GAPBETWEEN
;
665 * A progress bar (from Common Controls). We like our progress bars
666 * to be smooth and unbroken, without those ugly divisions; some
667 * older compilers may not support that, but that's life.
669 void progressbar(struct ctlpos
*cp
, int id
) {
672 r
.left
= GAPBETWEEN
; r
.top
= cp
->ypos
;
673 r
.right
= cp
->width
; r
.bottom
= PROGBARHEIGHT
;
674 cp
->ypos
+= r
.bottom
+ GAPBETWEEN
;
676 doctl(cp
, r
, PROGRESS_CLASS
,
677 WS_CHILD
| WS_VISIBLE
681 , WS_EX_CLIENTEDGE
, "", id
);