📄 winctrls.c
字号:
xpos = (cp->width + GAPBETWEEN) * percent / 100; left = xpos + GAPBETWEEN; percent += percents[i]; xpos = (cp->width + GAPBETWEEN) * percent / 100; wid = xpos - left; switch (i) { case 1: /* The drag list box. */ r.left = left; r.right = wid; r.top = cp->ypos; r.bottom = listheight; { HWND ctl; ctl = doctl(cp, r, "LISTBOX", WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS | LBS_USETABSTOPS, WS_EX_CLIENTEDGE, "", listid); MakeDragList(ctl); } break; case 2: /* The "Up" and "Down" buttons. */ /* XXX worry about accelerators if we have more than one * prefslist on a panel */ r.left = left; r.right = wid; r.top = cp->ypos + buttonpos; r.bottom = PUSHBTNHEIGHT; doctl(cp, r, "BUTTON", BS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, 0, "&Up", upbid); r.left = left; r.right = wid; r.top = cp->ypos + buttonpos + PUSHBTNHEIGHT + GAPBETWEEN; r.bottom = PUSHBTNHEIGHT; doctl(cp, r, "BUTTON", BS_NOTIFY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, 0, "&Down", dnbid); break; } } cp->ypos += totalheight + GAPBETWEEN;}/* * Helper function for prefslist: move item in list box. */static void pl_moveitem(HWND hwnd, int listid, int src, int dst){ int tlen, val; char *txt; /* Get the item's data. */ tlen = SendDlgItemMessage (hwnd, listid, LB_GETTEXTLEN, src, 0); txt = snewn(tlen+1, char); SendDlgItemMessage (hwnd, listid, LB_GETTEXT, src, (LPARAM) txt); val = SendDlgItemMessage (hwnd, listid, LB_GETITEMDATA, src, 0); /* Deselect old location. */ SendDlgItemMessage (hwnd, listid, LB_SETSEL, FALSE, src); /* Delete it at the old location. */ SendDlgItemMessage (hwnd, listid, LB_DELETESTRING, src, 0); /* Insert it at new location. */ SendDlgItemMessage (hwnd, listid, LB_INSERTSTRING, dst, (LPARAM) txt); SendDlgItemMessage (hwnd, listid, LB_SETITEMDATA, dst, (LPARAM) val); /* Set selection. */ SendDlgItemMessage (hwnd, listid, LB_SETCURSEL, dst, 0); sfree (txt);}int pl_itemfrompt(HWND hwnd, POINT cursor, BOOL scroll){ int ret; POINT uppoint, downpoint; int updist, downdist, upitem, downitem, i; /* * Ghastly hackery to try to figure out not which * _item_, but which _gap between items_, the user * is pointing at. We do this by first working out * which list item is under the cursor, and then * working out how far the cursor would have to * move up or down before the answer was different. * Then we put the insertion point _above_ the * current item if the upper edge is closer than * the lower edge, or _below_ it if vice versa. */ ret = LBItemFromPt(hwnd, cursor, scroll); if (ret == -1) return ret; ret = LBItemFromPt(hwnd, cursor, FALSE); updist = downdist = 0; for (i = 1; i < 4096 && (!updist || !downdist); i++) { uppoint = downpoint = cursor; uppoint.y -= i; downpoint.y += i; upitem = LBItemFromPt(hwnd, uppoint, FALSE); downitem = LBItemFromPt(hwnd, downpoint, FALSE); if (!updist && upitem != ret) updist = i; if (!downdist && downitem != ret) downdist = i; } if (downdist < updist) ret++; return ret;}/* * Handler for prefslist above. * * Return value has bit 0 set if the dialog box procedure needs to * return TRUE from handling this message; it has bit 1 set if a * change may have been made in the contents of the list. */int handle_prefslist(struct prefslist *hdl, int *array, int maxmemb, int is_dlmsg, HWND hwnd, WPARAM wParam, LPARAM lParam){ int i; int ret = 0; if (is_dlmsg) { if ((int)wParam == hdl->listid) { DRAGLISTINFO *dlm = (DRAGLISTINFO *)lParam; int dest = 0; /* initialise to placate gcc */ switch (dlm->uNotification) { case DL_BEGINDRAG: hdl->dummyitem = SendDlgItemMessage(hwnd, hdl->listid, LB_ADDSTRING, 0, (LPARAM) ""); hdl->srcitem = LBItemFromPt(dlm->hWnd, dlm->ptCursor, TRUE); hdl->dragging = 0; /* XXX hack Q183115 */ SetWindowLong(hwnd, DWL_MSGRESULT, TRUE); ret |= 1; break; case DL_CANCELDRAG: DrawInsert(hwnd, dlm->hWnd, -1); /* Clear arrow */ SendDlgItemMessage(hwnd, hdl->listid, LB_DELETESTRING, hdl->dummyitem, 0); hdl->dragging = 0; ret |= 1; break; case DL_DRAGGING: hdl->dragging = 1; dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE); if (dest > hdl->dummyitem) dest = hdl->dummyitem; DrawInsert (hwnd, dlm->hWnd, dest); if (dest >= 0) SetWindowLong(hwnd, DWL_MSGRESULT, DL_MOVECURSOR); else SetWindowLong(hwnd, DWL_MSGRESULT, DL_STOPCURSOR); ret |= 1; break; case DL_DROPPED: if (hdl->dragging) { dest = pl_itemfrompt(dlm->hWnd, dlm->ptCursor, TRUE); if (dest > hdl->dummyitem) dest = hdl->dummyitem; DrawInsert (hwnd, dlm->hWnd, -1); } SendDlgItemMessage(hwnd, hdl->listid, LB_DELETESTRING, hdl->dummyitem, 0); if (hdl->dragging) { hdl->dragging = 0; if (dest >= 0) { /* Correct for "missing" item. */ if (dest > hdl->srcitem) dest--; pl_moveitem(hwnd, hdl->listid, hdl->srcitem, dest); } ret |= 2; } ret |= 1; break; } } } else { if (((LOWORD(wParam) == hdl->upbid) || (LOWORD(wParam) == hdl->dnbid)) && ((HIWORD(wParam) == BN_CLICKED) || (HIWORD(wParam) == BN_DOUBLECLICKED))) { /* Move an item up or down the list. */ /* Get the current selection, if any. */ int selection = SendDlgItemMessage (hwnd, hdl->listid, LB_GETCURSEL, 0, 0); if (selection == LB_ERR) { MessageBeep(0); } else { int nitems; /* Get the total number of items. */ nitems = SendDlgItemMessage (hwnd, hdl->listid, LB_GETCOUNT, 0, 0); /* Should we do anything? */ if (LOWORD(wParam) == hdl->upbid && (selection > 0)) pl_moveitem(hwnd, hdl->listid, selection, selection - 1); else if (LOWORD(wParam) == hdl->dnbid && (selection < nitems - 1)) pl_moveitem(hwnd, hdl->listid, selection, selection + 1); ret |= 2; } } } if (array) { /* Update array to match the list box. */ for (i=0; i < maxmemb; i++) array[i] = SendDlgItemMessage (hwnd, hdl->listid, LB_GETITEMDATA, i, 0); } return ret;}/* * A progress bar (from Common Controls). We like our progress bars * to be smooth and unbroken, without those ugly divisions; some * older compilers may not support that, but that's life. */void progressbar(struct ctlpos *cp, int id){ RECT r; r.left = GAPBETWEEN; r.top = cp->ypos; r.right = cp->width; r.bottom = PROGBARHEIGHT; cp->ypos += r.bottom + GAPBETWEEN; doctl(cp, r, PROGRESS_CLASS, WS_CHILD | WS_VISIBLE#ifdef PBS_SMOOTH | PBS_SMOOTH#endif , WS_EX_CLIENTEDGE, "", id);}/* ---------------------------------------------------------------------- * Platform-specific side of portable dialog-box mechanism. *//* * This function takes a string, escapes all the ampersands, and * places a single (unescaped) ampersand in front of the first * occurrence of the given shortcut character (which may be * NO_SHORTCUT). * * Return value is a malloc'ed copy of the processed version of the * string. */static char *shortcut_escape(char *text, char shortcut){ char *ret; char *p, *q; if (!text) return NULL; /* sfree won't choke on this */ ret = snewn(2*strlen(text)+1, char); /* size potentially doubles! */ shortcut = tolower((unsigned char)shortcut); p = text; q = ret; while (*p) { if (shortcut != NO_SHORTCUT && tolower((unsigned char)*p) == shortcut) { *q++ = '&'; shortcut = NO_SHORTCUT; /* stop it happening twice */ } else if (*p == '&') { *q++ = '&'; } *q++ = *p++; } *q = '\0'; return ret;}void winctrl_add_shortcuts(struct dlgparam *dp, struct winctrl *c){ int i; for (i = 0; i < lenof(c->shortcuts); i++) if (c->shortcuts[i] != NO_SHORTCUT) { unsigned char s = tolower((unsigned char)c->shortcuts[i]); assert(!dp->shortcuts[s]); dp->shortcuts[s] = TRUE; }}void winctrl_rem_shortcuts(struct dlgparam *dp, struct winctrl *c){ int i; for (i = 0; i < lenof(c->shortcuts); i++) if (c->shortcuts[i] != NO_SHORTCUT) { unsigned char s = tolower((unsigned char)c->shortcuts[i]); assert(dp->shortcuts[s]); dp->shortcuts[s] = FALSE; }}static int winctrl_cmp_byctrl(void *av, void *bv){ struct winctrl *a = (struct winctrl *)av; struct winctrl *b = (struct winctrl *)bv; if (a->ctrl < b->ctrl) return -1; else if (a->ctrl > b->ctrl) return +1; else return 0;}static int winctrl_cmp_byid(void *av, void *bv){ struct winctrl *a = (struct winctrl *)av; struct winctrl *b = (struct winctrl *)bv; if (a->base_id < b->base_id) return -1; else if (a->base_id > b->base_id) return +1; else return 0;}static int winctrl_cmp_byctrl_find(void *av, void *bv){ union control *a = (union control *)av; struct winctrl *b = (struct winctrl *)bv; if (a < b->ctrl) return -1; else if (a > b->ctrl) return +1; else return 0;}static int winctrl_cmp_byid_find(void *av, void *bv){ int *a = (int *)av; struct winctrl *b = (struct winctrl *)bv; if (*a < b->base_id) return -1; else if (*a >= b->base_id + b->num_ids) return +1; else return 0;}void winctrl_init(struct winctrls *wc){ wc->byctrl = newtree234(winctrl_cmp_byctrl); wc->byid = newtree234(winctrl_cmp_byid);}void winctrl_cleanup(struct winctrls *wc){ struct winctrl *c; while ((c = index234(wc->byid, 0)) != NULL) { winctrl_remove(wc, c); sfree(c->data); sfree(c); } freetree234(wc->byctrl); freetree234(wc->byid); wc->byctrl = wc->byid = NULL;}void winctrl_add(struct winctrls *wc, struct winctrl *c){ struct winctrl *ret; if (c->ctrl) { ret = add234(wc->byctrl, c); assert(ret == c); } ret = add234(wc->byid, c); assert(ret == c);}void winctrl_remove(struct winctrls *wc, struct winctrl *c){ struct winctrl *ret; ret = del234(wc->byctrl, c); ret = del234(wc->byid, c); assert(ret == c);}struct winctrl *winctrl_findbyctrl(struct winctrls *wc, union control *ctrl){ return find234(wc->byctrl, ctrl, winctrl_cmp_byctrl_find);}struct winctrl *winctrl_findbyid(struct winctrls *wc, int id){ return find234(wc->byid, &id, winctrl_cmp_byid_find);}struct winctrl *winctrl_findbyindex(struct winctrls *wc, int index){ return index234(wc->byid, index);}void winctrl_layout(struct dlgparam *dp, struct winctrls *wc, struct ctlpos *cp, struct controlset *s, int *id){ struct ctlpos columns[16]; int ncols, colstart, colspan; struct ctlpos tabdelays[16]; union control *tabdelayed[16]; int ntabdelays; struct ctlpos pos; char shortcuts[MAX_SHORTCUTS_PER_CTRL]; int nshortcuts; char *escaped; int i, actual_base_id, base_id, num_ids; void *data; base_id = *id; /* Start a containing box, if we have a boxname. */ if (s->boxname && *s->boxname) { struct winctrl *c = snew(struct winctrl); c->ctrl = NULL; c->base_id = base_id; c->num_ids = 1; c->data = NULL; memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts)); winctrl_add(wc, c); beginbox(cp, s->boxtitle, base_id); base_id++; } /* Draw a title, if we have one. */ if (!s->boxname && s->boxtitle) { struct winctrl *c = snew(struct winctrl); c->ctrl = NULL; c->base_id = base_id; c->num_ids = 1; c->data = dupstr(s->boxtitle); memset(c->shortcuts, NO_SHORTCUT, lenof(c->shortcuts)); winctrl_add(wc, c); paneltitle(cp, base_id); base_id++; } /* Initially we have just one column. */ ncols = 1; columns[0] = *cp; /* structure copy */ /* And initially, there are no pending tab-delayed controls. */ ntabdelays = 0; /* Loop over each control in the controlset. */ for (i = 0; i < s->ncontrols; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -