Bestimmen der cursor Position in einem Fenster

FBIagent

Erfahrenes Mitglied
ich habe mir eine kleine Klasse für einen BitmapButton geschrieben.
Funktioniert soweit auch ohne Probleme, nur scheint es so, das ich nicht in der Lage
bin zu bestimmen, an welcher Position sich der Cursor in meinen Fenster besfindet.
Die Cursor Position brauche ich um zu bestimen ob der Button normal, im Focus oder
gerade geklickt angezeigt werden soll.

In Methode IsCursorInButton
C++:
#ifndef __BITMAPBUTTON_H__
#define __BITMAPBUTTON_H__

#include <windows.h>

enum BitmapButtonState
{
    BBS_NORMAL,
    BBS_FOCUS,
    BBS_DOWN
};

class WINAPI_BitmapButton
{
public:
    WINAPI_BitmapButton(POINT &StartPoint, SIZE &Size)
    : m_StartPoint(StartPoint), m_Size(Size), m_BBS(BBS_NORMAL), m_hBitmapNormal(NULL), m_hBitmapFocus(NULL), m_hBitmapDown(NULL), m_hDCNormal(NULL), m_hDCFocus(NULL), m_hDCDown(NULL)
    {}

    virtual ~WINAPI_BitmapButton()
    {
        if (m_hBitmapNormal != NULL)
            DeleteObject(m_hBitmapNormal);
        if (m_hBitmapFocus != NULL)
            DeleteObject(m_hBitmapFocus);
        if (m_hBitmapDown != NULL)
            DeleteObject(m_hBitmapDown);
        if (m_hDCNormal != NULL)
            DeleteObject(m_hDCNormal);
        if (m_hDCFocus != NULL)
            DeleteObject(m_hDCFocus);
        if (m_hDCDown != NULL)
            DeleteObject(m_hDCDown);
    }

    void SetNormalResource(HINSTANCE hInstance, unsigned int ResourceId)
    {
        m_hBitmapNormal = LoadBitmap(hInstance, MAKEINTRESOURCEA(ResourceId));
        m_hDCNormal = CreateCompatibleDC(NULL);
        SelectObject(m_hDCNormal, m_hBitmapNormal);
    }

    void SetFocusResource(HINSTANCE hInstance, unsigned int ResourceId)
    {
        m_hBitmapFocus = LoadBitmap(hInstance, MAKEINTRESOURCEA(ResourceId));
        m_hDCFocus = CreateCompatibleDC(NULL);
        SelectObject(m_hDCFocus, m_hBitmapFocus);
    }

    void SetDownResource(HINSTANCE hInstance, unsigned int ResourceId)
    {
        m_hBitmapDown = LoadBitmap(hInstance, MAKEINTRESOURCEA(ResourceId));
        m_hDCDown = CreateCompatibleDC(NULL);
        SelectObject(m_hDCDown, m_hBitmapDown);
    }

    bool IsCursorInButton(POINT &CursorPosition, RECT &ClientRect)
    {
        if (CursorPosition.x >= m_StartPoint.x+ClientRect.left && CursorPosition.x < m_StartPoint.x+m_Size.cx+ClientRect.left &&
            CursorPosition.y >= m_StartPoint.y+ClientRect.top && CursorPosition.y < m_StartPoint.y+m_Size.cy+ClientRect.top &&
            m_BBS == BBS_NORMAL)
            return true;

        return false;
    }

    void SetState(BitmapButtonState bbs)
    {
        m_BBS = bbs;
    }

    void DrawMe(HDC &hDC)
    {
        if (m_BBS == BBS_DOWN && m_hDCDown != NULL)
            BitBlt(hDC, m_StartPoint.x, m_StartPoint.y, m_Size.cx, m_Size.cy, m_hDCDown, 0, 0, SRCCOPY);
        else if (m_BBS == BBS_FOCUS && m_hDCFocus != NULL)
            BitBlt(hDC, m_StartPoint.x, m_StartPoint.y, m_Size.cx, m_Size.cy, m_hDCFocus, 0, 0, SRCCOPY);
        else if (m_BBS == BBS_NORMAL && m_hDCNormal != NULL)
            BitBlt(hDC, m_StartPoint.x, m_StartPoint.y, m_Size.cx, m_Size.cy, m_hDCNormal, 0, 0, SRCCOPY);
    }

    bool IsNormal()
    {
        return m_BBS == BBS_NORMAL;
    }

    bool IsInFocus()
    {
        return m_BBS == BBS_FOCUS;
    }

    bool IsDown()
    {
        return m_BBS == BBS_DOWN;
    }

    const POINT &GetStartPoint()
    {
        return m_StartPoint;
    }

