⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winctrls.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * winctrls.c: routines to self-manage the controls in a dialog * box. *//* * Possible TODO in new cross-platform config box stuff: * *  - When lining up two controls alongside each other, I wonder if *    we could conveniently arrange to centre them vertically? *    Particularly ugly in the current setup is the `Add new *    forwarded port:' static next to the rather taller `Remove' *    button. */#include <assert.h>#include <ctype.h>#include "putty.h"#include "misc.h"#include "dialog.h"#include <commctrl.h>#define GAPBETWEEN 3#define GAPWITHIN 1#define GAPXBOX 7#define GAPYBOX 4#define DLGWIDTH 168#define STATICHEIGHT 8#define TITLEHEIGHT 12#define CHECKBOXHEIGHT 8#define RADIOHEIGHT 8#define EDITHEIGHT 12#define LISTHEIGHT 11#define LISTINCREMENT 8#define COMBOHEIGHT 12#define PUSHBTNHEIGHT 14#define PROGBARHEIGHT 14void ctlposinit(struct ctlpos *cp, HWND hwnd,		int leftborder, int rightborder, int topborder){    RECT r, r2;    cp->hwnd = hwnd;    cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);    cp->ypos = topborder;    GetClientRect(hwnd, &r);    r2.left = r2.top = 0;    r2.right = 4;    r2.bottom = 8;    MapDialogRect(hwnd, &r2);    cp->dlu4inpix = r2.right;    cp->width = (r.right * 4) / (r2.right) - 2 * GAPBETWEEN;    cp->xoff = leftborder;    cp->width -= leftborder + rightborder;}HWND doctl(struct ctlpos *cp, RECT r,	   char *wclass, int wstyle, int exstyle, char *wtext, int wid){    HWND ctl;    /*     * Note nonstandard use of RECT. This is deliberate: by     * transforming the width and height directly we arrange to     * have all supposedly same-sized controls really same-sized.     */    r.left += cp->xoff;    MapDialogRect(cp->hwnd, &r);    /*     * We can pass in cp->hwnd == NULL, to indicate a dry run     * without creating any actual controls.     */    if (cp->hwnd) {	ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,			     r.left, r.top, r.right, r.bottom,			     cp->hwnd, (HMENU) wid, hinst, NULL);	SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));	if (!strcmp(wclass, "LISTBOX")) {	    /*	     * Bizarre Windows bug: the list box calculates its	     * number of lines based on the font it has at creation	     * time, but sending it WM_SETFONT doesn't cause it to	     * recalculate. So now, _after_ we've sent it	     * WM_SETFONT, we explicitly resize it (to the same	     * size it was already!) to force it to reconsider.	     */	    SetWindowPos(ctl, NULL, 0, 0, r.right, r.bottom,			 SWP_NOACTIVATE | SWP_NOCOPYBITS |			 SWP_NOMOVE | SWP_NOZORDER);	}    } else	ctl = NULL;    return ctl;}/* * A title bar across the top of a sub-dialog. */void bartitle(struct ctlpos *cp, char *name, int id){    RECT r;    r.left = GAPBETWEEN;    r.right = cp->width;    r.top = cp->ypos;    r.bottom = STATICHEIGHT;    cp->ypos += r.bottom + GAPBETWEEN;    doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, name, id);}/* * Begin a grouping box, with or without a group title. */void beginbox(struct ctlpos *cp, char *name, int idbox){    cp->boxystart = cp->ypos;    if (!name)	cp->boxystart -= STATICHEIGHT / 2;    if (name)	cp->ypos += STATICHEIGHT;    cp->ypos += GAPYBOX;    cp->width -= 2 * GAPXBOX;    cp->xoff += GAPXBOX;    cp->boxid = idbox;    cp->boxtext = name;}/* * End a grouping box. */void endbox(struct ctlpos *cp){    RECT r;    cp->xoff -= GAPXBOX;    cp->width += 2 * GAPXBOX;    cp->ypos += GAPYBOX - GAPBETWEEN;    r.left = GAPBETWEEN;    r.right = cp->width;    r.top = cp->boxystart;    r.bottom = cp->ypos - cp->boxystart;    doctl(cp, r, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0,	  cp->boxtext ? cp->boxtext : "", cp->boxid);    cp->ypos += GAPYBOX;}/* * Some edit boxes. Each one has a static above it. The percentages * of the horizontal space are provided. */void multiedit(struct ctlpos *cp, int password, ...){    RECT r;    va_list ap;    int percent, xpos;    percent = xpos = 0;    va_start(ap, password);    while (1) {	char *text;	int staticid, editid, pcwidth;	text = va_arg(ap, char *);	if (!text)	    break;	staticid = va_arg(ap, int);	editid = va_arg(ap, int);	pcwidth = va_arg(ap, int);	r.left = xpos + GAPBETWEEN;	percent += pcwidth;	xpos = (cp->width + GAPBETWEEN) * percent / 100;	r.right = xpos - r.left;	r.top = cp->ypos;	r.bottom = STATICHEIGHT;	doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);	r.top = cp->ypos + 8 + GAPWITHIN;	r.bottom = EDITHEIGHT;	doctl(cp, r, "EDIT",	      WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL |	      (password ? ES_PASSWORD : 0),	      WS_EX_CLIENTEDGE, "", editid);    }    va_end(ap);    cp->ypos += STATICHEIGHT + GAPWITHIN + EDITHEIGHT + GAPBETWEEN;}/* * A static line, followed by a full-width combo box. */void combobox(struct ctlpos *cp, char *text, int staticid, int listid){    RECT r;    r.left = GAPBETWEEN;    r.right = cp->width;    r.top = cp->ypos;    r.bottom = STATICHEIGHT;    doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);    r.top = cp->ypos + 8 + GAPWITHIN;    r.bottom = COMBOHEIGHT * 10;    doctl(cp, r, "COMBOBOX",	  WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |	  CBS_DROPDOWN | CBS_HASSTRINGS, WS_EX_CLIENTEDGE, "", listid);    cp->ypos += STATICHEIGHT + GAPWITHIN + COMBOHEIGHT + GAPBETWEEN;}struct radio { char *text; int id; };static void radioline_common(struct ctlpos *cp, char *text, int id,			     int nacross, struct radio *buttons, int nbuttons){    RECT r;    int group;    int i;    int j;    if (text) {	r.left = GAPBETWEEN;	r.top = cp->ypos;	r.right = cp->width;	r.bottom = STATICHEIGHT;	cp->ypos += r.bottom + GAPWITHIN;	doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);    }    group = WS_GROUP;    i = 0;    for (j = 0; j < nbuttons; j++) {	char *btext = buttons[j].text;	int bid = buttons[j].id;	if (i == nacross) {	    cp->ypos += r.bottom + (nacross > 1 ? GAPBETWEEN : GAPWITHIN);	    i = 0;	}	r.left = GAPBETWEEN + i * (cp->width + GAPBETWEEN) / nacross;	if (j < nbuttons-1)	    r.right =		(i + 1) * (cp->width + GAPBETWEEN) / nacross - r.left;	else	    r.right = cp->width - r.left;	r.top = cp->ypos;	r.bottom = RADIOHEIGHT;	doctl(cp, r, "BUTTON",	      BS_NOTIFY | BS_AUTORADIOBUTTON | WS_CHILD |	      WS_VISIBLE | WS_TABSTOP | group, 0, btext, bid);	group = 0;	i++;    }    cp->ypos += r.bottom + GAPBETWEEN;}/* * A set of radio buttons on the same line, with a static above * them. `nacross' dictates how many parts the line is divided into * (you might want this not to equal the number of buttons if you * needed to line up some 2s and some 3s to look good in the same * panel). *  * There's a bit of a hack in here to ensure that if nacross * exceeds the actual number of buttons, the rightmost button * really does get all the space right to the edge of the line, so * you can do things like *  * (*) Button1  (*) Button2  (*) ButtonWithReallyLongTitle */void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...){    va_list ap;    struct radio *buttons;    int i, nbuttons;    va_start(ap, nacross);    nbuttons = 0;    while (1) {	char *btext = va_arg(ap, char *);	int bid;	if (!btext)	    break;	bid = va_arg(ap, int);	nbuttons++;    }    va_end(ap);    buttons = snewn(nbuttons, struct radio);    va_start(ap, nacross);    for (i = 0; i < nbuttons; i++) {	buttons[i].text = va_arg(ap, char *);	buttons[i].id = va_arg(ap, int);    }    va_end(ap);    radioline_common(cp, text, id, nacross, buttons, nbuttons);    sfree(buttons);}/* * A set of radio buttons on the same line, without a static above * them. Otherwise just like radioline. */void bareradioline(struct ctlpos *cp, int nacross, ...){    va_list ap;    struct radio *buttons;    int i, nbuttons;    va_start(ap, nacross);    nbuttons = 0;    while (1) {	char *btext = va_arg(ap, char *);	int bid;	if (!btext)	    break;	bid = va_arg(ap, int);    }    va_end(ap);    buttons = snewn(nbuttons, struct radio);    va_start(ap, nacross);    for (i = 0; i < nbuttons; i++) {	buttons[i].text = va_arg(ap, char *);	buttons[i].id = va_arg(ap, int);    }    va_end(ap);    radioline_common(cp, NULL, 0, nacross, buttons, nbuttons);    sfree(buttons);}/* * A set of radio buttons on multiple lines, with a static above * them. */void radiobig(struct ctlpos *cp, char *text, int id, ...){    va_list ap;    struct radio *buttons;    int i, nbuttons;    va_start(ap, id);    nbuttons = 0;    while (1) {	char *btext = va_arg(ap, char *);	int bid;	if (!btext)	    break;	bid = va_arg(ap, int);    }    va_end(ap);    buttons = snewn(nbuttons, struct radio);    va_start(ap, id);    for (i = 0; i < nbuttons; i++) {	buttons[i].text = va_arg(ap, char *);	buttons[i].id = va_arg(ap, int);    }    va_end(ap);    radioline_common(cp, text, id, 1, buttons, nbuttons);    sfree(buttons);}/* * A single standalone checkbox. */void checkbox(struct ctlpos *cp, char *text, int id){    RECT r;    r.left = GAPBETWEEN;    r.top = cp->ypos;    r.right = cp->width;    r.bottom = CHECKBOXHEIGHT;    cp->ypos += r.bottom + GAPBETWEEN;    doctl(cp, r, "BUTTON",	  BS_NOTIFY | BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,	  text, id);}/* * Wrap a piece of text for a static text control. Returns the * wrapped text (a malloc'ed string containing \ns), and also * returns the number of lines required. */char *staticwrap(struct ctlpos *cp, HWND hwnd, char *text, int *lines){    HDC hdc = GetDC(hwnd);    int lpx = GetDeviceCaps(hdc, LOGPIXELSX);    int width, nlines, j;    INT *pwidths, nfit;    SIZE size;    char *ret, *p, *q;    RECT r;    HFONT oldfont, newfont;    ret = snewn(1+strlen(text), char);    p = text;    q = ret;    pwidths = snewn(1+strlen(text), INT);    /*     * Work out the width the text will need to fit in, by doing     * the same adjustment that the `statictext' function itself     * will perform.     */    SetMapMode(hdc, MM_TEXT);	       /* ensure logical units == pixels */    r.left = r.top = r.bottom = 0;    r.right = cp->width;    MapDialogRect(hwnd, &r);    width = r.right;    nlines = 1;    /*     * We must select the correct font into the HDC before calling     * GetTextExtent*, or silly things will happen.     */    newfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0);    oldfont = SelectObject(hdc, newfont);    while (*p) {	if (!GetTextExtentExPoint(hdc, p, strlen(p), width,				  &nfit, pwidths, &size) ||	    (size_t)nfit >= strlen(p)) {	    /*	     * Either GetTextExtentExPoint returned failure, or the	     * whole of the rest of the text fits on this line.	     * Either way, we stop wrapping, copy the remainder of	     * the input string unchanged to the output, and leave.	     */	    strcpy(q, p);	    break;	}	/*	 * Now we search backwards along the string from `nfit',	 * looking for a space at which to break the line. If we	 * don't find one at all, that's fine - we'll just break	 * the line at `nfit'.	 */	for (j = nfit; j > 0; j--) {	    if (isspace((unsigned char)p[j])) {		nfit = j;		break;	    }	}	strncpy(q, p, nfit);	q[nfit] = '\n';	q += nfit+1;	p += nfit;	while (*p && isspace((unsigned char)*p))	    p++;	nlines++;    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -