------ Create a coledropsource object to control the placement. For most applications, the default Implementation of the drag-and-drop function is enough. However, some applications may require changes to this standard behavior. Now you will see an example of changing the standard drag-and-drop behavior, which shows how simple it is. Maybe you will get some perceptual knowledge about custom drag-and-drop. On my toolbar, there is a button with the resource ID: id_drag_my_obj. After clicking this button, the drag-and-drop operation will begin (note, after you click this button, you have already clicked the lbuttondown and lbuttonup actions, instead of holding down the left mouse button without placing it). When the mouse moves in the view that accepts the drag-and-drop operation, the status is displayed as dragging and dropping, when you press the left mouse button in the view that receives the drag-and-drop operation, place the drag-and-drop data here. This operation is different from the standard drag-and-drop operation. How can we complete these operations? We should first prepare the required functions, step by step from the familiar default drag-and-drop to custom drag-and-drop. First, you need to respond to the function of this button. I put it in cmainframe, so cmainframe. cpp will add a function ondragmyobj () and a message ing on_command (id_drag_my_obj, ondragmyobj ):
Begin_message_map (cmainframe, uifoldtabframe )...
On_command (id_drag_my_obj, ondragmyobj)
...
End_message_map ()
...
Void cmainframe: ondragmyobj ()
{
// The specific implementation will be clearer later.
...
} Under the MFC framework, how does one accomplish a common drag-and-drop task? The target end places a coledroptarget object in the Form class that receives the drag-and-drop request and registers it through registerdragdropapi, implement the dragenter, dragovert, dragleave, and drop methods of the coledroptarget to process the dragging or placement of different mouse states in the receiving form, use revokedragdrop to cancel registration when the form does not need to receive any dragged data. The source end generates a coledatasource object and calls the dodragdrop method of the coledatasource object to start the drag-and-drop action. In this way, we started a drag-and-drop. We can also take a RichEdit as an example to illustrate the common drag-and-drop behavior. Please take a hard look at the following English: 1. whenthe mouse moves over a selected area of text it's cursor shape changes to anarrow. 2. whenthe left button is pressed, the selection is not removed. instead an internalstate is set to indicate that a drag-drop operation might be about to start. 3. whenthe mouse is first moved (and the internal state indicates that the Left buttonis curr Ently being held down inside a selected area of text), the drag and dropoperation starts. 4. atthis point, Ole takes over and handles all further mouse messages until theoperation is complete. 5. however, if the left button is released and the mouse didn't move at all, it is customaryfor the RichEdit's selection to be cleared and the text-caret positioned underthe mouse. next, let's take a look at the example of our expected implementation, according to the drag-and-drop General Is there a problem with the practice? If there is a problem, where is the problem?
To prepare the transmitted data, we have implemented a simple stringtohandle function. This function is used to convert a common char * string to the hglobal form so that it can be used in OLE.
Handle stringtohandle (char * sztext, intntextlen)
{
Void * PTR;
// If text length is-1 then treat as a NUL-terminated string
If (ntextlen =-1)
Ntextlen = lstrlen (sztext) + 1;
// Allocate and lock a global memory buffer. Make it fixed
// Data so we don't have to use globallock
PTR = (void *) globalalloc (gmem_fixed, ntextlen );
// Copy the string into the buffer
Memcpy (PTR, sztext, ntextlen );
Return PTR;
}
Then, let's modify the ondragmyobj function described above:
Void cmainframe: ondragmyobj ()
{
Hglobal hdata = stringtohandle ("Hello, world",-1 );
If (hdata! = NULL)
{
Coledatasource Ds;
DS. cacheglobaldata (cf_text, hdata );
Dropeffect de = Ds. dodragdrop (dropeffect_copy | dropeffect_move );
}
}
You only need to implement the dragenter, dragovert, dragleave, and drop methods for receiving drag-and-drop forms. I will not explain these methods in detail here, because you can find implementation examples of these functions in any drag-and-drop documents. Well, it should be said that the drag-and-drop code has been completed, but can it work correctly? No, at least not according to our requirements. To find out what the problem is, coledatasource is actually a big Butler, which uses dodragdrop to issue the commander. dodragdrop is actually the workflow of the big manager. Let's take a look at the coledatasource: dodragdrop parameter: dropeffect dodragdrop, this dropsource is a small worker under the coledatasource and will be arranged to do some chores in dodragdrop. if pdropsource is null The default dropsource. this is exactly what we use in the above Code. That is to say, the butler has a person who chooses coledropsource in advance. If no temporary employee can be found, coledropsource will do something he will do for us. Then, how does coledropsource help us do things? This is due to the querycontinuedrag function. I simplified it and removed unnecessary variables. Scode coledropsource: querycontinuedrag (boolbescapepressed, DWORD dwkeystate) {assert_valid (this); // check whether to press ESC or right-click? C. If yes, undrag and drop if (bescapepressed | (dwkeystate & mk_rbutton )! = 0) {m_bdragstarted = false; // avoid unecessary cursor setting return dragdrop_s_cancel;} // check whether the left mouse button is in the pop-up status, and execute the placement action if (dwkeystate & mk_lbutton) = 0) return m_bdragstarted? Dragdrop_s_drop: dragdrop_s_cancel; // otherwise, Ole continues to monitor the mouse status... Return s_ OK;} but why is there a wrong business trip? What is coledropsource doing? The reason is that coledropsource is actually a robot with no brains open. It does the same thing, just as it will do, and starts to drag and drop when the left mouse button is pressed, when the left mouse button pops up, the drag-and-drop operation ends and the manager is told to place the command. In the workflow dodragdrop, the manager sends the command to the next processor coledroptarget. What should I do? Since coledropsource's head is not open, we have to give the big manager a small engineer, which is actually another robot similar to coledropsource, it's just that he knows how to handle it based on the state of the mouse in the drag and drop. This robot is cmyoledropsource, classcmyoledropsource: Public coledropsource {public: cmyoledropsource (); Virtual ~ Cmyoledropsource (); Virtual scode querycontinuedrag (bool bescapepressed, DWORD dwkeystate) ;}; uioledropsource: uioledropsource () {} uioledropsource ::~ Uioledropsource () {} scodecmyoledropsource: querycontinuedrag (bool bescapepressed, DWORD dwkeystate) {assert_valid (this); // check whether to press ESC or right-click? C. If yes, undrag and drop if (bescapepressed | (dwkeystate & mk_rbutton )! = 0) {m_bdragstarted = false; // avoid unecessary cursor setting return dragdrop_s_cancel;} // check whether the left mouse button is pressed. If yes, the drag and drop ends, and execute the placement action if (dwkeystate & mk_lbutton )! = 0) return m_bdragstarted? Dragdrop_s_drop: dragdrop_s_cancel; // otherwise, Ole continues to monitor the mouse status... Return s_ OK;} Let's make the following changes to ondragmyobj. Void cmainframe: ondragmyobj () {hglobal hdata = stringtohandle ("Hello, world",-1); If (hdata! = NULL) {coledatasource Ds; DS. cacheglobaldata (cf_text, hdata); cmyoledropsourcedropsource; dropeffect de = Ds. dodragdrop (dropeffect_copy | dropeffect_move, 0, & dropsource) ;}