Membres inscrits :2359
Membres en ligne : 0 Invités en ligne : 3 |
Suite à une question sur le forum, voici un snippet sur d&d d'objets complexes.
Pour commencer, c'est quoi un objet complexe dans ce cadre précis ? Pour simplifier la vie des petits codeurs que nous sommes, wxWidgets intègre des objets permettant de faire des d&d des formats les plus courants : un chaine de caractère (wxTextDataObject), une liste de fichier (wxFileDataObject) ou une image (wxBitmapDataObject). Tous les autres formats sont des objets complexes ! Voici comment se présente le snippet : 1. Explication du d&d avec wxWidgets 2. La classe contenant les données à transférer 3. La classe créant les données à transférer 4. La classe recevant les données à transférer 5. Remarques divers Pour illustrer ce snippet, je crée un d&d qui transfère plusieurs variables différentes : un int, un double, un pointeur, une chaine de caractère (je verrais plus tard pour ajouter le transfère d'image et de liste de string). Il est également possible d'exporter (application vers extérieur) des strings.
1. Comment fonctionne les d&d avec wxWidgets
Rien de particulier dans le fonctionnement général : une source (wxDropSource) crée un objet contenant les données à transférer (wxDataObject), une cible (wxDropTarget) reçoit cet objet et traite les données reçues. Une particularité à signaler : lors de la création de la cible (wxDropTarget), un objet vide est crée (wxDataObject). Lors du d&d, un tampon en mémoire est créer, contenant une copie des données à transférer. Ce tampon est utilisé pour transférer les données entre l'objet crée lors du d&d et contenant les données et l'objet crée lors de la création de la cible. A charge au codeur d'écrire les fonctions qui lisent et écrivent les données sous forme de tampon. Pour simplifier le code, je passe simplement un pointeur sur l'objet pour les d&d internes. 2. L'objet à transférer L'objet à déplacer dérive de wxDataObjet. Cet objet contient les informations à transférer entre la source et la cible. le format (wxDataFormat) permet de définir le type de données qu'il est possible de lire (Get) ou d'écrire (Set). Par exemple, dans le cas présenté, il est possible de définir 2 formats : le format "MyDataObject" utilisé en interne pour copier les données et le format par défaut "wxDF_TEXT" permettant le d&d du nom de fichier seul (wxString) versl'extérieur de l'application. Code wxWidgets:#include <wx/wx.h> 3. La source La source peut être n'importe quel objet qui réagisse à un clic souris. En général, ca sera un objet dérivé d'un wxWindow. Lors d'un clic souris (par exemple un EVT_LEFT_DOWN), On crée un objet de type décrit en 1. Certaine classe possède des events spécifique pour les BeginDrag (par exemple "EVT_LIST_BEGIN_DRAG" pour wxListCtrl). Code wxWidgets:class MyDlg : public wxDialog 4. La cible La cible dérive de wxWindow. On crée une classe dérivée de wxDropTarget qui se charge de traiter les données transmises. Puis on "active" la cible avec la fonction SetDropTarget. Code wxWidgets:#include <wx/dnd.h> et dans la classe cible : Code wxWidgets:class MyDlg : public wxDialog 5. Remarques divers Voici ce qui se passe en pratique : 1. A l'initialisation : - création du dialog (MyDlg::MyDlg...) - création du control source (new wxListCtrl...) - création du control cible (new wxListCtrl...) - activation de la cible (SetDroptarget...) Un objet MyDropTarget contenant un object MyDataObject est créé. 2. Lors du "begin drag" (EVT_LEFT_DOWN) : - appel de la fonction OnBeginDrag (lié au EVT_LEFT_DOWN) - création d'un wxDataObject contenant les informations de la source à transmettre (MyDataObject data...) - création d'un wxDropSource (wxDropSource source...) - on laisse la main au système pour gérer le d&d (source.DoDragDrop(true) ![]() 3. Lors du "end drag" (aucun event associé) : - appel de MyDropTarget::OnData() de l'objet MyDropTarget créé lors de l'initialisation (lors du SetDropTarget). On a donc 2 objets MyDataOject : celui créer lors de l'initialisation (vide, lié à l'objet MyDropTarget) et celui créé lors du "begin drag" (contenant les informations). Les fonctions GetDataHere et SetData sont appelée pour transférer les données entre les 2 objets MyDataObject (sous forme d'un tampon mémoire de taille "MyDataObject::GetDataSize") - appel de MyDropTarget::OnDrop(). Les données transférées sont récuérable grace a la fonction MyDropTarget::GetDataObject(). Cette fonction appelle (ici) la fonction MyDlg::OnDrop() pour créer le nouvel item. - Le transfert d'une wxString par buffer (dans les fonctions GetDataSize(), GetDataHere() et SetData()) est plus complexe que ce que j'ai écris. En particulier, il peut être nécessaire d'utiliser différentes implémentation en fonction des constantes de compilation wxNEEDS_UTF8_FOR_TEXT_DATAOBJ, wxUSE_UNICODE_WCHAR, wxUSE_UNICODE_UTF8, wxNEEDS_UTF16_FOR_TEXT_DATAOBJ... (voir le fichier common/dobjcmn.cpp pour les différentes implémentations : http:/trac.wxwidgets.org/browser/wxWidg … objcmn.cpp)
J'espère que cet exemple aidera ceux qui utilise le d&d.
|