Hypercell ein ] Hypercell aus ] Zeige Navigation ] Verstecke Navigation ]
c++.de  
   
Forentreff 2012     
Bücher-Shop mit Amazon (Buchkategorien)C++ : Referenzen zu C++ : C++ Builder : Visual C++ : C# : Java : Spieleprogrammierung : Systemprogrammierung Linux : Software-Entwicklung : .NET : Compilertechnik : Algorithmen & Datenstrukturen : Objektorientierung : Entwurfsmuster : UML : eXtreme Programming : Scrum : Projektmanagement : Software-Testing : Datenbanken : Tom DeMarco : Dilbert : User Friendly
C/C++ Forum :: FAQ - MFC ::  CListCtrl - Drag & Drop     Zeige alle Beiträge auf einer Seite Auf Beitrag antworten
Autor Nachricht
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 14:14:00 05.03.2003   Titel:   CListCtrl - Drag & Drop            Zitieren

Hallo,
ich habe in einem Dialog 2 CListCtrl Objekte, und wich würde gern von der linken Liste mit Drag & Drop Einträge in die rechte ziehen. In der FAQ hab ich das
Drag&Drop mit CListCtrl gefunden. Ich hab eine Klasse CDropTarget von COleDropTarget abgeleitet, und als Member in meinen Dialog genommen. In OnInit hab ich CDropTarget auf meine 2. Liste registriert. Aber mit der Message OnLButtonUp komm ich nicht so ganz klar. Er geht da nur rein wenn ich die Mautaste im Dialog loslasse. Wenn ich sie über der 2. Liste loslasse passiert nix.
Kann mir da jemand noch nen Tip geben??


Zuletzt bearbeitet von estartu am 11:32:25 16.01.2006, insgesamt 1-mal bearbeitet
Werbeunterbrechung
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 14:31:00 05.03.2003   Titel:              Zitieren

Du musst COleDropTarget ableiten und OnDrop überschreiben
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 14:42:00 05.03.2003   Titel:              Zitieren

Danke für Deine Antwort aber,
ich hab eine Klasse CDropTarget von COleDropTarget abgeleitet.
In die Funktion OnDrop komm ich gar nicht rein.
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 14:52:00 05.03.2003   Titel:              Zitieren

Siehe
C++-Grundlagen->virtuelle Funktionen
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 15:15:00 05.03.2003   Titel:              Zitieren

was ne virtuelle Funktion ist weiß ich. Aber ich bekomm den Event gar nicht. Ich weiß nicht wie ich mein Dialog, die Liste und das COleDropTarget unter einen Hut bekomme. In der FAQ steht was von OnLButtonUp da komm ich rein aber nur wenn ich die Maus nicht über meiner Liste loslasse.
Gib deinem Herz einen Stoß :rolleyes: und gib mir einen Tip.
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 15:29:00 05.03.2003   Titel:              Zitieren

Der Tip war ok, Du hast ihn nur nicht verstanden!

Du bekommst doch den Event. Denn ab der Registrierung Deines CDropTarget in der 2. Liste werden alle DragEnter/DragOver/DragLeave/Drop-Ereignisse an die virtuellen Funktionen des COleDropTarget weitergeleitet!

Du musst dazu WM_LBUTTONUP nicht verarbeiten.
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 16:19:00 05.03.2003   Titel:              Zitieren

ich habs soweit glaub ich verstanden wie es theoretisch gehen soll. Aber den Event bekomm ich nicht.
Ich hab in meinem Dialog 2 CListCtrl Objekte als Membervariablen und eine Membervariable m_Drop (Objekt von COleDropTarget). Um die zu registrieren mach ich in OnInitDlg m_Drop.Register(&m_LstRechts). In der Hilfe steht wenn Register erfolgreich war kommt ein Wert <> 0 zurück (bei mir 1 also wohl OK). Dann hab ich noch in meinem Dialog die Funktion:
CDialog::OnLvnBegindragLinks(NMHDR *pNMHDR, LRESULT *pResult) da komm ich rein aber wenn ich die Maustaste wieder loslasse passiert einfach nix. :confused:
Bitte helft mir nochmal.
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 16:38:00 05.03.2003   Titel:              Zitieren

Also in BeginDragLinks erstellst Du (mit new) ein neues COleDataSource-Objekt, welchem Du das Item mitgibst, welches gerade unter der Maus liegt.
Dann rufst Du von diesem OleDataSource-Objekt DoDragDrop auf.
Damit springt er dann in eine Schleife, die solange ausgeführt wird, bis LBUTTONUP empfangen wird.
Bewegst Du jetzt die Maus auf Deine rechte Liste, ruft DoDragDrop OnDragEnter/OnDragOver des OleDropTargets auf. Dort werden dann normalerweise die Daten innerhalb der OleDataSource abgeprüft, ob sie für dieses Fenster gültig sind. Je nachdem gibt man dann eine der Konstanten
DROPEFFECT_NONE
DROPEFFECT_COPY
DROPEFFECT_MOVE
DROPEFFECT_LINK
DROPEFFECT_SCROLL
zurück.

