7

I'm trying to run a Windows Forms app on a Windows 10 tablet (Dell Venue 8 Pro). In general, Windows translates touch events into the obvious mouse event counterparts. However, it's doing something strange with vertical swipes.

My app has a custom control (derived directly from Control with a call to SetStyle(ControlStyles.Selectable..., true) in its constructor) that shows graphics rendered by Direct3D. The control interprets MouseDown -> MouseMove -> MouseUp sequences as requests to rotate the view about the lookat position. This works fine on the desktop, but on a tablet it breaks: vertical swipes on my custom control are somehow being caught by Windows and passed to a nearby DataGridView, where they are interpreted as requests to scroll through the table. The DataGridView and my control are not siblings under the same container; they are at completely different levels of the control hierarchy. Here's a screenshot:

Screenshot of the application showing the different interpretations of vertical and horizontal swipes

I've done some debugging to prove to myself that no mouse events are making it to my control during the vertical swipe. A few trickle in right when I lift my finger, but during the vertical swipe there's nothing.

The trouble seems to be that my code (in the event handlers) simply isn't getting run because no input is making its way to my control.

What is going on here, and is there any way I can tell Windows not to send vertical swipe events that happen over my control to a completely unrelated control?

Edit: I should add that I'm calling Focus() all over the place in my code to make sure my control is focused while the mouse is over it. I put it in OnMouseMove, OnMouseDown, and pretty much on every other mouse event.

Edit: I have built a small Visual Studio 2010 solution demonstrating this problem. It's too much code to reproduce here inline, but it's easy to grok. Build it, install it on a Windows 10 tablet, and try swiping vertically in the rightmost control. Note that rather than that control receiving a bunch of mouse events, the DataGridView fires Scroll.

Update: I've explicitly tested whether my control is focused when the DataGridView gets a Scroll event. If I call Focus() on my control in response to MouseMove etc. as mentioned above, my control does get the focus and holds it during the vertical swipe while DataGridView.Scroll is firing. In the DataGridView.Scroll event handler, I have printed out whether my control is focused, and it is. So this is not a matter of the DataGridView stealing focus; it's a matter of the DataGridView handling a swipe intended for my control even when my control is focused.

Note: If I set dataGridView.ScrollBars to ScrollBars.None, the mouse events for the swipe do go to my control. I've been messing with ugly hacks that hide the scrollbars every time my control gets focused and show them every time the DataGridView gets focused. But they're all ugly hacks with unpleasant side effects.

adv12
  • 8,443
  • 2
  • 24
  • 48
  • 1
    Okay, for the ambitious I added a link to a zipped VS solution that reproduces the problem (when run on a Windows 10 tablet). It was too much code to post inline, though much of it is designer code and repetitive event handler code. – adv12 Nov 19 '15 at 16:02
  • My intuition tells me **[this](http://stackoverflow.com/questions/30948205/excel-customtaskpane-with-webbrowser-control-keyboard-focus-issues)** is one of the best QA's on the behaviour, see all the links in there too - the message is not pumped to your code. I have a surface pro with Win10 and am keen to repro. I'd be looking at this `protected override void WndProc(ref Message m)` – Jeremy Thompson Nov 20 '15 at 09:04
  • @JeremyThompson, I think it must be something different. I added the suggested WndProc to my custom control, and the DataGridView still scrolls. Notably, no other events fire on the DataGridView (for instance, no mouse events). It behaves like Windows itself is intercepting the touch events, accumulating a few of them to identify vertical swipe, and if a vertical swipe is detected, directly scrolling the DataGridView, otherwise generating mouse events for my control. Even when I swipe horizontally, there's a lag before the mouse events start showing up.... – adv12 Nov 20 '15 at 14:58
  • Here's what i observed in a Windows 10 Dell Touch Laptop: if i first do some LEFT-RIGHT swipes and then, without lifting my finger off the screen, do some UP-DOWN swipes, it works... meaning all events go to `MyControl` and none to `DataGridView`. At this point, once it is "locked-in", so to speak, i can even consistently drag the shape around in a circular motion without observing any events going to the `DataGridView`. Other than that, it reproduces the problem described in your post. It seems as if the message queue takes a while to "figure out / synchronize" with what the user is doing. – jsanalytics Nov 22 '15 at 15:29
  • @jstreet, that's what I'm seeing too; I probably didn't explain it as clearly. – adv12 Nov 22 '15 at 18:44
  • How about handling touch events on your own, and not await a proper implementation of Microsoft of it's own. [link](https://msdn.microsoft.com/en-us/library/windows/desktop/dd940546(v=vs.85).aspx) – Yosh Synergi Nov 25 '15 at 10:47
  • @YoshSynergi, today I tried calling `RegisterTouchWindow` as suggested by that article and it solved my problem. I didn't actually override `WndProc` to process WM_TOUCH messages, but apparently calling `RegisterTouchWindow` is enough to tell Windows not to interpret them as requests to scroll the `DataGridView`. Anyway, I wouldn't have known to try it without your comment, so if you want to convert your comment to an answer I'll upvote and accept it. The bounty period has expired, or I'd award that as well. – adv12 Nov 30 '15 at 17:20
  • I didn't tried to assist you because of the bounty or points, I just wanted to assist, so it's fine x) – Yosh Synergi Dec 01 '15 at 07:55

1 Answers1

1

How about handling touch events on your own, and not await a proper implementation of Microsoft of it's own. link

Yosh Synergi
  • 314
  • 3
  • 12
  • For future readers: just calling `RegisterTouchWindow` on the window handle of the custom control is enough to stop the `DataGridView` from scrolling in response to a vertical swipe on the custom control. Windows still converts touch events to mouse events for the custom control, so single-finger touch scenarios "just work." Unfortunately, your control now gets no `WM_GESTURE` messages, so you have to detect multi-touch gestures (like pinch/stretch) yourself. The linked article, combined with the full source code (found in the Windows 7.1 SDK samples) should get you started. – adv12 Dec 01 '15 at 14:11