Flush Events

  • Thread starter Thread starter Mobile Application Developer (MAD)
  • Start date Start date
M

Mobile Application Developer (MAD)

Hi,

First, I am processing button MouseDown/MouseUp events directly on Custom
Control Screen. On an MouseDown Event, I want to first flush any pending
MouseDown events, do some logic, and then go back to accepting mouse down
events again. How do I do this?
 
Hi,

First, I am processing button MouseDown/MouseUp events directly on Custom
Control Screen. On an MouseDown Event, I want to first flush any pending
MouseDown events, do some logic, and then go back to accepting mouse down
events again. How do I do this?

Hi,

You could use Application.DoEvents to force the message pump to be
flushed to the system. Just be careful as that method will actually
flush the message pump as it were being unstacked, not unqueued. It
will flush ALL the message pump, that includes all sort of messages:
mouse events, keyboard events, network messages, hardware
interruptions, etc, so, again: *be careful*.

Also, remember events are not guaranteed to be fired instantly or in a
particular order, so you should probably review your design in a way
you do not depend on events being processed in a particular fashion.

Hope this helps!

Diogo
 
DoEvents flushes the windows message queue and nothing more (via a loop call
on GetMessage, TranslateMessage, DispatchMessage). It will not do anything
with hardware interrupts, network messages or anything of the sort unless
they for some reason are using Windows messages for communication (and if
they are, you have much bigger worries).

The messages also don't get tossed on the floor, any handlers get invoked
so, as a general rule, if a call to DoEvents ever causes bad behavior
(beyond poor perf or UI flicker) in an application, the application is
poorly designed.


--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Giving back to the embedded community
http://community.OpenNETCF.com


Hi,

First, I am processing button MouseDown/MouseUp events directly on Custom
Control Screen. On an MouseDown Event, I want to first flush any pending
MouseDown events, do some logic, and then go back to accepting mouse down
events again. How do I do this?

Hi,

You could use Application.DoEvents to force the message pump to be
flushed to the system. Just be careful as that method will actually
flush the message pump as it were being unstacked, not unqueued. It
will flush ALL the message pump, that includes all sort of messages:
mouse events, keyboard events, network messages, hardware
interruptions, etc, so, again: *be careful*.

Also, remember events are not guaranteed to be fired instantly or in a
particular order, so you should probably review your design in a way
you do not depend on events being processed in a particular fashion.

Hope this helps!

Diogo
 
Clarification, by flush I want to empty MouseDown/MouseUp events from queue
and not have them processed... I want these events to go to bit bucket...
this will do that?
 
Then call GetMessage in a loop until it returns false without calling
translate and dsipatch.


--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Giving back to the embedded community
http://community.OpenNETCF.com



"Mobile Application Developer (MAD)"
 
I call GetMessage from custom Control?

Chris Tacke said:
Then call GetMessage in a loop until it returns false without calling
translate and dsipatch.


--

Chris Tacke, Embedded MVP
OpenNETCF Consulting
Giving back to the embedded community
http://community.OpenNETCF.com



"Mobile Application Developer (MAD)"
 
Rather than handling these windows messages, can you not just override them
at a higher managed level in your code and throw them away?

--
Simon Hart
Visual Developer - Device Application Development MVP
http://www.simonrhart.com

"Mobile Application Developer (MAD)"
 
I tried that and it did not work. They get buffered I think. I will try to
illustrate what is happening with some pseudocode;

1) The method StartSound() essentially hides button and starts sound output.
(see below)
class Test : Control
{
void StartSound()
{
button.visible=false
button.enabled=false
refresh();
soundclass.PlaySound()
}
}

2A) The method soundclass.PlaySound() signals a SoundVisualizer class that
it has started to
play sound via EventHandler in SoundVisualizer::SoundEventHandler(object
s, SoundEventArgs e).

class SoundVisualizer
{
void SoundEventHandler(object s, SoundEventArgs e)
{
startSoundProgressBar()
ShowButtonEventHandler()
}
}

2B) SoundVisualizer::SoundEventHandler(object s, SoundEventArgs e) starts
progress bar animation
and via event handler in Test class, tells it to show 'button'.

class Test : Control
{
void ShowButtonEventHandler(object s, SoundEventArgs e)
{
button.visible=true;
button.enable=true;
}
}

3A) A little information, in Test class when button is pressed I stop the
Sound and Visualization
animation and do business logic and then start sequence again.
3B) In class SoundClass the method PlaySound() goes into a loop to send data
to a external
device via bluetooth. During this loop everything is blocked, nature of
bluetooth library
that is being used I don't like it but is what I have to work with. Well,
because of this,
if user presses button once everything is fine I process and move on.
However, if it is
pressed multiple times multiple MouseDown events and when Test get it's
chance to run it
processes all of them. This is wrong, because thet next sound is stopped
before it is started.


class SoundClass
{
public PlaySound()
{
// ... other code to get stuff started.
while (!playSoundCancelled && (bytesRead = fs.Read(data, 0,
DATA_CHUNK_SIZE)) != 0)
{
Application.DoEvents();
bluetooth.SendAudio(data, bytesRead);
}
}
}


I tried adding flags to this does not synchronize well and I can not use
syncrhonize() because of
timing issues with device. I am thinking that MouseDown events get queued by
system and when
Application.DoEvents() is called in SOundClass:PlaySOund() loop Test class
get a burst of them
and processes each one of them.

My solution is on button handler is to forget any pending MouseDown events
or flush them.

I hope this clears up why I am doing this.
 
I assume you are using P/Invoke, sorry I should have been more specific. What
I was trying to get at in last question do I have to use P/Invoke to do this?
I am not using a Form but a Custom Control to display screen on which button
and graphics are located. However, this Custom Control is a child of a Form.
 
Hello,

so the advice given to you was correct: replace your DoEvents with a
custom message loop where every mousedown events get eaten but all
others get properly handled (means: passed to Windows -> Translate and
Dispatch). This should work and rewuires P/Invoking GetMessage.

Greetings

Markus
 
It is not working. I did make some changes though. Since GetMessage() blocks,
I use PeekMessage() with 'PM_REMOVE|PM_NOYIELD' so it is removed, otherwise
it waits for these messages.

How I use PeekMessage() function;
-----------------------------------------
NativeWin32.MessageQueueFunctions.MSG msg;
while (NativeWin32.MessageQueueFunctions.PeekMessage(out msg,
IntPtr.Zero,
NativeWin32.MessageQueueFunctions.WM_MOUSEFIRST,
NativeWin32.MessageQueueFunctions.WM_MOUSELAST,

NativeWin32.MessageQueueFunctions.PM_REMOVE|NativeWin32.MessageQueueFunctions.PM_NOYIELD)) { }

Implementation of PeekMessage PInvoke;
--------------------------------------
public sealed class MessageQueueFunctions
{
public const uint WM_MOUSEFIRST = 0x0200;
public const uint WM_MOUSELAST = 0x020D;

// PeekMessage() Options
public const uint PM_NOREMOVE = 0x0000;
public const uint PM_REMOVE = 0x0001;
public const uint PM_NOYIELD = 0x0002;

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public uint wParam;
public int lParam;
public uint time;
public POINT pt;
}

[DllImportAttribute("coredll.dll", EntryPoint = "PeekMessageW")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool PeekMessage(out MSG lpMsg, System.IntPtr hWnd,
uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
}
 
It is not working. I did make some changes though. Since GetMessage() blocks,
I use PeekMessage() with 'PM_REMOVE|PM_NOYIELD' so it is removed, otherwise
it waits for these messages.

How I use PeekMessage() function;
-----------------------------------------
NativeWin32.MessageQueueFunctions.MSG msg;
while (NativeWin32.MessageQueueFunctions.PeekMessage(out msg,
IntPtr.Zero,
NativeWin32.MessageQueueFunctions.WM_MOUSEFIRST,
NativeWin32.MessageQueueFunctions.WM_MOUSELAST,

NativeWin32.MessageQueueFunctions.PM_REMOVE|NativeWin32.MessageQueueFunctions.PM_NOYIELD)) { }

Implementation of PeekMessage PInvoke;
--------------------------------------
public sealed class MessageQueueFunctions
{
public const uint WM_MOUSEFIRST = 0x0200;
public const uint WM_MOUSELAST = 0x020D;

// PeekMessage() Options
public const uint PM_NOREMOVE = 0x0000;
public const uint PM_REMOVE = 0x0001;
public const uint PM_NOYIELD = 0x0002;

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public uint wParam;
public int lParam;
public uint time;
public POINT pt;
}

[DllImportAttribute("coredll.dll", EntryPoint = "PeekMessageW")]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool PeekMessage(out MSG lpMsg, System.IntPtr hWnd,
uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
}
 
From what I understand your bluetooth code blocks the UI thread and
the mouse clicks stack up and then when the bluetooth code finishes
they all get processed at once?

Why don't you execute the bluetooth code in a worker thread and use
some threadsync to let the UI thread know when the bluetooth stuff has
finished, and in-between that time you can ignore the events for mouse
clicks in the event handlers...

Matt
 
That would be fine but changing that code is not an option. I do not have
access to it even though it. This Managed code uses the bluetooth (native
code) library to access the device and I don't have access to Managed code
and I tried worker thread and it caused bluetooth device to timeout. This
method is working I just need to flush events after a MouseDown event. What
is wrong with code in previous post?
 
The first thing that stands out is the declaration of wParam and
lParam in your MSG struct, they are the same size (int and uint are
the same size, just signed and unsigned), according to the MSDN docs,
lParam is a ULONG_PTR which is defined as an unsigned long, and wParam
is an UINT_PTR (defined as unsigned int)

I'd check your p/invoke stuff is correct, according to

http://www.pinvoke.net/default.aspx/user32/PeekMessage.html

there are some differences between your declarations and the
declarations there. May not make a difference, but my experience with
p/invoke has always been that the declarations need to be made just
so. :)

Matt
 
Those declarations *are* the same size in native code, also.

'int' in C is the defined to be the basic size of a machine word on the
target platform. So, in 16-bit Windows, int was 16 bits. On Win32,
including Windows CE, however, it's 32 bits. 'long' in C is defined to
always be 32 bits. The sizes of uint and int are both 32 bits in C#. That
part, at least, of the declaration is correct.

Paul T.
 
Hi,

Mouse Pressed are not being purged, inaddition, the call to PeekMessage() is
returning 120 after it loops through while a few times. See code below ( I
made changes based on previous input from this group);


///
/// TestUI.cs this class uses PeekMessage() PInvoke;
///
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.Security;
using CSFittingFormula;
using System.Text;

namespace MyNamespace {
class TestUI : Control {
private void PurgeMouseEvents() {
NativeApi.MessageQueueFunctions.MSG msg=new
NativeApi.MessageQueueFunctions.MSG();
while (NativeApi.MessageQueueFunctions.PeekMessage(out msg,
IntPtr.Zero,
NativeApi.MessageQueueFunctions.WM_MOUSEFIRST,
NativeApi.MessageQueueFunctions.WM_MOUSELAST,
NativeApi.MessageQueueFunctions.PM_REMOVE |
NativeApi.MessageQueueFunctions.PM_NOYIELD)) { }
int error = Marshal.GetLastWin32Error();
}
}
}


///
/// NativeApi.cs - this class does pinvoke and is compiled into a .NET CF DLL
///
using System;
using System.Runtime.InteropServices;

namespace NativeApi {
public sealed class MessageQueueFunctions {
public const uint WM_MOUSEFIRST = 0x0200;
public const uint WM_MOUSELAST = 0x020D;

// PeekMessage() Options
public const uint PM_NOREMOVE = 0x0000;
public const uint PM_REMOVE = 0x0001;
public const uint PM_NOYIELD = 0x0002;

[StructLayout(LayoutKind.Sequential)]
public struct MSG {
public IntPtr hwnd;
public uint message;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public int pt_x;
public int pt_y;
}
[DllImport("coredll.dll", EntryPoint = "PeekMessageW", SetLastError =
true)]
public static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint
wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);

[DllImport("coredll.dll", EntryPoint = "GetMessageW", SetLastError =
true)]
public static extern bool GetMessage(out MSG lpMsg, IntPtr hWnd, uint
wMsgFilterMin, uint wMsgFilterMax);
}
}
 
Back
Top