//////////////////////////////////////////////////////////////////////////////
/// Mac Button implementation
#pragma once
#define RADIOBOX_CHECKBOX_BMP_WIDTH 16 //radiobox��checkboxλͼ���
#define RADIOBOX_CHECKBOX_BMP_HEIGHT 16 //radiobox��checkboxλͼ�߶�
#define GROUPBOX_TEXT_SPACE 7 //groupbox���������ң��߿����
//��ť����
#define BASETYPE_OWNERDRAW 0
#define BASETYPE_GROUPBOX 1
#define BASETYPE_RADIOBUTTON 2
#define BASETYPE_CHECKBOX 3
#define BASETYPE_BUTTON 4
#define MAC_TRANPARENT_COLOR RGB(255, 0, 255)
#define MAC_DISABLE_COLOR RGB(128, 128, 128)
class CMacButton : public CWidgetHook<CMacButton, CButton>
{
public:
enum{
MAC_BTN_WIDTH = 10,
MAC_BTN_HEIGHT = 22,
MAC_BTN_MIN = 20,
MAC_CHECK_WIDTH = 16,
MAC_CHECK_HEIGHT = 17,
MAC_RADIO_WIDTH = 16,
MAC_RADIO_HEIGHT = 16
};
enum{
STATE_NORMAL = 0,
STATE_PUSHED = 1,
STATE_HOT = 2
};
BEGIN_MSG_MAP(CMacButton)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnRefresh)
MESSAGE_HANDLER(WM_KILLFOCUS, OnRefresh)
MESSAGE_HANDLER(WM_SETFOCUS, OnRefresh)
MESSAGE_HANDLER(BM_SETCHECK, OnStateChange)
MESSAGE_HANDLER(BM_SETSTATE, OnStateChange)
MESSAGE_HANDLER(WM_ENABLE, OnRefresh)
END_MSG_MAP()
void Initialize()
{
m_nState = STATE_NORMAL;
m_bTracking = false;
}
//���ʼ��, ����Դ
static void InitializeClass()
{
CBitmap bmp;
m_ilButton.Create(MAC_BTN_WIDTH, MAC_BTN_HEIGHT, ILC_COLOR24, 0, 6);
bmp.LoadBitmap(IDB_BUTTON);
m_ilButton.Add(bmp);
bmp.DeleteObject();
m_ilCheck.Create(MAC_CHECK_WIDTH, MAC_CHECK_HEIGHT, ILC_COLOR24, 0, 6);
bmp.LoadBitmap(IDB_CHECK);
m_ilCheck.Add(bmp);
bmp.DeleteObject();
m_ilRadio.Create(MAC_RADIO_WIDTH, MAC_RADIO_HEIGHT, ILC_COLOR24, 0, 6);
bmp.LoadBitmap(IDB_RADIO);
m_ilRadio.Add(bmp);
bmp.DeleteObject();
}
//����ֹ,������Դ
static void FinalizeClass()
{
m_ilButton.Destroy();
m_ilCheck.Destroy();
m_ilRadio.Destroy();
}
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
return 0;
}
///////////////////////////////////////
// �������
LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
//bHandled = FALSE;
DefWindowProc();
long lStyle = GetWindowLong(GWL_STYLE);
if ( !(lStyle & WS_DISABLED) )
{
m_nState = STATE_PUSHED;
long lBaseType = GetBaseType();
if ( lBaseType && lBaseType != BASETYPE_GROUPBOX )//ownerdraw��groupbox���ù�
{
Invalidate(FALSE);
}
}
return 0;
}
///////////////////////////////////
// ����ͷ�
LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
LONG lBaseType = GetBaseType();
if ( lBaseType && lBaseType != BASETYPE_GROUPBOX )//ownerdraw��groupbox���ù�
{
if ( m_nState == STATE_PUSHED )//˵���ڱ��ؼ��ϰ��£�Ȼ��ſ���
{
Invalidate(FALSE);
m_nState = STATE_NORMAL;
}
}
return 0;
}
///////////////////////////////////
// ����ƶ�
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
if (!m_bTracking)
{
m_nState = STATE_HOT;
TRACKMOUSEEVENT tmt = {sizeof(TRACKMOUSEEVENT),
TME_LEAVE, m_hWnd, 0};//��������뿪��Ϣ
if ( _TrackMouseEvent(&tmt) )//��ʼ����
m_bTracking = true;
Invalidate(FALSE);
}
return 0;
}
///////////////////////////////////
// ����Ƴ�
LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
m_bTracking = false;
Invalidate(FALSE);
return 0;
}
//////////////////////////////
// ��ͼ
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
long lType = GetBaseType();
switch (lType)
{
case BASETYPE_GROUPBOX:
DrawGroup();
break;
case BASETYPE_BUTTON:
DrawButton();
break;
case BASETYPE_CHECKBOX:
DrawCheck();
break;
case BASETYPE_RADIOBUTTON:
DrawRadio();
break;
default:
bHandled = FALSE;
}
return 0;
}
////////////////////////////////////
// ˢ����ʾ
LRESULT OnRefresh(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
LONG lBaseType = GetBaseType();
if ( lBaseType && lBaseType != BASETYPE_GROUPBOX )//��groupbox���ҷ��Ի�
{
//Invalidate();
CWindow wndParent = GetParent();
if (wndParent.m_hWnd)
{
CRect rcWin;
GetWindowRect(&rcWin);
wndParent.InvalidateRect(&rcWin, FALSE);
}
}
return 0;
}
////////////////////////////////////
// ״̬�ı�, ˢ����ʾ
LRESULT OnStateChange(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
LONG lBaseType = GetBaseType();
if ( lBaseType && lBaseType != BASETYPE_GROUPBOX )//��groupbox���ҷ��Ի�
{
Invalidate(FALSE);
// CWindow wndParent = GetParent();
// if (wndParent.m_hWnd)
// {
// CRect rcWin;
// GetWindowRect(&rcWin);
// wndParent.InvalidateRect(&rcWin);
// }
}
return 0;
}
/********************************************************************
* �� ����GetBaseType() *
* �� �ܣ��õ�button�Ļ������group��check��radio����ͨbutton) *
* �� ������ *
* ����ֵ�������ownerdraw���� ��BASETYPE_OWNERDRAW *
* �����groupbox ��BASETYPE_GROUPBOX *
* �����radiobutton ��BASETYPE_RADIOBUTTON *
* �����checkbox ��BASETYPE_CHECKBOX *
* �������ͨ��ť ��BASETYPE_BUTTON *
* ˵ ��: *
********************************************************************/
long GetBaseType()
{
long lStyle = GetWindowLong(GWL_STYLE);
if ( (lStyle & BS_OWNERDRAW) == BS_OWNERDRAW )//ownerdraw
return BASETYPE_OWNERDRAW;
if ((lStyle & BS_GROUPBOX)==BS_GROUPBOX)//groupbox
return BASETYPE_GROUPBOX;
else if ((lStyle & BS_CHECKBOX)==BS_CHECKBOX
|| (lStyle & BS_AUTOCHECKBOX) == BS_AUTOCHECKBOX )//checkbox
return BASETYPE_CHECKBOX;
else if ((lStyle & BS_AUTORADIOBUTTON)==BS_AUTORADIOBUTTON
|| (lStyle & BS_RADIOBUTTON)==BS_RADIOBUTTON)//radiobox
return BASETYPE_RADIOBUTTON;
//��ͨ��ť
return BASETYPE_BUTTON;
}
/**************************************************************
* ������ͨ��ť
***************************************************************/
void DrawButton(void)
{
CPaintDC dc(m_hWnd);
LONG lStyle = GetWindowLong(GWL_STYLE);
BOOL bEnabled = !(lStyle & WS_DISABLED);//�Ƿ�ֹ
BOOL bDefault = (lStyle & BS_DEFPUSHBUTTON);
CRect rect;//�ؼ����ھ���
GetClientRect(&rect);
CDC memdc;
memdc.CreateCompatibleDC(dc);
//draw back
CBitmap bmp;
bmp.CreateCompatibleBitmap(dc, MAC_BTN_WIDTH, MAC_BTN_HEIGHT);
memdc.SelectBitmap(bmp);
int rgindex[3]; //ͼ����������
if (m_nState == STATE_PUSHED && m_bTracking)
{
rgindex[0] = 6; rgindex[1] = 7; rgindex[2] = 8;
}
else if (m_nState == STATE_PUSHED && !m_bTracking)
{
rgindex[0] = 0; rgindex[1] = 1; rgindex[2] = 2;
}
else if (bDefault)
{
rgindex[0] = 3; rgindex[1] = 4; rgindex[2] = 5;
}
else
{
rgindex[0] = 0; rgindex[1] = 1; rgindex[2] = 2;
}
m_ilButton.Draw(memdc, rgindex[0], 0, 0, ILD_NORMAL);
dc.TransparentBlt(rect.left, rect.top, MAC_BTN_WIDTH, rect.Height(),
memdc, 0, 0, MAC_BTN_WIDTH, MAC_BTN_HEIGHT, MAC_TRANPARENT_COLOR);
m_ilButton.Draw(memdc, rgindex[1], 0, 0, ILD_NORMAL);
dc.TransparentBlt(rect.left + MAC_BTN_WIDTH, rect.top, rect.Width() - MAC_BTN_WIDTH*2, rect.Height(),
memdc, 0, 0, MAC_BTN_WIDTH, MAC_BTN_HEIGHT, MAC_TRANPARENT_COLOR);
m_ilButton.Draw(memdc, rgindex[2], 0, 0, ILD_NORMAL);
dc.TransparentBlt(rect.right - MAC_BTN_WIDTH, rect.top, MAC_BTN_WIDTH, rect.Height(),
memdc, 0, 0, MAC_BTN_WIDTH, MAC_BTN_HEIGHT, MAC_TRANPARENT_COLOR);
//draw text
CComBSTR bstrText;
GetWindowText(&bstrText);
HFONT hOldFont = dc.SelectFont(GetCtrlFont(m_hWnd));
USES_CONVERSION;
dc.SetBkMode(TRANSPARENT);
if (!bEnabled)
dc.SetTextColor(MAC_DISABLE_COLOR);
dc.DrawText(OLE2T(bstrText), strlen(OLE2T(bstrText)), &rect, GetButtonTextFormat(lStyle));
dc.SelectFont(hOldFont);
}
/********************************************************************
* �� ����DrawCheck() *
* �� �ܣ���checkbox *
* �� ������ *
* ����ֵ���� *
* ˵ ��: ��λͼ������ *
********************************************************************/
void DrawCheck(void)
{
CPaintDC dc(m_hWnd);
LONG lStyle = GetWindowLong(GWL_STYLE);
BOOL bEnabled = !(lStyle & WS_DISABLED);//�Ƿ�ֹ
BOOL bChecked = GetCheck();
//�ؼ����ھ���
CRect rect;
GetClientRect(&rect);
dc.FillSolidRect(&rect, RGB(255, 255, 255));
CDC memdc;
memdc.CreateCompatibleDC(dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(dc, MAC_CHECK_WIDTH, MAC_CHECK_HEIGHT);
memdc.SelectBitmap(bmp);
int nIndex;
CWindow wndActive = GetActiveWindow();
if (wndActive.m_hWnd && wndActive.IsChild(m_hWnd))
{
if (bChecked)
nIndex = (m_nState==STATE_PUSHED) ? 2 : 0;
else
nIndex = (m_nState==STATE_PUSHED) ? 3 : 1;
}
else
{
nIndex = bChecked ? 4 : 1;
}
m_ilCheck.Draw(memdc, nIndex, 0, 0, ILD_NORMAL);
dc.BitBlt(rect.left, rect.top, MAC_CHECK_WIDTH, MAC_CHECK_HEIGHT,
memdc, 0, 0, SRCCOPY);
//�������
CComBSTR bstrText;
GetWindowText(&bstrText);
USES_CONVERSION;
dc.SetBkMode(TRANSPARENT);
if (!bEnabled)
dc.SetTextColor(MAC_DISABLE_COLOR);
HFONT hOldFont = dc.SelectFont(GetCtrlFont(m_hWnd));
rect.left += MAC_CHECK_WIDTH + 2;
rect.top += 2;
dc.DrawText(OLE2T(bstrText), strlen(OLE2T(bstrText)), &rect, GetButtonTextFormat(lStyle));
dc.SelectFont(hOldFont);
}
/********************************************************************
* �� ����DrawRadio() *
* �� �ܣ���radiobox *
* �� ������ *
* ����ֵ���� *
* ˵ ��: ��λͼ������ *
********************************************************************/
void DrawRadio()
{
CPaintDC dc(m_hWnd);
LONG lStyle = GetWindowLong(GWL_STYLE);
BOOL bEnabled = !(lStyle & WS_DISABLED);//�Ƿ�ֹ
BOOL bChecked = GetCheck();
//�ؼ����ھ���
CRect rect;
GetClientRect(&rect);
dc.FillSolidRect(&rect, RGB(255, 255, 255));
CDC memdc;
memdc.CreateCompatibleDC(dc);
CBitmap bmp;
bmp.CreateCompatibleBitmap(dc, MAC_RADIO_WIDTH, MAC_RADIO_HEIGHT);
memdc.SelectBitmap(bmp);
int nIndex;
CWindow wndActive = GetActiveWindow();
if (wndActive.m_hWnd && wndActive.IsChild(m_hWnd))
{
if (bChecked)
nIndex = (m_nState==STATE_PUSHED) ? 2 : 0;
else
nIndex = (m_nState==STATE_PUSHED) ? 3 : 1;
}
else
{
nIndex = bChecked ? 4 : 1;
}
m_ilRadio.Draw(memdc, nIndex, 0, 0, ILD_NORMAL);
dc.BitBlt(rect.left, rect.top, MAC_RADIO_WIDTH, MAC_RADIO_HEIGHT,
memdc, 0, 0, SRCCOPY);
//�������
CComBSTR bstrText;
GetWindowText(&bstrText);
USES_CONVERSION;
dc.SetBkMode(TRANSPARENT);
if (!bEnabled)
dc.SetTextColor(MAC_DISABLE_COLOR);
HFONT hOldFont = dc.SelectFont(GetCtrlFont(m_hWnd));
rect.left += MAC_RADIO_WIDTH + 2;
rect.top += 2;
dc.DrawText(OLE2T(bstrText), strlen(OLE2T(bstrText)), &rect, GetButtonTextFormat(lStyle));
dc.SelectFont(hOldFont);
}
/********************************************************************
* �� ����GetButtonTextFormat() *
* �� �ܣ��õ�Button���ֵĶ��뷽ʽ(��DrawText()���ʱ�ĸ�ʽ�� *
* �� ����lStyle �ؼ���� *
* ����ֵ����DrawText()���ʱ�ĸ�ʽ *
* ˵ ��: button�ϵ��ֱ�����һ�� *
********************************************************************/
UINT GetButtonTextFormat(const LONG lStyle)
{
UINT uFormat = DT_SINGLELINE;//button�ϵ��ֱ�����һ��
//x����
if ( (lStyle & BS_CENTER)==BS_CENTER )//x������
uFormat |= DT_CENTER;
else if ( (lStyle & BS_RIGHT)==BS_RIGHT )//x������
uFormat |= DT_RIGHT;
else if ( (lStyle & BS_LEFT) == BS_LEFT )//x������
uFormat |= DT_LEFT;
else//ȱʡ��x��
uFormat |= DT_CENTER;
//y����
if ( (lStyle & BS_VCENTER ) == BS_VCENTER )//y����
uFormat |= DT_VCENTER;
else if ( (lStyle & BS_TOP)==BS_TOP )//y������
uFormat |= DT_TOP;
else if ( (lStyle & BS_BOTTOM)==BS_BOTTOM )//y������
uFormat |= DT_BOTTOM;
else//ȱʡ��y��
uFormat |= DT_VCENTER;
return uFormat;
}
/********************************************************************
* �� ����DrawGroup() *
* �� �ܣ���groupbox *
* �� ������ *
* ����ֵ���� *
* ˵ ��: �ô����ɫ��Ϊ���ֵĵ�ɫ�������������ڸ����ڵ�ɫ�ĸı�� *
* ������ɫ�IJ�һ�� *
********************************************************************/
void DrawGroup()
{
//�豸
CPaintDC dc(m_hWnd);
CRect rect;//�ؼ�����
GetClientRect(&rect);
CPen pen;
pen.CreatePen(PS_SOLID,1,0xBFD0D0);//�߿��
HPEN hOldPen = dc.SelectPen(pen.m_hPen);
char sCaption[256];//�ؼ�����
GetWindowText(sCaption,256);
if ( strlen(sCaption) == 0 )//û�����֣�ֻ�����߿�
{
dc.MoveTo(rect.left,rect.top);
dc.LineTo(rect.right,rect.top);
dc.LineTo(rect.right,rect.bottom);
dc.LineTo(rect.left,rect.bottom);
dc.LineTo(rect.left,rect.top);
dc.SelectPen(hOldPen);
return;
}
//����
HFONT hOldFont = dc.SelectFont(GetCtrlFont(m_hWnd));
CSize Extent;
if ( ! dc.GetTextExtent(sCaption,strlen(sCaption),&Extent))
return;//�õ�����ռ�ռ����
CPoint ptText;//�������Ͻ�λ��
ptText.y = rect.top-Extent.cy/2;//y�����Dz����
LONG lStyle = GetWindowLong(GWL_STYLE);
//���£�GROUPBOX_TEXT_SPACE��ʾ������ߣ��ұߣ���ؼ����ң��ľ���
if ( (lStyle & BS_CENTER) == BS_CENTER )//x�������־���
{
ptText.x = rect.Width() / 2 - Extent.cx / 2;//�������Ͻ�x����
if ( ptText.x > rect.left )//����û�г���rect��߽�
{
dc.MoveTo(ptText.x-1, rect.top);
dc.LineTo(rect.left,rect.top);
dc.LineTo(rect.left,rect.bottom);
dc.LineTo(rect.right,rect.bottom);
dc.LineTo(rect.right,rect.top);
//�����Ǿ��У���Ȼû������߽磬��һ��Ҳû�г����ұ߽�
dc.LineTo(ptText.x+Extent.cx,rect.top);
}
else//���ֳ�������߽磬���ұ߽�����ֵ��¿�ʼ��
{
int nYTop = ptText.y+Extent.cy;
dc.MoveTo(rect.left,nYTop+1);
dc.LineTo(rect.left,rect.bottom);
dc.LineTo(rect.right,rect.bottom);
dc.LineTo(rect.right,nYTop);
}
}
else if ( (lStyle & BS_RIGHT)==BS_RIGHT )//x���������Ҷ���
{
ptText.x = rect.right - GROUPBOX_TEXT_SPACE - Extent.cx;//�������Ͻ�x����
//�Ҷ��룬��֤�ұߵ�����
dc.MoveTo(rect.right-GROUPBOX_TEXT_SPACE,rect.top);
dc.LineTo(rect.right,rect.top);
dc.LineTo(rect.right,rect.bottom);
dc.LineTo(rect.left,rect.bottom);
if ( ptText.x > rect.left )//�������û�����ؼ���߽�
{
dc.LineTo(rect.left,rect.top);
dc.LineTo(ptText.x,rect.top);
}
else//������߳����˿ؼ���߽�
dc.LineTo(rect.left,ptText.y+Extent.cy);
}
else//x������������루ȱʡ��
{
ptText.x = rect.left + GROUPBOX_TEXT_SPACE;//�������Ͻ�x����
//��������룬��֤�������������
dc.MoveTo(rect.left+GROUPBOX_TEXT_SPACE-1,rect.top);
dc.LineTo(rect.left,rect.top);
dc.LineTo(rect.left,rect.bottom);
dc.LineTo(rect.right,rect.bottom);
if ( ptText.x+Extent.cx < rect.right)//����û�����ؼ��ұ߽�
{
dc.LineTo(rect.right,rect.top);
dc.LineTo(ptText.x + Extent.cx,rect.top);
}
else//���ֳ����ؼ��ұ߽�
dc.LineTo(rect.right,ptText.y+Extent.cy);
}
CRect rcText;//�������ھ���
rcText.left = ptText.x;
rcText.top = ptText.y;
rcText.right = rcText.left+Extent.cx;
rcText.bottom = rcText.top+Extent.cy;
dc.DrawText(sCaption,strlen(sCaption),rcText,DT_LEFT|DT_TOP|DT_SINGLELINE);
dc.SelectFont(hOldFont);
dc.SelectPen(hOldPen);
}
static HFONT GetCtrlFont(HWND hwnd)
{
HFONT hFont;
//���sendmessage�õ�����NULL,��ʹ�õ���ϵͳ����
if ( (hFont = (HFONT)::SendMessage(hwnd,WM_GETFONT,0,0))==NULL)
hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
return hFont;
}
private:
static CImageList m_ilButton;
static CImageList m_ilCheck;
static CImageList m_ilRadio;
int m_nState;
bool m_bTracking;
};
CImageList CMacButton::m_ilButton;
CImageList CMacButton::m_ilCheck;
CImageList CMacButton::m_ilRadio;