65.9K
CodeProject 正在变化。 阅读更多。
Home

一个不可点击的按钮

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (36投票s)

2002年5月22日

CPOL
viewsIcon

411383

downloadIcon

3676

看起来像一个普通的按钮 - 直到用户尝试点击它。

Sample Image - trick_button.gif

介绍 

我很多年前为一位朋友编写了这个程序。它基本上就是一个普通的按钮,只不过当用户尝试点击它时,它会移开位置,使其几乎无法点击。 

我不知道任何人会在他们的应用程序中使用这样的控件有什么用处,除了想极度地让用户感到恼火(而且,我们偶尔都会这样,不是吗?):)

这个按钮只是一个普通的按钮,重写了OnMouseMove:(m_nJumpDistance 是鼠标移动到控件上后跳跃的像素距离)。

WM_SETFOCUS 消息也被处理,以便将焦点弹回先前具有焦点的窗口,并且重写了 PreSubclassWindow 以允许删除 WS_TABSTOP 窗口样式位。这确保了用户无法通过 Tab 键选择该控件。

核心代码

void CTrickButton::OnMouseMove(UINT nFlags, CPoint point) 
{
    CWnd* pParent = GetParent();
    if (!pParent) pParent = GetDesktopWindow();

    CRect ParentRect;                                   // Parent client area (Parent coords)
    pParent->GetClientRect(ParentRect);

    ClientToScreen(&point);                             // Convert point to parent coords
    pParent->ScreenToClient(&point);

    CRect ButtonRect;                                   // Button Dimensions (Parent coords)
    GetWindowRect(ButtonRect);  
    pParent->ScreenToClient(ButtonRect);
    CPoint Center = ButtonRect.CenterPoint();           // Center of button (parent coords)

    CRect NewButtonRect = ButtonRect;                   // New position (parent coords)

    if (point.x > Center.x)                             // Mouse is right of center
    {
        if (ButtonRect.left > ParentRect.left + ButtonRect.Width() + m_nJumpDistance)
            NewButtonRect -= CSize(ButtonRect.right - point.x + m_nJumpDistance, 0);
        else
            NewButtonRect += CSize(point.x - ButtonRect.left + m_nJumpDistance, 0);
    }
    else if (point.x < Center.x)                       // Mouse is left of center
    {
        if (ButtonRect.right < ParentRect.right - ButtonRect.Width() - m_nJumpDistance)
            NewButtonRect += CSize(point.x - ButtonRect.left + m_nJumpDistance, 0);
        else
            NewButtonRect -= CSize(ButtonRect.right - point.x + m_nJumpDistance, 0);
    }

    if (point.y > Center.y)                           // Mouse is below center
    {
        if (ButtonRect.top > ParentRect.top + ButtonRect.Height() + m_nJumpDistance)
            NewButtonRect -= CSize(0, ButtonRect.bottom - point.y + m_nJumpDistance);
        else
            NewButtonRect += CSize(0, point.y - ButtonRect.top + m_nJumpDistance);
    }
    else if (point.y < Center.y)                      // Mouse is above center
    {
        if (ButtonRect.bottom < ParentRect.bottom - ButtonRect.Height() - m_nJumpDistance)
            NewButtonRect += CSize(0, point.y - ButtonRect.top + m_nJumpDistance);
        else
            NewButtonRect -= CSize(0, ButtonRect.bottom - point.y + m_nJumpDistance);
    }

    MoveWindow(NewButtonRect);
    RedrawWindow();
    
    CButton::OnMouseMove(nFlags, point);
}

void CTrickButton::OnSetFocus(CWnd* pOldWnd)
{
    CButton::OnSetFocus(pOldWnd);

    // Give the focus right back to the window that justn gave it to us
    if (pOldWnd!=NULL && ::IsWindow(pOldWnd->GetSafeHwnd()))
        pOldWnd->SetFocus();
}

void CTrickButton::PreSubclassWindow()
{
    // Ensure that the TabStop style is removed from the control
    ModifyStyle(WS_TABSTOP, 0);
    CButton::PreSubclassWindow();
}

历史

2002年5月31日 - 更新以包括删除 WM_TABSTOP,以及一些小的清理。

© . All rights reserved.