Why do CursorPositionChanged events stop flowing when I turn off IsUserSelectionEnabled? - winforms

I want the user to be able to click on a Chart to relocate the X axis cursor. When the user does this, calculations need to occur and other controls need to update with new information. So I wrote a CursorPositionChanged handler in my main Form. It worked.
But I don't want the user to select a range, or have the chart zoom in along the X axis in case the user accidentally drags the mouse while attempting to just click. So in the GUI designer I set the chart's IsUserSelectionEnabled to false, leaving IsUserEnabled true.
Now I get no CursorPositionChanged events! Why?
As far as I understand, I'm doing this right, but am no expert on WinForms. Is there some other setting I need to deal with?

I can verify your issue and can only offer a work-around.
Use the Chart.CursorPositionChanging Event instead of the Chart.CursorPositionChanged Event as the CursorPositionChanging event fires. They both supply a CursorEventArgs parameter.
I don't know why I bothered linking to the worthless documentation, but maybe someday it won't be worthless.

Related

When does each event occur in WinForms

As I am trying to make my own custom "WinForms", I am left confused on when does each mouse event occurs. I have made my own custom classes, but now the events are something I have to rework, as they won't work right.
I have a custom class for controls. Objects from that class can contain other controls, which can contain other controls and so on. There is a main control, which gets input from a picture box. That input is what is where the mouse is and what even has been activated in the picture box.
So far I have figured, that MouseMove, MouseHover and MouseDown events are the simplest to write, as they occur in simple conditions. But the rest require additional data about the mouse's location, state and past. MouseDoubleClick seems to activate after a specific sequence of events (strictly down-up-down-up, down-up-down-move-up and down-up-down-move-leave-enter-move-up, with the movement events not activating). With that in mind, I am even more confused.
In what conditions and sequences does each mouse event occur?
EDIT
Further testing made things even more confusing. For one, now I want to know at what rate is the MouseMove being registered, and testing it shows that between each event there is a different time (or so does my use of a StopWatch say). This is important, because then that raises the question when is Hover being triggered.
Click is down-up, where moving is allowed between the two.
DoubleClick proved to be simple enough - down-up-down-up, where moving is allowed explicitly only between the second down-up.
Hover activates only once after each Enter, when the mouse remains stationary; if you want to trigger Hover again, the mouse has to leave and then re-enter.
So the question now is how the system tracks the mouse's activity - how does it detect the mouse moving, being held down and being released. Hopefully that would help me get the full answer.

Cannot change cursor in a WinForms control at designt time