Sollte der letzte bekannte Wert nun != DROPEFFECT_NONE sein, wenn die Maus losgelassen wird, wird die virtuelle Funktion OnDrop aufgerufen, in der dann das eigentliche Droppen passiert, also das ListCtrl-Item wieder aus der DataSource extrahiert und dann in die neue Liste eingefügt wird.
Danach wird das mit new angelegte DataSource-Objekt automatisch gelöscht.

[ Dieser Beitrag wurde am 05.03.2003 um 15:39 Uhr von RenéG editiert. ]
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 19:00:00 05.03.2003   Titel:              Zitieren

W A H N S I N N ich habs geschaft Vielen Dank.

Wenn du aber trotzdem noch etwas Lust hast, dann könntest du vielleicht noch etwas über dieses abgefahrene Objekt COleDataSource erzählen, z.B. wie man da Daten reinschreiben kann und wieder rausbekommt.

Ich habs mal so probiert:
C/C++ Code:
    COleDataSource* data = new COleDataSource;
    HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(int));
    hgData = &pNMLV->iItem;
    data->CacheGlobalData(CF_TEXT,hgData);
C/C++ Code:
COleDataSource* data = new COleDataSource;
HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(int));
hgData = &pNMLV->iItem;
data->CacheGlobalData(CF_TEXT,hgData);
C/C++ Code:
    COleDataSource* data = new COleDataSource;
    HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(int));
    hgData = &pNMLV->iItem;
    data->CacheGlobalData(CF_TEXT,hgData);

und um die Daten rasuzuholen hab ich :
C/C++ Code:
    HGLOBAL hgData = pDataObject->GetGlobalData(CF_TEXT);
C/C++ Code:
HGLOBAL hgData = pDataObject->GetGlobalData(CF_TEXT);
C/C++ Code:
    HGLOBAL hgData = pDataObject->GetGlobalData(CF_TEXT);

aber da fliegt er gnadenlos raus
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 09:24:00 06.03.2003   Titel:              Zitieren

Erstens darfst Du den mit GlobalAlloc erstellten Pointer nicht einfach so mit &iItem überschreiben, zweitens ist iItem kein CF_TEXT-Format und drittens darfst Du auch niemals einen nur im m_LstLinks definierten Index-Integerwert an irgendein Objekt weitergeben, welches schlimmstenfalls in einem anderen Prozess definiert ist.

Die Idee mit dem CacheGlobalData war aber schon nicht schlecht.

Als erstes definierst Du Dir ein eigenes Clipboard-Format mit RegisterClipboardFormat. Einer der beiden Werte, entweder der String-Parameter oder der Rückgabewert von RegisterClipboardFormat müssen dann auch dem rechten ListCtrl bzw. dem COleDropTarget bekannt gemacht werden.
Als nächstes lässt Du Dir ein Übergabeformat für ListCtrl-Items einfallen. Schlimmstenfalls haben diese mehrere Spalten, Icons oder Checkboxes. Je nachdem, wie komplex das ist, kannst Du natürlich auch das Handle des ListCtrls übergeben. Dazu muss allerdings dann das COleDropTarget wissen, dass es sich bei dem Handle um ein ListCtrl handelt, nehmen wir das mal in Deinem Fall an.

Jetzt ein Beispiel:

C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// global
const UINT CF_MYLISTRCTRL = RegisterClipboardFormat( _T("Mein ListCtrl"));

// in OnLvnBegindragLinks
COleDataSource* data = new COleDataSource;
HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(HWND));
HWND* pData = (HWND*)GlobalLock( hgData);
*pData = pNMLV->hdr.hwndFrom;
GlobalUnlock( pData);
data->CacheGlobalData(CF_MYLISTCTRL, hgData);

// In OnDrop
HGLOBAL hgData = pDataObject->GetGlobalData(CF_MYLISTCTRL);
HWND hWndListLinks = *(HWND*)GlobalLock( hgData);
GlobalUnlock( hgData);
if( !::IsWindow( hWndListLinks))
  return FALSE;
CListCtrl list;
list.Attach( hWndListLinks);
// hier dann die Selektion aus dem ListCtrl holen
// ...

list.Detach();
return TRUE;
// fertig
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// global
const UINT CF_MYLISTRCTRL = RegisterClipboardFormat( _T("Mein ListCtrl"));

