【问题标题】:How to make static window increase size on mouse hover如何使静态窗口在鼠标悬停时增加大小
【发布时间】:2020-08-01 22:40:02
【问题描述】:

我在另一个窗口中有一堆窗口。 子窗口在MainWindow 类的CreateBoard() 方法中创建。 MainWindowGemWindowCreate() 方法来自 MS Documentation BaseWindow 抽象类,这是通过调用 RegisterClass() 注册每个类的地方

template <class DERIVED_TYPE>
class BaseWindow
{
public:
    static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        DERIVED_TYPE* pThis = NULL;

        if (uMsg == WM_NCCREATE)
        {
            CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
            pThis = (DERIVED_TYPE*)pCreate->lpCreateParams;
            SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);

            pThis->m_hwnd = hwnd;
        }
        else
        {
            pThis = (DERIVED_TYPE*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
        }
        if (pThis)
        {
            //getting read access violation here why?
            //because on resize you are not initializing tiles
            //but resizing the thing
            return pThis->HandleMessage(uMsg, wParam, lParam);
        }
        else
        {
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
        }
    }

    BaseWindow() : m_hwnd(NULL) { }

    BOOL Create(
        PCWSTR lpWindowName,
        DWORD dwStyle,
        DWORD dwExStyle = 0,
        int x = CW_USEDEFAULT,
        int y = CW_USEDEFAULT,
        int nWidth = CW_USEDEFAULT,
        int nHeight = CW_USEDEFAULT,
        HWND hWndParent = 0,
        HMENU hMenu = 0
    )
    {
        WNDCLASS wc = { 0 };

        wc.lpfnWndProc = DERIVED_TYPE::WindowProc;
        wc.hInstance = GetModuleHandle(NULL);
        wc.lpszClassName = ClassName();

        RegisterClass(&wc);

        m_hwnd = CreateWindowEx(
            dwExStyle, ClassName(), lpWindowName, dwStyle, x, y,
            nWidth, nHeight, hWndParent, hMenu, GetModuleHandle(NULL), this
        );

        return (m_hwnd ? TRUE : FALSE);
    }

    //returns handle
    HWND Window() const { return m_hwnd; }

protected:

    virtual PCWSTR  ClassName() const = 0;
    virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;

    HWND m_hwnd;
};

CreateBoard() 方法在棋盘中创建宝石。

BOOL MainWindow::CreateBoard()
{
    for (unsigned int i = 0; i < GetcGem(); i++)
    {
        for (unsigned int j = 0; j < GetcGem(); j++)
        {
            if (Gems[i][j].Create(L"gem", WS_CHILDWINDOW | WS_VISIBLE, NULL, 
              5 + i * GetsGem().cx + i * 10, 
              5 + j * GetsGem().cy + j * 10, GetsGem().cx, GetsGem().cy, Window(), NULL))
            {
                //pass from main window to Gem object
                Gems[i][j].SetSize(GetsGem().cx, GetsGem().cy);
                Gems[i][j].SetPosition(5 + i * GetsGem().cx + i * 10, 5 + j * GetsGem().cy + j * 10);

                HBRUSH hbrush = CreateSolidBrush(RGB(125,125,125));
                HBRUSH hOldBrush = (HBRUSH)SetClassLongPtr(Gems[i][j].Window(), GCLP_HBRBACKGROUND, (LONG_PTR)hbrush);
                DeleteObject(hOldBrush);
                InvalidateRect(Gems[i][j].Window(), NULL, TRUE);

            }
            else
            {
                return FALSE;
            }
        }
    }
    return TRUE;
}

我希望每个子窗口在鼠标悬停时分别将其大小增加 4 个像素。但是,扩大尺寸后,它们会留下痕迹,有时悬停在单个窗口上会增加整行或整列的大小。引用Image,例如:

我有每个子窗口的处理代码如下。 trackingGemWindow 类中的 static BOOL

BOOL GemWindow::tracking = false;

LRESULT GemWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_DESTROY:
        DestroyWindow(Window());
        break;

    case WM_MOUSEMOVE:
    {
        if (!tracking) {
            TrackMouse();
            tracking = true;
        }

    }break;

    case WM_MOUSEHOVER:
    {
        MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
        InvalidateRect(Window(), NULL, TRUE);
        OutputDebugString(L"MOUSE ENTERED\n");
    }break;

    case WM_MOUSELEAVE:
    {
        MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
        InvalidateRect(Window(), NULL, TRUE);
        OutputDebugString(L"MOUSE LEFT\n");
        tracking = false;
    }break;


    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(m_hwnd, &ps);
        //FillRect(hdc, &ps.rcPaint, CreateSolidBrush(color));
        EndPaint(m_hwnd, &ps);
        //OutputDebugString(L"PAINT\n");
    }
    return 0;

    default:
        return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
    }
    return TRUE;
}

TrackMouse()GemWindow的一个方法,它初始化一个TRACKMOUSEEVENT并调用TrackMouseEvent()

    //method for tracking mouse
    void TrackMouse(/*reusability enhanced if you add arguments in the future*/)
    {
        TRACKMOUSEEVENT tme;
        tme.cbSize = sizeof(TRACKMOUSEEVENT);
        tme.dwFlags = TME_HOVER | TME_LEAVE; //Type of events to track & trigger.
        tme.dwHoverTime = 1; //How long the mouse has to be in the window to trigger a hover event.
        tme.hwndTrack = Window();
        TrackMouseEvent(&tme);
    }

我认为这是因为我没有更新区域,但这样做并没有改变任何东西。我对这个错误感到困惑,想不出任何好的理由。

感谢所有花时间提供帮助的人。

【问题讨论】:

  • 包含您的 STATIC 的窗口是如何创建的?请特别说明WNDCLASS 是如何注册的。另外,题外话,但调用DestroyWindow 响应WM_DESTROY 是错误的,WM_DESTROY 在调用DestroyWindow 时发送,而不是相反。
  • @PaulSanders 我使用了 MS documentation 中给出的 BaseWindow 类,继承了我自己的 GemWindow 类,并在每个 Gem 上使用了 Create 方法,因为 Gems[i][j].Create(L"gem", WS_CHILDWINDOW | WS_VISIBLE, NULL, 5 + i * GetsGem().cx + i * 10, 5 + j * GetsGem().cy + j * 10, GetsGem().cx, GetsGem().cy, Window(), NULL)the method I use to create the board 在这里。
  • 请将相关代码添加到您的问题中。不要依赖外部链接。
  • @PaulSanders 根据您的建议更新了帖子。不想首先将所有内容都放在问题中以使其尽可能简短,我意识到问题的可理解性的整个代码应该在问题部分中,但这里是the project repository的链接,因为最小的方面(这似乎与我无关)代码的各个部分可能导致问题
  • 您需要显示注册窗口类的代码。这可能就是问题所在。

标签: c++ windows winapi button hover


【解决方案1】:
BOOL MoveWindow(
  HWND hWnd,
  int  X,  //The new position of the left side of the window.
  int  Y,  //The new position of the top of the window.
  int  nWidth, //The new width of the window.
  int  nHeight, //The new height of the window.
  BOOL bRepaint
);

修改如下代码:

   case WM_MOUSEHOVER:
    {
//      MoveWindow(Window(), GetSize().cx + 4, GetSize().cy + 4, GetPosition().x - 2, GetPosition().y - 2, TRUE);
        MoveWindow(Window(), GetPosition().x - 2, GetPosition().y - 2, GetSize().cx + 4, GetSize().cy + 4, TRUE);            
        ...

    case WM_MOUSELEAVE:
    {
 //     MoveWindow(Window(), GetSize().cx, GetSize().cy, GetPosition().x, GetPosition().y, TRUE);
        MoveWindow(Window(), GetPosition().x, GetPosition().y, GetSize().cx, GetSize().cy,  TRUE);
        ...

调试:

【讨论】:

  • 所以我混淆了MoveWindow() 函数的位置参数和大小参数,这是一个可怕的错误。感谢您的回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 2010-11-02
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 2011-10-03
  • 2018-07-01
相关资源
最近更新 更多