///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  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);
    }
}