Einen Handcursor solange die Maus über dem Button ist



  • Hallo zusammen und ein frohes neues Jahr.
    Ich bin ein C++ Neuling und benutze Visual C++ 6.0 als Entwicklungsumgebung.
    Ich habe ein kleines Programm geschrieben in welchem es einen Button gibt.
    Ich will nun das der Mauscursor zur Hand wird solange sich der Cursor auf dem Button befindet. Verlässt die Maus den Button soll wieder der normale Pfeilcursor erscheinen.
    Kann ich dem Button einen bestimmten Cursor zuweisen?
    zardoz



  • Den Cursor kannst du setzen mit SetCursor() (merk dir den Rückgabewert der Funktion, damit du später wieder den normalen Cursor zurücksetzen kannst).

    (und der beste Ort für den Aufruf dürfte die OnMouseMove() des Buttons (zum Einschalten) bzw. des Hauptfenster (zum Ausschalten) sein)



  • Guten Tag CStoll.
    Ich habe also ein Dialogbasierendes Projekt angelegt.
    Du schriebst „der beste Ort für den Aufruf dürfte die OnMouseMove() des Buttons sein„
    Wie soll ich dem Button nun aber auf die OnMouseMove reagieren lassen.
    Ich habe das Projekt Mousemove genannt und habe somit die MousemoveDlg.cpp.
    Wenn ich die öffne und dann den Klassenassistenten öffne und unter Objekt-IDs
    IDC_BUTTON_1 wähle kann ich nur die Nachrichten BN_CLICKED und BN_DOUBLECLCKED auswählen.
    Nur wenn ich als Objekt-ID CMousemoveDlg wähle kann ich auch WM_MOUSEMOVE wählen. Da gibt es recht viele Nachrichten die ich auswählen kann. Beim Button allerdings nur zwei.
    Wie bringe ich also dem Button bei auf WM_MOUSEMOVE zu reagieren?
    Gruss zardoz



  • Hmm, dann mußt du wohl beide Punkte auf Dialog-Ebene erledigen (und dort selber unterscheiden, ob du über dem Button bist oder nicht).

    HCURSOR m_hand,m_default;
    bool m_ishand;
    CButton m_btn;
    
    CMouseMoveDlg():m_hand(LoadCursor(NULL,IDC_HAND)),m_ishand(false)
    {...}
    
    CMouseMoveDlg::OnMouseMove(UINT nFlags,CPoint pt)
    {
      //ich bin mir nicht sicher, ob du noch die Koordinatensysteme umrechnen mußt
      bool ishand = m_btn.GetWindowRect().PtInRect(pt);
      if(ishand!=m_ishand)//Grenzüberschreitung
      {
        if(ishand)
          m_default=::SetCursor(m_hand);
        else
          ::SetCursor(m_default);
        m_ishand=ishand;
      }
      CDialog::OnMouseMove(nFlags,pt);
    }
    


  • Hallo CStoll.
    Ich habe das mal fast so gemacht wie du schreibst. Ich habe folgendes in den Konstruktor eingefügt.

    CMousemoveDlg::CMousemoveDlg(CWnd* pParent /=NULL/)
    : CDialog(CMousemoveDlg::IDD, pParent)
    {
    //{{AFX_DATA_INIT(CMousemoveDlg)
    // HINWEIS: Der Klassenassistent fügt hier Member-Initialisierung ein
    //}}AFX_DATA_INIT
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); //bis hier war schon alles drinn

    m_hand = LoadCursor(NULL,IDC_HAND); //von mir eingetragen
    m_ishand = false; //von mir eingetragen
    }

    Die OnMouseMove sieht nun so aus.
    void CMousemoveDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
    bool ishand = m_btn.GetWindowRect().PtInRect(point);
    if(ishand!=m_ishand)//Grenzüberschreitung
    {
    if(ishand)
    m_default=::SetCursor(m_hand);
    else
    ::SetCursor(m_default);
    m_ishand=ishand;
    }
    CDialog::OnMouseMove(nFlags, point);
    }

    Ich bekomme als erste Fehlermeldung “error C2065: 'IDC_HAND' : nichtdeklarierter Bezeichner“
    Habe also aus IDC_HAND IDC_CROSS gemacht.

    Nun die nächsten Fehlermeldungen.
    : error C2660: 'GetWindowRect' : Funktion akzeptiert keine 0 Parameter
    : error C2228: Der linke Teil von '.PtInRect' muss eine Klasse/Struktur/Union sein

    Habe nun folgende Änderung vorgenommen.
    bool ishand = m_btn.GetWindowRect(PtInRect(point));

    Nun die Fehlermeldung :error C2660: 'PtInRect' : Funktion akzeptiert keine 1 Parameter

    Laut MSDN sollte aber ein Parameter ausreichen.
    Und laut MSDN gibt es auch IDC_HAND. Wenn ich in der winuser.h nachsehe wo die ganzen Cursor-Formen deklariert sind finde ich aber auch IDC_HAND. Komisch.
    gruss zardoz



  • zardoz schrieb:

    Nun die nächsten Fehlermeldungen.
    : error C2660: 'GetWindowRect' : Funktion akzeptiert keine 0 Parameter
    : error C2228: Der linke Teil von '.PtInRect' muss eine Klasse/Struktur/Union sein

    Habe nun folgende Änderung vorgenommen.
    bool ishand = m_btn.GetWindowRect(PtInRect(point));

    Nun die Fehlermeldung :error C2660: 'PtInRect' : Funktion akzeptiert keine 1 Parameter

    Ich hätte vielleicht dazuschreiben sollen, daß ich den Code ohne einen ausführlichen Blick in die MSDN geschrieben habe. Richtig müsste es so aussehen:

    CRect r;
    m_btn.GetWindowRect(r);
    bool ishand = r.PtInRect(point);
    

    Laut MSDN sollte aber ein Parameter ausreichen.

    Laut MSDN gibt es die Funktion entweder als Member von CRect oder als globale Funktion (und letztere erwartet 2 Parameter)

    Und laut MSDN gibt es auch IDC_HAND. Wenn ich in der winuser.h nachsehe wo die ganzen Cursor-Formen deklariert sind finde ich aber auch IDC_HAND. Komisch.

    Laut MSDN ist die IDC_HAND definiert für "Windows NT 5.0 and later" - was für ein System verwendest du? (und hast du auch diese Version der winuser.h eingebunden?)



  • Hallo CStoll.
    Bin wieder ein Stück weiter aber noch nicht am Ziel. Die OnMouseMove sieht nun so aus.
    Der cursor bleibt aber wie er ist.

    void CMousemoveDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
    CRect r;
    m_button.GetWindowRect(r); // m_button ist von hier DDX_Control(pDX, IDC_BUTTON1, m_button);
    ishand = (r.PtInRect(point));
    TRACE("\n das ist ishand == %i \n\n", ishand);

    if(ishand!=m_ishand)//Grenzüberschreitung
    {
    if(ishand)
    {
    m_default=::SetCursor(m_hand);
    }
    else
    {
    ::SetCursor(m_default);
    }
    m_ishand=ishand;
    }
    CDialog::OnMouseMove(nFlags, point);
    }

    Habe durch das TRACE festgestellt das ishand immer false bleibt.

    Habe nun die OnMouseMove folgendermassen umgeändert um ein reinspringen in die if zu erzwingen.

    void CMousemoveDlg::OnMouseMove(UINT nFlags, CPoint point)
    {
    CRect r;
    m_button.GetWindowRect(r);
    ishand = (r.PtInRect(point));
    TRACE("\n das ist ishand == %i \n\n", ishand);

    if(true)//Grenzüberschreitung
    {
    if(true)
    {
    m_default=::SetCursor(m_hand);
    }
    else
    {
    ::SetCursor(m_default);
    }
    m_ishand=ishand;
    }
    CDialog::OnMouseMove(nFlags, point);
    }

    Das Ergebnis ist das im Dialogfenster solange ein Cross-Cursor zu sehen ist bis ich über dem Button angelangt bin ab dann ist wieder der normale Pfeilcursor zu sehen.

    Zu diesem IDC_HAND. Ich habe hier Winxp Professional.
    Die winuser.h habe ich nun mal mit
    #include "winuser.h" eingebunden ohne das sich etwas ändert. Die anderen Cursor die in der winuser.h drinnen stehen gehen ja auch ohne das ich diese Datei extra einbinde.

    gruss zardoz


Anmelden zum Antworten