gizmo.c

来自「英文版的 想要的话可以下载了 为大家服务」· C语言 代码 · 共 797 行 · 第 1/2 页

C
797
字号
/*
 * GIZMO.C
 *
 * Allocate, free, find, and enumerate functions for the GIZMO
 * structure and a generic subclass procedure to handle tabbing
 * between gizmos.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */


#include "inoledll.h"


/*
 * In order to control tabbing in the gizmos, we need to subclass
 * real pushbuttons, edit controls, listboxes, and comboboxes.  So
 * we keep an array of the four original procs for such controls.
 */
WNDPROC     pfnOrg[CSUBGIZMOS]={NULL, NULL, NULL, NULL};


TCHAR szStatic[]=TEXT("static");
TCHAR szEdit[]=TEXT("edit");
TCHAR szCombobox[]=TEXT("combobox");
TCHAR szListbox[]=TEXT("listbox");
TCHAR szButton[]=TEXT("button");


//Here so GIZMOBAR.C can get at it.
TOOLDISPLAYDATA tdd;



/*
 * GizmoPAllocate
 *
 * Purpose:
 *  Allocates and initializes a GIZMO data structure.
 *
 * Parameters:
 *  pfSuccess       int * flag indicating success of failure.
 *  ppFirst         PPGIZMO providing the first gizmo in this list.
 *  hWndParent      HWND of the parent of this gizmo.  Can be NULL
 *                  for iType==GIZMOTYPE_BUTTON* or
 *                  GIZMOTYPE_SEPARATOR.
 *  iType           UINT gizmo control type.
 *  iGizmo          UINT index of this gizmo in the GizmoBar.
 *  uID             UINT identifier to send with WM_COMMAND for this
 *                  control.
 *  dx, dy          UINT width and height of the gizmo.
 *  pszText         LPTSTR to the text for edits, listboxes, combobox,
 *                  and text.
 *  dwStyle         DWORD style for edits, lists, and combos, and
 *                  texts.
 *  hBmp            HBITMAP for button gizmos, is applicable.
 *  iImage          UINT index into hBmp for the button image, if
 *                  applicable.
 *  uState          UINT initial state of the control.
 *
 * Return Value:
 *  PGIZMO          If NULL returned then GizmoPAllocate could not
 *                  allocate memory.  If a non-NULL pointer is
 *                  returned with *pfSuccess, then call GizmoPFree
 *                  immediately.  If you get a non-NULL pointer and
 *                  *pfSuccess==TRUE then the function succeeded.
 */

