778 lines
21 KiB
C++
778 lines
21 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// MBUTTON.CPP
|
||
|
//
|
||
|
// Multimedia Button Control class; helper functions
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation 1997
|
||
|
//
|
||
|
// 12/14/97 David Stewart / dstewart
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#include "mbutton.h"
|
||
|
#include <windowsx.h> //for GetWindowFont
|
||
|
#include <winuser.h> //for TrackMouseEvent
|
||
|
#include <commctrl.h> //for WM_MOUSELEAVE
|
||
|
#include <TCHAR.H>
|
||
|
#include "resource.h"
|
||
|
#include "dib.h"
|
||
|
#include "mmfw.h"
|
||
|
|
||
|
//file-local default values for buttons
|
||
|
#define NUM_STATES 3
|
||
|
#define STATE_UP 0
|
||
|
#define STATE_DN 1
|
||
|
#define STATE_HI 2
|
||
|
#define BOFF_STANDARDLEFT 0
|
||
|
#define BOFF_TOGGLELEFT 1
|
||
|
#define BOFF_STANDARDRIGHT 2
|
||
|
#define BOFF_DROPRIGHT 3
|
||
|
#define BOFF_TOGGLERIGHT 4
|
||
|
#define BOFF_MIDDLE 5
|
||
|
#define BOFF_SYSTEM 6
|
||
|
#define BOFF_MINIMIZE 7
|
||
|
#define BOFF_RESTORE 8
|
||
|
#define BOFF_MAXIMIZE 9
|
||
|
#define BOFF_CLOSE 10
|
||
|
#define BOFF_MUTE 11
|
||
|
#define BOFF_END 12
|
||
|
#define BUTTON_BITMAP_HEIGHT 19
|
||
|
#define BUTTON_FONT_SIZE 8
|
||
|
#define BUTTON_DBCS_FONT_SIZE 9
|
||
|
#define BUTTON_FONT_WEIGHT FW_BOLD
|
||
|
|
||
|
#define MBUTTON_TEXT_COLOR RGB(0xFF,0xFF,0xFF)
|
||
|
|
||
|
HFONT hFont = NULL;
|
||
|
HANDLE hbmpButtonToolkit = NULL;
|
||
|
int nStateOffset = 0;
|
||
|
int nButtonOffsets[BOFF_END+1];
|
||
|
extern HPALETTE hpalMain;
|
||
|
extern int g_nColorMode;
|
||
|
CMButton* pButtonFocus = NULL;
|
||
|
CMButton* pButtonMouse = NULL;
|
||
|
BOOL fAllowFocus = TRUE;
|
||
|
|
||
|
|
||
|
//for this to work on a Win95 machine, we need to make TrackMouseEvent
|
||
|
//a dynamically loaded thing ... but then you get NO HOVER-OVER EFFECT
|
||
|
typedef BOOL (PASCAL *TRACKPROC)(LPTRACKMOUSEEVENT);
|
||
|
TRACKPROC procTrackMouseEvent = NULL;
|
||
|
|
||
|
BOOL InitMButtons(HINSTANCE hInst, HWND hwnd)
|
||
|
{
|
||
|
BOOL fReturn = TRUE;
|
||
|
|
||
|
//if TrackMouseEvent exists, use it
|
||
|
HMODULE hUser = GetModuleHandle(TEXT("USER32"));
|
||
|
if (hUser)
|
||
|
{
|
||
|
procTrackMouseEvent = (TRACKPROC)GetProcAddress(hUser,"TrackMouseEvent");
|
||
|
}
|
||
|
|
||
|
//create font, named store in IDS_MBUTTON_FONT in string table
|
||
|
LOGFONT lf;
|
||
|
ZeroMemory( &lf, sizeof(lf) );
|
||
|
|
||
|
HFONT hTempFont = GetWindowFont( hwnd );
|
||
|
if (hTempFont == NULL)
|
||
|
{
|
||
|
hTempFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
|
||
|
}
|
||
|
|
||
|
GetObject(hTempFont,sizeof(lf),&lf);
|
||
|
|
||
|
lf.lfHeight = (-BUTTON_FONT_SIZE * STANDARD_PIXELS_PER_INCH) / 72;
|
||
|
if (lf.lfCharSet == ANSI_CHARSET)
|
||
|
{
|
||
|
lf.lfWeight = BUTTON_FONT_WEIGHT;
|
||
|
}
|
||
|
else if (IS_DBCS_CHARSET(lf.lfCharSet)) {
|
||
|
lf.lfHeight = (-BUTTON_DBCS_FONT_SIZE * STANDARD_PIXELS_PER_INCH) / 72;
|
||
|
}
|
||
|
|
||
|
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||
|
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||
|
lf.lfQuality = PROOF_QUALITY;
|
||
|
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
|
||
|
|
||
|
LoadString(hInst,IDS_MBUTTON_FONT,lf.lfFaceName,LF_FACESIZE-1);
|
||
|
|
||
|
hFont = CreateFontIndirect(&lf);
|
||
|
|
||
|
//create bitmap, has all states for all buttons
|
||
|
int nBitmap = IDB_BUTTON_TOOLKIT;
|
||
|
switch (g_nColorMode)
|
||
|
{
|
||
|
case COLOR_16 : nBitmap = IDB_BUTTON_TOOLKIT_16; break;
|
||
|
case COLOR_HICONTRAST : nBitmap = IDB_BUTTON_TOOLKIT_HI; break;
|
||
|
}
|
||
|
|
||
|
HBITMAP hbmpTemp = (HBITMAP)LoadImage(hInst,MAKEINTRESOURCE(nBitmap),IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION);
|
||
|
hbmpButtonToolkit = DibFromBitmap((HBITMAP)hbmpTemp,0,0,NULL,0);
|
||
|
BITMAP bm;
|
||
|
GetObject(hbmpTemp,sizeof(bm),&bm);
|
||
|
DeleteObject(hbmpTemp);
|
||
|
|
||
|
nStateOffset = bm.bmWidth / NUM_STATES;
|
||
|
|
||
|
//offsets within bitmap
|
||
|
nButtonOffsets[BOFF_STANDARDLEFT] = 0;
|
||
|
nButtonOffsets[BOFF_TOGGLELEFT] = 9;
|
||
|
nButtonOffsets[BOFF_STANDARDRIGHT] = 11;
|
||
|
nButtonOffsets[BOFF_DROPRIGHT] = 20;
|
||
|
nButtonOffsets[BOFF_TOGGLERIGHT] = 42;
|
||
|
nButtonOffsets[BOFF_MIDDLE] = 44;
|
||
|
nButtonOffsets[BOFF_SYSTEM] = 52;
|
||
|
nButtonOffsets[BOFF_MINIMIZE] = 64;
|
||
|
nButtonOffsets[BOFF_RESTORE] = 78;
|
||
|
nButtonOffsets[BOFF_MAXIMIZE] = 92;
|
||
|
nButtonOffsets[BOFF_CLOSE] = 106;
|
||
|
nButtonOffsets[BOFF_MUTE] = 121;
|
||
|
nButtonOffsets[BOFF_END] = nStateOffset;
|
||
|
|
||
|
//SetDibUsage(hbmpButtonToolkit,hpalMain,DIB_RGB_COLORS);
|
||
|
|
||
|
return (fReturn);
|
||
|
}
|
||
|
|
||
|
void UninitMButtons()
|
||
|
{
|
||
|
GlobalFree(hbmpButtonToolkit);
|
||
|
DeleteObject(hFont);
|
||
|
}
|
||
|
|
||
|
//Given a parent window and a control ID, return the CMButton object
|
||
|
CMButton* GetMButtonFromID(HWND hwndParent, int nID)
|
||
|
{
|
||
|
HWND hwnd = GetDlgItem(hwndParent, nID);
|
||
|
return (GetMButtonFromHWND(hwnd));
|
||
|
}
|
||
|
|
||
|
//Given the window handle of the button, return the CMButton object
|
||
|
CMButton* GetMButtonFromHWND(HWND hwnd)
|
||
|
{
|
||
|
CMButton* pButton = (CMButton*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||
|
return (pButton);
|
||
|
}
|
||
|
|
||
|
CMButton* CreateMButton(TCHAR* szCaption, int nIconID, DWORD dwWindowStyle, DWORD dwMButtonStyle, int x, int y, int width, int height, HWND hwndParentOrSub, BOOL fSubExisting, int nID, int nToolTipID, HINSTANCE hInst)
|
||
|
{
|
||
|
CMButton* pButton = new CMButton;
|
||
|
|
||
|
//ensure the button is a child, pushbutton, owner-draw
|
||
|
//caller should specify WS_VISIBLE|WS_TABSTOP if desired
|
||
|
dwWindowStyle = dwWindowStyle|WS_CHILD|BS_PUSHBUTTON|BS_OWNERDRAW;
|
||
|
|
||
|
HWND hwnd;
|
||
|
|
||
|
if (fSubExisting)
|
||
|
{
|
||
|
//user already created button, is probably calling from WM_INITDIALOG
|
||
|
hwnd = hwndParentOrSub;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//need to create the button ourselves
|
||
|
hwnd = CreateWindow(TEXT("BUTTON"),
|
||
|
szCaption,
|
||
|
dwWindowStyle,
|
||
|
x,
|
||
|
y,
|
||
|
width,
|
||
|
height,
|
||
|
hwndParentOrSub,
|
||
|
(HMENU)IntToPtr(nID),
|
||
|
hInst,
|
||
|
NULL);
|
||
|
}
|
||
|
|
||
|
if (hwnd == NULL)
|
||
|
{
|
||
|
//if we can't create the window, nuke it and fail
|
||
|
delete pButton;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
pButton->m_hInst = hInst;
|
||
|
pButton->m_fRedraw = FALSE;
|
||
|
pButton->m_dwStyle = dwMButtonStyle;
|
||
|
pButton->m_hwnd = hwnd;
|
||
|
pButton->SetIcon(nIconID);
|
||
|
pButton->SetFont(hFont);
|
||
|
pButton->m_fRedraw = TRUE;
|
||
|
pButton->m_nID = nID;
|
||
|
pButton->SetToolTipID(nToolTipID);
|
||
|
|
||
|
pButton->PreDrawUpstate(width,height);
|
||
|
|
||
|
//subclass the button; allows tracking of mouse events
|
||
|
pButton->m_fnOldButton = (WNDPROC)SetWindowLongPtr(hwnd,GWLP_WNDPROC,(LONG_PTR)CMButton::ButtonProc);
|
||
|
|
||
|
//put the button's pointer into the window's user bytes
|
||
|
SetWindowLongPtr(hwnd,GWLP_USERDATA,(LONG_PTR)pButton);
|
||
|
|
||
|
return (pButton);
|
||
|
}
|
||
|
|
||
|
void CMButton::PreDrawUpstate(int width, int height)
|
||
|
{
|
||
|
//pre-draw the up states of the buttons for a faster-seeming first blit
|
||
|
if (m_hbmpUp) DeleteObject(m_hbmpUp);
|
||
|
if (m_hbmpDn) DeleteObject(m_hbmpDn);
|
||
|
if (m_hbmpHi) DeleteObject(m_hbmpHi);
|
||
|
m_hbmpUp = NULL;
|
||
|
m_hbmpDn = NULL;
|
||
|
m_hbmpHi = NULL;
|
||
|
|
||
|
DRAWITEMSTRUCT drawItem;
|
||
|
|
||
|
drawItem.rcItem.left = 0;
|
||
|
drawItem.rcItem.top = 0;
|
||
|
drawItem.rcItem.right = width;
|
||
|
drawItem.rcItem.bottom = height;
|
||
|
|
||
|
drawItem.itemState = 0;
|
||
|
drawItem.hDC = GetDC(m_hwnd);
|
||
|
HPALETTE hpalOld = SelectPalette(drawItem.hDC,hpalMain,FALSE);
|
||
|
RealizePalette(drawItem.hDC);
|
||
|
|
||
|
DrawButtonBitmap(&drawItem,FALSE,NULL);
|
||
|
|
||
|
SelectPalette(drawItem.hDC,hpalOld,TRUE);
|
||
|
RealizePalette(drawItem.hDC);
|
||
|
ReleaseDC(m_hwnd,drawItem.hDC);
|
||
|
}
|
||
|
|
||
|
LRESULT CALLBACK CMButton::ButtonProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
CMButton* pButton = (CMButton*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||
|
|
||
|
if (pButton == NULL)
|
||
|
{
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
switch (iMsg)
|
||
|
{
|
||
|
case WM_MOUSEMOVE :
|
||
|
{
|
||
|
if (!pButton->m_fMouseInButton)
|
||
|
{
|
||
|
if (procTrackMouseEvent)
|
||
|
{
|
||
|
//only do this if the trackmouseevent function exists,
|
||
|
//otherwise, the button color will never turn off
|
||
|
pButton->m_fMouseInButton = TRUE;
|
||
|
TRACKMOUSEEVENT tme;
|
||
|
tme.cbSize = sizeof(tme);
|
||
|
tme.dwFlags = TME_LEAVE;
|
||
|
tme.dwHoverTime = HOVER_DEFAULT;
|
||
|
tme.hwndTrack = hwnd;
|
||
|
procTrackMouseEvent(&tme);
|
||
|
InvalidateRect(hwnd,NULL,FALSE);
|
||
|
} //end proctrackmouseevent is valid
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_KEYUP :
|
||
|
{
|
||
|
//for the close, min, and view buttons, we want to shunt
|
||
|
//any keyboard movement to the knob ... although tempting,
|
||
|
//don't do this on the setfocus, or the mouse won't work right
|
||
|
|
||
|
if (
|
||
|
(pButton->m_nID == IDB_CLOSE) ||
|
||
|
(pButton->m_nID == IDB_MINIMIZE) ||
|
||
|
(pButton->m_nID == IDB_SET_TINY_MODE) ||
|
||
|
(pButton->m_nID == IDB_SET_NORMAL_MODE)
|
||
|
)
|
||
|
{
|
||
|
HWND hwndFocus = GetDlgItem(GetParent(hwnd),IDB_VOLUME);
|
||
|
if (IsWindowVisible(hwndFocus))
|
||
|
{
|
||
|
SetFocus(hwndFocus);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hwndFocus = GetDlgItem(GetParent(hwnd),IDB_OPTIONS);
|
||
|
SetFocus(hwndFocus);
|
||
|
}
|
||
|
} //end if
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_SETFOCUS :
|
||
|
{
|
||
|
SendMessage(GetParent(pButton->m_hwnd),DM_SETDEFID,pButton->m_nID,0);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_MOUSELEAVE :
|
||
|
{
|
||
|
pButton->m_fMouseInButton = FALSE;
|
||
|
InvalidateRect(hwnd,NULL,FALSE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_ERASEBKGND :
|
||
|
{
|
||
|
DRAWITEMSTRUCT drawItem;
|
||
|
drawItem.hDC = (HDC)wParam;
|
||
|
GetClientRect(hwnd,&(drawItem.rcItem));
|
||
|
drawItem.itemState = pButton->m_LastState;
|
||
|
pButton->Draw(&drawItem);
|
||
|
return TRUE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
} //end switch
|
||
|
|
||
|
LRESULT lResult = CallWindowProc((WNDPROC)pButton->m_fnOldButton,hwnd,iMsg,wParam,lParam);
|
||
|
|
||
|
if ((iMsg == WM_DESTROY) && ((pButton->m_dwStyle & MBS_NOAUTODELETE) == 0))
|
||
|
{
|
||
|
//auto-delete the button class
|
||
|
SetWindowLongPtr(hwnd,GWLP_USERDATA,0);
|
||
|
delete pButton;
|
||
|
pButton = NULL;
|
||
|
}
|
||
|
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
CMButton::CMButton()
|
||
|
{
|
||
|
//init all data values
|
||
|
m_fMouseInButton = FALSE;
|
||
|
m_dwStyle = MBS_STANDARDLEFT | MBS_STANDARDRIGHT;
|
||
|
m_hFont = hFont;
|
||
|
m_nID = 0;
|
||
|
m_IconID = 0;
|
||
|
m_hwnd = NULL;
|
||
|
m_hbmpUp = NULL;
|
||
|
m_hbmpDn = NULL;
|
||
|
m_hbmpHi = NULL;
|
||
|
m_fRedraw = FALSE;
|
||
|
m_fMenu = FALSE;
|
||
|
m_fMenuingOff = FALSE;
|
||
|
m_LastState = 0;
|
||
|
}
|
||
|
|
||
|
CMButton::~CMButton()
|
||
|
{
|
||
|
if (m_hbmpUp) DeleteObject(m_hbmpUp);
|
||
|
if (m_hbmpDn) DeleteObject(m_hbmpDn);
|
||
|
if (m_hbmpHi) DeleteObject(m_hbmpHi);
|
||
|
}
|
||
|
|
||
|
void CMButton::SetText(TCHAR* szCaption)
|
||
|
{
|
||
|
SetWindowText(m_hwnd,szCaption);
|
||
|
|
||
|
if (m_fRedraw)
|
||
|
{
|
||
|
InvalidateRect(m_hwnd,NULL,FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CMButton::SetIcon(int nIconID)
|
||
|
{
|
||
|
//assuming caller is responsible for cleaning up
|
||
|
m_IconID = nIconID;
|
||
|
|
||
|
if (m_fRedraw)
|
||
|
{
|
||
|
InvalidateRect(m_hwnd,NULL,FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CMButton::SetFont(HFONT hFont)
|
||
|
{
|
||
|
//assume caller is responsible for cleaning up
|
||
|
m_hFont = hFont;
|
||
|
}
|
||
|
|
||
|
void CMButton::DrawButtonBitmap(LPDRAWITEMSTRUCT lpdis, BOOL fDrawToScreen, RECT* pMidRect)
|
||
|
{
|
||
|
HANDLE hTemp = m_hbmpUp;
|
||
|
int nState = STATE_UP;
|
||
|
|
||
|
if (m_fMouseInButton)
|
||
|
{
|
||
|
pButtonMouse = this;
|
||
|
hTemp = m_hbmpHi;
|
||
|
nState = STATE_HI;
|
||
|
|
||
|
if (pButtonFocus!=NULL)
|
||
|
{
|
||
|
fAllowFocus = FALSE;
|
||
|
if (this != pButtonFocus)
|
||
|
{
|
||
|
InvalidateRect(pButtonFocus->GetHWND(),NULL,FALSE);
|
||
|
UpdateWindow(pButtonFocus->GetHWND());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (lpdis->itemState & ODS_FOCUS)
|
||
|
{
|
||
|
if (this == pButtonFocus)
|
||
|
{
|
||
|
if (fAllowFocus)
|
||
|
{
|
||
|
hTemp = m_hbmpHi;
|
||
|
nState = STATE_HI;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hTemp = m_hbmpUp;
|
||
|
nState = STATE_UP;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pButtonFocus = this;
|
||
|
hTemp = m_hbmpHi;
|
||
|
nState = STATE_HI;
|
||
|
fAllowFocus = TRUE;
|
||
|
if ((pButtonMouse!=NULL) && (pButtonMouse!=this))
|
||
|
{
|
||
|
pButtonMouse->m_fMouseInButton = FALSE;
|
||
|
InvalidateRect(pButtonMouse->GetHWND(),NULL,FALSE);
|
||
|
UpdateWindow(pButtonMouse->GetHWND());
|
||
|
pButtonMouse = NULL;
|
||
|
} //end if removing mouse highlight
|
||
|
}
|
||
|
}
|
||
|
} //end if mouse in or out of button
|
||
|
|
||
|
if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
|
||
|
{
|
||
|
hTemp = m_hbmpDn;
|
||
|
nState = STATE_DN;
|
||
|
}
|
||
|
|
||
|
int offLeft, widLeft;
|
||
|
int offRight, widRight;
|
||
|
int offMid, widMid;
|
||
|
|
||
|
offLeft = nButtonOffsets[BOFF_STANDARDLEFT] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_STANDARDLEFT+1] - nButtonOffsets[BOFF_STANDARDLEFT];
|
||
|
|
||
|
if ((m_dwStyle & MBS_TOGGLELEFT) == MBS_TOGGLELEFT)
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_TOGGLELEFT] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_TOGGLELEFT+1] - nButtonOffsets[BOFF_TOGGLELEFT];
|
||
|
}
|
||
|
|
||
|
if ((m_dwStyle & MBS_SYSTEMTYPE) == MBS_SYSTEMTYPE)
|
||
|
{
|
||
|
switch (m_IconID)
|
||
|
{
|
||
|
case IDB_CLOSE :
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_CLOSE] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_CLOSE+1] - nButtonOffsets[BOFF_CLOSE];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDB_MINIMIZE :
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_MINIMIZE] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_MINIMIZE+1] - nButtonOffsets[BOFF_MINIMIZE];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDB_SET_TINY_MODE :
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_RESTORE] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_RESTORE+1] - nButtonOffsets[BOFF_RESTORE];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDB_SET_NORMAL_MODE :
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_MAXIMIZE] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_MAXIMIZE+1] - nButtonOffsets[BOFF_MAXIMIZE];
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case IDB_MUTE :
|
||
|
{
|
||
|
offLeft = nButtonOffsets[BOFF_MUTE] + (nState * nStateOffset);
|
||
|
widLeft = nButtonOffsets[BOFF_MUTE+1] - nButtonOffsets[BOFF_MUTE];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
offRight = nButtonOffsets[BOFF_STANDARDRIGHT] + (nState * nStateOffset);
|
||
|
widRight = nButtonOffsets[BOFF_STANDARDRIGHT+1] - nButtonOffsets[BOFF_STANDARDRIGHT];
|
||
|
|
||
|
if ((m_dwStyle & MBS_TOGGLERIGHT) == MBS_TOGGLERIGHT)
|
||
|
{
|
||
|
offRight = nButtonOffsets[BOFF_TOGGLERIGHT] + (nState * nStateOffset);
|
||
|
widRight = nButtonOffsets[BOFF_TOGGLERIGHT+1] - nButtonOffsets[BOFF_TOGGLERIGHT];
|
||
|
}
|
||
|
|
||
|
if ((m_dwStyle & MBS_DROPRIGHT) == MBS_DROPRIGHT)
|
||
|
{
|
||
|
offRight = nButtonOffsets[BOFF_DROPRIGHT] + (nState * nStateOffset);
|
||
|
widRight = nButtonOffsets[BOFF_DROPRIGHT+1] - nButtonOffsets[BOFF_DROPRIGHT];
|
||
|
}
|
||
|
|
||
|
offMid = nButtonOffsets[BOFF_MIDDLE] + (nState * nStateOffset);
|
||
|
widMid = (lpdis->rcItem.right - lpdis->rcItem.left) - widLeft - widRight;
|
||
|
|
||
|
if (pMidRect)
|
||
|
{
|
||
|
if (m_dwStyle & MBS_DROPRIGHT)
|
||
|
{
|
||
|
//set rect to just the middle of the button part
|
||
|
SetRect(pMidRect,
|
||
|
lpdis->rcItem.left,
|
||
|
lpdis->rcItem.top,
|
||
|
lpdis->rcItem.left + widLeft + widMid,
|
||
|
lpdis->rcItem.top + BUTTON_BITMAP_HEIGHT);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//set rect to whole button
|
||
|
SetRect(pMidRect,
|
||
|
lpdis->rcItem.left,
|
||
|
lpdis->rcItem.top,
|
||
|
lpdis->rcItem.right,
|
||
|
lpdis->rcItem.bottom);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (hTemp == NULL)
|
||
|
{
|
||
|
//draw and save bumps
|
||
|
HDC memDC = CreateCompatibleDC(lpdis->hDC);
|
||
|
HPALETTE hpalOld = SelectPalette(memDC, hpalMain, FALSE);
|
||
|
HBITMAP holdbmp;
|
||
|
|
||
|
switch (nState)
|
||
|
{
|
||
|
case STATE_UP :
|
||
|
{
|
||
|
m_hbmpUp = CreateCompatibleBitmap(lpdis->hDC,
|
||
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
||
|
BUTTON_BITMAP_HEIGHT);
|
||
|
|
||
|
holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpUp);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STATE_DN :
|
||
|
{
|
||
|
m_hbmpDn = CreateCompatibleBitmap(lpdis->hDC,
|
||
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
||
|
BUTTON_BITMAP_HEIGHT);
|
||
|
holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpDn);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case STATE_HI :
|
||
|
{
|
||
|
m_hbmpHi = CreateCompatibleBitmap(lpdis->hDC,
|
||
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
||
|
BUTTON_BITMAP_HEIGHT);
|
||
|
holdbmp = (HBITMAP)SelectObject(memDC,m_hbmpHi);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//draw left
|
||
|
DibBlt(memDC,
|
||
|
lpdis->rcItem.left,
|
||
|
lpdis->rcItem.top,
|
||
|
-1,
|
||
|
-1,
|
||
|
hbmpButtonToolkit,
|
||
|
offLeft,0,
|
||
|
SRCCOPY,0);
|
||
|
|
||
|
if ((m_dwStyle & MBS_SYSTEMTYPE) != MBS_SYSTEMTYPE)
|
||
|
{
|
||
|
//draw middle
|
||
|
StretchDibBlt(memDC,
|
||
|
lpdis->rcItem.left + widLeft,
|
||
|
lpdis->rcItem.top,
|
||
|
widMid,
|
||
|
BUTTON_BITMAP_HEIGHT,
|
||
|
hbmpButtonToolkit,
|
||
|
offMid,0,
|
||
|
nButtonOffsets[BOFF_MIDDLE+1] - nButtonOffsets[BOFF_MIDDLE],
|
||
|
BUTTON_BITMAP_HEIGHT,
|
||
|
SRCCOPY,0);
|
||
|
|
||
|
//draw right
|
||
|
DibBlt(memDC,
|
||
|
lpdis->rcItem.right - widRight,
|
||
|
lpdis->rcItem.top,
|
||
|
-1,
|
||
|
-1,
|
||
|
hbmpButtonToolkit,
|
||
|
offRight,0,
|
||
|
SRCCOPY,0);
|
||
|
}
|
||
|
|
||
|
SelectObject(memDC,holdbmp);
|
||
|
SelectPalette(memDC, hpalOld, TRUE);
|
||
|
DeleteDC(memDC);
|
||
|
} //end not already drawn
|
||
|
|
||
|
if (fDrawToScreen)
|
||
|
{
|
||
|
//should have bumps ready to go now
|
||
|
hTemp = m_hbmpUp;
|
||
|
|
||
|
if (m_fMouseInButton)
|
||
|
{
|
||
|
hTemp = m_hbmpHi;
|
||
|
}
|
||
|
|
||
|
if (lpdis->itemState & ODS_FOCUS)
|
||
|
{
|
||
|
if (fAllowFocus)
|
||
|
{
|
||
|
hTemp = m_hbmpHi;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
|
||
|
{
|
||
|
hTemp = m_hbmpDn;
|
||
|
}
|
||
|
|
||
|
if (!(lpdis->itemState & ODS_SELECTED) && (m_fMenuingOff))
|
||
|
{
|
||
|
m_fMenu = FALSE;
|
||
|
m_fMenuingOff = FALSE;
|
||
|
hTemp = m_hbmpUp;
|
||
|
}
|
||
|
|
||
|
HDC memDC = CreateCompatibleDC(lpdis->hDC);
|
||
|
HBITMAP holdbmp = (HBITMAP)SelectObject(memDC,hTemp);
|
||
|
|
||
|
BitBlt(lpdis->hDC,
|
||
|
lpdis->rcItem.left,
|
||
|
lpdis->rcItem.top,
|
||
|
lpdis->rcItem.right - lpdis->rcItem.left,
|
||
|
lpdis->rcItem.bottom - lpdis->rcItem.top,
|
||
|
memDC,
|
||
|
0,0,
|
||
|
SRCCOPY);
|
||
|
|
||
|
SelectObject(memDC,holdbmp);
|
||
|
DeleteDC(memDC);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CMButton::Draw(LPDRAWITEMSTRUCT lpdis)
|
||
|
{
|
||
|
HPALETTE hpalOld = SelectPalette(lpdis->hDC,hpalMain,FALSE);
|
||
|
RealizePalette(lpdis->hDC);
|
||
|
|
||
|
SetTextColor(lpdis->hDC, MBUTTON_TEXT_COLOR);
|
||
|
|
||
|
m_LastState = lpdis->itemState;
|
||
|
|
||
|
if (lpdis->itemState & ODS_DISABLED)
|
||
|
{
|
||
|
SetTextColor(lpdis->hDC, GetSysColor(COLOR_GRAYTEXT));
|
||
|
}
|
||
|
|
||
|
RECT midRect;
|
||
|
DrawButtonBitmap(lpdis,TRUE,&midRect);
|
||
|
|
||
|
if ((m_dwStyle & MBS_SYSTEMTYPE) == MBS_SYSTEMTYPE)
|
||
|
{
|
||
|
SelectPalette(lpdis->hDC,hpalOld,TRUE);
|
||
|
RealizePalette(lpdis->hDC);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
SetBkMode(lpdis->hDC,TRANSPARENT);
|
||
|
|
||
|
if (m_IconID == 0)
|
||
|
{
|
||
|
HFONT hOldFont = (HFONT)SelectObject(lpdis->hDC,m_hFont);
|
||
|
|
||
|
TCHAR szCaption[MAX_PATH];
|
||
|
GetWindowText(m_hwnd,szCaption,sizeof(szCaption)/sizeof(TCHAR));
|
||
|
SIZE size;
|
||
|
|
||
|
GetTextExtentPoint32( lpdis->hDC, szCaption, _tcslen(szCaption), &size );
|
||
|
|
||
|
//center text
|
||
|
int x = (((midRect.right - midRect.left) - size.cx) / 2) + midRect.left;
|
||
|
int y = (((lpdis->rcItem.bottom - lpdis->rcItem.top) - size.cy) / 2) + lpdis->rcItem.top;
|
||
|
|
||
|
//simulate a press
|
||
|
if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
|
||
|
{
|
||
|
x++;
|
||
|
y++;
|
||
|
}
|
||
|
|
||
|
ExtTextOut( lpdis->hDC, x, y, 0, NULL, szCaption, _tcslen(szCaption), NULL );
|
||
|
|
||
|
SelectObject(lpdis->hDC,hOldFont);
|
||
|
} //end if no icon
|
||
|
else
|
||
|
{
|
||
|
//center icon
|
||
|
int x = (((midRect.right - midRect.left) - 32) / 2) + midRect.left;
|
||
|
int y = (((lpdis->rcItem.bottom - lpdis->rcItem.top) - 32) / 2) + lpdis->rcItem.top;
|
||
|
//simulate a press
|
||
|
if ((lpdis->itemState & ODS_SELECTED) || (m_fMenu))
|
||
|
{
|
||
|
x++;
|
||
|
y++;
|
||
|
}
|
||
|
|
||
|
HICON hIcon = (HICON)LoadImage(m_hInst, MAKEINTRESOURCE(m_IconID), IMAGE_ICON, 32, 32, LR_MONOCHROME);
|
||
|
DrawIcon(lpdis->hDC,x,y,hIcon);
|
||
|
DestroyIcon(hIcon);
|
||
|
}
|
||
|
|
||
|
SelectPalette(lpdis->hDC,hpalOld,TRUE);
|
||
|
RealizePalette(lpdis->hDC);
|
||
|
}
|
||
|
|
||
|
void CMButton::SetMenuingState(BOOL fMenuOn)
|
||
|
{
|
||
|
if (fMenuOn)
|
||
|
{
|
||
|
m_fMenu = fMenuOn;
|
||
|
m_fMenuingOff = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_fMenuingOff = TRUE;
|
||
|
InvalidateRect(m_hwnd,NULL,FALSE);
|
||
|
UpdateWindow(m_hwnd);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CMButton::SetToolTipID(int nID)
|
||
|
{
|
||
|
m_nToolTipID = nID;
|
||
|
|
||
|
//for buttons with icons, set the window text to equal the tooltip text.
|
||
|
//this helps for accessibility aids, so they can read the button's function
|
||
|
if (m_IconID != 0)
|
||
|
{
|
||
|
TCHAR szCaption[MAX_PATH];
|
||
|
LoadString(m_hInst,nID,szCaption,sizeof(szCaption)/sizeof(TCHAR));
|
||
|
SetWindowText(m_hwnd,szCaption);
|
||
|
}
|
||
|
}
|
||
|
|