userover8k
userover8k

Reputation: 33

How to make static window increase size on mouse hover

I have a bunch of windows inside another window. Child Windows are created in the CreateBoard() method of MainWindow class. Create() method of MainWindow and GemWindow is from the MS Documentation BaseWindow abstract class and this is where the each class is registered with a call to 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() method creates the Gems in the board.

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;
}

I want each child window to increase their size by 4 pixels on mouse hover separately. However, after expanding the size, they leave a trace, and sometimes hovering on a single-window increases the size of the whole row or column. Referer to Image, for example:

Problem demo

I have the handling code for each child window as below. tracking is a static BOOL in the GemWindow class

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() is a method of GemWindow which initialize a TRACKMOUSEEVENTand call 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);
    }

I thought it is because I am not Updating regions, but doing that did not change anything. I am confused about this bug and can't think of any good reason for it.

Thanks to all who take their time to help.

Upvotes: 0

Views: 134

Answers (1)

Strive Sun
Strive Sun

Reputation: 6289

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
);

Modify the following code:

   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);
        ...

Debug:

enter image description here

Upvotes: 1

Related Questions