Replies: 8 comments 8 replies
-
Creating MouseEventArgs is a very limited way of testing a behavior, because a lot of things are happening during mouse events, activation, capture, changing status of related dependency properties through the whole tree etc. It's would be of very limited use to enable this if the event handler would not see effects of all the above.
Could you use the SendInput native API to send messages to the window? Related: #5743 In terms of WPF, I think a better option would be opening up the input system to allow 3rd party input providers to report input. |
Beta Was this translation helpful? Give feedback.
-
I disagree. First, I can explicitly send all the events that would be sent IRL. Second, in my controls I would typically handle only a very specific set of events, the others being ignored so I don't need to send them.
Yes, it needs to be converted to the specific visual. Just like what is done now, except the screen position is queried from the device while it could be fed from the message.
I used to do that in windows forms, but it's horribly hackish, requires a window to be displayed, and is generally frail. I thought WPF was supposed to spare us from all low level horrors. Plus I don't even think it would work since the mouse position is queried from the device instead of being read from the message: I would probably need to explicitly set the pointer position. I have done this in the past but it's super frail, it means no one must do anything on the machine while the test is running. At the moment, the only workaround I see is something like
Then in tests I can call OnMouseLeftButtonDownImpl with the position I like. That's awkward and only works if I have total control of the class. |
Beta Was this translation helpful? Give feedback.
-
OK, then it's not as bad as I feared. I guess I could use reflection to modify _lastPosition, rather than having to fight with SendInput. |
Beta Was this translation helpful? Give feedback.
-
I suppose adding a function |
Beta Was this translation helpful? Give feedback.
-
However, the state of buttons is not stored inside the mousedevice, but queried from the system. The function is virtual though, so all hope is not lost. Would it be ok to define a class derived from MouseDevice (defining GetButtonStateFromSystem), instantiate it, and pass it to my MouseEventArgs, or will something explode? Same question about KeyboardDevice and GetKeyStatesFromSystem BTW. |
Beta Was this translation helpful? Give feedback.
-
May I ask how wpf is tested internally by Microsoft? I'm not seeing much in the tests directory in the published sources. |
Beta Was this translation helpful? Give feedback.
-
I think I have devised a way around the impossibility of defining GetButtonStateFromSystem in a custom MouseDevice class. At the same time, it spares me from having to define a custom KeyboardDevice class. I'm using Detours to hook GetKeyState which is used for both GetButtonStateFromSystem and GetKeyStatesFromSystem! I have this code in a C++/CLI library:
Then in my test code, I can type:
which outputs Down None None None as expected. |
Beta Was this translation helpful? Give feedback.
-
An extra subtlety: the mousedevice must be made active by assigning its _inputSource field for GetButtonStateFromSystem to work. I wrote the following code for that.
With this taken care of, you can set a button down with |
Beta Was this translation helpful? Give feedback.
-
In automated tests, I would like to be able to create instances of MouseEventArgs, MouseButtonEventArgs, ... with specific coordinates, then use RaiseEvent to test the reaction of my controls to the event.
But this is not possible because MouseEventArgs does not contain coordinates; instead GetPosition has to query the mousedevice for the position. It doesn't look possible to define a fake mousedevice for my purpose. I don't understand why this choice was made: the coordinates are available in the mouse window messages, so it should be possible to extract them in the WndProc and pass them to the mouseeventargs.
I understand a fundamental change of logic is not possible for backwards compatibility reasons, but I can think of two workarounds that wouldn't break bytecode compatibility:
Add a publically settable Point field in MouseEventArgs that would be returned by GetPosition if it has been assigned. Pretty ugly, but would be very handy.
Then we could create derived classes that would override GetPositionImpl to return what we want. That would be less handy because we'd have to define one derived class for each class derived from MouseEventArgs, and every programmer would have to reinvent the square wheel on their side.
Beta Was this translation helpful? Give feedback.
All reactions