TOOLBAR.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:55k
源码类别:
Windows编程
开发平台:
Visual C++
- /**************************************************************************
- *
- * 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 - 1997 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
- char szToolBarClass[] = "ToolBarClass";
- HBRUSH ghbrToolbar; // brush for toolbar background
- //
- // Window proc for buttons, THIS FUNCTION MUST BE EXPORTED
- //
- LONG FAR PASCAL toolbarWndProc(HWND, unsigned, UINT, LONG);
- typedef long (FAR PASCAL *LPWNDPROC)();
- /*
- Defines
- */
- #ifdef _WIN32
- #define GETARRAYBUTT(hwnd) ((HANDLE)GetWindowLong(hwnd,GWL_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)GetWindowLong(hwnd,GWL_BMPHANDLE))
- #define GETBMPINT(hwnd) ((int)GetWindowLong(hwnd,GWL_BMPINT))
- #define GETBUTTONSIZE(hwnd) GetWindowLong(hwnd,GWL_BUTTONSIZE)
- #define GETHINST(hwnd) ((HANDLE)GetWindowLong(hwnd,GWL_HINST))
- #define SETARRAYBUTT(hwnd, h) SetWindowLong(hwnd, GWL_ARRAYBUTT, (UINT)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) SetWindowLong(hwnd, GWL_BMPHANDLE, (UINT)h)
- #define SETBMPINT(hwnd, i) SetWindowLong(hwnd, GWL_BMPINT, (UINT)i)
- #define SETBUTTONSIZE(hwnd, l) SetWindowLong(hwnd, GWL_BUTTONSIZE, l)
- #define SETHINST(hwnd, h) SetWindowLong(hwnd, GWL_HINST, (UINT)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;
- /* 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;
- LPBITMAPINFOHEADER lpbi;
- HANDLE h;
- HDC hdc;
- LPDWORD lprgb;
- int isize;
- HANDLE hmem;
- LPBYTE lpCopy;
- // convert a RGB into a RGBQ
- #define RGBQ(dw) RGB(GetBValue(dw),GetGValue(dw),GetRValue(dw))
- h = LoadResource (hInstance,FindResource(hInstance, szName, RT_BITMAP));
- 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);
- UnlockResource(h);
- FreeResource(h);
- 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
- 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
- ****************************************************************************/
- LONG FAR PASCAL toolbarWndProc(HWND hwnd, unsigned message,
- UINT wParam, LONG 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) 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);
- }