]>
Commit | Line | Data |
---|---|---|
1 | Drag-and-Drop Support in wxWindows | |
2 | ================================== | |
3 | ||
4 | 1. Overview | |
5 | -------- | |
6 | ||
7 | a) What is it? | |
8 | ||
9 | We're calling drag-and-drop (or d&d for short) the OLE mechanism of data | |
10 | transfer. Please note that it's not the same thing as the file oriented d&d | |
11 | of Windows 3.1 "File Manager" which is designed for and limited to the file | |
12 | names only. | |
13 | ||
14 | OLE d&d allows application to transfer data of any type to the same or | |
15 | another process. | |
16 | ||
17 | ||
18 | b) How is it done? (user's point of view) | |
19 | ||
20 | To start a d&d operation the user presses the mouse button 1 (left) and | |
21 | drags the selected object to another window (which must be at least partially | |
22 | visible on the screen) or to an icon on the taskbar in which case the | |
23 | corresponding window will be automatically restored. To finish the operation, | |
24 | the user releases the button. Default d&d operation is "move", but several key | |
25 | act as modifiers: keeping down the <Ctrl> key at the moment of drop does | |
26 | "copy", while <Shift> or <Alt> force the "move" (makes sense if default isn't | |
27 | "move"). | |
28 | ||
29 | ||
30 | c) How is it done? (programmer's point of view) | |
31 | ||
32 | There are several objects participating in a d&d operation. First of all, | |
33 | there is the data object itself. Second, there is the drop source which is | |
34 | responsible for creating the data object (if it doesn't exist yet) and starting | |
35 | the d&d operation. Finally, the drop target recieves the notification when | |
36 | the data is dropped onto the associated window (see below) and is responsible | |
37 | for pasting the data and returning the result code (copy, move or failure). | |
38 | There is one class for each one of these roles in wxWindows d&d implementation, | |
39 | plese see their descriptions below for details. | |
40 | ||
41 | ||
42 | ||
43 | 2. Drop Target | |
44 | ----------- | |
45 | ||
46 | a) Being a drop target | |
47 | ||
48 | ... is as easy as deriving your window class from wxDropTarget and | |
49 | associating it with a wxWindow object (or perhaps some wxWindow-derived class, | |
50 | such as wxFrame). The pure virtual function wxDropTarget::OnDrop() must be | |
51 | implemented in your application and will be called whenever the mouse button | |
52 | is released over the window in question. Other virtual functions that will be | |
53 | called in the process of the d&d operation are OnEnter and OnLeave. | |
54 | ||
55 | @@ should OnDragOver() be user overridable also? | |
56 | ||
57 | You should associate wxDropTarget and wxWindow calling SetDropTarget: | |
58 | wxWindow *pWindow = GetTopWindow(); | |
59 | pWindow->SetDropTarget(new MyDropTarget); | |
60 | ||
61 | The object created passed to SetDropTarget becomes the propriety of wxWindow | |
62 | and will be deleted with the window (or when you call SetDropTarget next | |
63 | time). You can always break the association by calling SetDropTarget(NULL). | |
64 | ||
65 | When some data is dragged over a window, the program must decide if it's | |
66 | going to accept this data or not. The virtual function IsAcceptedData() is | |
67 | called to do it. The default implementation takes care of OLE interface | |
68 | pointer manipulations and only requires you to override GetCountFormats() | |
69 | and GetFormat(n) functions to let it know what data formats you support. | |
70 | If it's not flexible enough for your application (i.e. the set of supported | |
71 | formats changes over time...), you should override IsAcceptedData(). In 99% | |
72 | of cases the default implementation is ok and you only have to return count | |
73 | of supported formats (CF_xxx constants or one of your custom formats which | |
74 | must have been registered) and their values. | |
75 | ||
76 | b) OnDrop(long x, long y, const void *pData) | |
77 | ||
78 | (x, y) are drop point (client) coordinates, pData is the pointer to data | |
79 | (whatever it is). | |
80 | ||
81 | If 'true' is returned from OnDrop, the operation is considered to be | |
82 | successful and the corresponding code (MOVE or COPY depending on the | |
83 | keyboard control keys) is returned. Otherwise, the operation is cancelled. | |
84 | ||
85 | Please remember that returning 'true' here may mean 'move' and so the | |
86 | drop source will delete the corresponding data - which would lead to | |
87 | data loss if you didn't paste it properly. | |
88 | ||
89 | c) OnEnter() | |
90 | ||
91 | called when the mouse enters the window: you might use this function to | |
92 | give some additional visual feedback. | |
93 | ||
94 | d) OnLeave() | |
95 | ||
96 | called when the mouse leaves the window; might be a good place to clean | |
97 | up things allocated in OnEnter. | |
98 | ||
99 | e) Simple wxDropTarget specializations | |
100 | ||
101 | Two (very simple) wxDropTarget-derived classes are provided for two most | |
102 | common situations: d&d of text and file d&d. To use them you only need to | |
103 | override one virtual function OnDropText in wxTextDropTarget's case and | |
104 | OnDropFiles for wxFileDropTarget. | |
105 | ||
106 | The (x, y) are the same as for OnDrop() function. OnDropText's last | |
107 | parameter points to a (always ANSI, not Unicode) text string, while | |
108 | OnDropFiles() parameter is the array of file names just dropped (and the | |
109 | count of them is passed in the 3rd parameter). | |
110 | ||
111 | 3. Data Object | |
112 | ----------- | |
113 | ||
114 | a) Drag and drop and clipboard | |
115 | ||
116 | The effect of a d&d operation is the same as using the clipboard to | |
117 | cut/copy and paste data and it would be nice to use the same code to implement | |
118 | these two data transfer mechanisms. The wxDataObject allows you to do exactly | |
119 | this. It encapsulates the data which can be passed either through the clipboard | |
120 | or d&d. | |
121 | ||
122 | ||
123 | b) Data format | |
124 | ||
125 | There are several standard clipboard formats, such as text, bitmap or | |
126 | metafile picture. All of them are defined in wxDataObject::StdFormats | |
127 | enumeration. Of course, it's not always enough and you'll often need your | |
128 | own format for data transfer. The simple helper class wxDataFormat may help | |
129 | you: when you create an object of this class, it registers a new clipboard | |
130 | data format identified by the string passed to it's ctor. | |
131 | ||
132 | After your new format is registered, you may use it as any other one. | |
133 | ||
134 | 4. Drop Source | |
135 | ----------- | |
136 | ||
137 | a) Starting the d&d operation | |
138 | ||
139 | In order to start the d&d operation you should call the DoDragDrop function | |
140 | (typically in reply to a "mouse button press" message). NB: DoDragDrop() is a | |
141 | blocking function which enters into it's own message loop and may return after | |
142 | an arbitrarily long time interval. During it, the QueryContinueDrag() is called | |
143 | whenever the mouse or keyboard state changes. The default behaviour is quite | |
144 | reasonable for 99% of cases: the drag operation is cancelled if the <Esc> key | |
145 | is preessed and the drop is initiated if the mouse button is released. | |
146 | ||
147 | b) After the end of d&d | |
148 | ||
149 | The drop source behaviour depends on DoDragDrop() return code. If it | |
150 | returns wxDropSource::None or wxDropSource::Copy there is normally nothing to | |
151 | do, but you shouldn't forget to delete your data if it returns the | |
152 | wxDropSource::Move code. | |
153 | ||
154 | c) DoDragDrop | |
155 | ||
156 | d) QueryContinueDrag | |
157 | ||
158 | ||
159 | 5. Remarks | |
160 | ------- | |
161 | ||
162 | ||
163 | @@@@ TODO: support tymed != TYMED_HGLOBAL; | |
164 | better support of CF_BMP, CF_METAFILE | |
165 | scrolling support!! (how?) | |
166 | sample demonstrating use of user-defined formats | |
167 | sample which really does something useful |