📄 buttonst.cpp
字号:
//
// Class: CButtonST
//
// Compiler: Visual C++
// Tested on: Visual C++ 5.0
// Visual C++ 6.0
//
// Version: See GetVersionC() or GetVersionI()
//
// Created: xx/xxxx/1998
// Updated: 12/May/2001
//
// Author: Davide Calabro' davide_calabro@yahoo.com
//
// --------------------------------------------------------------------------
// Description : Port of CButtonST to WTL (http://www.codeproject.com/buttonctrl/cbuttonst.asp)
// Author : Serge Weinstock
//
// You are free to use, distribute or modify this code
// as long as this header is not removed or modified.
// --------------------------------------------------------------------------
#include "stdafx.h"
#include "ButtonST.h"
CButtonST::CButtonST()
{
m_bMouseOnButton = false;
FreeResources(false);
// Default type is "flat" button
m_bIsFlat = true;
// By default draw border in "flat" button
m_bDrawBorder = true;
// By default icon is aligned horizontally
m_nAlign = ST_ALIGN_HORIZ;
// By default, for "flat" button, don't draw the focus rect
m_bDrawFlatFocus = false;
// By default the button is not the default button
m_bIsDefault = false;
// By default the button is not a checkbox
m_bIsCheckBox = false;
m_nCheck = false;
// Set default colors
SetDefaultColors(false);
// No tooltip created
m_ToolTip.m_hWnd = 0;
// Do not draw as a transparent button
m_bDrawTransparent = false;
m_pbmpOldBk = 0;
// No URL defined
::ZeroMemory(&m_szURL, sizeof(m_szURL));
// No cursor defined
m_hCursor = 0;
// No autorepeat
m_bAutoRepeat = false;
m_dwPeriodAutoRepeat = 100;
m_bIsPressed = false;
m_bIsFocused = false;
m_bIsDisabled = false;
}
CButtonST::~CButtonST()
{
// Restore old bitmap (if any)
if (m_dcBk != 0 && m_pbmpOldBk != 0)
{
m_dcBk.SelectBitmap(m_pbmpOldBk);
}
FreeResources();
// Destroy the cursor (if any)
if (m_hCursor != 0) ::DestroyCursor(m_hCursor);
}
DWORD CButtonST::SetDefaultColors(bool bRepaint)
{
m_crColors[BTNST_COLOR_BK_IN] = ::GetSysColor(COLOR_BTNFACE);
m_crColors[BTNST_COLOR_FG_IN] = ::GetSysColor(COLOR_BTNTEXT);
m_crColors[BTNST_COLOR_BK_OUT] = ::GetSysColor(COLOR_BTNFACE);
m_crColors[BTNST_COLOR_FG_OUT] = ::GetSysColor(COLOR_BTNTEXT);
if (bRepaint) { Invalidate(); }
return BTNST_OK;
}
void CButtonST::FreeResources(bool bCheckFor0)
{
if (bCheckFor0)
{
// Destroy icons
// Note: the following two lines MUST be here! even if
// BoundChecker says they are unnecessary!
if (m_csIcons[0].hIcon != 0) { ::DeleteObject(m_csIcons[0].hIcon); }
if (m_csIcons[1].hIcon != 0) { ::DeleteObject(m_csIcons[1].hIcon); }
// Destroy bitmaps
if (m_csBitmaps[0].hBitmap != 0) { m_csBitmaps[0].hBitmap.DeleteObject(); }
if (m_csBitmaps[1].hBitmap != 0) { m_csBitmaps[1].hBitmap.DeleteObject(); }
// Destroy mask bitmaps
if (m_csBitmaps[0].hMask != 0) { m_csBitmaps[0].hMask.DeleteObject(); }
if (m_csBitmaps[1].hMask != 0) { m_csBitmaps[1].hMask.DeleteObject(); }
}
::ZeroMemory(&m_csIcons, sizeof(m_csIcons));
::ZeroMemory(&m_csBitmaps, sizeof(m_csBitmaps));
} // End of FreeResources
DWORD CButtonST::SetIcon(ATL::_U_STRINGorID nIconInId, ATL::_U_STRINGorID nIconOutId, HMODULE rsrcModule)
{
HICON hIconIn;
HICON hIconOut;
HINSTANCE hInstResource;
// Find correct resource handle
hInstResource = (rsrcModule != 0 ? rsrcModule : _Module.GetResourceInstance());
// Set icon when the mouse is IN the button
hIconIn = (HICON)::LoadImage(hInstResource, nIconInId.m_lpstr, IMAGE_ICON, 0, 0, 0);
// Set icon when the mouse is OUT the button
hIconOut = (HICON)::LoadImage(hInstResource, nIconOutId.m_lpstr, IMAGE_ICON, 0, 0, 0);
return SetIcon(hIconIn, hIconOut);
}
DWORD CButtonST::SetIcon(HIMAGELIST imagelist, int idxIn, int idxOut)
{
HICON hIconIn;
HICON hIconOut;
CImageList il(imagelist);
// Set icon when the mouse is IN the button
hIconIn = il.GetIcon(idxIn, ILD_TRANSPARENT);
// Set icon when the mouse is OUT the button
hIconOut = il.GetIcon(idxOut, ILD_TRANSPARENT);
return SetIcon(hIconIn, hIconOut);
}
DWORD CButtonST::SetIcon(HICON hIconIn, HICON hIconOut)
{
bool bRetValue;
ICONINFO ii;
// Free any loaded resource
FreeResources();
if (hIconIn != 0)
{
m_csIcons[0].hIcon = hIconIn;
// Get icon dimension
ZeroMemory(&ii, sizeof(ICONINFO));
bRetValue = (::GetIconInfo(hIconIn, &ii) != 0);
if (!bRetValue)
{
FreeResources();
return BTNST_INVALIDRESOURCE;
}
m_csIcons[0].dwWidth = (DWORD)(ii.xHotspot * 2);
m_csIcons[0].dwHeight = (DWORD)(ii.yHotspot * 2);
::DeleteObject(ii.hbmMask);
::DeleteObject(ii.hbmColor);
if (hIconOut != 0)
{
m_csIcons[1].hIcon = hIconOut;
// Get icon dimension
ZeroMemory(&ii, sizeof(ICONINFO));
bRetValue = (::GetIconInfo(hIconOut, &ii) != 0);
if (!bRetValue)
{
FreeResources();
return BTNST_INVALIDRESOURCE;
}
m_csIcons[1].dwWidth = (DWORD)(ii.xHotspot * 2);
m_csIcons[1].dwHeight = (DWORD)(ii.yHotspot * 2);
::DeleteObject(ii.hbmMask);
::DeleteObject(ii.hbmColor);
}
}
if (IsWindow()) { RedrawWindow(); }
return BTNST_OK;
}
bool CButtonST::SetBtnCursor(ATL::_U_STRINGorID nCursorId, HMODULE rsrcModule)
{
HINSTANCE hInstResource;
// Destroy any previous cursor
if (m_hCursor != 0) { ::DestroyCursor(m_hCursor); }
m_hCursor = 0;
// If we want a cursor
if (nCursorId.m_lpstr != MAKEINTRESOURCE(0))
{
hInstResource = (rsrcModule != 0 ? rsrcModule : _Module.GetResourceInstance());
// Load icon resource
m_hCursor = (HCURSOR)::LoadImage(hInstResource, nCursorId.m_lpstr, IMAGE_CURSOR, 0, 0, 0);
// If something wrong then return FALSE
if (m_hCursor == 0) { return false; }
}
return true;
}
void CButtonST::SetFlat(bool bState)
{
m_bIsFlat = bState;
if (IsWindow()) { Invalidate(); }
}
bool CButtonST::GetFlat()
{
return m_bIsFlat;
}
void CButtonST::SetFlatFocus(bool bDrawFlatFocus, bool bRepaint)
{
m_bDrawFlatFocus = bDrawFlatFocus;
// Repaint the button
if (bRepaint && IsWindow()) { Invalidate(); }
}
bool CButtonST::GetDefault()
{
return m_bIsDefault;
}
void CButtonST::SetAlign(Alignment nAlign)
{
switch (nAlign)
{
case ST_ALIGN_HORIZ:
case ST_ALIGN_HORIZ_RIGHT:
case ST_ALIGN_VERT:
m_nAlign = nAlign;
break;
}
if (IsWindow()) { Invalidate(); }
}
CButtonST::Alignment CButtonST::GetAlign()
{
return m_nAlign;
}
void CButtonST::DrawBorder(bool bEnable)
{
m_bDrawBorder = bEnable;
}
LRESULT CButtonST::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(m_ToolTip.IsWindow())
{
m_ToolTip.RelayEvent((LPMSG)m_pCurrentMsg);
}
bHandled = false;
return 1;
}
LRESULT CButtonST::OnMouseMove(UINT nFlags, CPoint point)
{
CWindow pWnd; // Active window
CWindow pParent; // Window that owns the button
DefWindowProc();
// If the mouse enter the button with the left button pressed then do nothing
if ((nFlags & MK_LBUTTON) != 0 && !m_bMouseOnButton) { return 0; }
// If our button is not flat then do nothing
if (!m_bIsFlat) { return 0; };
pWnd = ::GetActiveWindow();
pParent = GetParent();
if ((::GetCapture() != m_hWnd) &&
(
#ifndef ST_LIKEIE
pWnd.IsWindow() &&
#endif
pParent.IsWindow()))
{
m_bMouseOnButton = true;
SetCapture();
Invalidate();
}
else
{
CPoint p2 = point;
ClientToScreen(&p2);
CWindow wndUnderMouse = ::WindowFromPoint(p2);
if (wndUnderMouse && (wndUnderMouse.m_hWnd != m_hWnd))
{
// Redraw only if mouse goes out
if (m_bMouseOnButton)
{
m_bMouseOnButton = false;
Invalidate();
}
// If user is NOT pressing left button then release capture!
if (!(nFlags & MK_LBUTTON))
{
ReleaseCapture();
}
}
}
return 0;
}
LRESULT CButtonST::OnKillFocus(HWND hWnd)
{
DefWindowProc();
CancelHover();
return 0;
}
LRESULT CButtonST::OnLButtonDown(UINT nFlags, CPoint pt)
{
DefWindowProc();
if (m_bAutoRepeat)
{
MSG csMsg;
int nButtonID;
HWND hWndParent;
bool initialState = true;
nButtonID = GetDlgCtrlID();
hWndParent = GetParent();
SetCapture();
while(::PeekMessage(&csMsg, m_hWnd, WM_LBUTTONUP, WM_LBUTTONUP, PM_REMOVE) == FALSE)
{
::SendMessage(hWndParent, WM_COMMAND, MAKEWPARAM((WORD)nButtonID, BN_CLICKED), (LPARAM)m_hWnd);
::Sleep(m_dwPeriodAutoRepeat);
initialState = !initialState;
}
if(!initialState)
{
::SendMessage(hWndParent, WM_COMMAND, MAKEWPARAM((WORD)nButtonID, BN_CLICKED), (LPARAM)m_hWnd);
}
ReleaseCapture();
SendMessage(WM_LBUTTONUP);
CPoint ptCursor;
::GetCursorPos(&ptCursor);
ScreenToClient(&ptCursor);
SendMessage(WM_MOUSEMOVE, 0, MAKELPARAM(ptCursor.x, ptCursor.y));
}
return 0;
}
void CButtonST::CancelHover()
{
// If our button is not flat then do nothing
if (!m_bIsFlat) { return; }
if (m_bMouseOnButton)
{
m_bMouseOnButton = false;
Invalidate();
}
}
void CButtonST::OnActivate(UINT nState, BOOL bMinimized, HWND pWndOther)
{
DefWindowProc();
if (nState == WA_INACTIVE) { CancelHover(); }
}
void CButtonST::OnEnable(BOOL bEnable)
{
DefWindowProc();
if (!bEnable) CancelHover();
}
void CButtonST::OnCancelMode()
{
DefWindowProc();
CancelHover();
}
void CButtonST::OnCaptureChanged(HWND pWnd)
{
if (m_bMouseOnButton)
{
static int i = 0;
ReleaseCapture();
Invalidate();
}
// Call base message handler
SetMsgHandled(false);
}
BOOL CButtonST::OnSetCursor(HWND pWnd, UINT nHitTest, UINT message)
{
// If a cursor was specified then use it!
if (m_hCursor != 0)
{
::SetCursor(m_hCursor);
return true;
}
SetMsgHandled(false);
return 0;
}
void CButtonST::PaintBk(CDCHandle pDC)
{
CWindow parent = GetParent();
CClientDC clDC(parent);
CRect rect;
CRect rect1;
GetClientRect(rect);
GetWindowRect(rect1);
parent.ScreenToClient(rect1);
if (m_dcBk == 0)
{
m_dcBk.CreateCompatibleDC(clDC);
m_bmpBk.CreateCompatibleBitmap(clDC, rect.Width(), rect.Height());
m_pbmpOldBk = m_dcBk.SelectBitmap(m_bmpBk);
m_dcBk.BitBlt(0, 0, rect.Width(), rect.Height(), clDC, rect1.left, rect1.top, SRCCOPY);
}
pDC.BitBlt(0, 0, rect.Width(), rect.Height(), m_dcBk, 0, 0, SRCCOPY);
}
//
// Parameters:
// [IN] bHasTitle
// TRUE if the button has a text
// [IN] rpItem
// A pointer to a RECT structure indicating the allowed paint area
// [IN/OUT]rpTitle
// A pointer to a CRect object indicating the paint area reserved for the
// text. This structure will be modified if necessary.
// [IN] bIsPressed
// TRUE if the button is currently pressed
// [IN] dwWidth
// Width of the image (icon or bitmap)
// [IN] dwHeight
// Height of the image (icon or bitmap)
// [OUT] rpImage
// A pointer to a CRect object that will receive the area available to the image
//
void CButtonST::PrepareImageRect(bool bHasTitle, RECT &rpItem, CRect &rpTitle, bool bIsPressed, DWORD dwWidth, DWORD dwHeight, CRect &rpImage)
{
CRect rBtn;
rpImage = rpItem;
switch (m_nAlign)
{
case ST_ALIGN_HORIZ:
if (!bHasTitle)
{
// Center image horizontally
rpImage.left += ((rpImage.Width() - dwWidth)/2);
}
else
{
// Image must be placed just inside the focus rect
rpImage.left += 3;
rpTitle.left += dwWidth + 3;
}
// Center image vertically
rpImage.top += ((rpImage.Height() - dwHeight)/2);
break;
case ST_ALIGN_HORIZ_RIGHT:
GetClientRect(&rBtn);
if (bHasTitle == FALSE /*spTitle->IsEmpty()*/)
{
// Center image horizontally
rpImage.left += ((rpImage.Width() - dwWidth)/2);
}
else
{
// Image must be placed just inside the focus rect
rpTitle.right = rpTitle.Width() - dwWidth - 3;
rpTitle.left = 3;
rpImage.left = rBtn.right - dwWidth - 3;
// Center image vertically
rpImage.top += ((rpImage.Height() - dwHeight)/2);
}
break;
case ST_ALIGN_VERT:
// Center image horizontally
rpImage.left += ((rpImage.Width() - dwWidth)/2);
if (bHasTitle == FALSE /*spTitle->IsEmpty()*/)
{
// Center image vertically
rpImage.top += ((rpImage.Height() - dwHeight)/2);
}
else
{
rpImage.top = 3;
rpTitle.top += dwHeight;
}
break;
}
// If button is pressed then press image also
if (bIsPressed && !m_bIsCheckBox)
{
rpImage.OffsetRect(1, 1);
}
}
void CButtonST::DrawTheBitmap(CDCHandle pDC, bool bHasTitle, RECT &rItem, CRect &rCaption, bool bIsPressed, bool bIsDisabled)
{
CDC hdcBmpMem = 0;
CBitmapHandle hbmOldBmp = 0;
CDC hdcMem = 0;
CBitmapHandle hbmT = 0;
BYTE byIndex = 0;
// Select the bitmap to use
if (m_bIsCheckBox)
{
if (bIsPressed)
{
byIndex = 0;
}
else
{
byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
}
}
else
{
if (m_bMouseOnButton || bIsPressed)
{
byIndex = 0;
}
else
{
byIndex = (m_csBitmaps[1].hBitmap == NULL ? 0 : 1);
}
}
CRect rImage;
PrepareImageRect(bHasTitle, rItem, rCaption, bIsPressed, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, rImage);
hdcBmpMem.CreateCompatibleDC(pDC);
hbmOldBmp = hdcBmpMem.SelectBitmap(m_csBitmaps[byIndex].hBitmap);
hdcMem.CreateCompatibleDC(0);
hbmT = hdcMem.SelectBitmap(m_csBitmaps[byIndex].hMask);
pDC.BitBlt(rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcMem, 0, 0, SRCAND);
pDC.BitBlt(rImage.left, rImage.top, m_csBitmaps[byIndex].dwWidth, m_csBitmaps[byIndex].dwHeight, hdcBmpMem, 0, 0, SRCPAINT);
hdcMem.SelectBitmap(hbmT);
hdcBmpMem.SelectBitmap(hbmOldBmp);
}
void CButtonST::DrawTheIcon(CDCHandle pDC, bool bHasTitle, RECT &rpItem, CRect &rpTitle, bool bIsPressed, bool bIsDisabled)
{
BYTE byIndex = 0;
// Select the icon to use
if (m_bIsCheckBox)
{
if (bIsPressed)
{
byIndex = 0;
}
else
{
byIndex = (m_csIcons[1].hIcon == NULL ? 0 : 1);
}
}
else
{
if (m_bMouseOnButton || bIsPressed)
{
byIndex = 0;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -