Jump to content

  • Log In with Google      Sign In   
  • Create Account

Calling all IT Pros from Canada and Australia.. we need your help! Support our site by taking a quick sponsored surveyand win a chance at a $50 Amazon gift card. Click here to get started!


Weird behaviour when changing RIDEV_CAPTUREMOUSE on register


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 Tape_Worm   Crossbones+   -  Reputation: 2120

Like
1Likes
Like

Posted 15 August 2014 - 09:26 AM

So I'm having the weirdest issue with Raw Input.  

 

So I have a nice little wrapper class for Raw Input, and on that wrapper I have an "Exclusive" mode (kinda like what DirectInput did) property.  This property calls RegisterRawInputDevices with the dwFlags member set to RIDEV_CAPTUREMOUSE | RIDEV_INPUTSINK | RIDEV_NOLEGACY when Exclusive is TRUE and to 0 when I set Exclusive to FALSE.

 

Now for the weirdness.  If I try to set Exclusive to TRUE by right-clicking the mouse down and set Exclusive to FALSE on mouse up, it sometimes deactivates my window messes up the state since exclusive gets turned off when the window loses focus.  This happens randomly.  When it "works" and the mouse goes into exclusive mode and out of exclusive mode my window stops responding to mouse over events in the window decorations (e.g. the close button doesn't highlight), I can't press ALT+F4 to exit the application (although other key presses are intercepted with no problems), and I can't click on the close button until I left click on the window.  Also, sometimes Windows explorer gets all messed up when this happens.  For example, on the taskbar, no icons respond to mouse events and I have to right click a couple of times to get it responding again.

 

I've tried this code on two machines with Windows 7, and Windows 8.1 (x64 for both) and both exhibit the same behaviour.  I've dug around on-line and I can't find anything related to this.

 

I considered that it might be due to calling RegisterRawInputDevices multiple times without unregistering the device.  So, I unregistered by settings the dwFlags to RIDEV_REMOVE and setting the window handle to NULL before registering the device with the new dwFlags combination, but that didn't work.

 

Could it be due to the flags I'm using?  Could it be due to calling RegisterRawInputDevices multiple times?  Could this just be a quirk with Raw Input?  

 

Here's the code that registers the device just for clarity (FYI, GetRawData just reads the data sent back by the WM_INPUT message, and does little else, so I did not include it):

		protected override void BindDevice()
		{
			BoundControl.MouseLeave -= Owner_MouseLeave;

			_device.UsagePage = HIDUsagePage.Generic;
			_device.Usage = (ushort)HIDUsage.Mouse;
			_device.Flags = RawInputDeviceFlags.Remove;
			_device.WindowHandle = IntPtr.Zero;

			// Attempt to register the device.
		    if (!Win32API.RegisterRawInputDevices(_device))
		    {
		        throw new BindException(Resources.RAW_CANNOT_UNBIND_POINTING_DEVICE);
		    }


			if (_messageFilter != null)
			{
				_messageFilter.RawInputPointingDeviceData -= GetRawData;
				_messageFilter.RawInputPointingDeviceData += GetRawData;
			}

			_device.UsagePage = HIDUsagePage.Generic;
			_device.Usage = (ushort)HIDUsage.Mouse;
			_device.Flags = RawInputDeviceFlags.None;

			// Enable background access.
		    if ((AllowBackground) || (Exclusive))
		    {
		        _device.Flags |= RawInputDeviceFlags.InputSink;
		    }

		    // Enable exclusive access.
			if (Exclusive)
			{
				_device.Flags |= RawInputDeviceFlags.CaptureMouse | RawInputDeviceFlags.NoLegacy;
			}

		    _device.WindowHandle = BoundControl.Handle;

			// Attempt to register the device.
		    if (!Win32API.RegisterRawInputDevices(_device))
		    {
		        throw new BindException(Resources.RAW_CANNOT_BIND_POINTING_DEVICE);
		    }

			if (!Exclusive)
			{
				OnWindowBound(BoundControl);
			}
		}

And this is how I process the WM_INPUT message, I register this message filter using Application.AddMessageFilter(MessageFilter);:

	internal class MessageFilter
		: System.Windows.Forms.IMessageFilter
	{
		#region Events.
		/// <summary>
		/// Event fired when a raw input keyboard event occours.
		/// </summary>
		public event EventHandler<RawInputKeyboardEventArgs> RawInputKeyboardData = null;
		/// <summary>
		/// Event fired when a pointing device event occurs.
		/// </summary>
		public event EventHandler<RawInputPointingDeviceEventArgs> RawInputPointingDeviceData = null;
		/// <summary>
		/// Event fired when an HID event occurs.
		/// </summary>
		public event EventHandler<RawInputHIDEventArgs> RawInputHIDData = null;
		#endregion

		#region Variables.
		private readonly int _headerSize = DirectAccess.SizeOf<RAWINPUTHEADER>();	// Size of the input data in bytes.
		#endregion

		#region IMessageFilter Members
		/// <summary>
		/// Filters out a message before it is dispatched.
		/// </summary>
		/// <param name="m">The message to be dispatched. You cannot modify this message.</param>
		/// <returns>
		/// true to filter the message and stop it from being dispatched; false to allow the message to continue to the next filter or control.
		/// </returns>
		public bool PreFilterMessage(ref System.Windows.Forms.Message m)
		{
			// Handle raw input messages.
			if ((WindowMessages)m.Msg != WindowMessages.RawInput)
			{
				return false;
			}

			unsafe
			{
				int dataSize = 0;

				// Get data size.			
				int result = Win32API.GetRawInputData(m.LParam, RawInputCommand.Input, IntPtr.Zero, ref dataSize, _headerSize);

				if (result == -1)
				{
					throw new GorgonException(GorgonResult.CannotRead, Resources.GORINP_RAW_CANNOT_READ_DATA);
				}

				// Get actual data.
				var rawInputPtr = stackalloc byte[dataSize];
				result = Win32API.GetRawInputData(m.LParam, RawInputCommand.Input, (IntPtr)rawInputPtr, ref dataSize, _headerSize);

				if ((result == -1) || (result != dataSize))
				{
					throw new GorgonException(GorgonResult.CannotRead, Resources.GORINP_RAW_CANNOT_READ_DATA);
				}

				var rawInput = (RAWINPUT*)rawInputPtr;

				switch (rawInput->Header.Type)
				{
					case RawInputType.Mouse:
						if (RawInputPointingDeviceData != null)
						{
							RawInputPointingDeviceData(this,
							                           new RawInputPointingDeviceEventArgs(rawInput->Header.Device, ref rawInput->Union.Mouse));
						}
						break;
					case RawInputType.Keyboard:
						if (RawInputKeyboardData != null)
						{
							RawInputKeyboardData(this, new RawInputKeyboardEventArgs(rawInput->Header.Device, ref rawInput->Union.Keyboard));
						}
						break;
					default:
						if (RawInputHIDData != null)
						{
							var HIDData = new byte[rawInput->Union.HID.Size * rawInput->Union.HID.Count];
							var hidDataPtr = ((byte*)rawInput) + _headerSize + 8;

							fixed (byte* buffer = &HIDData[0])
							{
								DirectAccess.MemoryCopy(buffer, hidDataPtr, HIDData.Length);
							}

							RawInputHIDData(this, new RawInputHIDEventArgs(rawInput->Header.Device, ref rawInput->Union.HID, HIDData));
						}
						break;
				}
			}

			return false;
		}
		#endregion


Edited by Tape_Worm, 15 August 2014 - 09:29 AM.


Sponsor:

#2 Tape_Worm   Crossbones+   -  Reputation: 2120

Like
0Likes
Like

Posted 15 August 2014 - 10:41 AM

I forgot to mention that if I change my Exclusive mode via a keyboard key press (KeyDown -> Exclusive = TRUE, KeyUp -> Exclusive = FALSE) then it works flawlessly.  So that makes this even more weird.



#3 N0rF   Members   -  Reputation: 102

Like
0Likes
Like

Posted 09 October 2014 - 04:39 AM

Hi, I had similiar problem. I've discovered that if RegisterRawInputDevices is called with RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY flags when mouse button is pressed, problems would happen if application stops unexpectidely (crashed or stopped by breakpoint).

Just for me appropriate fix was to delay RegisterRawInputDevices before all mouse buttons would be unpressed.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS