Events für checkboxen im CTreeCtrl

JanZmus

Grünschnabel
Hallo,
ich habe einen CTreeCtrl mit Checkboxen vor jedem Eintrag (TVS_CHECKBOXES -Style). Jetzt suche ich ein Event, dass mir angibt, bei welchem Item ich gerade die Checkbox geklickt habe, aber so ein Event scheint es nicht zu geben.
Ich kann doch nicht jedesmal, wenn ich in meinem TreeView klicke ALLE Einträge durchgehen und mir CTreeCtrl->GetCheck() ausgeben lassen (und mir auch noch alle states merken um zu sehen, ob sich was an der Checkbox geändert hat) ?

vielen Dank,
Jan Zmus
 

MCoder

Erfahrenes Mitglied
Es gibt tatsächlich keinen Event dafür. Du musst einen Handler für OnClick... beim CTreeCtrl einfügen und dort prüfen, ob auf eine Checkbox geklickt wurde.
Code:
// Inhalt des OnClick-Handlers
// m_tree ist das CTreeCtrl-Objekt

NMTREEVIEW *pNM  = (NMTREEVIEW *)pNMHDR;
POINTS     pts   = MAKEPOINTS(::GetMessagePos());
UINT       nFlags;

HTREEITEM hItem = m_tree.HitTest(CPoint(pts.x, pts.y), &nFlags);

if( hItem && (nFlags & TVHT_ONITEMSTATEICON) )
{
    if( m_tree.GetCheck(hItem) )
    {
        // ...
    }    
}

*pResult = 0;
 

CodeFatal

Erfahrenes Mitglied
Moin Moin, Ich mal wieder,

hab gerade das selbe Problem gehabt wie JanZmus, und bin dankbar für die Antwort.

zwar jetzt allerdings nicht ohne Probleme.
1)
Code:
POINTS     pts   = MAKEPOINTS(::GetMessagePos());
muss ich als
Code:
DWORD r=::GetMessagePos();
	POINTS pts = MAKEPOINTS(::GetMessagePos());
schreiben
sonst erhalte ich den Fehler
"error C2102: '&' erwartet L-Wert"

2)
Ich bekomme die Koordinaten als Screen Koordinaten und muss die einmal noch durch die ScreentoClient Funktion jagen.

Daher meine Fragen: Wo ist der Sinn bei 1) den verstehe ich mal garnicht. :confused: Und ist die Transformation der Koordinaten wirklich nötig?

Gruß Michael
 

MCoder

Erfahrenes Mitglied
Du hast recht, in der Form konnte es nicht funktionieren. Da hatte ich Murks zusammengeschrieben :-( .
Man muss das Ergebnis von "GetMessagePos()" erst in einer Variablen speichern, bevor man MAKEPOINTS vewendet. Und die Koordinatentransformation hatte ich glatt unterschlagen.
Alternativ zu MAKEPOINTS kann man auch mit LOWORD, HIWORD die X/Y-Positionen herauslösen.
Der folgende Code sollte jetzt aber richtig funktionieren:
Code:
NMTREEVIEW *pNM  = (NMTREEVIEW *)pNMHDR;

DWORD      dwPos = ::GetMessagePos();
CPoint     pt(LOWORD(dwPos), HIWORD(dwPos));        

m_tree.ScreenToClient(&pt);

HTREEITEM hItem = m_tree.HitTest(pt, &nFlags);
UINT      nFlags;

if( hItem && (nFlags & TVHT_ONITEMSTATEICON) )
{
    if( m_tree.GetCheck(hItem) )
    {
        // ...
    }    
}

*pResult = 0;

Der OnClick-Event wird ausgelöst, wenn irgendwo auf dem Item geklickt wird. Um speziell die Checkbox zu testen, müssen daher die genauen Maus-Koordinaten beim Auslösen des Events bestimmt werden. Das ist der Sinn der GetMessagePos()-Geschichte.

Die Koordinatentransformation ist nötig, weil HitTest (stellt fest, auf welchen Bereich des Items denn nun geklickt wurde) mit Client-Korrdinaten arbeitet, GetMessagePos() aber Screen-Koordinaten liefert.

Kleine Ergänzung: Gemeinerweise wird die Checkbox erst geändert, wenn der OnClick-Code "durch" ist. Daher muss bei GetCheck() immer "andersherum" getestet werden.
 
Zuletzt bearbeitet:

CodeFatal

Erfahrenes Mitglied
Danke für die Erklärung. Hatte das auch so gelöst. Mich hatte es nur gewundert, wieso es bei JanZmus funzte und ich da noch was ändern musste. Nach den Änderungen funktioniert es bei mir aber auch super...
Die Erklärung dürfte auf jeden Fall anderen weiterhelfen.

Gruß Michael
 
T

Typhlosion

Gibt es denn auch eine Möglichkeit, die Checkbox abzufragen, wenn der Benutzer anstatt die Maus zu bewegen die Tastatur verwendet (Leertaste)?
Weil das Click-Event ja dann nicht ausgelöst wird...
 

MCoder

Erfahrenes Mitglied
Man müsste auf die TVN_KEYDOWN-Message reagieren und kann dann die CheckBox des jeweiligen Items abfragen.

Gruß
MCoder
 

Neue Beiträge