📄 winctrls.c
字号:
if (!ctrl || !ctrl->generic.handler)
return 0; /* nothing we can do here */
/*
* From here on we do not issue `return' statements until the
* very end of the dialog box: any event handler is entitled to
* ask for a colour selector, so we _must_ always allow control
* to reach the end of this switch statement so that the
* subsequent code can test dp->coloursel_wanted().
*/
ret = 0;
dp->coloursel_wanted = FALSE;
/*
* Now switch on the control type and the message.
*/
switch (ctrl->generic.type) {
case CTRL_EDITBOX:
if (msg == WM_COMMAND && !ctrl->editbox.has_list &&
(HIWORD(wParam) == EN_SETFOCUS || HIWORD(wParam) == EN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == EN_SETFOCUS);
if (msg == WM_COMMAND && ctrl->editbox.has_list &&
(HIWORD(wParam)==CBN_SETFOCUS || HIWORD(wParam)==CBN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == CBN_SETFOCUS);
if (msg == WM_COMMAND && !ctrl->editbox.has_list &&
HIWORD(wParam) == EN_CHANGE)
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
if (msg == WM_COMMAND &&
ctrl->editbox.has_list) {
if (HIWORD(wParam) == CBN_SELCHANGE) {
int index, len;
char *text;
index = SendDlgItemMessage(dp->hwnd, c->base_id+1,
CB_GETCURSEL, 0, 0);
len = SendDlgItemMessage(dp->hwnd, c->base_id+1,
CB_GETLBTEXTLEN, index, 0);
text = snewn(len+1, char);
SendDlgItemMessage(dp->hwnd, c->base_id+1, CB_GETLBTEXT,
index, (LPARAM)text);
SetDlgItemText(dp->hwnd, c->base_id+1, text);
sfree(text);
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
} else if (HIWORD(wParam) == CBN_EDITCHANGE) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
} else if (HIWORD(wParam) == CBN_KILLFOCUS) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_REFRESH);
}
}
break;
case CTRL_RADIO:
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
/*
* We sometimes get spurious BN_CLICKED messages for the
* radio button that is just about to _lose_ selection, if
* we're switching using the arrow keys. Therefore we
* double-check that the button in wParam is actually
* checked before generating an event.
*/
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) &&
IsDlgButtonChecked(dp->hwnd, LOWORD(wParam))) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
}
break;
case CTRL_CHECKBOX:
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED)) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
}
break;
case CTRL_BUTTON:
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
if (msg == WM_COMMAND &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED)) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_ACTION);
}
break;
case CTRL_LISTBOX:
if (msg == WM_COMMAND && ctrl->listbox.height != 0 &&
(HIWORD(wParam)==LBN_SETFOCUS || HIWORD(wParam)==LBN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == LBN_SETFOCUS);
if (msg == WM_COMMAND && ctrl->listbox.height == 0 &&
(HIWORD(wParam)==CBN_SETFOCUS || HIWORD(wParam)==CBN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == CBN_SETFOCUS);
if (msg == WM_COMMAND && id >= 2 &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
if (ctrl->listbox.draglist) {
int pret;
pret = handle_prefslist(c->data, NULL, 0, (msg != WM_COMMAND),
dp->hwnd, wParam, lParam);
if (pret & 2)
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
ret = pret & 1;
} else {
if (msg == WM_COMMAND && HIWORD(wParam) == LBN_DBLCLK) {
SetCapture(dp->hwnd);
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_ACTION);
} else if (msg == WM_COMMAND && HIWORD(wParam) == LBN_SELCHANGE) {
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_SELCHANGE);
}
}
break;
case CTRL_FILESELECT:
if (msg == WM_COMMAND && id == 1 &&
(HIWORD(wParam) == EN_SETFOCUS || HIWORD(wParam) == EN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == EN_SETFOCUS);
if (msg == WM_COMMAND && id == 2 &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
if (msg == WM_COMMAND && id == 1 && HIWORD(wParam) == EN_CHANGE)
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
if (id == 2 &&
(msg == WM_COMMAND &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED))) {
OPENFILENAME of;
char filename[FILENAME_MAX];
int ret;
memset(&of, 0, sizeof(of));
#ifdef OPENFILENAME_SIZE_VERSION_400
of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
of.lStructSize = sizeof(of);
#endif
of.hwndOwner = dp->hwnd;
if (ctrl->fileselect.filter)
of.lpstrFilter = ctrl->fileselect.filter;
else
of.lpstrFilter = "All Files (*.*)\0*\0\0\0";
of.lpstrCustomFilter = NULL;
of.nFilterIndex = 1;
of.lpstrFile = filename;
GetDlgItemText(dp->hwnd, c->base_id+1, filename, lenof(filename));
filename[lenof(filename)-1] = '\0';
of.nMaxFile = lenof(filename);
of.lpstrFileTitle = NULL;
of.lpstrInitialDir = NULL;
of.lpstrTitle = ctrl->fileselect.title;
of.Flags = 0;
if (ctrl->fileselect.for_writing)
ret = GetSaveFileName(&of);
else
ret = GetOpenFileName(&of);
if (ret) {
SetDlgItemText(dp->hwnd, c->base_id + 1, filename);
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
}
}
break;
case CTRL_FONTSELECT:
if (msg == WM_COMMAND && id == 2 &&
(HIWORD(wParam) == BN_SETFOCUS || HIWORD(wParam) == BN_KILLFOCUS))
winctrl_set_focus(ctrl, dp, HIWORD(wParam) == BN_SETFOCUS);
if (id == 2 &&
(msg == WM_COMMAND &&
(HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED))) {
CHOOSEFONT cf;
LOGFONT lf;
HDC hdc;
FontSpec fs = *(FontSpec *)c->data;
hdc = GetDC(0);
lf.lfHeight = -MulDiv(fs.height,
GetDeviceCaps(hdc, LOGPIXELSY), 72);
ReleaseDC(0, hdc);
lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
lf.lfItalic = lf.lfUnderline = lf.lfStrikeOut = 0;
lf.lfWeight = (fs.isbold ? FW_BOLD : 0);
lf.lfCharSet = fs.charset;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
strncpy(lf.lfFaceName, fs.name,
sizeof(lf.lfFaceName) - 1);
lf.lfFaceName[sizeof(lf.lfFaceName) - 1] = '\0';
cf.lStructSize = sizeof(cf);
cf.hwndOwner = dp->hwnd;
cf.lpLogFont = &lf;
cf.Flags = CF_FIXEDPITCHONLY | CF_FORCEFONTEXIST |
CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
if (ChooseFont(&cf)) {
strncpy(fs.name, lf.lfFaceName,
sizeof(fs.name) - 1);
fs.name[sizeof(fs.name) - 1] = '\0';
fs.isbold = (lf.lfWeight == FW_BOLD);
fs.charset = lf.lfCharSet;
fs.height = cf.iPointSize / 10;
dlg_fontsel_set(ctrl, dp, fs);
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_VALCHANGE);
}
}
break;
}
/*
* If the above event handler has asked for a colour selector,
* now is the time to generate one.
*/
if (dp->coloursel_wanted) {
static CHOOSECOLOR cc;
static DWORD custom[16] = { 0 }; /* zero initialisers */
cc.lStructSize = sizeof(cc);
cc.hwndOwner = dp->hwnd;
cc.hInstance = (HWND) hinst;
cc.lpCustColors = custom;
cc.rgbResult = RGB(dp->coloursel_result.r,
dp->coloursel_result.g,
dp->coloursel_result.b);
cc.Flags = CC_FULLOPEN | CC_RGBINIT;
if (ChooseColor(&cc)) {
dp->coloursel_result.r =
(unsigned char) (cc.rgbResult & 0xFF);
dp->coloursel_result.g =
(unsigned char) (cc.rgbResult >> 8) & 0xFF;
dp->coloursel_result.b =
(unsigned char) (cc.rgbResult >> 16) & 0xFF;
dp->coloursel_result.ok = TRUE;
} else
dp->coloursel_result.ok = FALSE;
ctrl->generic.handler(ctrl, dp, dp->data, EVENT_CALLBACK);
}
return ret;
}
/*
* This function can be called to produce context help on a
* control. Returns TRUE if it has actually launched WinHelp.
*/
int winctrl_context_help(struct dlgparam *dp, HWND hwnd, int id)
{
int i;
struct winctrl *c;
char *cmd;
/*
* Look up the control ID in our data.
*/
c = NULL;
for (i = 0; i < dp->nctrltrees; i++) {
c = winctrl_findbyid(dp->controltrees[i], id);
if (c)
break;
}
if (!c)
return 0; /* we have nothing to do */
/*
* This is the Windows front end, so we're allowed to assume
* `helpctx.p' is a context string.
*/
if (!c->ctrl || !c->ctrl->generic.helpctx.p)
return 0; /* no help available for this ctrl */
cmd = dupprintf("JI(`',`%s')", c->ctrl->generic.helpctx.p);
WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
sfree(cmd);
return 1;
}
/*
* Now the various functions that the platform-independent
* mechanism can call to access the dialog box entries.
*/
static struct winctrl *dlg_findbyctrl(struct dlgparam *dp, union control *ctrl)
{
int i;
for (i = 0; i < dp->nctrltrees; i++) {
struct winctrl *c = winctrl_findbyctrl(dp->controltrees[i], ctrl);
if (c)
return c;
}
return NULL;
}
void dlg_radiobutton_set(union control *ctrl, void *dlg, int whichbutton)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
assert(c && c->ctrl->generic.type == CTRL_RADIO);
CheckRadioButton(dp->hwnd,
c->base_id + 1,
c->base_id + c->ctrl->radio.nbuttons,
c->base_id + 1 + whichbutton);
}
int dlg_radiobutton_get(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int i;
assert(c && c->ctrl->generic.type == CTRL_RADIO);
for (i = 0; i < c->ctrl->radio.nbuttons; i++)
if (IsDlgButtonChecked(dp->hwnd, c->base_id + 1 + i))
return i;
assert(!"No radio button was checked?!");
return 0;
}
void dlg_checkbox_set(union control *ctrl, void *dlg, int checked)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
assert(c && c->ctrl->generic.type == CTRL_CHECKBOX);
CheckDlgButton(dp->hwnd, c->base_id, (checked != 0));
}
int dlg_checkbox_get(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
assert(c && c->ctrl->generic.type == CTRL_CHECKBOX);
return 0 != IsDlgButtonChecked(dp->hwnd, c->base_id);
}
void dlg_editbox_set(union control *ctrl, void *dlg, char const *text)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
assert(c && c->ctrl->generic.type == CTRL_EDITBOX);
SetDlgItemText(dp->hwnd, c->base_id+1, text);
}
void dlg_editbox_get(union control *ctrl, void *dlg, char *buffer, int length)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
assert(c && c->ctrl->generic.type == CTRL_EDITBOX);
GetDlgItemText(dp->hwnd, c->base_id+1, buffer, length);
buffer[length-1] = '\0';
}
/* The `listbox' functions can also apply to combo boxes. */
void dlg_listbox_clear(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
(c->ctrl->generic.type == CTRL_EDITBOX &&
c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_RESETCONTENT : CB_RESETCONTENT);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, 0, 0);
}
void dlg_listbox_del(union control *ctrl, void *dlg, int index)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
(c->ctrl->generic.type == CTRL_EDITBOX &&
c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_DELETESTRING : CB_DELETESTRING);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, index, 0);
}
void dlg_listbox_add(union control *ctrl, void *dlg, char const *text)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
(c->ctrl->generic.type == CTRL_EDITBOX &&
c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_ADDSTRING : CB_ADDSTRING);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, 0, (LPARAM)text);
}
/*
* Each listbox entry may have a numeric id associated with it.
* Note that some front ends only permit a string to be stored at
* each position, which means that _if_ you put two identical
* strings in any listbox then you MUST not assign them different
* IDs and expect to get meaningful results back.
*/
void dlg_listbox_addwithid(union control *ctrl, void *dlg,
char const *text, int id)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg, msg2, index;
assert(c &&
(c->ctrl->generic.type == CTRL_LISTBOX ||
(c->ctrl->generic.type == CTRL_EDITBOX &&
c->ctrl->editbox.has_list)));
msg = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_ADDSTRING : CB_ADDSTRING);
msg2 = (c->ctrl->generic.type==CTRL_LISTBOX && c->ctrl->listbox.height!=0 ?
LB_SETITEMDATA : CB_SETITEMDATA);
index = SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, 0, (LPARAM)text);
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg2, index, (LPARAM)id);
}
int dlg_listbox_getid(union control *ctrl, void *dlg, int index)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg;
assert(c && c->ctrl->generic.type == CTRL_LISTBOX);
msg = (c->ctrl->listbox.height != 0 ? LB_GETITEMDATA : CB_GETITEMDATA);
return
SendDlgItemMessage(dp->hwnd, c->base_id+1, msg, index, 0);
}
/* dlg_listbox_index returns <0 if no single element is selected. */
int dlg_listbox_index(union control *ctrl, void *dlg)
{
struct dlgparam *dp = (struct dlgparam *)dlg;
struct winctrl *c = dlg_findbyctrl(dp, ctrl);
int msg, ret;
assert(c && c->ctrl->generic.type == CTRL_LISTBOX &&
!c->ctrl->listbox.multisel);
msg = (c->ctrl->listbox.height != 0 ? LB_GETCURSEL : CB_GETCURSEL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -