📄 tkwinscrlbr.c
字号:
}}/* *---------------------------------------------------------------------- * * TkpComputeScrollbarGeometry -- * * After changes in a scrollbar's size or configuration, this * procedure recomputes various geometry information used in * displaying the scrollbar. * * Results: * None. * * Side effects: * The scrollbar will be displayed differently. * *---------------------------------------------------------------------- */voidTkpComputeScrollbarGeometry(scrollPtr) register TkScrollbar *scrollPtr; /* Scrollbar whose geometry may * have changed. */{ int fieldLength, minThumbSize; /* * Windows doesn't use focus rings on scrollbars, but we still * perform basic sanity checks to appease backwards compatibility. */ if (scrollPtr->highlightWidth < 0) { scrollPtr->highlightWidth = 0; } if (scrollPtr->vertical) { scrollPtr->arrowLength = vArrowHeight; fieldLength = Tk_Height(scrollPtr->tkwin); minThumbSize = vThumb; } else { scrollPtr->arrowLength = hArrowWidth; fieldLength = Tk_Width(scrollPtr->tkwin); minThumbSize = hThumb; } fieldLength -= 2*scrollPtr->arrowLength; if (fieldLength < 0) { fieldLength = 0; } scrollPtr->sliderFirst = (int) ((double)fieldLength * scrollPtr->firstFraction); scrollPtr->sliderLast = (int) ((double)fieldLength * scrollPtr->lastFraction); /* * Adjust the slider so that some piece of it is always * displayed in the scrollbar and so that it has at least * a minimal width (so it can be grabbed with the mouse). */ if (scrollPtr->sliderFirst > fieldLength) { scrollPtr->sliderFirst = fieldLength; } if (scrollPtr->sliderFirst < 0) { scrollPtr->sliderFirst = 0; } if (scrollPtr->sliderLast < (scrollPtr->sliderFirst + minThumbSize)) { scrollPtr->sliderLast = scrollPtr->sliderFirst + minThumbSize; } if (scrollPtr->sliderLast > fieldLength) { scrollPtr->sliderLast = fieldLength; } scrollPtr->sliderFirst += scrollPtr->arrowLength; scrollPtr->sliderLast += scrollPtr->arrowLength; /* * Register the desired geometry for the window (leave enough space * for the two arrows plus a minimum-size slider, plus border around * the whole window, if any). Then arrange for the window to be * redisplayed. */ if (scrollPtr->vertical) { Tk_GeometryRequest(scrollPtr->tkwin, scrollPtr->width, 2*scrollPtr->arrowLength + minThumbSize); } else { Tk_GeometryRequest(scrollPtr->tkwin, 2*scrollPtr->arrowLength + minThumbSize, scrollPtr->width); } Tk_SetInternalBorder(scrollPtr->tkwin, 0);}/* *---------------------------------------------------------------------- * * ScrollbarProc -- * * This function is call by Windows whenever an event occurs on * a scrollbar control created by Tk. * * Results: * Standard Windows return value. * * Side effects: * May generate events. * *---------------------------------------------------------------------- */static LRESULT CALLBACKScrollbarProc(hwnd, message, wParam, lParam) HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam;{ LRESULT result; POINT point; WinScrollbar *scrollPtr; Tk_Window tkwin = Tk_HWNDToWindow(hwnd); if (tkwin == NULL) { panic("ScrollbarProc called on an invalid HWND"); } scrollPtr = (WinScrollbar *)((TkWindow*)tkwin)->instanceData; switch(message) { case WM_HSCROLL: case WM_VSCROLL: { Tcl_Interp *interp; Tcl_DString cmdString; int command = LOWORD(wParam); int code; GetCursorPos(&point); Tk_TranslateWinEvent(NULL, WM_MOUSEMOVE, 0, MAKELPARAM(point.x, point.y), &result); if (command == SB_ENDSCROLL) { return 0; } /* * Bail out immediately if there isn't a command to invoke. */ if (scrollPtr->info.commandSize == 0) { Tcl_ServiceAll(); return 0; } Tcl_DStringInit(&cmdString); Tcl_DStringAppend(&cmdString, scrollPtr->info.command, scrollPtr->info.commandSize); if (command == SB_LINELEFT || command == SB_LINERIGHT) { Tcl_DStringAppendElement(&cmdString, "scroll"); Tcl_DStringAppendElement(&cmdString, (command == SB_LINELEFT ) ? "-1" : "1"); Tcl_DStringAppendElement(&cmdString, "units"); } else if (command == SB_PAGELEFT || command == SB_PAGERIGHT) { Tcl_DStringAppendElement(&cmdString, "scroll"); Tcl_DStringAppendElement(&cmdString, (command == SB_PAGELEFT ) ? "-1" : "1"); Tcl_DStringAppendElement(&cmdString, "pages"); } else { char valueString[TCL_DOUBLE_SPACE]; double pos = 0.0; switch (command) { case SB_THUMBPOSITION: pos = ((double)HIWORD(wParam)) / MAX_SCROLL; break; case SB_THUMBTRACK: pos = ((double)HIWORD(wParam)) / MAX_SCROLL; break; case SB_TOP: pos = 0.0; break; case SB_BOTTOM: pos = 1.0; break; } sprintf(valueString, "%g", pos); Tcl_DStringAppendElement(&cmdString, "moveto"); Tcl_DStringAppendElement(&cmdString, valueString); } interp = scrollPtr->info.interp; code = Tcl_GlobalEval(interp, cmdString.string); if (code != TCL_OK && code != TCL_CONTINUE && code != TCL_BREAK) { Tcl_AddErrorInfo(interp, "\n (scrollbar command)"); Tcl_BackgroundError(interp); } Tcl_DStringFree(&cmdString); Tcl_ServiceAll(); return 0; } default: if (Tk_TranslateWinEvent(hwnd, message, wParam, lParam, &result)) { return result; } } return CallWindowProc(scrollPtr->oldProc, hwnd, message, wParam, lParam);}/* *---------------------------------------------------------------------- * * TkpConfigureScrollbar -- * * This procedure is called after the generic code has finished * processing configuration options, in order to configure * platform specific options. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */voidTkpConfigureScrollbar(scrollPtr) register TkScrollbar *scrollPtr; /* Information about widget; may or * may not already have values for * some fields. */{}/* *-------------------------------------------------------------- * * ScrollbarBindProc -- * * This procedure is invoked when the default <ButtonPress> * binding on the Scrollbar bind tag fires. * * Results: * None. * * Side effects: * The event enters a modal loop. * *-------------------------------------------------------------- */static intScrollbarBindProc(clientData, interp, eventPtr, tkwin, keySym) ClientData clientData; Tcl_Interp *interp; XEvent *eventPtr; Tk_Window tkwin; KeySym keySym;{ TkWindow *winPtr = (TkWindow*)tkwin; if (eventPtr->type == ButtonPress) { winPtr->flags |= TK_DEFER_MODAL; } return TCL_OK;}/* *---------------------------------------------------------------------- * * ModalLoopProc -- * * This function is invoked at the end of the event processing * whenever the ScrollbarBindProc has been invoked for a ButtonPress * event. * * Results: * None. * * Side effects: * Enters a modal loop. * *---------------------------------------------------------------------- */static voidModalLoopProc(tkwin, eventPtr) Tk_Window tkwin; XEvent *eventPtr;{ TkWindow *winPtr = (TkWindow*)tkwin; WinScrollbar *scrollPtr = (WinScrollbar *) winPtr->instanceData; int oldMode; Tcl_Preserve((ClientData)scrollPtr); scrollPtr->winFlags |= IN_MODAL_LOOP; oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); TkWinResendEvent(scrollPtr->oldProc, scrollPtr->hwnd, eventPtr); (void) Tcl_SetServiceMode(oldMode); scrollPtr->winFlags &= ~IN_MODAL_LOOP; if (scrollPtr->hwnd && scrollPtr->winFlags & ALREADY_DEAD) { DestroyWindow(scrollPtr->hwnd); } Tcl_Release((ClientData)scrollPtr);}/* *-------------------------------------------------------------- * * TkpScrollbarPosition -- * * Determine the scrollbar element corresponding to a * given position. * * Results: * One of TOP_ARROW, TOP_GAP, etc., indicating which element * of the scrollbar covers the position given by (x, y). If * (x,y) is outside the scrollbar entirely, then OUTSIDE is * returned. * * Side effects: * None. * *-------------------------------------------------------------- */intTkpScrollbarPosition(scrollPtr, x, y) register TkScrollbar *scrollPtr; /* Scrollbar widget record. */ int x, y; /* Coordinates within scrollPtr's * window. */{ int length, width, tmp; if (scrollPtr->vertical) { length = Tk_Height(scrollPtr->tkwin); width = Tk_Width(scrollPtr->tkwin); } else { tmp = x; x = y; y = tmp; length = Tk_Width(scrollPtr->tkwin); width = Tk_Height(scrollPtr->tkwin); } if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset)) || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) { return OUTSIDE; } /* * All of the calculations in this procedure mirror those in * TkpDisplayScrollbar. Be sure to keep the two consistent. */ if (y < (scrollPtr->inset + scrollPtr->arrowLength)) { return TOP_ARROW; } if (y < scrollPtr->sliderFirst) { return TOP_GAP; } if (y < scrollPtr->sliderLast) { return SLIDER; } if (y >= (length - (scrollPtr->arrowLength + scrollPtr->inset))) { return BOTTOM_ARROW; } return BOTTOM_GAP;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -