#include "priv.h" #include "button.h" const static TCHAR c_szCoolButtonProp[] = TEXT("CCoolButton_This"); ///////////////////////////////////////////////////////////////////////////// // CCoolButton BOOL CCoolButton::Create(HWND hwndParent, INT_PTR nID, DWORD dwExStyle, DWORD dwStyle) { m_hwndButton = ::CreateWindowEx( dwExStyle, WC_BUTTON, NULL, dwStyle | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hwndParent, (HMENU)nID, HINST_THISDLL, NULL); if (m_hwndButton && SetProp(m_hwndButton, c_szCoolButtonProp, this)) { SetWindowLongPtr(m_hwndButton, GWLP_USERDATA, (LPARAM)(WNDPROC)(GetWindowLongPtr(m_hwndButton, GWLP_WNDPROC))); SetWindowLongPtr(m_hwndButton, GWLP_WNDPROC, (LPARAM)s_ButtonWndSubclassProc); } DWORD dwBtnStyle = GetWindowLong(m_hwndButton, GWL_STYLE); dwBtnStyle |= BS_PUSHBUTTON | BS_OWNERDRAW; SetWindowLong(m_hwndButton, GWL_STYLE, dwBtnStyle); ShowWindow(m_hwndButton, SW_SHOW); return m_hwndButton == NULL ? FALSE : TRUE; } CCoolButton::~CCoolButton() { if (m_hwndButton) DestroyWindow(m_hwndButton); if (m_hImageList) ImageList_Destroy(m_hImageList); if (m_bstrText) SysFreeString(m_bstrText); if (m_fIsCapture) ReleaseCapture(); if (m_hFont) DeleteObject(m_hFont); } LRESULT CALLBACK CCoolButton::s_ButtonWndSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { CCoolButton* pThis = (CCoolButton*)GetProp(hwnd, c_szCoolButtonProp); if (!pThis) return DefWindowProcWrap(hwnd, uMsg, wParam, lParam); WNDPROC pfnOldWndProc = (WNDPROC)(GetWindowLongPtr(hwnd, GWLP_USERDATA)); switch (uMsg) { case WM_ERASEBKGND: return (LRESULT)1; case WM_MEASUREITEM: { LPMEASUREITEMSTRUCT lpmis = (LPMEASUREITEMSTRUCT)lParam; IMAGEINFO imgInfo ; ImageList_GetImageInfo(pThis->m_hImageList, 0, &imgInfo); if (!pThis->m_bstrText) { lpmis->itemWidth = RECTWIDTH(imgInfo.rcImage) ; lpmis->itemHeight= RECTHEIGHT(imgInfo.rcImage) ; } else { lpmis->itemWidth = RECTWIDTH(imgInfo.rcImage) + 200; lpmis->itemHeight= RECTHEIGHT(imgInfo.rcImage) ; } } return TRUE; case WM_DRAWITEM: { LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam; HDC hdc = lpdis->hDC; int nIndex = ((lpdis->itemState & ODS_DISABLED) ? 2 : ((lpdis->itemState & ODS_SELECTED) ? 1 : ((lpdis->itemState & ODS_FOCUS) ? 1 : (pThis->m_fHover) ? 1 : 0))); RECT rcClient; GetClientRect(hwnd,&rcClient); HDC hdcMem = CreateCompatibleDC(hdc); HBITMAP hbmp = CreateCompatibleBitmap(hdc, RECTWIDTH(rcClient),RECTHEIGHT(rcClient)); HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcMem, hbmp); // fill rgn HBRUSH hBrush = CreateSolidBrush(RGB(244,244,240)); if (hBrush) { FillRect(hdcMem, &rcClient, hBrush); DeleteObject(hBrush); } BOOL fEnabled = (lpdis->itemState & ODS_DISABLED) ? FALSE : TRUE ; // Draw Button to the screen IMAGEINFO imgInfo ; ImageList_GetImageInfo(pThis->m_hImageList, nIndex, &imgInfo); ImageList_Draw(pThis->m_hImageList, nIndex, hdcMem, RECTWIDTH(rcClient) - RECTWIDTH(imgInfo.rcImage), 0, ILD_NORMAL); RECT rcFormat = { rcClient.left+2, rcClient.top , RECTWIDTH(rcClient)- RECTWIDTH(imgInfo.rcImage)-8, RECTHEIGHT(rcClient) }; if (pThis->m_bstrText) { // Get the caption to draw LPWSTR pszText = L""; pszText = pThis->m_bstrText; int nBkMode = SetBkMode(hdcMem, TRANSPARENT); HFONT hFontOld = (HFONT) SelectObject(hdcMem, pThis->m_hFont); int nOldTextColor = SetTextColor(hdcMem, RGB(0,255,0)); ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags()); /* int nOldTextColor = 0; // draw button caption depending upon button state if (fEnabled) { nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT)); ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags()); } else { nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_3DHILIGHT)); ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags()); SetTextColor(hdcMem, nOldTextColor); nOldTextColor = SetTextColor(hdcMem, GetSysColor(COLOR_3DSHADOW)); ::DrawText(hdcMem, pszText, -1, &rcFormat, pThis->GetDrawTextFlags()); SetTextColor(hdcMem, nOldTextColor); } */ SelectObject(hdcMem, hFontOld); SetBkMode(hdcMem, nBkMode); } BitBlt(hdc, 0, 0, RECTWIDTH(rcClient), RECTHEIGHT(rcClient),hdcMem, 0, 0,SRCCOPY); SelectObject(hdcMem, hOldBmp); DeleteObject(hbmp); DeleteDC(hdcMem); } return TRUE; case WM_LBUTTONDBLCLK : case WM_LBUTTONDOWN: { POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; pThis->CheckHover(pt); if (pThis->m_fHover && (UINT)wParam & MK_LBUTTON && !pThis->m_fMouseDown) { pThis->m_fMouseDown = TRUE; CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam); if (BT_MENU == pThis->GetButtonType()) { SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd),BN_CLICKED), (LPARAM)(hwnd)); } return 0; } } break; case WM_LBUTTONUP: { CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam); pThis->m_fMouseDown = FALSE; if (pThis->m_fIsCapture) { ReleaseCapture(); pThis->m_fIsCapture = FALSE; } POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; pThis->CheckHover(pt); } return 0; case WM_MOUSEMOVE: { CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam); POINT pt = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)}; pThis->CheckHover(pt); if (pThis->m_fHover && (UINT)wParam & MK_LBUTTON) { pThis->m_fMouseDown = TRUE; } RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } break; case WM_KEYDOWN: { SendMessage(GetParent(hwnd), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd),BN_CLICKED), (LPARAM)(pThis->m_hwndButton)); RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } break; case WM_KILLFOCUS: { if (pThis->m_fIsCapture) { ReleaseCapture(); pThis->m_fIsCapture = FALSE; } pThis->m_fHover = FALSE ; pThis->m_fHasFocus = FALSE ; pThis->m_fMouseDown = FALSE ; RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } break; case WM_SETFOCUS: { if (!pThis->m_fIsCapture) { SetCapture(hwnd); pThis->m_fIsCapture = TRUE; } pThis->m_fHasFocus = TRUE ; RedrawWindow(hwnd,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } break; case WM_DESTROY: { // // Unsubclass myself. // RemoveProp(hwnd, c_szCoolButtonProp); if (pfnOldWndProc) { SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) pfnOldWndProc); } } break; } return CallWindowProc(pfnOldWndProc, hwnd, uMsg, wParam, lParam); } BOOL CCoolButton::LoadBitmaps(UINT nImageList, UINT iImageWidth) { if (m_hImageList) ImageList_Destroy(m_hImageList); m_hImageList = ImageList_LoadImage(HINST_THISDLL, MAKEINTRESOURCE(nImageList), iImageWidth, 0, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION); SizeToContent(); return m_hImageList != NULL; } // SizeToContent will resize the button to the size of the bitmap HRESULT CCoolButton::SizeToContent() { SIZE sizeContent ; GetButtonSize(sizeContent); if (SetWindowPos(m_hwndButton,HWND_TOP, 0, 0, sizeContent.cx,sizeContent.cy, SWP_NOMOVE|SWP_NOZORDER|SWP_NOREDRAW|SWP_NOACTIVATE)) { return S_OK; } return S_FALSE; } VOID CCoolButton::CheckHover(POINT pt) { if (HitTest(pt)) { if (!m_fIsCapture || GetCapture() != m_hwndButton) { SetCapture(m_hwndButton); m_fIsCapture = TRUE; } if (!m_fHover) { m_fHover = TRUE; RedrawWindow(m_hwndButton,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } } else { if (m_fIsCapture) { m_fIsCapture = FALSE; ReleaseCapture(); } m_fHover = FALSE; RedrawWindow(m_hwndButton,NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); } } BOOL CCoolButton::HitTest(POINT point) { RECT rcClient; GetClientRect(m_hwndButton, &rcClient); return ::PtInRect(&rcClient, point); }