// in OnLvnBegindragLinks
COleDataSource* data = new COleDataSource;
HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(HWND));
HWND* pData = (HWND*)GlobalLock( hgData);
*pData = pNMLV->hdr.hwndFrom;
GlobalUnlock( pData);
data->CacheGlobalData(CF_MYLISTCTRL, hgData);

// In OnDrop
HGLOBAL hgData = pDataObject->GetGlobalData(CF_MYLISTCTRL);
HWND hWndListLinks = *(HWND*)GlobalLock( hgData);
GlobalUnlock( hgData);
if( !::IsWindow( hWndListLinks))
return FALSE;
CListCtrl list;
list.Attach( hWndListLinks);
// hier dann die Selektion aus dem ListCtrl holen
// ...

list.Detach();
return TRUE;
// fertig
C/C++ Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// global
const UINT CF_MYLISTRCTRL = RegisterClipboardFormat( _T("Mein ListCtrl"));

// in OnLvnBegindragLinks
COleDataSource* data = new COleDataSource;
HGLOBAL hgData = GlobalAlloc(GPTR,sizeof(HWND));
HWND* pData = (HWND*)GlobalLock( hgData);
*pData = pNMLV->hdr.hwndFrom;
GlobalUnlock( pData);
data->CacheGlobalData(CF_MYLISTCTRL, hgData);

// In OnDrop
HGLOBAL hgData = pDataObject->GetGlobalData(CF_MYLISTCTRL);
HWND hWndListLinks = *(HWND*)GlobalLock( hgData);
GlobalUnlock( hgData);
if( !::IsWindow( hWndListLinks))
  return FALSE;
CListCtrl list;
list.Attach( hWndListLinks);
// hier dann die Selektion aus dem ListCtrl holen
// ...

list.Detach();
return TRUE;
// fertig
dscho
Mitglied

Benutzerprofil
Anmeldungsdatum: 18.05.2002
Beiträge: 176
Beitrag dscho Mitglied 11:03:00 06.03.2003   Titel:              Zitieren

Ich hab das ausprobiert wie du es hier beschrieben hast. Aber er fliegt raus
und zwar hier
CListCtrl list;
list.Attach( hWndListLinks); //fliegt raus
Ich hab ein wenig rumprobiert und hab dann die 2 Zeilen durch die ersetzt:
CListCtrl* list = (CListCtrl*)list->FromHandle(hWndListLinks);
Kann man das so machen??
Muß ich hier auch list->Detach machen ?? Wenn ich die Hilfe richtig verstanden habe dann brauch ich das nicht.

Zum Abschluß muß ich wohl noch sagen, dass du wohl der absolute C++ Gott bist den ich kenne. :)
Vielleicht sollte das hier in die FAQ
Vielen Dank nochmal.

[ Dieser Beitrag wurde am 06.03.2003 um 10:25 Uhr von dscho editiert. ]
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 11:39:00 06.03.2003   Titel:              Zitieren

Ja, muss man wohl so machen mit dem FromHandle.
Da ich in der letzten Zeit mehr mit der WTL/ATL arbeite, habe ich vergessen, dass das so geht ;)

Zitat:

Wenn ich die Hilfe richtig verstanden habe dann brauch ich das nicht.

Du hast die Hilfe richtig verstanden, da *list ja ein Zeiger ist und somit der CWnd-Destruktor nicht aufgerufen wird.

Zitat:

Zum Abschluß muß ich wohl noch sagen, dass du wohl der absolute C++ Gott bist den ich kenne.

Danke, aber diese Ehre gebührt mir nicht. In C++ bin ich gar nicht soooo gut. Kenne mich nur mit bestimmten Windows-APIs ganz gut aus.
RenéG
Mitglied

Benutzerprofil
Anmeldungsdatum: 22.06.2000
Beiträge: 4357
Beitrag RenéG Mitglied 11:40:00 06.03.2003   Titel:              Zitieren

Ok, is was für die FAQ !
C/C++ Forum :: FAQ - MFC ::  CListCtrl - Drag & Drop   Auf Beitrag antworten

Zeige alle Beiträge auf einer Seite




Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Sie können keine Beiträge in dieses Forum schreiben.
Sie können auf Beiträge in diesem Forum nicht antworten.
Sie können Ihre Beiträge in diesem Forum nicht bearbeiten.
Sie können Ihre Beiträge in diesem Forum nicht löschen.
Sie können an Umfragen in diesem Forum nicht mitmachen.

Powered by phpBB © 2001, 2002 phpBB Group :: FI Theme

c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de Werbekostenerstattung verdient werden kann.

Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt (vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden. Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.