Пример #1
0
/***********************************************************************
 * UPDOWN_Draw
 *
 * Draw the arrows. The background need not be erased.
 */
static LRESULT UPDOWN_Draw (const UPDOWN_INFO *infoPtr, HDC hdc)
{
    BOOL uPressed, uHot, dPressed, dHot;
    RECT rect;
    HTHEME theme = GetWindowTheme (infoPtr->Self);
    int uPart = 0, uState = 0, dPart = 0, dState = 0;
    BOOL needBuddyBg = FALSE;

    uPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_INCR);
    uHot = (infoPtr->Flags & FLAG_INCR) && (infoPtr->Flags & FLAG_MOUSEIN);
    dPressed = (infoPtr->Flags & FLAG_PRESSED) && (infoPtr->Flags & FLAG_DECR);
    dHot = (infoPtr->Flags & FLAG_DECR) && (infoPtr->Flags & FLAG_MOUSEIN);
    if (theme) {
        uPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_UPHORZ : SPNP_UP;
        uState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED 
            : (uPressed ? DNS_PRESSED : (uHot ? DNS_HOT : DNS_NORMAL));
        dPart = (infoPtr->dwStyle & UDS_HORZ) ? SPNP_DOWNHORZ : SPNP_DOWN;
        dState = (infoPtr->dwStyle & WS_DISABLED) ? DNS_DISABLED 
            : (dPressed ? DNS_PRESSED : (dHot ? DNS_HOT : DNS_NORMAL));
        needBuddyBg = IsWindow (infoPtr->Buddy)
            && (IsThemeBackgroundPartiallyTransparent (theme, uPart, uState)
              || IsThemeBackgroundPartiallyTransparent (theme, dPart, dState));
    }

    /* Draw the common border between ourselves and our buddy */
    if (UPDOWN_HasBuddyBorder(infoPtr) || needBuddyBg) {
        if (!theme || !UPDOWN_DrawBuddyBackground (infoPtr, hdc)) {
            GetClientRect(infoPtr->Self, &rect);
	    DrawEdge(hdc, &rect, EDGE_SUNKEN,
		     BF_BOTTOM | BF_TOP |
		     (infoPtr->dwStyle & UDS_ALIGNLEFT ? BF_LEFT : BF_RIGHT));
        }
    }

    /* Draw the incr button */
    UPDOWN_GetArrowRect (infoPtr, &rect, FLAG_INCR);
    if (theme) {
        DrawThemeBackground(theme, hdc, uPart, uState, &rect, NULL);
    } else {
        DrawFrameControl(hdc, &rect, DFC_SCROLL,
            (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLRIGHT : DFCS_SCROLLUP) |
            ((infoPtr->dwStyle & UDS_HOTTRACK) && uHot ? DFCS_HOT : 0) |
            (uPressed ? DFCS_PUSHED : 0) |
            (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
    }

    /* Draw the decr button */
    UPDOWN_GetArrowRect(infoPtr, &rect, FLAG_DECR);
    if (theme) {
        DrawThemeBackground(theme, hdc, dPart, dState, &rect, NULL);
    } else {
        DrawFrameControl(hdc, &rect, DFC_SCROLL,
            (infoPtr->dwStyle & UDS_HORZ ? DFCS_SCROLLLEFT : DFCS_SCROLLDOWN) |
            ((infoPtr->dwStyle & UDS_HOTTRACK) && dHot ? DFCS_HOT : 0) |
            (dPressed ? DFCS_PUSHED : 0) |
            (infoPtr->dwStyle & WS_DISABLED ? DFCS_INACTIVE : 0) );
    }

    return 0;
}
Пример #2
0
/***********************************************************************
 *           UPDOWN_GetArrowRect
 * wndPtr   - pointer to the up-down wnd
 * rect     - will hold the rectangle
 * arrow    - FLAG_INCR to get the "increment" rect (up or right)
 *            FLAG_DECR to get the "decrement" rect (down or left)
 *            If both flags are present, the envelope is returned.
 */
static void UPDOWN_GetArrowRect (const UPDOWN_INFO* infoPtr, RECT *rect, int arrow)
{
    HTHEME theme = GetWindowTheme (infoPtr->Self);
    const int border = theme ? DEFAULT_BUDDYBORDER_THEMED : DEFAULT_BUDDYBORDER;
    const int spacer = theme ? DEFAULT_BUDDYSPACER_THEMED : DEFAULT_BUDDYSPACER;
    GetClientRect (infoPtr->Self, rect);

    /*
     * Make sure we calculate the rectangle to fit even if we draw the
     * border.
     */
    if (UPDOWN_HasBuddyBorder(infoPtr)) {
        if (infoPtr->dwStyle & UDS_ALIGNLEFT)
            rect->left += border;
        else
            rect->right -= border;

        InflateRect(rect, 0, -border);
    }

    /* now figure out if we need a space away from the buddy */
    if (IsWindow(infoPtr->Buddy) ) {
	if (infoPtr->dwStyle & UDS_ALIGNLEFT) rect->right -= spacer;
	else rect->left += spacer;
    }

    /*
     * We're calculating the midpoint to figure-out where the
     * separation between the buttons will lay. We make sure that we
     * round the uneven numbers by adding 1.
     */
    if (infoPtr->dwStyle & UDS_HORZ) {
        int len = rect->right - rect->left + 1; /* compute the width */
        if (arrow & FLAG_INCR)
            rect->left = rect->left + len/2;
        if (arrow & FLAG_DECR)
            rect->right =  rect->left + len/2 - (theme ? 0 : 1);
    } else {
        int len = rect->bottom - rect->top + 1; /* compute the height */
        if (arrow & FLAG_INCR)
            rect->bottom =  rect->top + len/2 - (theme ? 0 : 1);
        if (arrow & FLAG_DECR)
            rect->top =  rect->top + len/2;
    }
}
Пример #3
0
/***********************************************************************
 *           UPDOWN_SetBuddy
 *
 * Sets bud as a new Buddy.
 * Then, it should subclass the buddy
 * If window has the UDS_ARROWKEYS, it subcalsses the buddy window to
 * process the UP/DOWN arrow keys.
 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
 * the size/pos of the buddy and the control are adjusted accordingly.
 */
static HWND UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
{
    static const WCHAR editW[] = { 'E', 'd', 'i', 't', 0 };
    static const WCHAR listboxW[] = { 'L', 'i', 's', 't', 'b', 'o', 'x', 0 };
    RECT  budRect;  /* new coord for the buddy */
    int   x, width;  /* new x position and width for the up-down */
    WNDPROC baseWndProc;
    WCHAR buddyClass[40];
    HWND ret;

    TRACE("(hwnd=%p, bud=%p)\n", infoPtr->Self, bud);

    ret = infoPtr->Buddy;

    /* there is already a body assigned */
    if (infoPtr->Buddy)  RemovePropW(infoPtr->Buddy, BUDDY_UPDOWN_HWND);

    if(!IsWindow(bud))
        bud = 0;

    /* Store buddy window handle */
    infoPtr->Buddy = bud;

    if(bud) {

        /* keep upDown ctrl hwnd in a buddy property */
        SetPropW( bud, BUDDY_UPDOWN_HWND, infoPtr->Self);

        /* Store buddy window class type */
        infoPtr->BuddyType = BUDDY_TYPE_UNKNOWN;
        if (GetClassNameW(bud, buddyClass, COUNT_OF(buddyClass))) {
            if (lstrcmpiW(buddyClass, editW) == 0)
                infoPtr->BuddyType = BUDDY_TYPE_EDIT;
            else if (lstrcmpiW(buddyClass, listboxW) == 0)
                infoPtr->BuddyType = BUDDY_TYPE_LISTBOX;
        }

        if(infoPtr->dwStyle & UDS_ARROWKEYS){
            /* Note that I don't clear the BUDDY_SUPERCLASS_WNDPROC property
               when we reset the upDown ctrl buddy to another buddy because it is not
               good to break the window proc chain. */
            if (!GetPropW(bud, BUDDY_SUPERCLASS_WNDPROC)) {
                baseWndProc = (WNDPROC)SetWindowLongPtrW(bud, GWLP_WNDPROC, (LPARAM)UPDOWN_Buddy_SubclassProc);
                SetPropW(bud, BUDDY_SUPERCLASS_WNDPROC, (HANDLE)baseWndProc);
            }
        }

        /* Get the rect of the buddy relative to its parent */
        GetWindowRect(infoPtr->Buddy, &budRect);
        MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy), (POINT *)(&budRect.left), 2);

        /* now do the positioning */
        if  (infoPtr->dwStyle & UDS_ALIGNLEFT) {
            x  = budRect.left;
            budRect.left += DEFAULT_WIDTH + DEFAULT_XSEP;
        } else if (infoPtr->dwStyle & UDS_ALIGNRIGHT) {
            budRect.right -= DEFAULT_WIDTH + DEFAULT_XSEP;
            x  = budRect.right+DEFAULT_XSEP;
        } else {
            /* nothing to do */
            return ret;
        }

        /* first adjust the buddy to accommodate the up/down */
        SetWindowPos(infoPtr->Buddy, 0, budRect.left, budRect.top,
                     budRect.right  - budRect.left, budRect.bottom - budRect.top,
                     SWP_NOACTIVATE|SWP_NOZORDER);

        /* now position the up/down */
        /* Since the UDS_ALIGN* flags were used, */
        /* we will pick the position and size of the window. */
        width = DEFAULT_WIDTH;

        /*
         * If the updown has a buddy border, it has to overlap with the buddy
         * to look as if it is integrated with the buddy control.
         * We nudge the control or change its size to overlap.
         */
        if (UPDOWN_HasBuddyBorder(infoPtr)) {
            if(infoPtr->dwStyle & UDS_ALIGNLEFT)
                width += DEFAULT_BUDDYBORDER;
            else
                x -= DEFAULT_BUDDYBORDER;
        }

        SetWindowPos(infoPtr->Self, 0, x,
                     budRect.top - DEFAULT_ADDTOP, width,
                     budRect.bottom - budRect.top + DEFAULT_ADDTOP + DEFAULT_ADDBOT,
                     SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER);
    } else {
        RECT rect;
        GetWindowRect(infoPtr->Self, &rect);
        MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Self), (POINT *)&rect, 2);
        SetWindowPos(infoPtr->Self, 0, rect.left, rect.top, DEFAULT_WIDTH, rect.bottom - rect.top,
                     SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER);
    }
    return ret;
}
Пример #4
0
/***********************************************************************
 *           UPDOWN_SetBuddy
 *
 * Sets bud as a new Buddy.
 * Then, it should subclass the buddy
 * If window has the UDS_ARROWKEYS, it subclasses the buddy window to
 * process the UP/DOWN arrow keys.
 * If window has the UDS_ALIGNLEFT or UDS_ALIGNRIGHT style
 * the size/pos of the buddy and the control are adjusted accordingly.
 */
