/*-----------------------------------------------------------------------------+
| TOOLBAR.H                                                                    |
|                                                                              |
| Program Description: Implements a generic toolbar.                           |
|                                                                              |
| Here's how to use it:                                                        |
|                                                                              |
|           Include the source files "toolbar.h" and "toolbar.c" in your       |
| application.                                                                 |
|                                                                              |
|           Include a line in your application's RC file that gives a file     |
| name with a resource id eg. IDBMP_BUTTONS.  This is a .BMP file that         |
| contains all of the pictures of the buttons you want on your toolbar.        |
| Also, make a define for your label with a unique value.  If your app has     |
| more than one toolbar, and all toolbars don't share a bitmap file, then      |
| you will need several defines.                                               |
|                                                                              |
| e.g.         IDBMP_BUTTONS     BITMAP     "buttons.bmp"                      |
|              IDBMP_ARROWS      BITMAP     "arrows.bmp"                       |
|                                                                              |
|           This file must have the different buttons across horizontally      |
| and the different states for these buttons vertically.  Change the           |
| defines in this header file to match the button names and state names of     |
| your buttons.  You must include the states listed here, and actually         |
| you probably won't need to change them at all.  The numbers for a button     |
| or state are indexes into the bitmap, so the pictures must match.            |
|                                                                              |
| STATE DESCRIPTIONS:                                                          |
|                      GRAYED:  The button cannot be pressed & is inactive     |
|                          UP:  The button is up                               |
|                        DOWN:  The button is down                             |
|                     FOCUSUP:  The button is up and is the one with focus     |
|                   FOCUSDOWN:  The button is down and is the one with focus   |
|                    FULLDOWN:  A checkbox button has this additional state    |
|                               where it is all the way down when pressed      |
|                               and when it is let go, it will go into         |
|                               either the UP or DOWN state (maybe focused)    |
|                                                                              |
| When you draw the pictures, make sure to get the right state in the right    |
| vertical position in the bitmap to match the #define's.                      |
|                                                                              |
| A button can also have a type associated with it:                            |
|                                                                              |
|                PUSH:  When pressed it goes down, when let go it bounces      |
|                       up.  Therefore, when you aren't currently holding      |
|                       the mouse button or space bar on it, it will           |
|                       ALWAYS be in the up position. It can be in any         |
|                       state except FULLDOWN, which is invalid.               |
|                                                                              |
|            CHECKBOX:  This button can be up or down.  When pushed, it        |
|                       toggles into the opposite state.  However, it          |
|                       is always in the FULLDOWN state when being held        |
|                       down with the mouse button or space bar, and when      |
|                       let go, it will go into the opposite state of what     |
|                       it was in before you pressed it.  E.G.  The button     |
|                       is up.  You press it, and it goes way down. You let    |
|                       go, and it comes up a bit, but it's still down.  You   |
|                       press it again, and it goes further down before        |
|                       popping all the way up.                                |
|                                                                              |
|               RADIO:  This is a group of buttons that can be up or down,     |
|                       and also have the intermediate step of being           |
|                       FULLDOWN when being held down.  But, when you          |
|                       push one of the radio buttons down, all other radio    |
|                       buttons in its group will pop up.  Any group can       |
|                       have only 1 down at a time, and 1 must be down.        |
|                                                                              |
|               CUSTOM: If your application is wierd, you can have a custom    |
|                       type button that does anything you want it to.         |
|                                                                              |
| First, your app must call:    toolbarInit(hInst, hPrev);                     |
| with the two instance parameters to register a toolbar window class.         |
| Then your app is free to call CreateWindow with a class of                   |
| szToolBarClass   to create one or more toolbar windows anywhere it wants     |
| and of any size it wants, presumably as the child window of another of the   |
| app's windows.  The file that creates the window must declare an             |
| extern char szToolBarClass[];   All messages about activity to a toolbar     |
| button will go to the parent window of the toolbar.                          |
|                                                                              |
| Next, call:     toolbarSetBitmap(HWND hwnd, HANDLE hInst, int ibmp,          |
|                                                       POINT ptSize);         |
| Pass it the resource ID (eg. IDBMP_BUTTONS) to tell the toolbar where to     |
| find the pictures for the buttons.  Also pass a point with the width and     |
| height of each button (eg. 24 X 22) so it knows how to find individual       |
| buttons in the bitmap file.                                                  |
|                                                                              |
| Next, call:     toolbarAddTool(HWND hwnd, TOOLBUTTON tb);                    |
| as many times as you want to add a button to the toolbar specified by        |
| hwnd.  You fill in the "tb" struct with the following information:           |
|                                                                              |
|      tb.rc        = the rect in the toolbar window to place the button       |
|                     based at 0,0 and measured in pixels.                     |
|      tb.iButton   = the ID of the button you wish the add (which is          |
|                     the horizontal offset into the bitmap of buttons).       |
|                     Only one of each button allowed.  Use one of the         |
|                     defines (BTN_??????).                                    |
|      tb.iState    = the initial state of the button (GRAYED, UP, DOWN).      |
|                     If you wish, you can specify a FOCUS'ed state to give    |
|                     any button you wish the focus.  By default, it's the     |
|                     one furthest left and tabbing order goes to the right.   |
|                     This is the vertical offset into the bitmap.             |
|                     Use one of the defines (BTNST_?????).                    |
|      tb.iType     = The type of button (BTNTYPE_???).  Either pushbutton,    |
|                     checkbox, or radio button. (or custom).  If it is a      |
|                     radio button, you can have many groups of radio btn's    |
|                     on the same toolbar.  Type BTNTYPE_RADIO is one group.   |
|                     Use BTNTYPE_RADIO+1 for another group, BTNTYPE_RADIO+2   |
|                     for a third group, etc.  You have thousands.             |
|      tb.iString   = The resource ID of a string to be associated with        |
|                     this button (if you'd like).                             |
|                                                                              |
|                                                                              |
|  At any time in the app, you can call toolbarAddTool to add more buttons     |
|  or toolbarRemoveTool to take some away.  To take one away, identify it      |
|  with it's button ID (horizontal offset in the bitmap).                      |
|                                                                              |
|  You can also call toolbarRetrieveTool to get the TOOLBUTTON struct back     |
|  from a button that is on the toolbar.  This is the way to change a          |
|  button's position.  Change the tb.rc and then Remove and Add the button     |
|  again so that the tabbing order will be re-calculated based on the new      |
|  rect of the tool.                                                           |
|                                                                              |
|  Now, all buttons will automatically behave properly.  They'll go up and     |
|  down as you press on them, or use the keyboard, groups of radio buttons     |
|  will pop up as you press a different one down, etc. etc. etc.               |
|  You don't have to do a thing!                                               |
|                                                                              |
|  The parent of the toolbar window will get a WM_COMMAND message with         |
|  a wParam of IDC_TOOLBAR  whenever anything happens to a button.             |
|  On Win16:                                                                   |
|    LOWORD(lParam) == hwnd of the toolbar window that has the button on it.   |
|    (HIWORD(lParam) & 0xFF) == the button ID of the button.                   |
|  On Win32:                                                                   |
|    lParam         == hwnd of the toolbar window that has the button on it.   |
|    (HIWORD(wParam) & 0xFF) == the button ID of the button.                   |
|    (This relies on a 32 bit button id being ACTUALLY only 16 bits            |
|     Someday this could go sour and need redesign).                           |
|                                                                              |
|  Remember to change IDC_TOOLBAR to something unique.                         |
|                                                                              |
|  The app can then call   toolbarIndexFromButton(hwnd, buttonID)              |
|  to get the index of the button (used for subsequent calls).                 |
|                                                                              |
|  Then call:      toolbarStateFromButton(hwnd, buttonID)                      |
|                                                                              |
|                  to get either BTNST_UP or BTNST_DOWN.  This is the          |
|                  NEW state of the button since the activity on the           |
|                  button.  It can also be BTNST_GRAYED, but you won't get     |
|                  any activity messages while it's grayed, unless it is a     |
|                  cutsom button.                                              |
|                                                                              |
|            Call  toolbarFullStateFromButton(hwnd, buttonID)                  |
|                                                                              |
|                  to get more detail about the state.  It can also return     |
|                  BTNST_FULLDOWN as well as the above states. In the case     |
|                  of BTNST_FULLDOWN, you'll have to call                      |
|                  toolbarPrevStateFromButton(hwnd, btn ID) to get the state   |
|                  before it went full down.                                   |
|                                                                              |
|                  toolbarPrevStateFromButton(hwnd, buttonID)                  |
|                                                                              |
|                  is only valid when the state is BTNST_FULLDOWN.             |
|                                                                              |
|                  toolbarActivityFromIndex(hwnd, buttonID)                    |
|                                                                              |
|                  tells you what just happened to the button.                 |
|                  BTNACT_KEYDOWN, BTNACT_MOUSEUP, etc. are possibilities.     |
|                  BTNACT_MOUSEMOUSEOFF means that they pressed it down and    |
|                  moved the mouse off of the button (  so it was re- drawn    |
|                  in its previous state before being pressed).                |
|                  BTNACT_MOUSEMOUSEON  means that the above happened and      |
|                  then the mouse moved back on top of the button again, so    |
|                  the button was re-drawn as if it was pushed again.          |
|                                                                              |
|                  For any of the above activities.......                      |
|                                                                              |
|  HIWORD & BTN_SHIFT     is set if this activity involves the right mouse     |
|                         button, or else it is clear.                         |
|  HIWORD & BTN_DBLCLICK  is set means that this mouse button down activity    |
|                         is really a double click (if you care).              |
|                                                                              |
|          If you are a custom button, you can also receive this message...    |
|                                                                              |
|  HIWORD & BTN_REPEAT    is set means that the button or key is being held    |
|                         down, and you are being sent many down messages      |
|                         in a row.  The first such message is sent with       |
|                         this flag clear, all others have this flag set.      |
|                         If you are a custom button, you will have to         |
|                         ignore messages that are repeats if you don't        |
|                         want to get many down messages in a row.             |
|                                                                              |
|                                                                              |
|                   toolbarStringFromIndex(hwnd, index)                        |
|                                                                              |
|                   will return you the string resource ID you gave when       |
|                   you registered this button.                                |
|                                                                              |
|                                                                              |
| IMPORTANT !!!!!!!!!!!!!!!!!!!                                                |
| =============================                                                |
|                                                                              |
| When you get the state of a button, it's already been changed by the         |
| activity so it's the NEW STATE!!!!!!!!!                                      |
|                                                                              |
|  EXCEPT!!!   for a custom button!  For a custom button, NOTHING WILL         |
|  happen, you have to do it all yourself!!!! So the state is going to be      |
|  the state BEFORE the activity and you have to call                          |
|  toolbarModifyState(hwnd, buttonID, newState) to change the state            |
|  yourself!!!!                                                                |
|                                                                              |
|  You also have toolbarGetNumButtons(hwnd) to tell you how many are on the    |
|  the toolbar.                                                                |
|  And... you have other routines you can use if you really want.              |
|                                                                              |
|  ENJOY!!                                                                     |
|                                                                              |
| P.S.  Don't forget to pass on WM_SYSCOLORCHANGE msgs to each toolbar.        |
|                                                                              |
|                                                                              |
| (C) Copyright Microsoft Corporation 1992.  All rights reserved.              |
|                                                                              |
| Revision History                                                             |
| Created by Danny Miller, based on David Maymudes' code                       |
|           which was based on Todd Laney's SBUTTON code                       |
|           and stuff from Eric Ledoux.  Did I miss any-                       |
|           body?                                                              |
|    Oct-1992 Laurie Griffiths converted it to 32/16 bit                       |
|             common code.  Mike Tricker reviewed it.                          |
|                                                                              |
+-----------------------------------------------------------------------------*/

#include "ctrls.h"

#define TOOLGROW        8                // power of 2

#define IDC_TOOLBAR   189                // wParam sent to Parent

/* We keep an array of these around (one for each button on the toolbar) */

typedef struct {
        RECT       rc;             // draw it at this postion in the toolbar
        int        iButton;        // it's this button
        int        iState;         // in this state
        int        iPrevState;     // for non-push buttons - last state
        int        iType;          // type of button
        int        iActivity;      // what just happened to button
        int        iString;        // string resource associated with button
} TOOLBUTTON, FAR *LPTOOLBUTTON;

HWND CreateStaticStatusWindow(HWND hwndParent,BOOL fSizeGrip);
BOOL WriteStatusMessage(HWND hwnd, LPTSTR szMsg);
BOOL GetStatusTextExtent(HWND hwnd, LPSIZE pTextExtent);

/* We keep an array of these around (one for each button on the toolbar) */

BOOL FAR PASCAL toolbarInit(void);
HWND FAR PASCAL toolbarCreateMain(HWND hwndParent);
HWND FAR PASCAL toolbarCreateMark(HWND hwndParent);
HWND FAR PASCAL toolbarCreateArrows(HWND hwndParent);
BOOL FAR PASCAL toolbarStateFromButton(HWND hwnd, int iButton, int tbIndex);
BOOL FAR PASCAL toolbarAddTool(HWND hwnd, int iButton, int tbIndex, int iState);
BOOL FAR PASCAL toolbarSwapTools(HWND hwnd, int iButton, int jButton, int tbIndex);
BOOL FAR PASCAL toolbarRemoveTool(HWND hwnd, int iButton, int tbIndex);
BOOL FAR PASCAL toolbarModifyState(HWND hwnd, int iButton, int tbIndex, int iState);
BOOL FAR PASCAL toolbarSetFocus(HWND hwnd, int iButton);


HBITMAP FAR PASCAL  LoadUIBitmap(
    HANDLE      hInstance,          // EXE file to load resource from
    LPCTSTR     szName,             // name of bitmap resource
    COLORREF    rgbText,            // color to use for "Button Text"
    COLORREF    rgbFace,            // color to use for "Button Face"
    COLORREF    rgbShadow,          // color to use for "Button Shadow"
    COLORREF    rgbHighlight,       // color to use for "Button Hilight"
    COLORREF    rgbWindow,          // color to use for "Window Color"
    COLORREF    rgbFrame);          // color to use for "Window Frame"

/* In a bitmap file, each button is the same size, and contains
 * the picture of a button.  Each column contains the picture of a distinct
 * button (e.g. BTN_REWIND, BTN_REVERSE, etc.) and each row contains
 * a specific button state (BTNST_UP, BTNST_DOWN,
 * BTNBAR_GRAYED, etc. just as an example).
 *
 */

#define TB_FIRST            -1
#define TB_LAST             -2

#define BTN_PLAY            0
#define BTN_PAUSE           1
#define BTN_STOP            2
#define BTN_EJECT           3
#define BTN_HOME            4
#define BTN_RWD             5
#define BTN_FWD             6
#define BTN_END             7

#define ARROW_PREV          0
#define ARROW_NEXT          1

#define BTN_MARKIN          0
#define BTN_MARKOUT         1

#define BTNST_GRAYED        0
#define BTNST_UP            1
#define BTNST_DOWN          2
#define BTNST_FOCUSUP       3
#define BTNST_FOCUSDOWN     4
#define BTNST_FULLDOWN      5

#define BTN_REPEAT          0x100        // add this to button index
#define BTN_SHIFT           0x200
#define BTN_DBLCLICK        0x400


/* constants */
#define MSEC_BUTTONREPEAT   200        // milliseconds for auto-repeat

/* timers */
#define TIMER_BUTTONREPEAT  1        // timer for button auto-repeat

/* bitmap resources */
#define IDBMP_TOOLBAR       100        // main toolbar
#define IDBMP_ARROWS        101        // arrows for scrollbar
#define IDBMP_MARK          102        // arrows for scrollbar
                                        // 103 and 104 used by track.h