📄 tkwinbutton.c
字号:
* In order to avoid screen flashes, this procedure redraws * the button in a pixmap, then copies the pixmap to the * screen in a single operation. This means that there's no * point in time where the on-sreen image has been cleared. */ pixmap = Tk_GetPixmap(butPtr->display, Tk_WindowId(tkwin), Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); Tk_Fill3DRectangle(tkwin, pixmap, border, 0, 0, Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); /* * Display image or bitmap or text for button. */ if (butPtr->image != None) { Tk_SizeOfImage(butPtr->image, &width, &height); imageOrBitmap: TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, butPtr->indicatorSpace + width, height, &x, &y); x += butPtr->indicatorSpace; if (relief == TK_RELIEF_SUNKEN) { x += offset; y += offset; } if (butPtr->image != NULL) { if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, x, y); } else { Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, x, y); } } else { XSetClipOrigin(butPtr->display, gc, x, y); XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, (unsigned int) width, (unsigned int) height, x, y, 1); XSetClipOrigin(butPtr->display, gc, 0, 0); } y += height/2; } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); goto imageOrBitmap; } else { RECT rect; TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, butPtr->indicatorSpace + butPtr->textWidth, butPtr->textHeight, &x, &y); x += butPtr->indicatorSpace; if (relief == TK_RELIEF_SUNKEN) { x += offset; y += offset; } Tk_DrawTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x, y, 0, -1); Tk_UnderlineTextLayout(butPtr->display, pixmap, gc, butPtr->textLayout, x, y, butPtr->underline); /* * Draw the focus ring. If this is a push button then we need to put * it around the inner edge of the border, otherwise we put it around * the text. */ if (butPtr->flags & GOT_FOCUS && butPtr->type != TYPE_LABEL) { dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); if (butPtr->type == TYPE_BUTTON || !butPtr->indicatorOn) { rect.top = butPtr->borderWidth + 1 + defaultWidth; rect.left = rect.top; rect.right = Tk_Width(tkwin) - rect.left; rect.bottom = Tk_Height(tkwin) - rect.top; } else { rect.top = y-2; rect.left = x-2; rect.right = x+butPtr->textWidth + 1; rect.bottom = y+butPtr->textHeight + 1; } CkSetTextColor(dc, gc->foreground); CkSetBkColor(dc, gc->background); DrawFocusRect(dc, &rect); TkWinReleaseDrawableDC(pixmap, dc, &state); } y += butPtr->textHeight/2; } /* * Draw the indicator for check buttons and radio buttons. At this * point x and y refer to the top-left corner of the text or image * or bitmap. */ if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn && boxesPtr) { int xSrc, ySrc; x -= butPtr->indicatorSpace; y -= butPtr->indicatorDiameter / 2; xSrc = (butPtr->flags & SELECTED) ? boxWidth : 0; if (butPtr->state == tkActiveUid) { xSrc += boxWidth*2; } ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : boxHeight; /* * Update the palette in the boxes bitmap to reflect the current * button colors. Note that this code relies on the layout of the * bitmap's palette. Also, all of the colors used to draw the * bitmap must be in the palette that is selected into the DC of * the offscreen pixmap. This requires that the static colors * be placed into the palette. */ boxesPalette[PAL_CHECK] = FlipColor(gc->foreground); boxesPalette[PAL_TOP_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_DARK_GC)); boxesPalette[PAL_TOP_INNER] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_DARK2)); boxesPalette[PAL_BOTTOM_INNER] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT2)); boxesPalette[PAL_BOTTOM_OUTER] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT_GC)); if (butPtr->state == tkDisabledUid) { boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_LIGHT2)); } else if (butPtr->selectBorder != NULL) { boxesPalette[PAL_INTERIOR] = FlipColor(TkWinGetBorderPixels(tkwin, butPtr->selectBorder, TK_3D_FLAT_GC)); } else { boxesPalette[PAL_INTERIOR] = FlipColor(GetSysColor(COLOR_WINDOW)); } boxesPalette[PAL_BACKGROUND] = FlipColor(TkWinGetBorderPixels(tkwin, border, TK_3D_FLAT_GC)); dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); StretchDIBits(dc, x, y, boxWidth, boxHeight, xSrc, ySrc, boxWidth, boxHeight, boxesBits, (LPBITMAPINFO)boxesPtr, DIB_RGB_COLORS, SRCCOPY); TkWinReleaseDrawableDC(pixmap, dc, &state); } /* * If the button is disabled with a stipple rather than a special * foreground color, generate the stippled effect. If the widget * is selected and we use a different background color when selected, * must temporarily modify the GC. */ if ((butPtr->state == tkDisabledUid) && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { XSetForeground(butPtr->display, butPtr->disabledGC, Tk_3DBorderColor(butPtr->selectBorder)->pixel); } XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC, butPtr->inset, butPtr->inset, (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset), (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset)); if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { XSetForeground(butPtr->display, butPtr->disabledGC, Tk_3DBorderColor(butPtr->normalBorder)->pixel); } } /* * Draw the border and traversal highlight last. This way, if the * button's contents overflow they'll be covered up by the border. */ if (relief != TK_RELIEF_FLAT) { Tk_Draw3DRectangle(tkwin, pixmap, border, defaultWidth, defaultWidth, Tk_Width(tkwin) - 2*defaultWidth, Tk_Height(tkwin) - 2*defaultWidth, butPtr->borderWidth, relief); } if (defaultWidth != 0) { dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); TkWinFillRect(dc, 0, 0, Tk_Width(tkwin), defaultWidth, butPtr->highlightColorPtr->pixel); TkWinFillRect(dc, 0, 0, defaultWidth, Tk_Height(tkwin), butPtr->highlightColorPtr->pixel); TkWinFillRect(dc, 0, Tk_Height(tkwin) - defaultWidth, Tk_Width(tkwin), defaultWidth, butPtr->highlightColorPtr->pixel); TkWinFillRect(dc, Tk_Width(tkwin) - defaultWidth, 0, defaultWidth, Tk_Height(tkwin), butPtr->highlightColorPtr->pixel); TkWinReleaseDrawableDC(pixmap, dc, &state); } /* * Copy the information from the off-screen pixmap onto the screen, * then delete the pixmap. */ XCopyArea(butPtr->display, pixmap, Tk_WindowId(tkwin), butPtr->copyGC, 0, 0, (unsigned) Tk_Width(tkwin), (unsigned) Tk_Height(tkwin), 0, 0); Tk_FreePixmap(butPtr->display, pixmap);}/* *---------------------------------------------------------------------- * * TkpComputeButtonGeometry -- * * After changes in a button's text or bitmap, this procedure * recomputes the button's geometry and passes this information * along to the geometry manager for the window. * * Results: * None. * * Side effects: * The button's window may change size. * *---------------------------------------------------------------------- */voidTkpComputeButtonGeometry(butPtr) register TkButton *butPtr; /* Button whose geometry may have changed. */{ int width, height, avgWidth; Tk_FontMetrics fm; if (butPtr->highlightWidth < 0) { butPtr->highlightWidth = 0; } butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth; butPtr->indicatorSpace = 0; if (!boxesPtr) { InitBoxes(); } if (butPtr->image != NULL) { Tk_SizeOfImage(butPtr->image, &width, &height); imageOrBitmap: if (butPtr->width > 0) { width = butPtr->width; } if (butPtr->height > 0) { height = butPtr->height; } if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { butPtr->indicatorSpace = boxWidth * 2; butPtr->indicatorDiameter = boxHeight; } } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); goto imageOrBitmap; } else { Tk_FreeTextLayout(butPtr->textLayout); butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, butPtr->text, -1, butPtr->wrapLength, butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); width = butPtr->textWidth; height = butPtr->textHeight; avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); Tk_GetFontMetrics(butPtr->tkfont, &fm); if (butPtr->width > 0) { width = butPtr->width * avgWidth; } if (butPtr->height > 0) { height = butPtr->height * fm.linespace; } if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { butPtr->indicatorDiameter = boxHeight; butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth; } /* * Increase the inset to allow for the focus ring. */ if (butPtr->type != TYPE_LABEL) { butPtr->inset += 3; } } /* * When issuing the geometry request, add extra space for the indicator, * if any, and for the border and padding, plus an extra pixel so the * display can be offset by 1 pixel in either direction for the raised * or lowered effect. */ if ((butPtr->image == NULL) && (butPtr->bitmap == None)) { width += 2*butPtr->padX; height += 2*butPtr->padY; } if ((butPtr->type == TYPE_BUTTON) || ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn)) { width += 1; height += 1; } Tk_GeometryRequest(butPtr->tkwin, (int) (width + butPtr->indicatorSpace + 2*butPtr->inset), (int) (height + 2*butPtr->inset)); 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); return 0; } case BN_CLICKED: { int code; Tcl_Interp *interp = butPtr->info.interp; if (butPtr->info.state != tkDisabledUid) { 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 + -