PGIZMO GizmoPAllocate(int *pfSuccess, PPGIZMO ppFirst
    , HWND hWndParent, UINT iType, UINT iGizmo, UINT uID, UINT dx
    , UINT dy, LPTSTR pszText, HBITMAP hBmp, UINT iImage, UINT uState)
    {
    PGIZMO          pGizmo;
    PGIZMO          pCur, pPrev;
    LPTSTR          pszClass;
    HINSTANCE       hInst;
    UINT            i;
    DWORD           dwStyle;
    HWND            hWndE;

    if (NULL==pfSuccess)
        return NULL;

    //Make sure we know of this gizmo type.
    if (GIZMOTYPE_MIN > iType || GIZMOTYPE_MAX < iType)
        return NULL;

    *pfSuccess=FALSE;

    //Allocate the structure
    pGizmo=(PGIZMO)(TCHAR *)LocalAlloc(LPTR, CBGIZMO);

    if (NULL==pGizmo)
        return NULL;


    //Store the necessary information for this gizmo.
    pGizmo->iType   =iType;
    pGizmo->uID     =uID;
    pGizmo->hBmp    =hBmp;
    pGizmo->iBmp    =iImage;
    pGizmo->uState  =uState;
    pGizmo->fNotify =TRUE;


    /*
     * Insert this structure into our gizmo list.  Each time we scan
     * we increment the index counter (starting at zero) comparing it
     * to the desired index of insertion.  We then know exactly where
     * to insert this new gizmo.  Note that we insert the new gizmo
     * in the list appropriately for the given owner, so enumerations
     * will come out ordered in the same way for that owner.
     */

    i=0;
    pCur=*ppFirst;
    pPrev=NULL;

    while (NULL!=pCur && i++ < iGizmo)
        {
        pPrev=pCur;
        pCur =pCur->pNext;
        }

    //Point to our neighbors
    pGizmo->pPrev=pPrev;
    pGizmo->pNext=pCur;


    //Point out neighbors to us.
    if (NULL==pPrev)
        *ppFirst=pGizmo;
    else
        pPrev->pNext=pGizmo;

    if (NULL!=pCur)
        pCur->pPrev=pGizmo;


    //Our x-coordinate is the x of the previous gizmo plus its width.
    if (NULL!=pPrev)
        pGizmo->x=pGizmo->pPrev->x+pGizmo->pPrev->dx;
    else
        pGizmo->x=4;    //First gizmo is at x=4


    //If we're a separator or image button, force standards on dx.
    UIToolConfigureForDisplay(&tdd);
    pGizmo->cxImage=tdd.cxImage;
    pGizmo->cyImage=tdd.cyImage;

    if ((GIZMOTYPE_DRAWN & iType) && NULL==hBmp)
        dx=tdd.cxButton;

    if (GIZMOTYPE_SEPARATOR==iType)
        dx=6;

    /*
     * Now create windows for edits, texts, lists, and comboboxes.
     * First calculate the most often defaults used in the switch.
     */
    pGizmo->dx=dx+6;
    pGizmo->dy=min(dy, tdd.cyButton);
    pGizmo->y=2;
    pszClass=NULL;

    //If this is new gizmo is a window, create it.
    switch (iType)
        {
        case GIZMOTYPE_TEXT:
            pGizmo->dx=dx;

            //Center vertically.
            pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1;
            pszClass=szStatic;
            dwStyle=SS_LEFT;
            break;

        case GIZMOTYPE_EDIT:
            //Center vertically.
            pGizmo->y=(tdd.cyBar-1-pGizmo->dy) >> 1;
            pszClass=szEdit;
            dwStyle=ES_LEFT | WS_BORDER | WS_TABSTOP;
            break;

        case GIZMOTYPE_LISTBOX:
            pGizmo->dy=dy;
            pszClass=szCombobox;
            dwStyle=CBS_DROPDOWNLIST | WS_TABSTOP;
            break;

        case GIZMOTYPE_COMBOBOX:
            pGizmo->dy=dy;
            pszClass=szCombobox;
            dwStyle=CBS_DROPDOWN | WS_TABSTOP;
            break;

        case GIZMOTYPE_BUTTONNORMAL:
            pGizmo->dy=dy;
            pszClass=szButton;
            dwStyle=BS_PUSHBUTTON | WS_TABSTOP;
            break;

        case GIZMOTYPE_SEPARATOR:
            pGizmo->dx=dx;
            pGizmo->y=3;
            break;

        case GIZMOTYPE_BUTTONATTRIBUTEIN:
        case GIZMOTYPE_BUTTONATTRIBUTEEX:
        case GIZMOTYPE_BUTTONCOMMAND:
            pGizmo->dx=dx;
            pGizmo->y=3;
            break;
        }


    //If we matched a classname, create a window.
    if (GIZMOTYPE_WINDOWS & iType)
        {
        if (!IsWindow(hWndParent))
            return pGizmo;

        hInst=GETWINDOWINSTANCE(hWndParent);    //Macro in book1632.h

        pGizmo->hWnd=CreateWindow(pszClass, pszText
            , dwStyle | WS_CHILD | WS_VISIBLE, pGizmo->x, pGizmo->y
            , dx, pGizmo->dy, hWndParent, (HMENU)uID, hInst, NULL);

        if (NULL==pGizmo->hWnd)
            return pGizmo;

        /*
         * Subclass comboboxes, listboxes, edits, and windowed
         * buttons.  We use iType to index the original proc array
         * so we can use a single subclass procedure for all
         * controls.  If you mess with the gizmo type definitions,
         * this is going to break.
         */

        if (GIZMOTYPE_WINDOWS & iType && GIZMOTYPE_TEXT!=iType)
            {
            //Give the window its type.
            BITPOSITION(iType, i);
            SetProp(pGizmo->hWnd, SZTYPEPROP, (HANDLE)i);

            if (NULL==pfnOrg[i])
                {
                pfnOrg[i]=(WNDPROC)GetWindowLong(pGizmo->hWnd
                    , GWL_WNDPROC);
                }

            SetWindowLong(pGizmo->hWnd, GWL_WNDPROC
                , (LONG)GenericSubProc);

            //If we're a combobox, subclass edit control
            if (GIZMOTYPE_COMBOBOX==iType)
                {
                hWndE=GetDlgItem(pGizmo->hWnd, ID_COMBOEDIT);
                SetProp(hWndE, SZTYPEPROP, (HANDLE)-1);

                if (NULL==pfnOrg[0])
                    {
                    pfnOrg[0]=(WNDPROC)GetWindowLong(pGizmo->hWnd
                        , GWL_WNDPROC);
                    }

                SetWindowLong(hWndE, GWL_WNDPROC
                    , (LONG)GenericSubProc);
                }
            }
        }


    //Finally, move all our neighbors to the right to accomodate us.
    GizmosExpand(pGizmo);

    *pfSuccess=TRUE;
    return pGizmo;
    }






