📄 toolbar.c
字号:
/***************************************************************************/
/* 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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -