Mauszeiger



  • Hallo nochmals, ich habe noch eine Frage, ich möchte, dass wenn der Mauszeiger über eine Button Schaltfläche fährt, sein Aussehen sich ändert. Im Netz habe ich folgendes gelesen:

    ...OnInitDialog ...
    (CButton*) bu = (CButton*)GetDlgItem(IDB_BUTTON1);
    bu->SetCursor(::LoadCursor(NULL, IDC_HAND));

    klappt nicht ! der Mauszeiger verändert sich nicht. Wo muss obiger Code hin ?
    Weiss jemand Rat ?



  • Es muss natürlich heissen:

    ...OnInitDialog ...
    CButton* bu = (CButton*)GetDlgItem(IDB_BUTTON1);
    bu->SetCursor(::LoadCursor(NULL, IDC_HAND));

    Danke im Voraus !



  • Bei C# .NET gibt es die Ereignisse Enter und Leave, die ausgelöst werden, wenn der Mauszeiger ein Steuerelement betritt, bzw verlässt. Sowas sollte auch bei den MFC gehen ! Aber man könnte doch mit OnMouseMove abfragen, wo der Mauszeiger sich befindet. Aber MouseMove von der Dialogklasse, wird nicht ausgelöst, wenn der Zeiger eine CButton-Schaltfläche betritt. Dann müsste man nur abfragen, ob der Zeiger sich auf dem Button befindet, und die Cursorart anpassen. Gibt es sowas wie ein OnMouseMove, das über das ganze Dialogfeld einschliesslich Steuerelemente ausgelöst wird ?



  • Die Windowsnachricht WM_MOUSELEAVE gibt es zumindest, ein "Enter" kann man ja auch mit WM_MOUSEMOVE umsetzen.



  • Nur WM_MOUSEMOVE wird nicht ausgelöst, wenn man CButton betritt. Eine Möglichkeit ist Subclassing, da kann man WM_MOUSEMOVE abfangen. Aber umständlich ! Bei C#.NET ist es einfach: buttton1.Cursor = Cursors.Hand;
    MFC ist kompliziert, leider müssen viele Programme mit MFC weiterentwickelt werden. Was solls ...



  • Subclassing und auf WM_SETCURSOR reagieren...



  • Mit WM_SETCURSOR in der Subklasse habe ich folgendermaßen versucht:

    Header: HCURSOR mycur;
    Konstruktor: mycur = AfxGetApp()->LoadStandardCursor(IDC_HAND);
    OnSetCursor: SetCursor(mycur);

    Ging nicht ! Hier noch eine Frage ( obiger Thread ):
    Wie erreicht man eine randlose CButton, mit der Subklasse ?



  • Du bräuchtest noch nicht einmal subclassing, sorry. Wenn dein Dialog ein CDialog ist:

    // Möglichkeit 1
    
    BOOL MyDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
    {
    	if(pWnd==static_cast<CButton*>(GetDlgItem(IDB_BUTTON1)))
    	{
    		::SetCursor(::LoadCursor(nullptr, IDC_HAND));
    		return true; // wichtig
    	}
    	return CDialog::OnSetCursor(pWnd, nHitTest, message);
    }
    // mit
    
    BEGIN_MESSAGE_MAP(MyDlg, CDialog)
    ...
    	ON_WM_SETCURSOR()
    ...
    END_MESSAGE_MAP()
    
    // Möglichkeit 2: Subclassing an MFC vorbei
    // in OnInitDialog:
    
    ::SetWindowSubclass(::GetDlgItem(m_hWnd, IDB_BUTTON1), ButtonProc, 0, 0);
    
    // mit ButtonProc
    LRESULT CALLBACK ButtonProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, UINT_PTR subclassID, DWORD_PTR refData)
    {
    	switch(msg)
    	{
    		case WM_SETCURSOR:
    			::SetCursor(::LoadCursor(nullptr, IDC_HAND));
    			return true;
    	}
    	return ::DefSubclassProc(hwnd, msg, wParam, lParam);
    }
    

    Mit dem Button-Stil weiß ich nicht so richtig, was du meinst - aus vielmehr als dem Rahmen und Text besteht ein Button ja kaum.
    Buttonstyles können auch nur schlecht gesetzt werden, nachdem sie erzeugt wurden. Möglich wäre es, einen Button mit BS_PUSHBOX | BS_CENTER | BS_PUSHLIKE | WS_VISIBLE | WS_CHILD selber zu erstellen, also ein Control ohne Rahmen und zentriertem Text, das nur beim Klick darauf eine optische Rückmeldung gibt.
    Ansonsten natürlich Owner-Draw.



  • Danke fasfa, Möglichkeit1 funktioniert !
    Bleibt das Problem mit dem Rahmen, ich habe die CButton auch von "Hand" eingebaut, ohne Erfolg ...