Fragensteller
Wer weis mehr über IDragSourceHelper::InitializeFromWindow

Frage
-
Hallo,
falls ich hier falsch sein sollte, so bitte ich um einen freundlichen Hinweis.
Ich verwende die Methode IDragSourceHelper::InitializeFromWindow um für Drag & Drop das DragImage erzeugen zu lassen.
In der MSDN Doku steht unter Parameter die folgende Beschreibung:
hwnd [in] Type: HWND A handle to the window that receives the DI_GETDRAGIMAGE message. This value can be NULL.
Interessant ist der letzte Teil "This value can be NULL".Und zwar dann, wenn man Dateien per Drag&Drop kopieren/verschieben will und diese (und das ist unbedingt erforderlich) mit
CFSTR_SHELLIDLIST = "Shell IDList Array" zusätzlich zu CF_HDROP in das IDataObject bzw. ins Clipboard geschrieben hat.
Dann wird bei Übergabe von NULL für hwnd ein wunderschönes DragImage vollautomatisch erzeugt und zwar genau so wie es auch der Windows Explorer macht. Hat man mehrere Daten vorher ins Clipboard geschrieben, so wird auch aus allen Datei-Icons ein Image zusammengebaut mit der Anzahl aller Dateien in der Mitte. Es sieht wirklich super aus, bei minimalem Aufwand an Code.
Getestet habe ich das allerdings nur mit Windows 7, vermute aber dass diese Funktionalität bereits seit Vista existiert.
Mit XP geht es definitiv nicht.
Hat jemand mehr Informationen darüber oder einen Tip wo ich nachschauen könnte?
Im Moment sieht es für mich eher nach einer undokumentierten Funktion aus.
Dann gibt es da noch ein Problem, dass ich bisher nur unschön lösen konnte.
Bei manchen Dateiarten z.B. .PDF rendert er doch tatsächlich den Inhalt des Dokuments und zeigt diesen dann als mini Bild im Dragimage an.
Das ist zwar ganz nett, dauert aber manchmal einfach zu lange.
Der Windows Explorer macht das allerdings nicht. Er zeigt immer nur das der Dateiart zugeorgnete Icon an.
Leider finde ich keine Möglichkeit, wie ich das Verhalten vom Windows Explorer elegant ereichen kann.
Man müsste irgendwie erreichen, dass grundsätzlich keine Dragimages aus dem Dateiinhalt rendert werden.
Das Einzige was ich bisher gefunden habe ist mit der Funktion SHGetSetSetting() vor dem Aufruf von DODragDrop() den Schalter SSF_ICONSONLY zu setzen. Das führt zwar zum gewünschten Ziel, hat aber leider Nebenwirkungen. Es werden nämlich unzählige WM_SETTINGCHANGE Nachrichten an alle geöffneten Fenster geschickt, was bei manchen Fenstern durch ein leichtes kurzes Flackern zu sehen ist.
Da der Windows Explorer dieses Verhalten nicht zeigt, muss es offenbar noch andere Lösungen geben.
Googeln brachte leider nichts Verwertbares zu Tage oder ich stelle die falsche Fragen.
Wäre toll, wenn mir jemand weiterhelfen könnte.
Sven
- Bearbeitet Sven IB Mittwoch, 23. November 2011 19:51
Alle Antworten
-
Soweit ich es weiß verwendte der Explorer hier niemals NULL sondern gibt hier immer das entsprechende List Control an.
Vielleicht hilft Dir diese Diskussion:
http://www.ureader.com/message/1283952.aspxIch kenne auch nur COde, der hier ein Fenster angibt, wie diesen:
http://www.codeproject.com/KB/wtl/wtl4mfc10.aspx
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de -
Erstmal vielen Dank für Deine Antwort.
Die beiden Links waren mir bekannt, aber sie führen hier leider nicht weiter.
Vielleicht habe ich hier etwas gefunden, was wirklich undokumentiert ist und keiner weiss etwas darüber.
Obwohl , bei der Funktion SHDoDragDrop() habe ich folgenden Hinweis gefunden:
- As of Windows Vista, if a drag image is not already stored in the data object pdtobj and a drag image cannot be obtained from the window specified by hwnd, the Shell provides a generic drag image. A drag image can fail to be obtained from the specified window either because hwnd is NULL or the specified window does not support the DI_GETDRAGIMAGE message.
Da ich fest davon ausgehe, das SHDoDragDrop() intern auch IDragSourceHelper::InitializeFromWindow aufruft, gilt dieser Remark sicherlich auch für IDragSourceHelper::InitializeFromWindow.
Ich hoffte eben, dass dazu doch irgendwo noch mehr Dokumentation zu finden sein muss.
Ich glaube aber, dass das was ich meine noch nicht ganz klar geworden ist, deshalb hier nochmal kurz mit Bildern.
Wenn man, so wie vorgeschlagen, das Handle des ListView Controls an InitializeFromWindow() übergibt, dann sieht das DragImage bei mir so aus:
oder bei Multiselect so:
Fortsetzung in nächster Antwort
- Bearbeitet Sven IB Donnerstag, 24. November 2011 13:56
-
Wenn man aber einfach nur NULL an InitializeFromWindow (::InitializeFromWindow(NULL, NULL, oIDataObject)) und gleichzeitig vorher alle selektierten Dateien in als CFSTR_SHELLIDLIST ( "Shell IDList Array") Clipboard-Format in das oIDataObject schreibt, dann wird vollautomatisch folgendes DragImage erzeugt:
Für eine Einfachselektion sieht es dann so aus:
Dieses doch sehr ansprechende DragImage entspricht genau dem Verhalten vom Windows-Explorer von Windows 7 und das mit minimalem Aufwand (wenn man mal vom Erzeugen von CFSTR_SHELLIDLIST absieht).
Fortsetzung nächste Antwort
-
Wie ich am Anfang dieses Threads geschrieben hatte, bekomme ich dies aber nur durch einen etwas unsauberen Trick hin, in dem ich mit SHGetSetSettinggs() das Flag SSF_ICONSONLY während der DoDragDrop() Schleife temporär setze.
Mache ich dies nicht, so wird bei einigen Dateiarten (hier bei PDF's) das Image aus dem Inhalt der Datei gerendert und das sieht dann z:B. so aus:
Wie gesagt sieht es ja ganz schön aus, doch dauert es einfach meist zu lange und das stört dann mehr als es nützt.
Deshalb hat man es beim Windows Explorer 7 dann wohl auch abgeschltet.
Die Frage ist nur wie machen Sie es?
Mit der Funktion SHGetSetSettings() jedenfalls sicher nicht. Zur Erinnerung:
- Das führt zwar zum gewünschten Ziel, hat aber leider Nebenwirkungen. Es werden nämlich unzählige WM_SETTINGCHANGE Nachrichten an alle geöffneten Fenster geschickt, was bei manchen Fenstern durch ein leichtes kurzes Flackern zu sehen ist.
Die Preisfrage ist jetzt, welche anderen Möglichkeiten könnte man noch probieren?
Sven
-
Hallo Sven.
Ich hänge gerade am gleichen Problem. Konntest Du es mittlerweile lösen?
SHGetSetSettings() ändert Einstellungen ja global (bezogen auf die Session) und nicht pro Anwendung, wenn ich das richtig verstehe, daher kann es ja nicht die intendierte Lösung sein.
Viele Grüße ...
Joachim