Changing Cursor depending on drop position within a RichTextBox

robertb_NZ

Well-known member
Joined
May 11, 2010
Messages
146
Location
Auckland, New Zealand
Programming Experience
10+
I have a RichTextBox representing a program. It is enabled for Drag&Drop, items can be dragged around, and new items can be dragged to it. However some drop positions are invalid, so I?d like to change the cursor between DragDropEffects.None and DragDropEffects.Move, rather than just producing an error message (which is my interim solution).

I can calculate DropValid = True/False from the mouse position, but I can?t find an event to use this to do what I want. MouseMove doesn?t fire once a DragDrop has started, DragEnter fires only once, and a RichTextBox has no DragOver or similar event. So what do I do? RichTextBox doesn't enable GiveFeedback, so most of the posts that I have found don't seem applicable.

Any help gratefully accepted.
Robert.
 
I have a RichTextBox representing a program. It is enabled for Drag&Drop, items can be dragged around, and new items can be dragged to it. However some drop positions are invalid, so I?d like to change the cursor between DragDropEffects.None and DragDropEffects.Move, rather than just producing an error message (which is my interim solution).

I can calculate DropValid = True/False from the mouse position, but I can?t find an event to use this to do what I want. MouseMove doesn?t fire once a DragDrop has started, DragEnter fires only once, and a RichTextBox has no DragOver or similar event. So what do I do? RichTextBox doesn't enable GiveFeedback, so most of the posts that I have found don't seem applicable.

Any help gratefully accepted.
Robert.

You're going to have to find an event or sequence of events that indicate the start of your dragging, for example when I select some text inside a RTB and drag it, a MouseCaptureChanged immediately followed by a MouseLeave occurs. By using a class-wide boolean (that is normally false, you toggle it to true in MouseCaptureChanged, you toggle it to false and toggle another ("_dragIsOccurring") to true in MouseLeave) you can detect the sequence of events. At this point youre probably going to ahve to do something nasty, like starting a timer that polls the mouse position (System.Windows.Forms.Cursor.Position) on the screen, and knowing the RTB's position on screen (a function of form position on the screen and rtb position within the form) you can work out where the cursor is. Another (sequence of) event(s) occurs (mouse enter, followed by hover if the user is still, but you might only need the enter) occurs when an item is dropped, this can turn off your timer and set things normal. It's also harmless to do these things when the mouse enters in the sense of it rolling into the RTB for the first time

Note, I've written this post from the perspective of selecting some text inside anRTB and dragging it to somewhere else. THe sort of dragging youre talking about might be different. For what it's worth, my opinion on situations where you come up against the incredibly difficult and have to resort to nasty hacks; the solution needs throwing away and another approach creating. Not knowing anything about what you're envisaging and why you felt an RTB was the best choice (are you simulating some dos text program? If youre building a simulation of a GUI I probably wouldnt have used RTB..) I can't comment further, but perhaps would advise to be really critical about whether this approach with these components is the best way
 
Thanks cjard. I see why nobody else has replied. This is a difficult problem.

Let's see if I can explain what I'm doing, then we can hopefully discuss the best approach. As you say, this may not be RTB.

Background
I am developing a software product MANASYS Jazz, primarily aimed a programming mainframe computers. You write a Jazz program, this is translated into COBOL which then is compiled and run. See Jazz Software for more information.

I am currently implementing a feature that allows users to place data on to a report to graphically create the report that they want. Think Crystal Reports, but implemented by creating a COBOL program that, when compiled, will access VSAM and Sequential files on the mainframe to produce the report that they want.

When users are editing the report, the Window that they're working with looks like this: -
ReptEdit.jpg

The left-hand panel shows the data defined (so far) within the program. You can drag a field from this Treeview to the right-hand panel where the layout simulates a report page, with a ruler line at the top, various section markers, and lines within each section. I have uses a RichTextBox for the report page.

Suppose you click on Region and drag it into the report. It cannot be dropped on the ruler or marker lines, and it cannot be dropped on top of a field that is already in the report, but it can be dropped in any spare position (shown by "....") or on the line marked "+Add another line"

The question of this posting is "Can I change the cursor as it moves across the report pane?" Perhaps I should not use an RTB, but if so, what?

Thank you for your time,
Robert.
 
Had a play around with a few things, and the simplest hack(though it may have some caveats) would actually be to place transparent panels (or other controls) on top of your report covering regions where you don't want a drag to drop

To see this in action lash a new form into a test project, drop a rich text box on the form and then a label on top of it, run the app, scribble some text in the RTB and then highlight it and drag it over the label..

Consider that your label can have the same text font colour and background as your existing RTB elements and you could occlude parts of it with non-drop controls just by programmatically arranging them on top

If your ruler is to be a permanent feature it could go above the RTB with the fixed ruler text in it.. make it part of the same scrolling panel the rtb has and let the panel manage scrolling

With a fixed height and width font in the RTB you could mathematically work out where to place your overlay labels when the RTB is dragged into(or a tree drag begins)

However, for best results, consider:

Allowing the drop to succeed and if the position is illegal, colour it red, show a warning "field cannot be dropped here" etc
or
Implement your own report designer using a panel in flow/table layout and controls that are dropped. It's a lot of work, i'll admit

What about using a solution that someone else has already rolled and picking apart/enumerating its contents when save is pressed? https://documentation.devexpress.com/#XtraReports/CustomDocument2557 for example -> creates a winforms app that contains a reports deisgner
 

Attachments

  • Capture.PNG
    Capture.PNG
    1.6 KB · Views: 37
cjard, thank you very much. I really appreciate the effort that you've gone to to understand my problem and find a solution.

In the meantime I'll use the simple suggestion of producing a message if the drop if illegal. I've also changed the layout so that the top ruler has disappeared, but reappears on each "+Add another line" where dropping is valid, so now the only "invalid to drop" are the section markers and existing fields: surely not too difficult for a user to learn. I've recorded this thread, and I'll come back to when I've solved some other problems such as: "How to handle fields with dimension"
report.jpg

Thank you, Robert
 
Small tip, in terms of UI design, avoid the temptation to put a MessageBox telling the user that they dropped a field in an illegal place; they're very disruptive to the UI/work flow and could reasonably happen quite often. Coloring the illegal field, and showing a message in a normal label near the reports designer would be less disruptive to the user experience
 
Thanks Cjard, in this case the error message is shown in a normal label on the form with red message text. I try to use Msgbox only when I actually want to disrupt the flow, for example "Do you want to delete the whole line" Yes/No. Your point is valid however: I'm sure that I haven't always designed the UI well, and my software would benefit from more user exposure and feedback.
 
Back
Top