/*-----------------------------------------------------------------------------+ | TOOLBAR.C | | | | Contains the code which implements the toolbar and its buttons. | | | | (C) Copyright Microsoft Corporation 1991. All rights reserved. | | | | Revision History | | Oct-1992 MikeTri Ported to WIN32 / WIN16 common code | | | +-----------------------------------------------------------------------------*/ #include #include #include #include "toolbar.h" #include "mpole.h" #include "mplayer.h" #ifndef COLOR_BTNFACE #define COLOR_BTNFACE 15 #define COLOR_BTNSHADOW 16 #define COLOR_BTNTEXT 18 #endif extern void FAR cdecl dprintf(LPSTR szFormat, ...); extern HWND ghwndApp; extern HWND ghwndToolbar; extern HWND ghwndFSArrows; /* Variables */ HBRUSH hbrGray = NULL; // Gray for text HBRUSH hbrButtonFace; HBRUSH hbrButtonShadow; HBRUSH hbrButtonText; HBRUSH hbrButtonHighLight; HBRUSH hbrWindowFrame; HBRUSH hbrWindowColour; DWORD rgbButtonHighLight; DWORD rgbButtonFocus; DWORD rgbButtonFace; DWORD rgbButtonText; DWORD rgbButtonShadow; DWORD rgbWindowFrame; DWORD rgbWindowColour; TBBUTTON tbBtns[TB_NUM_BTNS + MARK_NUM_BTNS + ARROW_NUM_BTNS] = { {BTN_PLAY, IDT_PLAY, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_PAUSE, IDT_PAUSE, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_STOP, IDT_STOP, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_EJECT, IDT_EJECT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_HOME, IDT_HOME, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_RWD, IDT_RWD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_FWD, IDT_FWD, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_END, IDT_END, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {-1, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0}, {BTN_MARKIN, IDT_MARKIN, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {BTN_MARKOUT, IDT_MARKOUT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {ARROW_PREV, IDT_ARROWPREV, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0}, {ARROW_NEXT, IDT_ARROWNEXT, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0} }; int BtnIndex[TB_NUM_BTNS + MARK_NUM_BTNS + ARROW_NUM_BTNS]; static int iBtnOffset[3] = {0,TB_NUM_BTNS, TB_NUM_BTNS+MARK_NUM_BTNS}; WNDPROC fnTBWndProc = NULL; WNDPROC fnStatusWndProc = NULL; /* ControlInit( hInst ) This is called when the application is first loaded into memory. It performs all initialization. Arguments: hInst instance handle of current instance Returns: TRUE if successful, FALSE if not */ BOOL FAR PASCAL ControlInit( HANDLE hInst) { long patGray[4]; HBITMAP hbmGray; int i; /* initialize the brushes */ for (i=0; i < 4; i++) patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray hbmGray = CreateBitmap(8, 8, 1, 1, patGray); hbrGray = CreatePatternBrush(hbmGray); if (hbmGray) DeleteObject(hbmGray); rgbButtonFace = GetSysColor(COLOR_BTNFACE); rgbButtonShadow = GetSysColor(COLOR_BTNSHADOW); rgbButtonText = GetSysColor(COLOR_BTNTEXT); rgbButtonHighLight = GetSysColor(COLOR_BTNHIGHLIGHT); rgbButtonFocus = GetSysColor(COLOR_BTNTEXT); rgbWindowFrame = GetSysColor(COLOR_WINDOWFRAME); rgbWindowColour = GetSysColor(COLOR_WINDOW); if (rgbButtonFocus == rgbButtonFace) rgbButtonFocus = rgbButtonText; hbrButtonFace = CreateSolidBrush(rgbButtonFace); hbrButtonShadow = CreateSolidBrush(rgbButtonShadow); hbrButtonText = CreateSolidBrush(rgbButtonText); hbrButtonHighLight = CreateSolidBrush(rgbButtonHighLight); hbrWindowFrame = CreateSolidBrush(rgbWindowFrame); hbrWindowColour = CreateSolidBrush(rgbWindowColour); if (((UINT_PTR)hbrWindowFrame & // fail if any of them are NULL ??? (UINT_PTR)hbrButtonShadow & (UINT_PTR)hbrButtonText & (UINT_PTR)hbrButtonHighLight & (UINT_PTR)hbrWindowFrame) == (UINT_PTR)0) return FALSE; return TRUE; } /* ControlCleanup() Delete the brushes we've been using */ void FAR PASCAL ControlCleanup(void) { DeleteObject(hbrGray); DeleteObject(hbrButtonFace); DeleteObject(hbrButtonShadow); DeleteObject(hbrButtonText); DeleteObject(hbrButtonHighLight); DeleteObject(hbrWindowFrame); DeleteObject(hbrWindowColour); #if 0 DeleteObject(hbTBMain); DeleteObject(hbTBMark); DeleteObject(hbTBArrows); #endif } BOOL FAR PASCAL toolbarInit(void) { int i; InitCommonControls(); for(i = 0; i < TB_NUM_BTNS + MARK_NUM_BTNS + ARROW_NUM_BTNS; i++) BtnIndex[i] = -1; return TRUE; } LONG_PTR FAR PASCAL SubClassedTBWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch(wMsg) { case WM_SIZE: return 0; case WM_STARTTRACK: switch(wParam) { case IDT_RWD: case IDT_FWD: case IDT_ARROWPREV: case IDT_ARROWNEXT: PostMessage(ghwndApp, WM_COMMAND, wParam, REPEAT_ID); SetTimer(hwnd, (UINT_PTR)ghwndApp, MSEC_BUTTONREPEAT, NULL); } return 0; case WM_ENDTRACK: switch(wParam) { case IDT_RWD: case IDT_FWD: case IDT_ARROWPREV: case IDT_ARROWNEXT: KillTimer(hwnd, wParam); SendMessage(ghwndApp, WM_HSCROLL, (WPARAM)TB_ENDTRACK, (LPARAM)hwnd); } return 0; case WM_TIMER: { WPARAM cmd; if (wParam != (WPARAM)ghwndApp) break; if (hwnd == ghwndToolbar) { if(SendMessage(hwnd, TB_ISBUTTONPRESSED, tbBtns[BTN_RWD].idCommand, 0L)) cmd = IDT_RWD; else if(SendMessage(hwnd, TB_ISBUTTONPRESSED, tbBtns[BTN_FWD].idCommand, 0L)) cmd = IDT_FWD; else return 0; PostMessage(ghwndApp, WM_COMMAND, cmd, REPEAT_ID); return 0; } else if (hwnd == ghwndFSArrows) { if(SendMessage(hwnd, TB_ISBUTTONPRESSED, tbBtns[TB_NUM_BTNS+MARK_NUM_BTNS+ARROW_PREV].idCommand, 0L)) cmd = IDT_ARROWPREV; else if(SendMessage(hwnd, TB_ISBUTTONPRESSED, tbBtns[TB_NUM_BTNS+MARK_NUM_BTNS+ARROW_NEXT].idCommand, 0L)) cmd = IDT_ARROWNEXT; else return 0; PostMessage(ghwndApp, WM_COMMAND, cmd, REPEAT_ID); return 0; } KillTimer(hwnd, wParam); return 0; } } return CallWindowProc(fnTBWndProc, hwnd, wMsg, wParam, lParam); } void SubClassTBWindow(HWND hwnd) { if (!fnTBWndProc) fnTBWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC); if (hwnd) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)SubClassedTBWndProc); } #ifndef CCS_NODIVIDER /* For NT: */ #define CCS_NODIVIDER 0 #endif HWND FAR PASCAL toolbarCreateMain(HWND hwndParent) { HWND hwnd; hwnd = CreateToolbarEx(hwndParent, WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|TBSTYLE_BUTTON|TBSTYLE_TOOLTIPS| CCS_NODIVIDER, IDT_TBMAINCID, 8, ghInst, IDR_TOOLBAR, NULL, 0, 16, 16, 16, 16, sizeof(TBBUTTON)); if (hwnd) SubClassTBWindow(hwnd); return hwnd; } HWND FAR PASCAL toolbarCreateMark(HWND hwndParent) { HWND hwnd; hwnd = CreateToolbarEx(hwndParent, WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|TBSTYLE_BUTTON|TBSTYLE_TOOLTIPS| CCS_NODIVIDER, IDT_TBMARKCID, 2, ghInst, IDR_MARK, NULL, 0, 17, 16, 17, 16, sizeof(TBBUTTON)); if (hwnd) SubClassTBWindow(hwnd); return hwnd; } HWND FAR PASCAL toolbarCreateArrows(HWND hwndParent) { HWND hwnd; hwnd = CreateToolbarEx(hwndParent, WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|TBSTYLE_BUTTON|TBSTYLE_TOOLTIPS| CCS_NODIVIDER, IDT_TBARROWSCID, 2, ghInst, IDR_ARROWS, NULL, 0, 4, 7, 4, 7, sizeof(TBBUTTON)); if (hwnd) SubClassTBWindow(hwnd); return hwnd; } /***************************************************************************/ /* 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. */ /***************************************************************************/ BOOL FAR PASCAL toolbarStateFromButton(HWND hwnd, int iButton, int tbIndex) { int idBtn; int pos; pos = BtnIndex[iBtnOffset[tbIndex] + iButton]; if (pos == -1) return FALSE; idBtn = tbBtns[iBtnOffset[tbIndex] + iButton].idCommand; return (BOOL)SendMessage(hwnd, TB_ISBUTTONENABLED, (WPARAM)idBtn, 0L); } /***************************************************************************/ /* 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, int iButton, int tbIndex, int iState) { TBBUTTON tb; tb = tbBtns[iBtnOffset[tbIndex] + iButton]; if (iState) tb.fsState |= TBSTATE_ENABLED; else tb.fsState &= ~TBSTATE_ENABLED; if(!SendMessage(hwnd, TB_ADDBUTTONS, (WPARAM)1, (LPARAM)(const TBBUTTON FAR *)&tb)) return FALSE; BtnIndex[iBtnOffset[tbIndex] + iButton] = (int)SendMessage(hwnd, TB_BUTTONCOUNT, 0, 0L) - 1; return TRUE; } BOOL FAR PASCAL toolbarSwapTools(HWND hwnd, int iButton, int jButton, int tbIndex) { int pos; TBBUTTON tb; int newBut, oldBut; pos = BtnIndex[iBtnOffset[tbIndex] + iButton]; if (pos == -1) { pos = BtnIndex[iBtnOffset[tbIndex] + jButton]; if (pos == -1) return FALSE; newBut = iButton; oldBut = jButton; } else { newBut = jButton; oldBut = iButton; } SendMessage(hwnd, TB_DELETEBUTTON, (WPARAM)pos, 0L); BtnIndex[iBtnOffset[tbIndex] + oldBut] = -1; tb = tbBtns[iBtnOffset[tbIndex] + newBut]; if(!SendMessage(hwnd, TB_INSERTBUTTON, (WPARAM)pos, (LPARAM)(const TBBUTTON FAR *)&tb)) return FALSE; BtnIndex[iBtnOffset[tbIndex] + newBut] = pos; return TRUE; } /***************************************************************************/ /* toolbarModifyState: Given a button ID on the toolbar, change its */ /* state. */ /* returns FALSE for an error or if no such button */ /***************************************************************************/ BOOL FAR PASCAL toolbarModifyState(HWND hwnd, int iButton, int tbIndex, int iState) { int idBtn; int pos; pos = BtnIndex[iBtnOffset[tbIndex] + iButton]; if (pos == -1) return FALSE; idBtn = tbBtns[iBtnOffset[tbIndex] + iButton].idCommand; SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)idBtn, 0L); //unpress button first. commctrl bug if (idBtn == IDT_STOP) { SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)IDT_HOME, 0L); SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)IDT_END, 0L); SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)IDT_FWD, 0L); SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)IDT_RWD, 0L); } if (!iState) SendMessage(hwnd, TB_PRESSBUTTON, (WPARAM)IDT_EJECT, 0L); SendMessage(hwnd, TB_ENABLEBUTTON, (WPARAM)idBtn, (LPARAM)MAKELONG(iState, 0)); return TRUE; } /***************************************************************************/ /* toolbarSetFocus : Set the focus in the toolbar to the specified button.*/ /* If it's gray, it'll set focus to next ungrayed btn. */ /***************************************************************************/ BOOL FAR PASCAL toolbarSetFocus(HWND hwnd, int iButton) { int pos; if ((hwnd != ghwndToolbar) || (iButton != BTN_PLAY && iButton != BTN_PAUSE)) return TRUE; pos = BtnIndex[iButton]; if (pos != -1) return TRUE; toolbarSwapTools(hwnd, iButton, 1-iButton, TBINDEX_MAIN); return TRUE; } LONG_PTR FAR PASCAL SubClassedStatusWndProc(HWND hwnd, UINT wMsg, WPARAM wParam, LPARAM lParam) { switch(wMsg) { case WM_SIZE: return 0; } return CallWindowProc(fnStatusWndProc, hwnd, wMsg, wParam, lParam); } void SubClassStatusWindow(HWND hwnd) { if (!fnStatusWndProc) fnStatusWndProc = (WNDPROC)GetWindowLongPtr(hwnd, GWLP_WNDPROC); if (hwnd) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)SubClassedStatusWndProc); } /* SBS_SIZEGRIP isn't defined for NT!! */ #ifndef SBS_SIZEGRIP #define SBS_SIZEGRIP 0 #endif HWND CreateStaticStatusWindow(HWND hwndParent, BOOL fSizeGrip) { HWND hwnd; hwnd = CreateStatusWindow(WS_CHILD|WS_VISIBLE|(fSizeGrip ? 0 : CCS_NOMOVEY), TEXT(""), hwndParent, IDT_STATUSWINDOWCID); if (hwnd) SubClassStatusWindow(hwnd); return hwnd; } BOOL WriteStatusMessage(HWND hwnd, LPTSTR szMsg) { TCHAR Text[64]; SIZE StatusTextExtent; LONG StatusTextWidth; BOOL rc; Text[0] = TEXT('\0'); GetWindowText(hwnd, Text, CHAR_COUNT(Text)); if (lstrcmp(szMsg, Text) == 0) return TRUE; GetStatusTextExtent(ghwndStatic, &StatusTextExtent); StatusTextWidth = StatusTextExtent.cy; rc = (BOOL)SendMessage(hwnd, SB_SETTEXT, (WPARAM)0, (LPARAM)szMsg); GetStatusTextExtent(ghwndStatic, &StatusTextExtent); if (StatusTextWidth != StatusTextExtent.cy) Layout(); return rc; } BOOL GetStatusTextExtent(HWND hwnd, LPSIZE pTextExtent) { HDC hdc; HFONT hfontOld; TCHAR Text[64]; hdc = GetDC(NULL); if (hdc == NULL) return FALSE; Text[0] = TEXT('\0'); GetWindowText(hwnd, Text, CHAR_COUNT(Text)); hfontOld = SelectObject(hdc, (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0)); GetTextExtentPoint32(hdc, Text, STRLEN(Text), pTextExtent); SelectObject(hdc, hfontOld); ReleaseDC(NULL, hdc); return TRUE; }