Message Pump

G

Guest

I am trying to create a application with no UI that I can run as a background application.
The catch is that the application adds an icon to the taskbar and I need to be able to get a icon click event when the user clicks the icon. Someone pointed out that with out a form there is no Windows Message Pump and I woudl not get any events. So I need that pump and I can't see any other way to have a message pump than creating my own. So I gave it a shot:

public void MessagePump()
{
do
{
MSG msg = new MSG();
if ( PeekMessage( ref msg, 0, 0, 0, (int)PeekMessageOption.PM_REMOVE ) )
{
TranslateMessage( ref msg );
DispatchMessage( ref msg );
}
Thread.Sleep( 200 );
}while( true );
}

Unfortunately I am getting no events when I click on the icon at all. Does anyone have any ideas as to what I could be missing?
Note, I can get the event fine if I use a form, so it is not that the code is not getting the event at all, it's that my pump is not working.

Thanks
 
P

Paul G. Tobey [eMVP]

You don't just need a message pump; you also need a window to receive the
icon's events. What window are you telling the shell to send the icon
events to when you install the icon?

Are you sure that you don't want to do this in C++? Unless the program is
pretty sophisticated behind the scenes, you're going to save a lot of time.

Paul T.

fhunter said:
I am trying to create a application with no UI that I can run as a background application.
The catch is that the application adds an icon to the taskbar and I need
to be able to get a icon click event when the user clicks the icon. Someone
pointed out that with out a form there is no Windows Message Pump and I
woudl not get any events. So I need that pump and I can't see any other way
to have a message pump than creating my own. So I gave it a shot:
public void MessagePump()
{
do
{
MSG msg = new MSG();
if ( PeekMessage( ref msg, 0, 0, 0,
(int)PeekMessageOption.PM_REMOVE ) )
{
TranslateMessage( ref msg );
DispatchMessage( ref msg );
}
Thread.Sleep( 200 );
}while( true );
}

Unfortunately I am getting no events when I click on the icon at all. Does
anyone have any ideas as to what I could be missing?
Note, I can get the event fine if I use a form, so it is not that the code
is not getting the event at all, it's that my pump is not working.
 
C

Chris Tacke, eMVP

Take a look at OpenNETCF.Windows.Forms.ApplicationEx, specifically at the
Run() method. This is exactly how the Application.Run() method itself work
(but with the ability to have message filters).

http://opennetcf.org/SourceBrowse/v...urce/OpenNETCF.Windows.Forms/ApplicationEx.cs

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


fhunter said:
Thanks Paul,
I see were you are going.
What you mentioned got me a bit closer. I am using the Notify Icon example from Microsoft's site.
I see were they create a WindowSink : MessageWindow class, an now I see
that it is the one getting the events.
So why would this class get events when a Form is created but not
otherwise? There is not connection (in code) between the form and this
WindowSink :( How do I tell the shell to send the events to this window?
I am guessing that Application.Run( new Myform() ) is somehow doing this ?
Since when it is not called I get no events. But what exactly is it doing?
 
A

Alex Yakhnin [MVP]

Since I am the author of the code on MSDN, let me chip in ...

The MessageWindow class in CF is the unvisible window, which exposes it's
window handle and provides the ability to hook up into its WinProc. This is
why it is used to intersept the messages that are being sent from the
notification. Theoretically, you could execute the logic you require right
in the WndProc override, but you still'd need the place to create an
instance of WindowSink class..
So... I've created a test app, by combining the OpenNETCF's ApplicationEx
class (which provides the same message pump) with the NotifyIcon:


class TestClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
NotifyIcon notifyIcon = new NotifyIcon();
notifyIcon.Click+=new EventHandler(notifyIcon_Click);
IntPtr hIcon = LoadIcon(GetModuleHandle(null), "#32512");
notifyIcon.Add(hIcon);

OpenNETCF.Windows.Forms.ApplicationEx.Run();

}


[DllImport("coredll.dll")]
internal static extern IntPtr LoadIcon(IntPtr hInst, string IconName);

[DllImport("coredll.dll")]
internal static extern IntPtr GetModuleHandle(String lpModuleName);

private static void notifyIcon_Click(object sender, EventArgs e)
{
MessageBox.Show("Click");
}
}


--
Alex Yakhnin .NET CF MVP
www.intelliprog.com | www.opennetcf.org