/*
 * GizmoPFree
 *
 * Purpose:
 *  Reverses all initialization done by GizmoPAllocate, cleaning up
 *  any allocations including the application structure itself.
 *
 * Parameters:
 *  ppFirst         PPGIZMO providing the first gizmo in this list.
 *  pGizmo          PGIZMO to the structure
 *
 * Return Value:
 *  PGIZMO          NULL if successful, pGizmo if not, meaning we
 *                  couldn't free something.
 */

PGIZMO GizmoPFree(PPGIZMO ppFirst, PGIZMO pGizmo)
    {
    int     i;

    if (NULL==pGizmo)
        return NULL;

    //Move other gizmos to fill in this gap.
    GizmosCompact(pGizmo);

    //Unsubclass
    if (GIZMOTYPE_WINDOWS & pGizmo->iType
        && GIZMOTYPE_TEXT!=pGizmo->iType)
        {
        i=(int)GetProp(pGizmo->hWnd, SZTYPEPROP);
        RemoveProp(pGizmo->hWnd, SZTYPEPROP);

        if (GIZMOTYPE_COMBOBOX==pGizmo->iType)
            {
            HWND        hWndE;

            hWndE=GetDlgItem(pGizmo->hWnd, ID_COMBOEDIT);
            RemoveProp(hWndE, SZTYPEPROP);
            }

        SetWindowLong(pGizmo->hWnd, GWL_WNDPROC, (LONG)pfnOrg[i]);
        }

    //If this was a window gizmo, destroy the window.
    if (NULL!=pGizmo->hWnd && IsWindow(pGizmo->hWnd))
        DestroyWindow(pGizmo->hWnd);

    //Unlink ourselves.
    if (NULL!=pGizmo->pNext)
        pGizmo->pNext->pPrev=pGizmo->pPrev;

    if (NULL!=pGizmo->pPrev)
        pGizmo->pPrev->pNext=pGizmo->pNext;
    else
        *ppFirst=pGizmo->pNext;

    return (PGIZMO)LocalFree((HLOCAL)(UINT)(LONG)pGizmo);
    }






/*
 * GizmosExpand
 *
 * Purpose:
 *  Given a starting gizmo and a width, moves it and all gizmos to
 *  its right to the right by the width to make space for showing
 *  or creating a new gizmo.
 *
 * Parameters:
 *  pGizmo          PGIZMO specifying the gizmo that was inserted.
 *
 * Return Value:
 *  None
 */

void GizmosExpand(PGIZMO pGizmo)
    {
    int         cx;

    cx=(int)pGizmo->dx;

    /*
     * If we and the next control are buttons, use our width-1 to
     * expand so we overlap borders with our neighboring button.
     */

    if (NULL!=pGizmo->pNext)
        {
        if ((GIZMOTYPE_BUTTONS & pGizmo->pNext->iType)
            && (GIZMOTYPE_BUTTONS & pGizmo->iType))
            cx-=1;
        }

    //Walk the gizmo list moving them right by our width.
    pGizmo=pGizmo->pNext;

    while (NULL!=pGizmo)
        {
        pGizmo->x+=cx;

        //hWnd is NULL for buttons and separators.
        if (NULL!=pGizmo->hWnd)
            {
            SetWindowPos(pGizmo->hWnd, NULL, pGizmo->x, pGizmo->y

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?