You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

882 lines
18 KiB
C++

// XTButton.cpp : implementation of the CXTPButton class.
//
// This file is a part of the XTREME CONTROLS MFC class library.
// (c)1998-2012 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Common/XTPDrawHelpers.h"
#include "Common/XTPImageManager.h"
#include "Common/XTPMarkupRender.h"
#include "Common/XTPToolTipContext.h"
#include "Common/XTPMaskEditT.h"
#include "Common/XTPWinThemeWrapper.h"
#include "Common/XTPColorManager.h"
#include "../Util/XTPControlTheme.h"
#include "../Defines.h"
#include "XTPButton.h"
#include "XTPButtonTheme.h"
#include "../Edit/XTPEdit.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef WM_UPDATEUISTATE
#define WM_UPDATEUISTATE 0x0128
#endif
/////////////////////////////////////////////////////////////////////////////
// CXTPButton
/////////////////////////////////////////////////////////////////////////////
#ifndef _XTP_ACTIVEX_BUTTON
IMPLEMENT_DYNAMIC(CXTPButton, CXTPButtonBase)
#endif
CXTPButton::CXTPButton()
: m_pTheme(NULL)
{
m_bHot = FALSE;
m_bPushed = FALSE;
m_bChecked = FALSE;
m_bFlatStyle = FALSE;
m_bUseVisualStyle = TRUE;
m_bEnableMarkup = FALSE;
m_pMarkupContext = NULL;
m_pUIElement = NULL;
m_nPushButtonStyle = 0;
m_nBorderGap = 4;
m_nImageGap = 3;
m_pIcon = 0;
m_nImageAlignment = BS_VCENTER | BS_CENTER;
m_nTextImageRelation = xtpButtonImageBeforeText;
m_nBorderStyle = 0;
m_bShowFocus = TRUE;
m_hWndBuddy = 0;
m_pToolTipContext = new CXTPToolTipContext();
VERIFY(SetTheme(xtpControlThemeDefault));
}
CXTPButton::~CXTPButton()
{
CMDTARGET_RELEASE(m_pTheme);
XTPMarkupReleaseElement(m_pUIElement);
XTPMarkupReleaseContext(m_pMarkupContext);
CMDTARGET_RELEASE(m_pIcon);
CMDTARGET_RELEASE(m_pToolTipContext);
}
BEGIN_MESSAGE_MAP(CXTPButton, CXTPButtonBase)
//{{AFX_MSG_MAP(CXTPButton)
ON_WM_ERASEBKGND()
ON_WM_MOUSEMOVE()
ON_WM_SETFOCUS()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
ON_WM_CHAR()
ON_WM_KEYDOWN()
ON_MESSAGE(WM_GETDLGCODE, OnGetDlgCode)
//}}AFX_MSG_MAP
#ifndef _XTP_ACTIVEX_BUTTON
ON_WM_PAINT()
#endif
ON_MESSAGE_VOID(WM_MOUSELEAVE, OnMouseLeave)
ON_MESSAGE(BM_SETSTYLE, OnDefaultAndInvalidate)
ON_MESSAGE(BM_SETCHECK, OnDefaultAndInvalidate)
ON_MESSAGE(WM_CAPTURECHANGED, OnCaptureChanged)
ON_MESSAGE_VOID(WM_ENABLE, OnInvalidate)
ON_MESSAGE(WM_UPDATEUISTATE, OnUpdateUIState)
ON_MESSAGE(BM_SETSTATE, OnSetState)
ON_MESSAGE(WM_SETTEXT, OnSetText)
ON_MESSAGE(WM_XTP_SETCONTROLTHEME, OnSetTheme)
END_MESSAGE_MAP()
void CXTPButton::OnMouseMove(UINT nFlags, CPoint point)
{
if (GetButtonStyle() == BS_GROUPBOX)
return;
CXTPButtonBase::OnMouseMove(nFlags, point);
CRect rc = GetButtonRect();
BOOL bHot = rc.PtInRect(point);
if (bHot != m_bHot)
{
m_bHot = bHot;
RedrawButton();
if (m_bHot)
{
TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, m_hWnd, HOVER_DEFAULT};
_TrackMouseEvent(&tme);
}
}
}
void CXTPButton::OnMouseLeave()
{
OnMouseMove(0, CPoint(-1, -1));
}
void CXTPButton::OnLButtonDown(UINT nFlags, CPoint point)
{
if (m_nPushButtonStyle == xtpButtonSplitDropDown)
{
CRect rcDropDown(GetButtonRect());
rcDropDown.left = rcDropDown.right - 16 - GetBorderGap();
if (rcDropDown.PtInRect(point))
{
DoDropDown();
return;
}
}
CXTPButtonBase::OnLButtonDown(nFlags, point);
}
void CXTPButton::OnLButtonUp(UINT nFlags, CPoint point)
{
CXTPButtonBase::OnLButtonUp(nFlags, point);
}
LRESULT CXTPButton::OnSetState(WPARAM wParam, LPARAM /*lParam*/)
{
BOOL bVisible = GetStyle() & WS_VISIBLE;
if (bVisible) ModifyStyle(WS_VISIBLE, 0);
Default();
if (bVisible) ModifyStyle(0, WS_VISIBLE);
if (m_bPushed == 2)
return 0;
m_bPushed = (wParam != 0);
RedrawButton();
if (m_bPushed && IsDropDownStyle() && IsPushButton() && (m_nPushButtonStyle != xtpButtonSplitDropDown))
{
DoDropDown();
}
return 0;
}
CRect CXTPButton::GetButtonRect()
{
CXTPClientRect rc(this);
if (m_hWndBuddy)
{
CXTPEdit* pEditBuddy = DYNAMIC_DOWNCAST(CXTPEdit, CWnd::FromHandlePermanent(m_hWndBuddy));
if (pEditBuddy) pEditBuddy->AdjustBuddyRect(this, rc, UDS_ALIGNRIGHT);
}
return rc;
}
void CXTPButton::DoDropDown()
{
m_bPushed = 2;
RedrawButton();
OnDropDown();
m_bPushed = 0;
RedrawButton();
}
void CXTPButton::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (IsDropDownStyle() && (nChar == VK_SPACE))
{
DoDropDown();
return;
}
if ((m_nPushButtonStyle == xtpButtonDropDown || m_nPushButtonStyle == xtpButtonDropDownRight) && (nChar == VK_RETURN))
{
DoDropDown();
return;
}
CXTPButtonBase::OnChar(nChar, nRepCnt, nFlags);
}
LRESULT CXTPButton::OnGetDlgCode(WPARAM wParam, LPARAM lParam)
{
LRESULT lCode = CXTPButtonBase::OnGetDlgCode();
if (IsDropDownStyle() && lParam && ((LPMSG)lParam)->message == WM_CHAR && wParam == VK_SPACE)
{
lCode |= DLGC_WANTCHARS;
}
if ((m_nPushButtonStyle == xtpButtonDropDown || m_nPushButtonStyle == xtpButtonDropDownRight)
&& lParam && (((LPMSG)lParam)->message == WM_KEYDOWN || ((LPMSG)lParam)->message == WM_CHAR) && wParam == VK_RETURN)
{
lCode |= DLGC_WANTALLKEYS;
}
return lCode;
}
void CXTPButton::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if (nChar == VK_SPACE && IsDropDownStyle())
return;
if (nChar == VK_RETURN && (m_nPushButtonStyle == xtpButtonDropDown || m_nPushButtonStyle == xtpButtonDropDownNoGlyph || m_nPushButtonStyle == xtpButtonDropDownRight))
{
return;
}
CXTPButtonBase::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CXTPButton::OnDropDown()
{
GetParent()->SendMessage(WM_COMMAND,
(WPARAM)MAKELONG(::GetDlgCtrlID(GetSafeHwnd()), CBN_DROPDOWN),
(LPARAM)GetSafeHwnd());
}
void CXTPButton::OnSetFocus(CWnd* pOldWnd)
{
CXTPButtonBase::OnSetFocus(pOldWnd);
RedrawButton(TRUE);
}
void CXTPButton::OnKillFocus(CWnd* pNewWnd)
{
CXTPButtonBase::OnKillFocus(pNewWnd);
RedrawButton(TRUE);
}
LRESULT CXTPButton::OnCaptureChanged(WPARAM wParam, LPARAM lParam)
{
return OnDefaultAndInvalidate(wParam, lParam);
}
LRESULT CXTPButton::OnDefaultAndInvalidate(WPARAM, LPARAM)
{
LRESULT lResult = Default();
RedrawButton(TRUE);
return lResult;
}
void CXTPButton::OnInvalidate()
{
RedrawButton(TRUE);
}
LRESULT CXTPButton::OnPrintClient(WPARAM wParam, LPARAM lParam)
{
if ((lParam & PRF_CLIENT) == 0)
return Default();
CDC* pDC = CDC::FromHandle((HDC)wParam);
if (pDC) OnDraw(pDC);
return 1;
}
void CXTPButton::OnPaint()
{
CPaintDC dcPaint(this);
OnDraw(&dcPaint);
}
void CXTPButton::OnDraw(CDC* pDC)
{
if ((GetButtonStyle() == BS_GROUPBOX))
{
CFont* pOldFont = pDC->SelectObject(CWnd::GetFont());
pDC->SetBkColor(GetSysColor(COLOR_3DFACE));
pDC->SetBkMode(TRANSPARENT);
DoDraw(pDC);
pDC->SelectObject(pOldFont);
}
else
{
CXTPClientRect rc(this);
CXTPBufferDC memDC(*pDC, rc);
HBRUSH hBrush = (HBRUSH)GetParent()->SendMessage(WM_CTLCOLORBTN, (WPARAM)memDC.GetSafeHdc(), (LPARAM)GetSafeHwnd());
if (hBrush)
{
::FillRect(memDC.GetSafeHdc(), rc, hBrush);
}
else
{
memDC.FillSolidRect(rc, GetSysColor(COLOR_3DFACE));
}
CFont* pOldFont = memDC.SelectObject(CWnd::GetFont());
memDC.SetBkMode(TRANSPARENT);
DoDraw(&memDC);
memDC.SelectObject(pOldFont);
}
}
void CXTPButtonTheme::DrawButton(CDC* pDC, CXTPButton* pButton)
{
if (pButton->IsPushButton())
{
DrawButtonBackground(pDC, pButton);
DrawPushButtonText(pDC, pButton);
DrawPushButtonIcon(pDC, pButton);
if (pButton->IsDropDownStyle() && pButton->GetPushButtonStyle() != xtpButtonDropDownNoGlyph)
{
DrawPushButtonDropDown(pDC, pButton);
}
if (::GetFocus() == pButton->m_hWnd && pButton->GetShowFocus())
{
DrawFocusRect(pDC, pButton);
}
return;
}
switch (pButton->GetButtonStyle())
{
case BS_RADIOBUTTON:
case BS_AUTORADIOBUTTON:
DrawRadioButtonMark(pDC, pButton);
DrawButtonText(pDC, pButton);
break;
case BS_3STATE:
case BS_AUTO3STATE:
case BS_CHECKBOX:
case BS_AUTOCHECKBOX:
DrawCheckBoxMark(pDC, pButton);
DrawButtonText(pDC, pButton);
break;
case BS_GROUPBOX:
if (pButton->GetBorderStyle() != 2)
{
DrawGroupBox(pDC, pButton);
DrawButtonText(pDC, pButton);
}
break;
default:
TRACE(_T("Warning: unkown style"));
}
}
void CXTPButton::DoDraw(CDC* pDC)
{
if (m_hWndBuddy)
{
CXTPEdit* pEditBuddy = DYNAMIC_DOWNCAST(CXTPEdit, CWnd::FromHandlePermanent(m_hWndBuddy));
if (pEditBuddy) pEditBuddy->DrawBuddyBorders(this, pDC, CXTPClientRect(this), UDS_ALIGNRIGHT);
}
m_pTheme->DrawButton(pDC, this);
}
LRESULT CXTPButton::OnUpdateUIState(WPARAM wParam, LPARAM lParam)
{
LRESULT lResult = ::DefWindowProc(m_hWnd, WM_UPDATEUISTATE, wParam, lParam);
RedrawButton();
return lResult;
}
LRESULT CXTPButton::OnSetText(WPARAM wParam, LPARAM lParam)
{
BOOL bVisible = GetStyle() & WS_VISIBLE;
if (bVisible) ModifyStyle(WS_VISIBLE, 0);
LRESULT lResult = DefWindowProc(WM_SETTEXT, wParam, lParam);
if (bVisible) ModifyStyle(0, WS_VISIBLE);
InternalTextChanged();
RedrawButton();
return lResult;
}
BOOL CXTPButton::OnEraseBkgnd(CDC* /*pDC*/)
{
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
COLORREF CXTPButton::GetButtonTextColor()
{
return GetSysColor(COLOR_BTNTEXT);
}
COLORREF CXTPButton::GetButtonBackColor()
{
return GetSysColor(COLOR_BTNFACE);
}
BYTE CXTPButton::GetButtonStyle() const
{
BYTE bStyle = BYTE(GetStyle() & 0xF);
return bStyle;
}
CSize CXTPButton::GetImageSize()
{
if (m_pIcon)
return CSize(m_pIcon->GetWidth(), m_pIcon->GetHeight());
return CSize(0, 0);
}
void CXTPButton::DrawImage(CDC* pDC, CRect rc)
{
CXTPImageManagerIcon* pIcon = GetIcon();
if (pIcon)
{
BOOL bSelected = GetChecked() || IsPushed();
if (!IsWindowEnabled())
{
pIcon->Draw(pDC, rc.TopLeft(), pIcon->GetDisabledIcon(), rc.Size());
}
else if (IsHighlighted() || bSelected)
{
pIcon->Draw(pDC, rc.TopLeft(), GetChecked() ? pIcon->GetCheckedIcon() :
IsPushed() ? pIcon->GetPressedIcon() : pIcon->GetHotIcon(), rc.Size());
}
else
{
pIcon->Draw(pDC, rc.TopLeft(), pIcon->GetIcon(), rc.Size());
}
}
}
BOOL CXTPButton::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
if (message == WM_SETTINGCHANGE || message == WM_SYSCOLORCHANGE)
{
RefreshMetrics();
}
if (m_pUIElement)
{
if (XTPMarkupRelayMessage(m_pUIElement, message, wParam, lParam, pResult))
return TRUE;
}
if (m_pToolTipContext)
{
m_pToolTipContext->FilterToolTipMessage(this, message, wParam, lParam);
}
return CXTPButtonBase::OnWndMsg(message, wParam, lParam, pResult);
}
int CXTPButton::GetTextAlignment() const
{
DWORD bHorz;
DWORD bVert;
DWORD dwStyle = GetStyle();
bHorz = dwStyle & (BS_LEFT | BS_RIGHT | BS_CENTER);
bVert = dwStyle & (BS_TOP | BS_BOTTOM | BS_VCENTER);
if (!bHorz || !bVert)
{
if (IsPushButton())
{
if (!bHorz)
bHorz = BS_CENTER;
}
else
{
if (!bHorz)
bHorz = BS_LEFT;
}
if (!bVert)
bVert = BS_VCENTER;
}
return bHorz | bVert;
}
CSize CXTPButton::GetGlyphSize(BOOL bCheckBox)
{
CRect rcButton = GetButtonRect();
CSize sz(13, 13);
if (m_bUseVisualStyle && m_pTheme->m_themeButton->IsAppThemed())
{
m_pTheme->m_themeButton->GetThemePartSize(NULL,
bCheckBox ? BP_CHECKBOX : BP_RADIOBUTTON,
1, rcButton, TS_TRUE, &sz);
}
return sz;
}
void CXTPButton::InternalTextChanged()
{
if (m_pMarkupContext)
{
XTPMarkupReleaseElement(m_pUIElement);
m_pUIElement = XTPMarkupParseText(m_pMarkupContext, GetButtonText());
}
}
CString CXTPButton::GetButtonText()
{
CString str;
if (m_hWnd) GetWindowText(str);
return str;
}
void CXTPButton::EnableMarkup(BOOL bEnableMarkup)
{
m_bEnableMarkup = bEnableMarkup;
XTPMarkupReleaseElement(m_pUIElement);
XTPMarkupReleaseContext(m_pMarkupContext);
if (m_bEnableMarkup)
{
m_pMarkupContext = XTPMarkupCreateContext(m_hWnd);
}
InternalTextChanged();
}
BOOL CXTPButton::IsPushButton() const
{
DWORD dwStyle = GetStyle();
switch (GetButtonStyle())
{
case LOBYTE(BS_PUSHBUTTON):
case LOBYTE(BS_DEFPUSHBUTTON):
case LOBYTE(BS_OWNERDRAW):
return TRUE;
default:
if ((dwStyle & BS_PUSHLIKE) == BS_PUSHLIKE)
return TRUE;
break;
}
return FALSE;
}
void CXTPButton::SetTheme(CXTPButtonTheme* pPaintManager)
{
CMDTARGET_RELEASE(m_pTheme);
m_pTheme = pPaintManager;
m_bUseVisualStyle = pPaintManager->GetThemeStyle() == xtpControlThemeDefault;
if (m_pTheme)
{
m_pTheme->RefreshMetrics(this);
}
if (::IsWindow(m_hWnd))
{
RedrawButton();
}
}
LRESULT CXTPButton::OnSetTheme(WPARAM wParam, LPARAM /*lParam*/)
{
XTPControlTheme eTheme = (XTPControlTheme)wParam;
SetTheme(eTheme);
return 0;
}
void CXTPButton::RefreshMetrics()
{
if (m_pTheme)
m_pTheme->RefreshMetrics(this);
if (::IsWindow(m_hWnd))
RedrawButton();
}
BOOL CXTPButton::SetTheme(XTPControlTheme eTheme)
{
CMDTARGET_RELEASE(m_pTheme);
switch (eTheme)
{
case xtpControlThemeFlat:
m_pTheme = new CXTPButtonFlatTheme();
break;
case xtpControlThemeUltraFlat:
m_pTheme = new CXTPButtonUltraFlatTheme();
break;
case xtpControlThemeOffice2000:
m_pTheme = new CXTPButtonOffice2000Theme();
break;
case xtpControlThemeOfficeXP:
m_pTheme = new CXTPButtonOfficeXPTheme();
break;
case xtpControlThemeOffice2003:
m_pTheme = new CXTPButtonOffice2003Theme();
break;
case xtpControlThemeResource:
m_pTheme = new CXTPButtonResourceTheme();
break;
default:
m_pTheme = new CXTPButtonTheme();
}
m_bUseVisualStyle = (eTheme == xtpControlThemeDefault);
RefreshMetrics();
return (m_pTheme != NULL);
}
void CXTPButton::SetUseVisualStyle(BOOL bUseVisualStyle/* = TRUE*/)
{
m_bUseVisualStyle = bUseVisualStyle;
m_pTheme->RefreshMetrics(this);
RedrawButton();
}
BOOL CXTPButton::GetChecked()
{
if (IsPushButton() || !m_hWnd)
{
return m_bChecked;
}
return (BOOL)::SendMessage(m_hWnd, BM_GETCHECK, 0, 0);
}
void CXTPButton::SetChecked(BOOL bChecked)
{
if (IsPushButton() || !m_hWnd)
{
m_bChecked = bChecked;
RedrawButton();
}
else
{
::SendMessage(m_hWnd, BM_SETCHECK, bChecked, 0);
}
}
BOOL CXTPButton::SetIcon(CSize size, UINT nID, UINT nHotID/*= 0*/, BOOL bRedraw/*= TRUE*/)
{
return CXTPButton::SetIcon(
size, MAKEINTRESOURCE(nID), MAKEINTRESOURCE(nHotID), bRedraw);
}
BOOL CXTPButton::SetIcon(CSize size, LPCTSTR lpszID, LPCTSTR lpszHotID/*= NULL*/, BOOL bRedraw/*= TRUE*/)
{
CXTPImageManagerIconHandle hIcon;
CXTPImageManagerIconHandle hIconHot;
hIcon.CreateIconFromResource(lpszID, size);
// Return false if the icon handle is NULL.
if (hIcon.IsEmpty())
{
TRACE0("Failed to load Icon resource.\n");
return FALSE;
}
// If we are using a pushed image as well...
if (lpszHotID)
{
hIconHot.CreateIconFromResource(lpszHotID, size);
// Return false if the icon handle is NULL.
if (hIconHot.IsEmpty())
{
TRACE0("Failed to load Icon resource.\n");
return FALSE;
}
}
return CXTPButton::SetIcon(size, hIcon, hIconHot, bRedraw);
}
BOOL CXTPButton::SetIcon(CSize /*size*/, CXTPImageManagerIcon* pIcon, BOOL bRedraw/*= TRUE*/)
{
// Construct the icon manager.
CMDTARGET_RELEASE(m_pIcon);
m_pIcon = pIcon;
// Redraw the button.
if (bRedraw)
RedrawButton();
return TRUE;
}
BOOL CXTPButton::SetIcon(CSize size, const CXTPImageManagerIconHandle& hIcon, const CXTPImageManagerIconHandle& hIconHot, BOOL bRedraw/*= TRUE*/)
{
ASSERT(!hIcon.IsEmpty());
// Save the image size and set the icon
// handles to NULL.
size = size != CSize(0) ? size : hIcon.GetExtent();
CXTPImageManagerIcon* pIcon = new CXTPImageManagerIcon(0, size.cx, size.cy);
pIcon->SetIcon(hIcon);
if (!hIconHot.IsEmpty())
pIcon->SetHotIcon(hIconHot);
return SetIcon(size, pIcon, bRedraw);
}
BOOL CXTPButton::SetIcon(CSize size, HICON hIcon, HICON hIconHot/*= NULL*/, BOOL bRedraw/*= TRUE*/)
{
return SetIcon(size, CXTPImageManagerIconHandle(hIcon), CXTPImageManagerIconHandle(hIconHot), bRedraw);
}
BOOL CXTPButton::SetBitmap(CSize size, UINT nID, BOOL bRedraw/*= TRUE*/)
{
// Free previous resources (if any).
CXTPImageManagerIconHandle hIconHandle;
BOOL bAlphaBitmap = FALSE;
HBITMAP hBitmap = CXTPImageManagerIcon::LoadBitmapFromResource(MAKEINTRESOURCE(nID), &bAlphaBitmap);
if (!hBitmap)
return FALSE;
if (bAlphaBitmap)
{
hIconHandle = hBitmap; // Will call DeleteObject;
}
else
{
CBitmap bmpIcon;
bmpIcon.Attach(hBitmap);
// convert the bitmap to a transparent icon.
HICON hIcon = CXTPTransparentBitmap(bmpIcon).ConvertToIcon();
hIconHandle = hIcon; // Will call DestoyIcon;
}
if (hIconHandle.IsEmpty())
return FALSE;
return CXTPButton::SetIcon(size, hIconHandle, CXTPImageManagerIconHandle(), bRedraw);
}
void CXTPButton::SetBuddy(CWnd* pWndBuddy, BOOL bMoveButton)
{
m_hWndBuddy = pWndBuddy->GetSafeHwnd();
if (!m_hWndBuddy)
return;
CRect rcBuddy;
::GetWindowRect(m_hWndBuddy, &rcBuddy);
GetParent()->ScreenToClient(rcBuddy);
CXTPWindowRect rc(this);
int nWidth = rc.Width();
if (bMoveButton)
{
::MoveWindow(m_hWndBuddy, rcBuddy.left, rcBuddy.top, rcBuddy.Width() - nWidth + 2, rcBuddy.Height(), TRUE);
}
else
{
GetParent()->ScreenToClient(rc);
::MoveWindow(m_hWndBuddy, rcBuddy.left, rcBuddy.top, (rc.left + 2) - rcBuddy.left, rcBuddy.Height(), TRUE);
rcBuddy.right = rc.left + nWidth;
}
CRect rcButton = rcBuddy;
rcButton.left = rcButton.right - nWidth;
::MoveWindow(m_hWnd, rcButton.left, rcButton.top, rcButton.Width(), rcButton.Height(), TRUE);
}
INT_PTR CXTPButton::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
CString strTip = GetTooltip();
if (strTip.GetLength() == 0)
return -1;
CXTPButton* pButton = (CXTPButton*)this;
CXTPClientRect rc(pButton);
rc.DeflateRect(2, 2);
if (rc.PtInRect(point))
{
CXTPToolTipContext::FillInToolInfo(pTI, m_hWnd, rc, 1, strTip, pButton->GetButtonText(), strTip);
return 1;
}
return -1;
}