fhunter said:
Thanks Paul,
I see were you are going.
What you mentioned got me a bit closer. I am using the Notify Icon example from Microsoft's site.
I see were they create a WindowSink : MessageWindow class, an now I see
that it is the one getting the events.
So why would this class get events when a Form is created but not
otherwise? There is not connection (in code) between the form and this
WindowSink :( How do I tell the shell to send the events to this window?
I am guessing that Application.Run( new Myform() ) is somehow doing this ?
Since when it is not called I get no events. But what exactly is it doing?
 
C

Chris Tacke, eMVP

Just as an added FYI, before running Alex's code, you may want to add a way
to get back *out* of the Run() pump, or you'll have an unstoppable process
and will have to restart your PPC to kill it.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Alex Yakhnin said:
Since I am the author of the code on MSDN, let me chip in ...

The MessageWindow class in CF is the unvisible window, which exposes it's
window handle and provides the ability to hook up into its WinProc. This is
why it is used to intersept the messages that are being sent from the
notification. Theoretically, you could execute the logic you require right
in the WndProc override, but you still'd need the place to create an
instance of WindowSink class..
So... I've created a test app, by combining the OpenNETCF's ApplicationEx
class (which provides the same message pump) with the NotifyIcon:


class TestClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
NotifyIcon notifyIcon = new NotifyIcon();
notifyIcon.Click+=new EventHandler(notifyIcon_Click);
IntPtr hIcon = LoadIcon(GetModuleHandle(null), "#32512");
notifyIcon.Add(hIcon);

OpenNETCF.Windows.Forms.ApplicationEx.Run();

}


[DllImport("coredll.dll")]
internal static extern IntPtr LoadIcon(IntPtr hInst, string IconName);

[DllImport("coredll.dll")]
internal static extern IntPtr GetModuleHandle(String lpModuleName);

private static void notifyIcon_Click(object sender, EventArgs e)
{
MessageBox.Show("Click");
}
}


--
Alex Yakhnin .NET CF MVP
www.intelliprog.com | www.opennetcf.org

fhunter said:
Thanks Paul,
I see were you are going.
What you mentioned got me a bit closer. I am using the Notify Icon
example
from Microsoft's site.
I see were they create a WindowSink : MessageWindow class, an now I see
that it is the one getting the events.
So why would this class get events when a Form is created but not
otherwise? There is not connection (in code) between the form and this
WindowSink :( How do I tell the shell to send the events to this window?
I am guessing that Application.Run( new Myform() ) is somehow doing this
?
Since when it is not called I get no events. But what exactly is it doing?
Thanks so much Paul, I got a little closer. Any other comments ?

C++ would be nice, but I have not done C++ in 4 years and to be honest I am afraid :( ...
 
A

Alex Yakhnin [MVP]

Yep, realized that after hit send button.

--
Alex Yakhnin .NET CF MVP
www.intelliprog.com | www.opennetcf.org

Chris Tacke said:
Just as an added FYI, before running Alex's code, you may want to add a way
to get back *out* of the Run() pump, or you'll have an unstoppable process
and will have to restart your PPC to kill it.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
Windows CE Product Manager
Applied Data Systems
www.applieddata.net


Alex Yakhnin said:
Since I am the author of the code on MSDN, let me chip in ...

The MessageWindow class in CF is the unvisible window, which exposes it's
window handle and provides the ability to hook up into its WinProc. This is
why it is used to intersept the messages that are being sent from the
notification. Theoretically, you could execute the logic you require right
in the WndProc override, but you still'd need the place to create an
instance of WindowSink class..
So... I've created a test app, by combining the OpenNETCF's ApplicationEx
class (which provides the same message pump) with the NotifyIcon:


class TestClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main(string[] args)
{
NotifyIcon notifyIcon = new NotifyIcon();
notifyIcon.Click+=new EventHandler(notifyIcon_Click);
IntPtr hIcon = LoadIcon(GetModuleHandle(null), "#32512");
notifyIcon.Add(hIcon);

OpenNETCF.Windows.Forms.ApplicationEx.Run();

}


[DllImport("coredll.dll")]
internal static extern IntPtr LoadIcon(IntPtr hInst, string IconName);

[DllImport("coredll.dll")]
internal static extern IntPtr GetModuleHandle(String lpModuleName);

private static void notifyIcon_Click(object sender, EventArgs e)
{
MessageBox.Show("Click");
}
}


--
Alex Yakhnin .NET CF MVP
www.intelliprog.com | www.opennetcf.org

fhunter said:
Thanks Paul,
I see were you are going.
What you mentioned got me a bit closer. I am using the Notify Icon
example
from Microsoft's site.
I see were they create a WindowSink : MessageWindow class, an now I
see
that it is the one getting the events.
So why would this class get events when a Form is created but not
otherwise? There is not connection (in code) between the form and this
WindowSink :( How do I tell the shell to send the events to this window?
I am guessing that Application.Run( new Myform() ) is somehow doing
this
?
Since when it is not called I get no events. But what exactly is it doing? I
am afraid :( ...
 
G

Guest

That works awesome :
Thanks guys

The only thing I need to figure out is how to get rid of the stupid spinning cursor completly, which probably can't be done. And how to make it so it does not show the application name on the top tool bar. :

However, this is pretty great !

Ahg, I can breath now ! :)
 
P

Peter Foot [MVP]

If you set focus on another window (e.g. the today screen) the titlebar
should redraw. With regards the Spinning cursor, you can disable this with
Cursor.Current = Cursors.Default

You may need to experiment with where best to place this statement. I had
this issue when calling some system dialogs from a class-library project and
was able to workaround it in this way.

Peter
 
G

Guest

Hate to abuse your help but can you be more specific about how I would go about setting the Focus on the Today Screen ? :(. How do I get a handle to the Today Screen

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top