📄 tkwinbutton.c
字号:
imgHeight = 0; haveImage = 0; } /* * Figure out font metrics (even if we don't have text because we need * DLUs (based on font, not text) for some spacing calculations below). */ Tk_FreeTextLayout(butPtr->textLayout); butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); txtWidth = butPtr->textWidth; txtHeight = butPtr->textHeight; haveText = (*(Tcl_GetString(butPtr->textPtr)) != '\0'); avgWidth = (Tk_TextWidth(butPtr->tkfont, "abcdefghijklmnopqurstuvwzyABCDEFGHIJKLMNOPQURSTUVWZY", 52) + 26) / 52; Tk_GetFontMetrics(butPtr->tkfont, &fm); /* Compute dialog units for layout calculations. */ hDLU = avgWidth / 4.0; vDLU = fm.linespace / 8.0; /* * First, let's try to compute button size "by the book" (See "Microsoft * Windows User Experience" (ISBN 0-7356-0566-1), Chapter 14 - Visual * Design, Section 4 - Layout (page 448)). * * Note, that Tk "buttons" are Microsoft "Command buttons", Tk * "checkbuttons" are Microsoft "check boxes", Tk "radiobuttons" are * Microsoft "option buttons", and Tk "labels" are Microsoft "text * labels". */ /* * Set width and height by button type; See User Experience table, p449. * These are text-based measurements, even if the text is "". * If there is an image, height will get set again later. */ switch (butPtr->type) { case TYPE_BUTTON: { /* * First compute the minimum width of the button in * characters. MWUE says that the button should be * 50 DLUs. We allow 6 DLUs padding left and right. * (There is no rule but this is consistent with the * fact that button text is 8 DLUs high and buttons * are 14 DLUs high.) * * The width is specified in characters. A character * is, by definition, 4 DLUs wide. 11 char * 4 DLU * is 44 DLU + 6 DLU padding = 50 DLU. Therefore, * width = -11 -> MWUE compliant buttons. */ if (butPtr->width < 0) { /* Min width in characters */ minWidth = -(butPtr->width); /* Allow for characters */ width = avgWidth * minWidth; /* Add for padding */ width += (int)(0.5 + (6 * hDLU)); } /* * If shrink-wrapping was requested (width = 0) or * if the text is wider than the default button width, * adjust the button width up to suit. */ if (butPtr->width == 0 || (txtWidth + (int)(0.5 + (6 * hDLU)) > width)) { width = txtWidth + (int)(0.5 + (6 * hDLU)); } /* * The User Experience says 14 DLUs. Since text is, by * definition, 8 DLU/line, this allows for multi-line text * while working perfectly for single-line text. */ height = txtHeight + (int)(0.5 + (6 * vDLU)); /* * The above includes 6 DLUs of padding which should include * defaults of 1 pixel of highlightwidth, 2 pixels of * borderwidth, 1 pixel of padding and 1 pixel of extra inset * on each side. Those will be added later so reduce width * and height now to compensate. */ width -= 10; height -= 10; if (!haveImage) { /* * Extra inset for the focus ring. */ butPtr->inset += 1; } break; } case TYPE_LABEL: { /* * The User Experience says, "as wide as needed". */ width = txtWidth; /* * The User Experience says, "8 (DLUs) per line of text." * Since text is, by definition, 8 DLU/line, this allows * for multi-line text while working perfectly for single-line * text. */ if (txtHeight) { height = txtHeight; } else { /* * If there's no text, we want the height to be one linespace. */ height = fm.linespace; } break; } case TYPE_RADIO_BUTTON: case TYPE_CHECK_BUTTON: { /* See note for TYPE_LABEL */ width = txtWidth; /* * The User Experience says 10 DLUs. (Is that one DLU above * and below for the focus ring?) See note above about * multi-line text and 8 DLU/line. */ height = txtHeight + (int)(0.5 + (2.0 * vDLU)); /* * The above includes 2 DLUs of padding which should include * defaults of 1 pixel of highlightwidth, 0 pixels of * borderwidth, and 1 pixel of padding on each side. Those * will be added later so reduce height now to compensate. */ height -= 4; /* * Extra inset for the focus ring. */ butPtr->inset += 1; break; } }/* switch */ /* * At this point, the width and height are correct for a Tk text * button, excluding padding and inset, but we have to allow for * compound buttons. The image may be above, below, left, or right * of the text. */ /* * If the button is compound (i.e., it shows both an image and text), * the new geometry is a combination of the image and text geometry. * We only honor the compound bit if the button has both text and an * image, because otherwise it is not really a compound button. */ if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { switch ((enum compound) butPtr->compound) { case COMPOUND_TOP: case COMPOUND_BOTTOM: { /* Image is above or below text */ if (imgWidth > width) { width = imgWidth; } height += imgHeight + butPtr->padY; break; } case COMPOUND_LEFT: case COMPOUND_RIGHT: { /* Image is left or right of text */ /* * Only increase width of button if image doesn't fit in * slack space of default button width */ if ((imgWidth + txtWidth + butPtr->padX) > width) { width = imgWidth + txtWidth + butPtr->padX; } if (imgHeight > height) { height = imgHeight; } break; } case COMPOUND_CENTER: { /* Image and text are superimposed */ if (imgWidth > width) { width = imgWidth; } if (imgHeight > height) { height = imgHeight; } break; } } /* switch */ /* Fix up for minimum width */ if (butPtr->width < 0) { /* minWidth in pixels (because there's an image */ minWidth = -(butPtr->width); if (width < minWidth) { width = minWidth; } } else if (butPtr->width > 0) { width = butPtr->width; } if (butPtr->height > 0) { height = butPtr->height; } width += 2*butPtr->padX; height += 2*butPtr->padY; } else if (haveImage) { if (butPtr->width > 0) { width = butPtr->width; } else { width = imgWidth; } if (butPtr->height > 0) { height = butPtr->height; } else { height = imgHeight; } } else { /* No image. May or may not be text. May or may not be compound. */ /* * butPtr->width is in characters. We need to allow for that * many characters on the face, not in the over-all button width */ if (butPtr->width > 0) { width = butPtr->width * avgWidth; } /* * butPtr->height is in lines of text. We need to allow for * that many lines on the face, not in the over-all button * height. */ if (butPtr->height > 0) { height = butPtr->height * fm.linespace; /* * Make the same adjustments as above to get same height for * e.g. a one line text with -height 0 or 1. [Bug #565485] */ switch (butPtr->type) { case TYPE_BUTTON: { height += (int)(0.5 + (6 * vDLU)) - 10; break; } case TYPE_RADIO_BUTTON: case TYPE_CHECK_BUTTON: { height += (int)(0.5 + (2.0 * vDLU)) - 4; break; } } } width += 2 * butPtr->padX; height += 2 * butPtr->padY; } /* Fix up width and height for indicator sizing and spacing */ if (butPtr->type == TYPE_RADIO_BUTTON || butPtr->type == TYPE_CHECK_BUTTON) { if (butPtr->indicatorOn) { butPtr->indicatorDiameter = tsdPtr->boxHeight; /* * Make sure we can see the whole indicator, even if the text * or image is very small. */ if (height < butPtr->indicatorDiameter) { height = butPtr->indicatorDiameter; } /* * There is no rule for space between the indicator and * the text (the two are atomic on 'Windows) but the User * Experience page 451 says leave 3 hDLUs between "text * labels and their associated controls". */ butPtr->indicatorSpace = butPtr->indicatorDiameter + (int)(0.5 + (3.0 * hDLU)); width += butPtr->indicatorSpace; } } /* * Inset is always added to the size. */ width += 2 * butPtr->inset; height += 2 * butPtr->inset; Tk_GeometryRequest(butPtr->tkwin, width, height); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset);}/* *---------------------------------------------------------------------- * * ButtonProc -- * * This function is call by Windows whenever an event occurs on * a button control created by Tk. * * Results: * Standard Windows return value. * * Side effects: * May generate events. * *---------------------------------------------------------------------- */static LRESULT CALLBACKButtonProc(hwnd, message, wParam, lParam) HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam;{ LRESULT result; WinButton *butPtr; Tk_Window tkwin = Tk_HWNDToWindow(hwnd); if (tkwin == NULL) { panic("ButtonProc called on an invalid HWND"); } butPtr = (WinButton *)((TkWindow*)tkwin)->instanceData; switch(message) { case WM_ERASEBKGND: return 0; case BM_GETCHECK: if (((butPtr->info.type == TYPE_CHECK_BUTTON) || (butPtr->info.type == TYPE_RADIO_BUTTON)) && butPtr->info.indicatorOn) { return (butPtr->info.flags & SELECTED) ? BST_CHECKED : BST_UNCHECKED; } return 0; case BM_GETSTATE: { DWORD state = 0; if (((butPtr->info.type == TYPE_CHECK_BUTTON) || (butPtr->info.type == TYPE_RADIO_BUTTON)) && butPtr->info.indicatorOn) { state = (butPtr->info.flags & SELECTED) ? BST_CHECKED : BST_UNCHECKED; } if (butPtr->info.flags & GOT_FOCUS) { state |= BST_FOCUS; } return state; } case WM_ENABLE: break; case WM_PAINT: { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); EndPaint(hwnd, &ps); TkpDisplayButton((ClientData)butPtr); /* * Special note: must cancel any existing idle handler * for TkpDisplayButton; it's no longer needed, and * TkpDisplayButton cleared the REDRAW_PENDING flag. */ Tcl_CancelIdleCall(TkpDisplayButton, (ClientData)butPtr); return 0; } case BN_CLICKED: { int code; Tcl_Interp *interp = butPtr->info.interp; if (butPtr->info.state != STATE_DISABLED) { Tcl_Preserve((ClientData)interp); code = TkInvokeButton((TkButton*)butPtr); if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (button invoke)"); Tcl_BackgroundError(interp); } Tcl_Release((ClientData)interp); } Tcl_ServiceAll(); return 0; } default: if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) { return result; } } return DefWindowProc(hwnd, message, wParam, lParam);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -