|
|
/**************************************************************************
* * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * PURPOSE. * * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved. * **************************************************************************/ /****************************************************************************
* * toolbar.c: Toolbar control window * * Vidcap32 Source code * ***************************************************************************/
#include <string.h>
#include <windows.h>
#include <windowsx.h>
//#include <win32.h>
#include "toolbar.h" // use this for generic app
/************************************************************************/
/* work for win3.0 */ #ifndef COLOR_BTNHIGHLIGHT
#define COLOR_BTNHIGHLIGHT 20
#endif
TCHAR szToolBarClass[] = "ToolBarClass"; HBRUSH ghbrToolbar; // brush for toolbar background
//
// Window proc for buttons, THIS FUNCTION MUST BE EXPORTED
//
LRESULT FAR PASCAL toolbarWndProc(HWND, unsigned, WPARAM, LPARAM);
typedef long (FAR PASCAL *LPWNDPROC)();
/*
Defines */
#ifdef _WIN32
#define GETARRAYBUTT(hwnd) ((HANDLE)GetWindowLongPtr(hwnd,GWLP_ARRAYBUTT))
#define GETNUMBUTTONS(hwnd) ((int)GetWindowLong(hwnd,GWL_NUMBUTTONS))
#define GETPRESSED(hwnd) ((BOOL)GetWindowLong(hwnd,GWL_PRESSED))
#define GETKEYPRESSED(hwnd) ((BOOL)GetWindowLong(hwnd,GWL_KEYPRESSED))
#define GETWHICH(hwnd) ((int)GetWindowLong(hwnd,GWL_WHICH))
#define GETSHIFTED(hwnd) ((BOOL)GetWindowLong(hwnd,GWL_SHIFTED))
#define GETBMPHANDLE(hwnd) ((HANDLE)GetWindowLongPtr(hwnd,GWLP_BMPHANDLE))
#define GETBMPINT(hwnd) ((int)GetWindowLong(hwnd,GWL_BMPINT))
#define GETBUTTONSIZE(hwnd) GetWindowLong(hwnd,GWL_BUTTONSIZE)
#define GETHINST(hwnd) ((HANDLE)GetWindowLongPtr(hwnd,GWLP_HINST))
#define SETARRAYBUTT(hwnd, h) SetWindowLongPtr(hwnd, GWLP_ARRAYBUTT, (UINT_PTR)h)
#define SETNUMBUTTONS(hwnd, wNumButtons) \
SetWindowLong(hwnd, GWL_NUMBUTTONS, wNumButtons) #define SETPRESSED(hwnd, f) SetWindowLong(hwnd, GWL_PRESSED, (UINT)f)
#define SETKEYPRESSED(hwnd, f) SetWindowLong(hwnd, GWL_KEYPRESSED, (UINT)f)
#define SETWHICH(hwnd, i) SetWindowLong(hwnd, GWL_WHICH, (UINT)i)
#define SETSHIFTED(hwnd, i) SetWindowLong(hwnd, GWL_SHIFTED, (UINT)i)
#define SETBMPHANDLE(hwnd, h) SetWindowLongPtr(hwnd, GWLP_BMPHANDLE, (UINT_PTR)h)
#define SETBMPINT(hwnd, i) SetWindowLong(hwnd, GWL_BMPINT, (UINT)i)
#define SETBUTTONSIZE(hwnd, l) SetWindowLong(hwnd, GWL_BUTTONSIZE, l)
#define SETHINST(hwnd, h) SetWindowLongPtr(hwnd, GWLP_HINST, (UINT_PTR)h)
#else
#define GETARRAYBUTT(hwnd) ((HANDLE)GetWindowWord(hwnd,GWW_ARRAYBUTT))
#define GETNUMBUTTONS(hwnd) ((int)GetWindowWord(hwnd,GWW_NUMBUTTONS))
#define GETPRESSED(hwnd) ((BOOL)GetWindowWord(hwnd,GWW_PRESSED))
#define GETKEYPRESSED(hwnd) ((BOOL)GetWindowWord(hwnd,GWW_KEYPRESSED))
#define GETWHICH(hwnd) ((int)GetWindowWord(hwnd,GWW_WHICH))
#define GETSHIFTED(hwnd) ((BOOL)GetWindowWord(hwnd,GWW_SHIFTED))
#define GETBMPHANDLE(hwnd) ((HANDLE)GetWindowWord(hwnd,GWW_BMPHANDLE))
#define GETBMPINT(hwnd) ((int)GetWindowWord(hwnd,GWW_BMPINT))
#define GETBUTTONSIZE(hwnd) GetWindowLong(hwnd,GWL_BUTTONSIZE)
#define GETHINST(hwnd) ((HANDLE)GetWindowWord(hwnd,GWW_HINST))
#define SETARRAYBUTT(hwnd, h) SetWindowWord(hwnd, GWW_ARRAYBUTT, (WORD)h)
#define SETNUMBUTTONS(hwnd, wNumButtons) \
SetWindowWord(hwnd, GWW_NUMBUTTONS, wNumButtons) #define SETPRESSED(hwnd, f) SetWindowWord(hwnd, GWW_PRESSED, (WORD)f)
#define SETKEYPRESSED(hwnd, f) SetWindowWord(hwnd, GWW_KEYPRESSED, (WORD)f)
#define SETWHICH(hwnd, i) SetWindowWord(hwnd, GWW_WHICH, (WORD)i)
#define SETSHIFTED(hwnd, i) SetWindowWord(hwnd, GWW_SHIFTED, (WORD)i)
#define SETBMPHANDLE(hwnd, h) SetWindowWord(hwnd, GWW_BMPHANDLE, (WORD)h)
#define SETBMPINT(hwnd, i) SetWindowWord(hwnd, GWW_BMPINT, (WORD)i)
#define SETBUTTONSIZE(hwnd, l) SetWindowLong(hwnd, GWL_BUTTONSIZE, l)
#define SETHINST(hwnd, h) SetWindowWord(hwnd, GWW_HINST, (WORD)h)
#endif
#define lpCreate ((LPCREATESTRUCT)lParam)
/* Prototypes */
static void NEAR PASCAL NotifyParent(HWND, int);
/**************************************************************************
toolbarInit( hInst, hPrev )
Call this routine to initialize the toolbar code.
Arguments: hPrev instance handle of previous instance hInst instance handle of current instance
Returns: TRUE if successful, FALSE if not ***************************************************************************/
BOOL FAR PASCAL toolbarInit(HANDLE hInst, HANDLE hPrev) { WNDCLASS cls; /* Register the tool bar window class */ if (!hPrev) {
cls.hCursor = LoadCursor(NULL,IDC_ARROW); cls.hIcon = NULL; cls.lpszMenuName = NULL; cls.lpszClassName = (LPSTR)szToolBarClass; cls.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); cls.hInstance = hInst; cls.style = CS_DBLCLKS; cls.lpfnWndProc = toolbarWndProc; cls.cbClsExtra = 0; cls.cbWndExtra = TOOLBAR_EXTRABYTES; if (!RegisterClass(&cls)) return FALSE; }
return TRUE; }
/***************************************************************************/ /* toolbarSetBitmap: takes a resource ID and associates that bitmap with */ /* a given toolbar. Also takes the instance handle and */ /* the size of the buttons on the toolbar. */ /***************************************************************************/ BOOL FAR PASCAL toolbarSetBitmap(HWND hwnd, HANDLE hInst, int ibmp, POINT ptSize) { SETHINST(hwnd, hInst); SETBMPHANDLE(hwnd, NULL); SETBMPINT(hwnd, ibmp); SETBUTTONSIZE(hwnd, MAKELONG(ptSize.y, ptSize.x)); return (BOOL)SendMessage(hwnd, WM_SYSCOLORCHANGE, 0, 0L); // do the work
}
/***************************************************************************/ /* toolbarGetNumButtons: return the number of buttons registered on a */ /* given toolbar window. */ /***************************************************************************/ int FAR PASCAL toolbarGetNumButtons(HWND hwnd) { return GETNUMBUTTONS(hwnd); }
/***************************************************************************/ /* toolbarButtonFromIndex: Given an index into the array of buttons on */ /* this toolbar, return which button is there. */ /* Returns -1 for an error code. */ /***************************************************************************/ int FAR PASCAL toolbarButtonFromIndex(HWND hwnd, int iBtnPos) { int iButton; HANDLE h; TOOLBUTTON far *lpaButtons;
/* Get the array of buttons on this toolbar */ h = GETARRAYBUTT(hwnd); if (!h) return -1; /* Validate the index passed in */ if (iBtnPos > GETNUMBUTTONS(hwnd) || iBtnPos < 0) return -1;
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Read off the answer */ iButton = lpaButtons[iBtnPos].iButton;
GlobalUnlock(h); return iButton; }
/***************************************************************************/ /* toolbarIndexFromButton: Given a button ID, return the position in the */ /* array that it appears at. */ /* Returns -1 for an error code. */ /***************************************************************************/ int FAR PASCAL toolbarIndexFromButton(HWND hwnd, int iButton) { int i, iBtnPos = -1; HANDLE h; TOOLBUTTON far *lpButton;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* loop through until you find it */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (lpButton->iButton == iButton) { iBtnPos = i; break; }
GlobalUnlock(h); return iBtnPos; }
/***************************************************************************/ /* toolbarPrevStateFromButton: Given a button ID, return the state that */ /* the button was in before it was pressed */ /* all the way down (for non-push buttons). */ /* Return -1 for an error code. */ /***************************************************************************/ int FAR PASCAL toolbarPrevStateFromButton(HWND hwnd, int iButton) { int i, iPrevState = -1; HANDLE h; TOOLBUTTON far *lpButton;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* look for what we need */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (lpButton->iButton == iButton) { iPrevState = lpButton->iPrevState; break; }
GlobalUnlock(h); return iPrevState; }
/***************************************************************************/ /* toolbarActivityFromButton: Given a button ID, return the most recent */ /* activity that happened to it. (eg DBLCLK) */ /* Return -1 for an error code. */ /***************************************************************************/ int FAR PASCAL toolbarActivityFromButton(HWND hwnd, int iButton) { int i, iActivity = -1; HANDLE h; TOOLBUTTON far *lpButton;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* loop through until you find it */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (lpButton->iButton == iButton) iActivity = lpButton->iActivity;
GlobalUnlock(h); return iActivity; }
/***************************************************************************/ /* toolbarIndexFromPoint: Given a point in the toolbar window, return the */ /* index of the button beneath that point. */ /* Return -1 for an error code. */ /***************************************************************************/ int FAR PASCAL toolbarIndexFromPoint(HWND hwnd, POINT pt) { int i, iBtnPos = -1; HANDLE h; TOOLBUTTON far *lpButton;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* loop through until we find an intersection */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (PtInRect(&lpButton->rc, pt)) { iBtnPos = i; break; }
GlobalUnlock(h); return iBtnPos; }
/***************************************************************************/ /* toolbarRectFromIndex: Given an index into our array of buttons, return*/ /* the rect occupied by that button. */ /* Return a NULL rect for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarRectFromIndex(HWND hwnd, int iBtnPos, LPRECT lprc) { HANDLE h; TOOLBUTTON far *lpaButtons; /* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* Validate the index passed in */ if (iBtnPos > GETNUMBUTTONS(hwnd) || iBtnPos < 0) return FALSE;
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Read off the rect */ *lprc = lpaButtons[iBtnPos].rc;
GlobalUnlock(h); return TRUE; }
/***************************************************************************/ /* toolbarFullStateFromButton: Given a button in our array of buttons, */ /* return the state of that button. */ /* (including the wierd state FULLDOWN). For */ /* just UP or DOWN or GRAYED, */ /* call toolbarStateFromButton. */ /* Return -1 for an error. */ /***************************************************************************/ int FAR PASCAL toolbarFullStateFromButton(HWND hwnd, int iButton) { int iState, iBtnPos; HANDLE h; TOOLBUTTON far *lpaButtons;
iBtnPos = toolbarIndexFromButton(hwnd, iButton); if (iBtnPos == -1) return -1;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1;
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Read off the state */ iState = lpaButtons[iBtnPos].iState;
GlobalUnlock(h); return iState; }
/***************************************************************************/ /* toolbarStateFromButton: This fn is called by the parent application */ /* to get the state of a button. It will only */ /* return DOWN, or UP or GRAYED as opposed to */ /* toolbarFullStateFromButton which could return */ /* FULLDOWN. */ /***************************************************************************/ int FAR PASCAL toolbarStateFromButton(HWND hwnd, int iButton) { int iState;
/* If a checkbox button is all the way down, it's previous state is */ /* the one we want. */ if ((iState = toolbarFullStateFromButton(hwnd, iButton)) == BTNST_FULLDOWN) { iState = toolbarPrevStateFromButton(hwnd, iButton); return iState; } else return iState; }
/***************************************************************************/ /* toolbarStringFromIndex: Given an index into our array of buttons, return*/ /* the string resource associated with it. */ /* Return -1 for an error. */ /***************************************************************************/ int FAR PASCAL toolbarStringFromIndex(HWND hwnd, int iBtnPos) { int iString; HANDLE h; TOOLBUTTON far *lpaButtons;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1;
/* Validate the index passed in */ if (iBtnPos > GETNUMBUTTONS(hwnd) || iBtnPos < 0) return -1;
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Read off the ID */ iString = lpaButtons[iBtnPos].iString;
GlobalUnlock(h); return iString; }
/***************************************************************************/ /* toolbarTypeFromIndex: Given an index into our array of buttons, return*/ /* the type of button it is (PUSH, RADIO, etc.) */ /* Return -1 for an error. */ /***************************************************************************/ int FAR PASCAL toolbarTypeFromIndex(HWND hwnd, int iBtnPos) { int iType; HANDLE h; TOOLBUTTON far *lpaButtons;
/* Get the Array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return -1;
/* Validate the index passed in */ if (iBtnPos > GETNUMBUTTONS(hwnd) || iBtnPos < 0) return -1;
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Read off the type */ iType = lpaButtons[iBtnPos].iType;
GlobalUnlock(h); return iType; }
/***************************************************************************/ /* toolbarAddTool: Add a button to this toolbar. Sort them by leftmost */ /* position in the window (for tabbing order). */ /* Return FALSE for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarAddTool(HWND hwnd, TOOLBUTTON tb) { HANDLE h; TOOLBUTTON far *lpaButtons; int cButtons, i, j; BOOL fInsert = FALSE;
/* We better not have this button on the toolbar already */ if (toolbarIndexFromButton(hwnd, tb.iButton) != -1) return FALSE;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons are there already? */ cButtons = GETNUMBUTTONS(hwnd);
/* If we have filled our alloced memory for this array already, we */ /* need to re-alloc some more memory */ if ( ((cButtons & (TOOLGROW - 1)) == 0) && (cButtons > 0) ) {
/* Re-alloc it bigger */ h = GlobalReAlloc(h, GlobalSize(h) + TOOLGROW * sizeof(TOOLBUTTON), GMEM_MOVEABLE | GMEM_SHARE); if (!h) return FALSE; }
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Look for the spot we need to insert this new guy at. */ /* Remember, we sort by left x position breaking ties */ /* with top y position. */ for (i = 0; i < cButtons; i++) { // Here it goes
if (lpaButtons[i].rc.left > tb.rc.left || (lpaButtons[i].rc.left == tb.rc.left && lpaButtons[i].rc.top > tb.rc.top)) { fInsert = TRUE; /* Open up a spot in the array */ for (j = cButtons; j > i; j--) lpaButtons[j] = lpaButtons[j-1]; /* Add our new guy */ lpaButtons[i] = tb; // redraw now
InvalidateRect(hwnd, &(lpaButtons[i].rc), FALSE); break; } }
/* If our loop didn't insert it, we need to add it to the end */ if (!fInsert) lpaButtons[i] = tb;
/* If we are told that this button has the focus, we better */ /* change the focus to it. Then use the normal state. */ if (tb.iState == BTNST_FOCUSUP) { tb.iState = BTNST_UP; SETWHICH(hwnd, i); } else if (tb.iState == BTNST_FOCUSDOWN || tb.iState == BTNST_FULLDOWN){ tb.iState = BTNST_DOWN; // nonsense to init to FULLDOWN
SETWHICH(hwnd, i); }
cButtons++; // one more button now.
GlobalUnlock(h);
SETNUMBUTTONS(hwnd, cButtons); // new count
SETARRAYBUTT(hwnd, h); // re-alloc might have changed it
/* Just in case no one else makes this new button draw */ InvalidateRect(hwnd, &(tb.rc), FALSE);
return TRUE; }
/***************************************************************************/ /* toolbarRetrieveTool: Get the TOOLBUTTON struct for the given button. */ /* Return FALSE for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarRetrieveTool(HWND hwnd, int iButton, LPTOOLBUTTON lptb) { int i; HANDLE h; TOOLBUTTON far *lpButton; BOOL fFound = FALSE; /* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* look for what we need */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (lpButton->iButton == iButton) { *lptb = *lpButton; fFound = TRUE; break; }
GlobalUnlock(h); return fFound; }
/***************************************************************************/ /* toolbarRemoveTool: Remove this button ID from our array of buttons on */ /* the toolbar. (only 1 of each button ID allowed). */ /* Return FALSE for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarRemoveTool(HWND hwnd, int iButton) { HANDLE h; TOOLBUTTON far *lpaButtons; int cButtons, i, j; BOOL fFound = FALSE;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons are on there now? */ cButtons = GETNUMBUTTONS(hwnd);
lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* Find a match, remove it, and close the array around it. */ for (i = 0; i < cButtons; i++) if (lpaButtons[i].iButton == iButton) { fFound = TRUE; // redraw now
InvalidateRect(hwnd, &(lpaButtons[i].rc), FALSE); if (i != cButtons - 1) // Last button? Don't bother!
for (j = i; j < cButtons; j++) lpaButtons[j] = lpaButtons[j + 1]; break; }
GlobalUnlock(h);
/* Didn't find it! */ if (!fFound) return FALSE;
/* One less button */ cButtons--;
/* Every once in a while, re-alloc a smaller array chunk to */ /* save memory. */ if ( ((cButtons & (TOOLGROW - 1)) == 0) && (cButtons > 0) ) {
/* Re-alloc it smaller */ h = GlobalReAlloc(h, GlobalSize(h) - TOOLGROW * sizeof(TOOLBUTTON), GMEM_MOVEABLE | GMEM_SHARE); if (!h) return FALSE; }
SETNUMBUTTONS(hwnd, cButtons); // new count
SETARRAYBUTT(hwnd, h); // re-alloc could have changed it
return TRUE; }
/***************************************************************************/ /* toolbarModifyString: Given a button ID on the toolbar, change it's */ /* string resource associated with it. */ /* returns FALSE for an error or if no such button */ /***************************************************************************/ BOOL FAR PASCAL toolbarModifyString(HWND hwnd, int iButton, int iString) { HANDLE h; TOOLBUTTON far *lpButton; int cButtons, i; BOOL fFound = FALSE;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons? */ cButtons = GETNUMBUTTONS(hwnd); lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* Find that button, and change it's state */ for (i = 0; i < cButtons; i++, lpButton++) if (lpButton->iButton == iButton) { lpButton->iString = iString; fFound = TRUE; // redraw now
break; }
GlobalUnlock(h); return fFound; }
/***************************************************************************/ /* toolbarModifyState: Given a button ID on the toolbar, change it's */ /* state. */ /* returns FALSE for an error or if no such button */ /***************************************************************************/ BOOL FAR PASCAL toolbarModifyState(HWND hwnd, int iButton, int iState) { HANDLE h; TOOLBUTTON far *lpButton; int cButtons, i; BOOL fFound = FALSE;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons? */ cButtons = GETNUMBUTTONS(hwnd); lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* Find that button, and change it's state */ for (i = 0; i < cButtons; i++, lpButton++) if (lpButton->iButton == iButton) { if (lpButton->iState != iState) { lpButton->iState = iState; InvalidateRect(hwnd, &(lpButton->rc), FALSE); } fFound = TRUE; // redraw now
/* if we're pushing a radio button down, bring */ /* all others in its group up */ if (lpButton->iType >= BTNTYPE_RADIO && iState == BTNST_DOWN) toolbarExclusiveRadio(hwnd, lpButton->iType, iButton); break; }
GlobalUnlock(h); return fFound; }
/***************************************************************************/ /* toolbarModifyPrevState: Given a button on the toolbar, change it's prev-*/ /* ious state. Used for non-PUSH buttons to remember */ /* what state a button was in before pressed all the */ /* way down, so that when you let go, you know what */ /* state to set it to (the opposite of what it was). */ /* returns FALSE for an error (no button array) */ /***************************************************************************/ BOOL FAR PASCAL toolbarModifyPrevState(HWND hwnd, int iButton, int iPrevState) { HANDLE h; TOOLBUTTON far *lpButton; int cButtons, i;
/* Get button array */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons? */ cButtons = GETNUMBUTTONS(hwnd);
lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* Find the button, change the state */ for (i = 0; i < cButtons; i++, lpButton++) if (lpButton->iButton == iButton) { lpButton->iPrevState = iPrevState; break; }
GlobalUnlock(h); return TRUE; }
/***************************************************************************/ /* toolbarModifyActivity: Given a button ID on the toolbar, change it's */ /* activity. This tells the app what just happened */ /* to the button (ie. KEYUP, MOUSEDBLCLK, etc.) */ /* returns FALSE for an error or if no such button */ /***************************************************************************/ BOOL FAR PASCAL toolbarModifyActivity(HWND hwnd, int iButton, int iActivity) { HANDLE h; TOOLBUTTON far *lpButton; int cButtons, i;
/* Get the button array */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE;
/* How many buttons */ cButtons = GETNUMBUTTONS(hwnd);
lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* loop through and change the right one */ for (i = 0; i < cButtons; i++, lpButton++) if (lpButton->iButton == iButton) { lpButton->iActivity = iActivity; break; }
GlobalUnlock(h); return TRUE; }
/***************************************************************************/ /* toolbarFixFocus: SETWHICH() has been called to tell us which button */ /* has the focus, but the states of all the buttons are */ /* not updated (ie. take focus away from the old button) */ /* This routine is called from the Paint routine to fix */ /* the states of all the buttons before drawing them. */ /* Returns FALSE for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarFixFocus(HWND hwnd) { int iFocus; HANDLE h; TOOLBUTTON far *lpaButtons;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE; lpaButtons = (TOOLBUTTON far *)GlobalLock(h);
/* if focus is on an illegal button, default to the first one */ iFocus = GETWHICH(hwnd); if (iFocus < 0 || iFocus >= GETNUMBUTTONS(hwnd)) SETWHICH(hwnd, 0);
/* First of all, make sure that the focus in not on a grayed button. */ /* if so, we advance focus. If it runs out of buttons without */ /* finding a non-gray one, we start back at the beginning and start */ /* looking for a non-gray one from there. If every button is grayed,*/ /* we leave no focus anywhere. */ if (lpaButtons[GETWHICH(hwnd)].iState == BTNST_GRAYED) { if (!toolbarMoveFocus(hwnd, FALSE)) { SETWHICH(hwnd, -1); toolbarMoveFocus(hwnd, FALSE); } }
GlobalUnlock(h); return TRUE; }
/***************************************************************************/ /* toolbarExclusiveRadio: For radio buttons, we need to pop all others */ /* in the group up when one goes down. Pass the */ /* button that is going down, and its group, and */ /* this routine will pop all others up. */ /* Returns FALSE for an error. */ /***************************************************************************/ BOOL FAR PASCAL toolbarExclusiveRadio(HWND hwnd, int iType, int iButton) { int i; HANDLE h; TOOLBUTTON far *lpButton;
/* Get the array of buttons */ h = GETARRAYBUTT(hwnd); if (!h) return FALSE; lpButton = (TOOLBUTTON far *)GlobalLock(h);
/* all buttons with this type that aren't this button come up */ /* if they are not grayed */ for(i = 0; i < GETNUMBUTTONS(hwnd); i++, lpButton++) if (lpButton->iType == iType) if (lpButton->iButton != iButton && lpButton->iState != BTNST_GRAYED) { toolbarModifyState(hwnd, lpButton->iButton, BTNST_UP); }
GlobalUnlock(h); return TRUE; }
/* NotifyParent() of activity to a button */
static void NEAR PASCAL NotifyParent(HWND hwnd, int iButton) { #ifdef _WIN32
PostMessage( GetParent(hwnd), WM_COMMAND, GET_WM_COMMAND_MPS(GetWindowLong(hwnd, GWL_ID), hwnd, iButton)); #else
PostMessage(GetParent(hwnd),WM_COMMAND, GetWindowWord(hwnd,GWW_ID),MAKELONG(hwnd,iButton)); #endif
}
/***************************************************************************/ /* toolbarPaintControl: Handles paint messages by blitting each bitmap */ /* that is on the toolbar to its rect. */ /* First, it fixes the states of the buttons to give */ /* the focus to the proper button. */ /* Returns FALSE for an error. */ /***************************************************************************/ static BOOL NEAR PASCAL toolbarPaintControl(HWND hwnd, HDC hdc) { int iBtnPos; /* 0 to toolbarGetNumButtons inclusive */ int iButton; /* 0 to NUMBUTTONS-1 inclusive */ int iState; /* 0 to NUMSTATES-1 inclusive */ HDC hdcBtn; /* DC onto button bitmap */
RECT rcDest; POINT pt; long l; HANDLE hbm;
/* Make a source HDC for the button pictures, and select the button */ /* bitmap into it. */ hdcBtn = CreateCompatibleDC(hdc); if (!hdcBtn) return FALSE; hbm = GETBMPHANDLE(hwnd); if (hbm) { if (!SelectObject(hdcBtn, GETBMPHANDLE(hwnd))) { DeleteDC(hdcBtn); return FALSE; } }
toolbarFixFocus(hwnd); // set the focus field correctly
/* Go through all buttons on the toolbar */ for (iBtnPos = 0; iBtnPos < toolbarGetNumButtons(hwnd); iBtnPos++) {
iButton = toolbarButtonFromIndex(hwnd, iBtnPos); // button
iState = toolbarFullStateFromButton(hwnd, iButton); // state
toolbarRectFromIndex(hwnd, iBtnPos, &rcDest); // Dest Rect
/* If we have the focus, we should draw it that way */ if (GetFocus() == hwnd && GETWHICH(hwnd) == iBtnPos && iState == BTNST_UP) iState = BTNST_FOCUSUP; if (GetFocus() == hwnd && GETWHICH(hwnd) == iBtnPos && iState == BTNST_DOWN) iState = BTNST_FOCUSDOWN;
/* If we don't have the focus, we should take it away */ if ((GetFocus() != hwnd || GETWHICH(hwnd) != iBtnPos) && iState == BTNST_FOCUSUP) iState = BTNST_UP; if ((GetFocus() != hwnd || GETWHICH(hwnd) == iBtnPos) && iState == BTNST_FOCUSDOWN) iState = BTNST_DOWN;
/* The size of each button */ l = GETBUTTONSIZE(hwnd); pt.x = HIWORD(l); pt.y = LOWORD(l);
/* Blit from the button picture to the toolbar window */ BitBlt(hdc, rcDest.left, rcDest.top, rcDest.right - rcDest.left, rcDest.bottom - rcDest.top, hdcBtn, pt.x * iButton, pt.y * iState, SRCCOPY); }
DeleteDC(hdcBtn);
return TRUE; }
/***************************************************************************/ /* toolbarMoveFocus: Move Focus forward or backward one button. You give */ /* it the direction to move the focus. The routine will*/ /* stop at the end of the button list without wrapping */ /* around. */ /* Returns TRUE if focus moved, or FALSE if it ran out */ /* of buttons before finding a non-grayed one. */ /***************************************************************************/ BOOL FAR PASCAL toolbarMoveFocus(HWND hwnd, BOOL fBackward) { int iBtnPos, iButton, nOffset, nStopAt; RECT rc; int iPrevPos = GETWHICH(hwnd); /* Who used to have focus? */
/* Fix illegal value. It's OK to be one less or greater than range */ if (iPrevPos < -1 || iPrevPos > GETNUMBUTTONS(hwnd)) SETWHICH(hwnd, 0); // good a default as any
if (fBackward) { nOffset = -1; nStopAt = -1; } else { nOffset = 1; nStopAt = GETNUMBUTTONS(hwnd); } /* look for next button that isn't grayed */ /* DON'T wrap around - future code will pass */ /* the focus to another window (???) */ for (iBtnPos = GETWHICH(hwnd) + nOffset; iBtnPos != nStopAt; iBtnPos += nOffset) { iButton = toolbarButtonFromIndex(hwnd, iBtnPos); if (toolbarStateFromButton(hwnd, iButton) != BTNST_GRAYED) { SETWHICH(hwnd, iBtnPos); // set focus
/* Redraw both old and new focused button */ toolbarRectFromIndex(hwnd, iPrevPos, &rc); InvalidateRect(hwnd, &rc, FALSE); toolbarRectFromIndex(hwnd, iBtnPos, &rc); InvalidateRect(hwnd, &rc, FALSE); break;
} }
if (GETWHICH(hwnd) != iPrevPos) return TRUE; else return FALSE; }
/***************************************************************************/ /* toolbarSetFocus : Set the focus in the toolbar to the specified button.*/ /* If it's gray, it'll set focus to next ungrayed btn. */ /* Returns TRUE if focus set, or FALSE if the button */ /* doesn't exist or if it and all buttons after it were */ /* grayed... You can use TB_FIRST or TB_LAST in */ /* place of a button ID. This uses the first or last */ /* un-grayed button. */ /***************************************************************************/ BOOL FAR PASCAL toolbarSetFocus(HWND hwnd, int iButton) { int iBtnPos; RECT rc = {0};
/* Don't move focus while a button is down */ if (GetCapture() != hwnd && !GETKEYPRESSED(hwnd)) {
/* redraw button with focus in case focus moves */ toolbarRectFromIndex(hwnd, GETWHICH(hwnd), &rc); InvalidateRect(hwnd, &rc, FALSE);
if (iButton == TB_FIRST) { SETWHICH(hwnd, -1); // move forward to 1st button
return toolbarMoveFocus(hwnd, FALSE); } else if (iButton == TB_LAST) { SETWHICH(hwnd, GETNUMBUTTONS(hwnd)); return toolbarMoveFocus(hwnd, TRUE); } else { iBtnPos = toolbarIndexFromButton(hwnd, iButton); if (iBtnPos != -1) { SETWHICH(hwnd, --iBtnPos); return toolbarMoveFocus(hwnd, FALSE); } else return FALSE; } return TRUE;
} else return FALSE; }
//
// LoadUIBitmap() - load a bitmap resource
//
// load a bitmap resource from a resource file, converting all
// the standard UI colors to the current user specifed ones.
//
// this code is designed to load bitmaps used in "gray ui" or
// "toolbar" code.
//
// the bitmap must be a 4bpp windows 3.0 DIB, with the standard
// VGA 16 colors.
//
// the bitmap must be authored with the following colors
//
// Button Text Black (index 0)
// Button Face lt gray (index 7)
// Button Shadow gray (index 8)
// Button Highlight white (index 15)
// Window Color yellow (index 11)
// Window Frame green (index 10)
//
// Example:
//
// hbm = LoadUIBitmap(hInstance, "TestBmp",
// GetSysColor(COLOR_BTNTEXT),
// GetSysColor(COLOR_BTNFACE),
// GetSysColor(COLOR_BTNSHADOW),
// GetSysColor(COLOR_BTNHIGHLIGHT),
// GetSysColor(COLOR_WINDOW),
// GetSysColor(COLOR_WINDOWFRAME));
//
// Author: JimBov, ToddLa
//
//
HBITMAP FAR PASCAL LoadUIBitmap( HANDLE hInstance, // EXE file to load resource from
LPCSTR 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"
{ LPBYTE lpb; HBITMAP hbm = NULL; LPBITMAPINFOHEADER lpbi; HANDLE h; HDC hdc; LPDWORD lprgb; int isize; HANDLE hmem; LPBYTE lpCopy; HRSRC hRes;
// convert a RGB into a RGBQ
#define RGBQ(dw) RGB(GetBValue(dw),GetGValue(dw),GetRValue(dw))
hRes = FindResource(hInstance, szName, RT_BITMAP); if (NULL == hRes) { return NULL; } if ( !(h = LoadResource (hInstance,hRes) ) ) return NULL;
lpbi = (LPBITMAPINFOHEADER)LockResource(h);
if (!lpbi) return(NULL);
if (lpbi->biSize != sizeof(BITMAPINFOHEADER)) return NULL;
if (lpbi->biBitCount != 4) return NULL;
/*
* copy the resource since they are now loaded read-only */ #ifdef _WIN32
isize = lpbi->biSize + lpbi->biSizeImage + ((int)lpbi->biClrUsed ? (int)lpbi->biClrUsed : (1 << (int)lpbi->biBitCount)) * sizeof(RGBQUAD); hmem = GlobalAlloc(GHND, isize); lpCopy = GlobalLock(hmem); if ((hmem == NULL) || (lpCopy == NULL)) { UnlockResource(h); FreeResource(h); return(NULL); }
CopyMemory(lpCopy, lpbi, isize);
lpbi = (LPBITMAPINFOHEADER)lpCopy; #endif
/* Calcluate the pointer to the Bits information */ /* First skip over the header structure */
lprgb = (LPDWORD)((LPBYTE)(lpbi) + lpbi->biSize);
/* Skip the color table entries, if any */ lpb = (LPBYTE)lprgb + ((int)lpbi->biClrUsed ? (int)lpbi->biClrUsed : (1 << (int)lpbi->biBitCount)) * sizeof(RGBQUAD);
lprgb[0] = RGBQ(rgbText); // Black
lprgb[7] = RGBQ(rgbFace); // lt gray
lprgb[8] = RGBQ(rgbShadow); // gray
lprgb[15] = RGBQ(rgbHighlight); // white
lprgb[11] = RGBQ(rgbWindow); // yellow
lprgb[10] = RGBQ(rgbFrame); // green
if ( hdc = GetDC(NULL) ) { hbm = CreateDIBitmap (hdc, lpbi, CBM_INIT, (LPVOID)lpb, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
ReleaseDC(NULL, hdc); }
UnlockResource(h); FreeResource(h);
return(hbm); }
/****************************************************************************
toolbarWndProc()
Window proc for toolbar.
Arguments: Standard window proc ****************************************************************************/
LRESULT FAR PASCAL toolbarWndProc(HWND hwnd, unsigned message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; POINT pt; RECT rc; int iBtnPos, iButton, ibmp; HANDLE lpaButtons, hbm, hInst;
switch (message) {
case WM_CREATE: // do all initialization
/* What do these do? */ SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); SetWindowLong(hwnd,GWL_STYLE,lpCreate->style & 0xFFFF00FF); /* Alloc some space for the array of buttons on this bar */ lpaButtons = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, TOOLGROW * sizeof(TOOLBUTTON));
SETARRAYBUTT(hwnd, lpaButtons); // list of buttons on toolbar
SETNUMBUTTONS(hwnd, 0); // # buttons in toolbar
SETPRESSED(hwnd, FALSE); // mouse button being pressed?
SETKEYPRESSED(hwnd, FALSE); // is a key being pressed?
SETWHICH(hwnd, -1); // which button has the focus?
SETSHIFTED(hwnd, FALSE); // shift-click or right-click?
/* This wParam will be sent to the parent window to indentify */ /* that the toolbar sent the WM_COMMAND msg. The hwnd of the */ /* toolbar that sent the msg will be in the lParam. */ #ifdef _WIN32
SetWindowLong(hwnd, GWL_ID, IDC_TOOLBAR); #else
SetWindowWord(hwnd, GWW_ID, (WORD)IDC_TOOLBAR); #endif
/* later on, someone will set the bmp handle of the buttons */ SETBMPHANDLE(hwnd, NULL);
break;
case WM_LBUTTONDOWN: // button goes down on a toolbar button
case WM_RBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK:
/* If we don't give ourself focus, we'll never get KEYDOWN */ /* or KEYUP messages. */ /* Get the focus only if we're a TABSTOP and the app wants */ /* us to take focus. */ if ( (GetWindowLong(hwnd, GWL_STYLE) & WS_TABSTOP) && GetFocus() != hwnd) SetFocus(hwnd);
/* ignore messages if window is disabled */ if (!IsWindowEnabled(hwnd)) return 0L;
/* ignore multiple down messages (we set Capture here) */ /* also ignore if a key is down */ if (GetCapture() == hwnd || GETPRESSED(hwnd)) return 0L; /* Where did the mouse go down? */ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
/* which button was pressed? */ iBtnPos = toolbarIndexFromPoint(hwnd, pt);
/* If it was a valid button... */ if (iBtnPos >= 0) { int iOldPos; int iState, iType, iButton;
/* Everything you wanted to know about this button */ iType = toolbarTypeFromIndex(hwnd, iBtnPos); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iState = toolbarFullStateFromButton(hwnd, iButton);
/* ignore downs on a grayed button, unless it's a */ /* custom button, then tell them anyway */ if (iType != BTNTYPE_CUSTOM && iState == BTNST_GRAYED) return 0;
/* We better get all mouse messages from now on */ SetCapture(hwnd);
/* Shift key or right button indicates a SHIFT down */ SETSHIFTED(hwnd, (message == WM_RBUTTONDOWN) || (wParam & MK_SHIFT));
/* Yes, we've pressed the button down */ SETPRESSED(hwnd, TRUE);
/* Remember who used to have the focus, and we get it now */ iOldPos = GETWHICH(hwnd); SETWHICH(hwnd, iBtnPos);
/* For a push button, send it down */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_DOWN);
/* for a checkbox or radio button (of any group), */ /* remember what state it was in, and send it FULL down */ /* (with focus). */ if (iType == BTNTYPE_CHECKBOX || iType >= BTNTYPE_RADIO) { toolbarModifyPrevState(hwnd, iButton, iState); toolbarModifyState(hwnd,iButton,BTNST_FULLDOWN); }
toolbarModifyActivity(hwnd, iButton, BTNACT_MOUSEDOWN);
/* Set Double click flag appropriately */ if (message == WM_LBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + BTN_DBLCLICK + iButton); else NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + iButton);
/* Invalidate the Rect of the button being pressed */ toolbarRectFromIndex(hwnd, iBtnPos, &rc); InvalidateRect(hwnd, &rc, FALSE);
/* Invalidate the Rect of the button losing focus */ toolbarRectFromIndex(hwnd, iOldPos, &rc); InvalidateRect(hwnd, &rc, FALSE);
/* Force re-paint now */ UpdateWindow(hwnd);
/* Set a timer for repeated mouse downs */ SetTimer(hwnd, TIMER_BUTTONREPEAT, MSEC_BUTTONREPEAT, NULL); } return 0L;
case WM_MOUSEMOVE:
#if 0
/* This should be impossible - it means that the system lost */ /* a mouse up (maybe codeview is up?) We need to force a */ /* mouse up at this point. */ if (GetCapture() == hwnd && (wParam & (MK_LBUTTON | MK_RBUTTON) == 0)) SendMessage(hwnd, WM_LBUTTONUP, 0, lParam); #endif
/* Mouse moving while pressing a button? If not, ignore. */ if (GetCapture() == hwnd) { int iPrevState, iState, iButton, iType; BOOL fPressed; /* Which button is being pressed down? */ iBtnPos = GETWHICH(hwnd);
/* Where is mouse cursor now? */ pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam);
/* where is button being pressed? Are we still on */ /* top of that button or have we moved? */ toolbarRectFromIndex(hwnd, iBtnPos, &rc); fPressed = PtInRect(&rc, pt);
/* Let go if we move off of the button, but don't */ /* act like it was pressed. */ /* Also, push it back down if we move back on top */ /* of it (while the mouse button is STILL down). */ if (fPressed != GETPRESSED(hwnd)) {
/* update: is this button pressed anymore? */ SETPRESSED(hwnd, fPressed);
iType = toolbarTypeFromIndex(hwnd, iBtnPos); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iState = toolbarFullStateFromButton(hwnd, iButton);
/* The mouse moved back onto the button while */ /* the mouse button was still pressed. */ if (fPressed) {
/* Push the push button back down again */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_DOWN);
/* Push the radio or checkbox button ALL the */ /* way down again. */ if (iType >= BTNTYPE_RADIO || iType == BTNTYPE_CHECKBOX) toolbarModifyState(hwnd, iButton, BTNST_FULLDOWN);
toolbarModifyActivity(hwnd, iButton, BTNACT_MOUSEMOVEON); NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + iButton);
/* We moved the mouse off of the toolbar button */ /* while still holding the mouse button down. */ } else {
/* lift the push button up */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_UP);
/* Restore radio button or checkbox button to */ /* where it was before pressed */ if (iType >= BTNTYPE_RADIO || iType == BTNTYPE_CHECKBOX) { iPrevState = toolbarPrevStateFromButton(hwnd, iButton); toolbarModifyState(hwnd, iButton, iPrevState); }
toolbarModifyActivity(hwnd, iButton, BTNACT_MOUSEMOVEOFF); NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + toolbarButtonFromIndex(hwnd, iBtnPos)); } } } return 0L;
case WM_LBUTTONUP: case WM_RBUTTONUP:
/* If we don't have capture, we aren't expecting this. Ignore */ if (GetCapture() == hwnd) { int iPrevState, iState, iButton, iType; /* Who has the focus? */ iBtnPos = GETWHICH(hwnd);
/* Release the mouse */ ReleaseCapture(); /* No more repeats of the mouse button downs */ KillTimer(hwnd, TIMER_BUTTONREPEAT); /* Everything you wanted to know about the button */ toolbarRectFromIndex(hwnd, iBtnPos, &rc); iType = toolbarTypeFromIndex(hwnd, iBtnPos); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iState = toolbarFullStateFromButton(hwnd, iButton);
/* Don't do anything if we've moved off the button */ if (GETPRESSED(hwnd)) {
/* No longer down */ SETPRESSED(hwnd, FALSE);
/* Bring the push button up */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_UP);
/* Bring the checkbox to the opposite state it was in */ if (iType == BTNTYPE_CHECKBOX) { iPrevState = toolbarPrevStateFromButton(hwnd, iButton); if (iPrevState == BTNST_DOWN) toolbarModifyState(hwnd, iButton, BTNST_UP); if (iPrevState == BTNST_UP) toolbarModifyState(hwnd, iButton, BTNST_DOWN); }
/* Force a radio button down, and bring all */ /* other radio buttons of this type up */ if (iType >= BTNTYPE_RADIO) { toolbarModifyState(hwnd, iButton, BTNST_DOWN); toolbarExclusiveRadio(hwnd, iType, iButton); }
/* Notify the parent that the mouse button came up */ /* on this button so the app can do something. */ /* Every button should notify the app, not just a */ /* custom button. */ toolbarModifyActivity(hwnd, iButton, BTNACT_MOUSEUP); NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + iButton); } }
return 0L;
case WM_TIMER:
/* If we have a tool button down, send a repeat message */ if (GETPRESSED(hwnd)) { int iButton, iType;
iBtnPos = GETWHICH(hwnd); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iType = toolbarTypeFromIndex(hwnd, iBtnPos);
NotifyParent(hwnd, BTN_REPEAT + (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + toolbarButtonFromIndex(hwnd, iBtnPos)); } break;
case WM_DESTROY: if (GETBMPHANDLE(hwnd)) DeleteObject(GETBMPHANDLE(hwnd)); SETBMPHANDLE(hwnd, NULL); if (GETARRAYBUTT(hwnd)) GlobalFree(GETARRAYBUTT(hwnd)); SETARRAYBUTT(hwnd, NULL); break;
case WM_SETTEXT: break; /* MANY, MANY cases deleted */
case WM_SETFOCUS: // focus comes to toolbar window
{ /* Remember who had the focus and give it back. Of course, */ /* if by some wierdness that button is now grayed, give it */ /* to the next person in line. */ iBtnPos = GETWHICH(hwnd); if (iBtnPos < 0 || iBtnPos >= toolbarGetNumButtons(hwnd)) { iBtnPos = 0; SETWHICH(hwnd, 0); }
do { iButton = toolbarButtonFromIndex(hwnd, iBtnPos); if (toolbarFullStateFromButton(hwnd, iButton) != BTNST_GRAYED) break; // give it here
iBtnPos++; if (iBtnPos >= toolbarGetNumButtons(hwnd)) iBtnPos = 0; // wrap around
if (iBtnPos == GETWHICH(hwnd)) return 0L; // uh-oh! They're all gray!
} while (iBtnPos != GETWHICH(hwnd)); SETWHICH(hwnd, iBtnPos); // give focus here
/* And redraw! */ toolbarRectFromIndex(hwnd, iBtnPos, &rc); InvalidateRect(hwnd, &rc, FALSE); UpdateWindow(hwnd); return 0; } case WM_KILLFOCUS:
/* Send a KEYUP if one is pending */ if (GETKEYPRESSED(hwnd)) SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0L);
/* Redraw the focused button, because now that focus is gone */ /* from our toolbar window, the focused button won't be */ /* focused anymore, although we remember which one it was. */ toolbarRectFromIndex(hwnd, GETWHICH(hwnd), &rc); InvalidateRect(hwnd, &rc, FALSE); UpdateWindow(hwnd); return 0;
case WM_SYSKEYDOWN: /* Send a KEYUP if one is pending */ if (GETKEYPRESSED(hwnd)) SendMessage(hwnd, WM_KEYUP, VK_SPACE, 0L); break; // MUST LET DEFWNDPROC RUN!!! (to handle the key)
case WM_GETDLGCODE: return DLGC_WANTARROWS | DLGC_WANTTAB;
case WM_KEYDOWN:
/* Window disabled or a key is already down */ if (IsWindowEnabled(hwnd) && !GETPRESSED(hwnd)) {
/* Tab forward to next button and move focus there */ if (wParam == VK_TAB && GetKeyState(VK_SHIFT) >= 0 ) {
/* Move Focus forward one. If */ /* we've tabbed off of the toolbar, it's time */ /* to go on to the next control. We need to invldte */ /* because we might be the only control and we need */ /* to repaint to show the new button with highlight */ /* after it wrapped around the end of the toolbar. */ if (!toolbarMoveFocus(hwnd, FALSE)) { PostMessage(GetParent(hwnd), WM_NEXTDLGCTL, 0, 0L); toolbarRectFromIndex(hwnd, GETWHICH(hwnd), &rc); InvalidateRect(hwnd, &rc, FALSE); }
return 0L; } if (wParam == VK_TAB && GetKeyState(VK_SHIFT) < 0 ) {
/* Move focus backward one. If */ /* We've tabbed off of the toolbar, it's time */ /* to go on to the next control. We need to invldte */ /* because we might be the only control and we need */ /* to repaint to show the new button with highlight */ /* after it wrapped around the end of the toolbar. */ if (!toolbarMoveFocus(hwnd, TRUE)) { PostMessage(GetParent(hwnd), WM_NEXTDLGCTL, 1, 0L); toolbarRectFromIndex(hwnd, GETWHICH(hwnd), &rc); InvalidateRect(hwnd, &rc, FALSE); }
return 0L; } if ((wParam == VK_SPACE) && (GetCapture() != hwnd)) {
int iButton, iType, iState;
/* Same as mouse button down -- Press the button! */ iBtnPos = GETWHICH(hwnd); iType = toolbarTypeFromIndex(hwnd, iBtnPos); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iState = toolbarFullStateFromButton(hwnd, iButton);
/* ignore multiple key downs */ if (!GETKEYPRESSED(hwnd)) {
SETKEYPRESSED(hwnd, TRUE); // a key is pressed
SETSHIFTED(hwnd, FALSE); // NEVER shifted
SETPRESSED(hwnd, TRUE); // a button is pressed
/* Push button goes down - with focus */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_DOWN);
/* Radio or checkbox button goes full down */ /* with focus - and remember previous state*/ if (iType >= BTNTYPE_RADIO || iType == BTNTYPE_CHECKBOX) { toolbarModifyPrevState(hwnd, iButton, iState); toolbarModifyState(hwnd, iButton, BTNST_FULLDOWN); }
toolbarModifyActivity(hwnd, iButton, BTNACT_KEYDOWN); NotifyParent(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + iButton);
return 0L; } /* If this is another KEYDOWN msg, it's a REPEAT */ /* Notify parent. */ NotifyParent(hwnd, BTN_REPEAT + (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + toolbarButtonFromIndex(hwnd, GETWHICH(hwnd))); } } break; case WM_KEYUP:
/* A button was pressed and should come up now */ if ((wParam == VK_SPACE) && (GETKEYPRESSED(hwnd))) { int iButton, iState, iType, iPrevState;
iBtnPos = GETWHICH(hwnd); // which button?
SETKEYPRESSED(hwnd, FALSE); // let go
SETPRESSED(hwnd, FALSE);
/* Everything about this button */ toolbarRectFromIndex(hwnd, iBtnPos, &rc); iType = toolbarTypeFromIndex(hwnd, iBtnPos); iButton = toolbarButtonFromIndex(hwnd, iBtnPos); iState = toolbarFullStateFromButton(hwnd, iButton);
/* Bring a push button up */ if (iType == BTNTYPE_PUSH) toolbarModifyState(hwnd, iButton, BTNST_UP);
/* Bring a checkbox to the opposite state it was in */ if (iType == BTNTYPE_CHECKBOX) { iPrevState = toolbarPrevStateFromButton(hwnd, iButton); if (iPrevState == BTNST_DOWN) toolbarModifyState(hwnd, iButton, BTNST_UP); if (iPrevState == BTNST_UP) toolbarModifyState(hwnd, iButton, BTNST_DOWN); }
/* Bring a radio button down, and bring all others in */ /* its group up. */ if (iType >= BTNTYPE_RADIO) { toolbarModifyState(hwnd, iButton, BTNST_DOWN); toolbarExclusiveRadio(hwnd, iType, iButton); }
toolbarModifyActivity(hwnd, iButton, BTNACT_KEYUP); NotifyParent(hwnd, toolbarButtonFromIndex(hwnd, (GETSHIFTED(hwnd) ? BTN_SHIFT : 0) + GETWHICH(hwnd))); } break; case WM_SYSCOLORCHANGE: /* load the bitmap of what all the buttons look like */ /* and change the colours to the system colours. */ hInst = GETHINST(hwnd); ibmp = GETBMPINT(hwnd); hbm = GETBMPHANDLE(hwnd); if (hbm) DeleteObject(hbm); hbm = LoadUIBitmap(hInst, MAKEINTRESOURCE(ibmp), GetSysColor(COLOR_BTNTEXT), GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_BTNSHADOW), GetSysColor(COLOR_BTNHIGHLIGHT), GetSysColor(COLOR_BTNFACE), GetSysColor(COLOR_WINDOWFRAME)); SETBMPHANDLE(hwnd, hbm); #ifdef _WIN32
return (LONG_PTR) hbm; #else
return MAKELONG(hbm, 0); #endif
case WM_ERASEBKGND: break;
case WM_PAINT:
/* Call our paint code */ BeginPaint(hwnd, &ps); toolbarPaintControl(hwnd, ps.hdc); EndPaint(hwnd, &ps);
return 0L; }
return DefWindowProc(hwnd, message, wParam, lParam);
}
|