static HWND UPDOWN_SetBuddy (UPDOWN_INFO* infoPtr, HWND bud)
{
    RECT  budRect;  /* new coord for the buddy */
    int   x, width;  /* new x position and width for the up-down */
    WCHAR buddyClass[40];
    HWND ret;

    TRACE("(hwnd=%p, bud=%p)\n", infoPtr->Self, bud);

    ret = infoPtr->Buddy;

    /* there is already a buddy assigned */
    if (infoPtr->Buddy) RemoveWindowSubclass(infoPtr->Buddy, UPDOWN_Buddy_SubclassProc,
                BUDDY_SUBCLASSID);
    if (!IsWindow(bud)) bud = NULL;

    /* Store buddy window handle */
    infoPtr->Buddy = bud;

    if(bud) {
        /* Store buddy window class type */
        infoPtr->BuddyType = BUDDY_TYPE_UNKNOWN;
        if (GetClassNameW(bud, buddyClass, COUNT_OF(buddyClass))) {
            if (lstrcmpiW(buddyClass, WC_EDITW) == 0)
                infoPtr->BuddyType = BUDDY_TYPE_EDIT;
            else if (lstrcmpiW(buddyClass, WC_LISTBOXW) == 0)
                infoPtr->BuddyType = BUDDY_TYPE_LISTBOX;
        }

        if (infoPtr->dwStyle & UDS_ARROWKEYS)
            SetWindowSubclass(bud, UPDOWN_Buddy_SubclassProc, BUDDY_SUBCLASSID,
                              (DWORD_PTR)infoPtr->Self);

        /* Get the rect of the buddy relative to its parent */
        GetWindowRect(infoPtr->Buddy, &budRect);
        MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Buddy), (POINT *)(&budRect.left), 2);

        /* now do the positioning */
        if  (infoPtr->dwStyle & UDS_ALIGNLEFT) {
            x  = budRect.left;
            budRect.left += DEFAULT_WIDTH + DEFAULT_XSEP;
        } else if (infoPtr->dwStyle & UDS_ALIGNRIGHT) {
            budRect.right -= DEFAULT_WIDTH + DEFAULT_XSEP;
            x  = budRect.right+DEFAULT_XSEP;
        } else {
            /* nothing to do */
            return ret;
        }

        /* first adjust the buddy to accommodate the up/down */
        SetWindowPos(infoPtr->Buddy, 0, budRect.left, budRect.top,
                     budRect.right  - budRect.left, budRect.bottom - budRect.top,
                     SWP_NOACTIVATE|SWP_NOZORDER);

        /* now position the up/down */
        /* Since the UDS_ALIGN* flags were used, */
        /* we will pick the position and size of the window. */
        width = DEFAULT_WIDTH;

        /*
         * If the updown has a buddy border, it has to overlap with the buddy
         * to look as if it is integrated with the buddy control.
         * We nudge the control or change its size to overlap.
         */
        if (UPDOWN_HasBuddyBorder(infoPtr)) {
            if(infoPtr->dwStyle & UDS_ALIGNLEFT)
                width += DEFAULT_BUDDYBORDER;
            else
                x -= DEFAULT_BUDDYBORDER;
        }

        SetWindowPos(infoPtr->Self, 0, x,
                     budRect.top - DEFAULT_ADDTOP, width,
                     budRect.bottom - budRect.top + DEFAULT_ADDTOP + DEFAULT_ADDBOT,
                     SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER);
    } else {
        RECT rect;
        GetWindowRect(infoPtr->Self, &rect);
        MapWindowPoints(HWND_DESKTOP, GetParent(infoPtr->Self), (POINT *)&rect, 2);
        SetWindowPos(infoPtr->Self, 0, rect.left, rect.top, DEFAULT_WIDTH, rect.bottom - rect.top,
                     SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOZORDER);
    }
    return ret;
}