We have a WinForms control (inherits Systems.Windows.Forms.Control) with a custom designer attached to it (inherits ControlDesigner). We need to process some mouse events like clicks in a special area inside our control at design time. To indicate that mouse click is available in that area, we need to change the default 4-arrow cursor to something else - at least, to the standard arrow, but we could not find a way to do that.
We redefined the ControlDesigner.GetHitTest method to return true for that special click rectangle, but the cursor simply flashes when it is over the area. It is changed to the default arrow for some milliseconds, and then back to the 4-arrow cursor which implies the whole control can be selected and moved on the form. Overriding ControlDesigner.OnSetCursor does not have any effect as it seems this virtual method is called only when the cursor is changed to the default 4-arrow cursor. Games with WndProc (trying to intercept WM_MOUSE* events) did not get us any positive results too.
Even when we try to implement samples from related books (like the SimpleLineControl from Eric White's "GDI+ Programming-Creating Custom Controls Using C#"), we have the same behavior.
Our dev env is VS2010/.NET 4.0 which is the minimal requirement. How to make it work in this and later environments?

How to indicate allowable drage & drop targets?

I'm considering a UI design (using WPF), but I'm not sure how to implement a critical feature: The user will be assigning needs to resources. There are some rules about what assignments can be made, such as compatibility and availability. I would like to display a list of resources, and a list of needs. The user can make an assignment by dragging a need and dropping it onto an resource.
What I would like to do is show the user what possible assignments can be made by highlighting all assignable resources for a given need. This should be done when dragging any given need.
(I'm comfortable performing the highlight using a property on the resource ViewModels and triggers in XAML, and performing the drag & drop action.)
I don't see any events that are generic to dragging starting or stopping; they are either relevant to the source element, or to elements that are actively being dragged over. How can I evaluate a method to evaluate compatibility on every resource item when a drag is started?
EDIT:
As I am thinking about this more, it might be better to perform the highlighting function upon selection of the item rather than the start of dragging. As the items will typically be in ListViews or TreeViews, dragging will also cause the item to become selected. Additionally, the user will not have to initiate and hold a drag while considering their choices. As the list of targets may be long, the user may need to scroll to find one they want, which is not practical while dragging.
I can easily listen for the SelectionChanged events to evaluate the potential drop targets.
In WPF the drag drop services are well defined along with indicating applicability of which are valid draggable and droppable visuals for the dragged data.
http://msdn.microsoft.com/en-us/library/ms742859.aspx
EDIT
As per your requirement you need to indicate \ highlight \ focus valid droppable targets when drag starts.
For this the droppable visuals must register themselves for the type of data that is getting dragged. All drop targets will thus be notified when such data that they have registered for is getting dragged i.e. in DragDrop.DoDragDrop(..., <dragged data>, ...) call.
Now this is tricky, but you could use Clipboard services to hold the dragged data. The registered target visuals will be notified by the same Clipboard service when such data is added to the clipboard. You could have a command CanExecute() that constantly executes on the drag - drop view and checks the clipboard data is of the registered data type. If so it will set some view model based boolean property that has been attached against all those valid drop targets to true, that will highlight them thru the attached behavior.
In the case of falling back (drag or drop lost), the clipboard must be cleared.
But ofcourse this is easy said than done.... but worth a try.
While I have updated the question with my plans to pursue another UI approach (highlight upon selection), I have still been pondering what I perceive as a shortcoming in the WPF Drag & Drop services.
Suddenly I realized that the start of dragging calls my code in order to get the data being dragged. I can do whatever I want there, including the triggering of any additional UI effects! With this, it seems a little silly to expect such functionality in the DragDrop class...

Drop outside the control

I'm improving standart WPF TabControl. I want to add undocking functionality to it:
user drags the page just outside the TabControl and this page undocks in the window.
I want two events in this control - PageDragStart (raises when the page dragged outside) and PageDragEnd (raises when the page dropped outside)
I've got no problem with the first event.
But the second... OnDrop doesn't call, because the item dropped outside the tabcontol container. How can I know that it was dropped?
P.S. I want a universal control (so, undocking functionality shouldn't be connected and hardcoded with the window tabcontrol is placed or something like this)
Why use DoDragDrop at all? As I was reading your description, using Mouse.Capture by itself seemed the obvious solution:
Handle OnMouseLeftButtonDown on the tab and start capture
Handle OnMouseMove on the tab and update the cursor based on hit testing
Handle OnMouseLeftButtonUp on the tab, and stop the capture and make the appropriate change
The reasons you might ever consider DoDragDrop over simple mouse capture are:
Integration with Windows' OLE drag and drop so you can drag and drop between applications and technologies
Modal nature of DoDragDrop call (which actually seems to be more of a disadvantage to me)
Automated hit testing of targets
Standardized "drop operation" API to allow unrelated applications to handle copy vs move, etc.
You apparently don't need the OLE integration or multi-application support and you want to customize the hit testing, so it seems that DoDragDrop has no advantages over directly handling the mouse capture.
I solved the problem - in rather brutal and unsafe way. But for it's gonna work as the temporary solution.
Well, when I'm raising PageDragStart event, I call Mouse.Capture(this, CaptureMode.SubTree);
When the page is dropped somewhere - DoDragDrop throws different exceptions (COMException, NullReference (I couldn't find which object is null) and some others I don't remember).
I catch exception and call PageDragEnd event (if the property IsPageDraggingOut set to true).
As far as you can see this solution is really dirty and bad. But it works.
So, any other ideas (or some ideas how to work with Mouse.Capture properly)?

How to tell if a button click event was triggered by keyboard or mouse in WPF?

Is there a simple way to tell what triggered Click event of a Button apart from setting multiple flags in Mouse/Key Up/Down event handlers? I'm currently only interested in distinguishing mouse from everything else, but it would be nice to handle Stylus and other input types if possible. Do I have to create my own button control to achieve this?
Edit: To clarify why I care: in this particular case I'm trying to implement "next" and "previous" buttons for a sort of picture viewer. Pictures in question may be of different size and buttons' positions will change (so they are always centered below picture). It's quite annoying to follow such buttons with mouse if you need to scroll through several pictures, so I want to keep mouse position constant relative to clicked button, but only if it was clicked by mouse, not keyboard.
Edit2: It does not matter whether the buttons are on top or down at the bottom, since the center can change anyway. "Picture viewer" here is just an abstraction and in this particular case it's important for me that top left corner of the picture retains it's position, but it's out of the scope of the question to go in details. Scaling the picture is not so trivial in this sort of application as well, so I do want to know the answer to the question I asked not going into UI implementation discussion.
if (InputManager.Current.MostRecentInputDevice is KeyboardDevice)
You should instead handle specifically the MouseXXX, StylusXXx, and KeyboardXXX events.
Could you elaborate on why you would care?
Having written many custom controls myself over the years, I cannot recall one instance where I cared how a click event was triggered. (Except for that pre VB6 control lifecycle glitch that fired the got focus-click-lost focus in a different order depending on whether you clicked a button, used an accelerator key, or pressed ENTER as the default).
Personally I find it annoying when people place buttons at the bottom of Windows forms and web pages. Read some of the literature on UI and you will find that most people don't even get that far if they don't find something interesting on the page/form. I like to be able to click next as soon as I know the content is of no interest to me, so keep the nav buttons prominent at the top.
I would put the prev/next at the top of the picture where you can control their position. Dancing those buttons around goes against most opinions on UI consistency. Further creating a different experience for a mouse user versus a keyboard user also goes against most current wisdom on good UI design.
The alternative is to choose a constant max size a picture can obtain on the UI and if it exceeds that scale to fit, otherwise allow it to change freely within a frame. This keeps your buttons at the same place if you absolutely must have them on the bottom.
You could create an enumeration with the different devices, have a global property that you set every time the mouse/keyboard/etc. is initiated, and just refer to this when needed.

Resources