530 lines
15 KiB
C
530 lines
15 KiB
C
/*-----------------------------------------------------------------------------+
|
||
| 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 <windows.h>
|
||
#include <string.h>
|
||
#include <shellapi.h>
|
||
|
||
#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;
|
||
}
|
||
|