    const SIZE &GetSize()
    {
        return m_Size;
    }
private:
    POINT m_StartPoint;
    SIZE m_Size;
    BitmapButtonState m_BBS;
    HBITMAP m_hBitmapNormal;
    HBITMAP m_hBitmapFocus;
    HBITMAP m_hBitmapDown;
    HDC m_hDCNormal;
    HDC m_hDCFocus;
    HDC m_hDCDown;
};

#endif

Code der den ButtonState eigentlich ändern sollte.
C++:
LRESULT CALLBACK MainWindowProc(HWND hWindow, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    HDC hDC;
    PAINTSTRUCT ps;
    static RECT rect;
    static POINT CurrentCursorPos;

    switch(Msg)
    {
    case WM_CREATE:
        POINT Point;
        SIZE Size;
        Point.x = 30;
        Point.y = 30;
        Size.cx = 114;
        Size.cy = 26;
        WBB = new WINAPI_BitmapButton(Point, Size);
        WBB->SetNormalResource(MainWindowClass.hInstance, IDB_BUTTON_NORMAL);
        WBB->SetFocusResource(MainWindowClass.hInstance, IDB_BUTTON_FOCUS);
        WBB->SetDownResource(MainWindowClass.hInstance, IDB_BUTTON_DOWN);
        GetCursorPos(&CurrentCursorPos);
        break;
    case WM_MOUSEMOVE:
        GetCursorPos(&CurrentCursorPos);
        GetClientRect(hWindow, &rect);

        if (WBB->IsCursorInButton(CurrentCursorPos, rect) && WBB->IsNormal())
            WBB->SetState(BBS_FOCUS);

        InvalidateRect(hMainWindow, &rect, FALSE);
        break;
    case WM_LBUTTONDOWN:
        if (WBB->IsCursorInButton(CurrentCursorPos, rect))
            WBB->SetState(BBS_DOWN);

        InvalidateRect(hMainWindow, &rect, FALSE);
        break;
    case WM_LBUTTONUP:
        if (WBB->IsDown())
            WBB->SetState(BBS_NORMAL);

        InvalidateRect(hMainWindow, &rect, FALSE);
        break;
    case WM_PAINT:
        hDC = BeginPaint(hWindow, &ps);
        GetClientRect(hWindow, &rect);

        MainWindowDrawBackground(hDC, rect);
        WBB->DrawMe(hDC);

        EndPaint(hWindow, &ps);
        break;
    case WM_COMMAND: // handling buttons here
        break;
    case WM_DESTROY: // on closing
        PostQuitMessage(WM_QUIT);
        break;
    case WM_QUIT: // cleanup here
        if (L2DirStr != NULL)
            delete[] L2DirStr;

        DeleteObject(hDCBG);
        DeleteObject(hBitmapBG);
        delete WBB;
        break;
    default:
        return DefWindowProc(hWindow, Msg, wParam, lParam);
    }

    return 0;
}

Wäre nicht schlecht wenn sich das Jemand mal anschauen könnte und gegebenfalls
sagen könnte was ich falsch mache.

Danke.

Best wishes
FBIagent
 
Zuletzt bearbeitet von einem Moderator:
Da ich es in keinster Form hinbekommen, habe ich mir für eine temporäre Lösung
entschieden, die auch nur möglich ist da das fenster ein popup ist und nicht verschoben
werden kann. Ich hole mir mittels GetSystemMetrics die auflösung vom user, setze das
Fenster in die mitte des Bildschirms und weis somit wo der Button welchen state hat.

Best wishes
FBIagent
 
Ich hab dazu jetzt noch nichts gefunden, aber im Prinzip müsstest du die Events von anderen Objekten deiner Klasse vererben und dann kannst du mit den schon vorgefertigten MouseHover MouseEnter MouseDown usw. Aktionen arbeiten.

Ich kenn das nur aus Delphi - du müsstest was unter (User)Controls finden können, wie man sowas selber macht.

Für meine Zwecke hat es meist gereicht eine Picturebox zu verwenden, in der ich dann bei den Mouseevents die Grafik geändert habe.
 
Danke für die bemühungen, aber das ist C WinApi und hat keine Event handlers.
Die MainWIndowClass is ein Objekt von dem WinApi struct WNDCLASSEX.
Dad einzigste was man hier vieleicht als event handler bezeichnen kann ist die
MainWindowProc funktion.

Ich habe nochmal in die MSDN geschaut, habe mir gedacht, das so etwas ja vieleicht
im WPARAM oder LPARAM enthalten ist, und siehe da bei der WM_MOUSEMOVE
message is in LPARAM low-order word die x achse relativ zum statpunkt des
Clientbereiches angegeben, und im high-order word die y achse relativ zum startpunkt
des Clientbereichs.
 
Zurück