Does a Window have to be visible to receive Messages

G

Guest

I am trying to monitor incoming messages by overriding the
System.windows.form WndProc method. I have a radar device that sends messages
via the Message parameter for the WndProc method. The program i am developing
should be a console application but the radar only sends messages via the
wndproc method, so I am wondering if a window form has to be visible in order
for the messages to be received? I would like to just create an object of my
window class and use the methods I've created to manipulate my messages but
it appears that this won't work or I'm doing something wrong. I would
appreciate any help. Thanks
 
S

sb

I'm not clear on your question but I will tell you a few things that may
help.

1) Windows do not have to be visible to receive/process messages sent to
their WndProc.
2) "Console Applications" lack any underlying window or message pump...so
they can't process Window messages by default.

You *could* create/register a window inside a console app...but why would
you want to? In most cases, you're better off creating a simple 1 form
application and hiding the main form.

I threw together a possible way to do the hidden form approach below.

HTH
-sb

using System;
using System.Windows.Forms;

namespace MyApplication
{
static class Program
{
[STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
public class MyForm: Form
{
public MyForm()
{
this.ShowInTaskbar = false;
this.WindowState = FormWindowState.Minimized;
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
}
}
}
 
G

Guest

Thanks for your reply! Let me try to clarify my question. I am writing a
program that will be run on windows xp embedded. The only interface with the
radar will be via the console.

The radar was designed to send it's response to speeding cars to a
System.windows.form.Message via the WndProc method, but since this is a
console application i will not have a window open. I did write a test
application using a window form and I was able to receive the messages from
the radar fine but now I'm trying to write the actual program which will only
have a console to display information.

My main class is not a windows form, however, I did create another class
which is a windows form. I wanted to create an instance of the windows form
class so that I can get the messages from the wndproc method but this does
not seem to work unless I have a window open. I want to know if I can use my
windows form class without having the window to receive the messages from my
radar? If you understand this and there is a better way to do this I welcome
your suggestions.

sb said:
I'm not clear on your question but I will tell you a few things that may
help.

1) Windows do not have to be visible to receive/process messages sent to
their WndProc.
2) "Console Applications" lack any underlying window or message pump...so
they can't process Window messages by default.

You *could* create/register a window inside a console app...but why would
you want to? In most cases, you're better off creating a simple 1 form
application and hiding the main form.

I threw together a possible way to do the hidden form approach below.

HTH
-sb

using System;
using System.Windows.Forms;

namespace MyApplication
{
static class Program
{
[STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
public class MyForm: Form
{
public MyForm()
{
this.ShowInTaskbar = false;
this.WindowState = FormWindowState.Minimized;
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
}
}
}


NickiC said:
I am trying to monitor incoming messages by overriding the
System.windows.form WndProc method. I have a radar device that sends
messages
via the Message parameter for the WndProc method. The program i am
developing
should be a console application but the radar only sends messages via the
wndproc method, so I am wondering if a window form has to be visible in
order
for the messages to be received? I would like to just create an object of
my
window class and use the methods I've created to manipulate my messages
but
it appears that this won't work or I'm doing something wrong. I would
appreciate any help. Thanks
 
G

Guest

Actually, I guess my problem is that I have a loop that continues to monitor
input from the user and I created a separate thread for this loop to run on,
but it appears that as long as the loop is looping there are no window
messages that are coming accross. So i guess my question is now: as long as
a console is waiting for input will the WndProc method not receive messages?

NickiC said:
Thanks for your reply! Let me try to clarify my question. I am writing a
program that will be run on windows xp embedded. The only interface with the
radar will be via the console.

The radar was designed to send it's response to speeding cars to a
System.windows.form.Message via the WndProc method, but since this is a
console application i will not have a window open. I did write a test
application using a window form and I was able to receive the messages from
the radar fine but now I'm trying to write the actual program which will only
have a console to display information.

My main class is not a windows form, however, I did create another class
which is a windows form. I wanted to create an instance of the windows form
class so that I can get the messages from the wndproc method but this does
not seem to work unless I have a window open. I want to know if I can use my
windows form class without having the window to receive the messages from my
radar? If you understand this and there is a better way to do this I welcome
your suggestions.

sb said:
I'm not clear on your question but I will tell you a few things that may
help.

1) Windows do not have to be visible to receive/process messages sent to
their WndProc.
2) "Console Applications" lack any underlying window or message pump...so
they can't process Window messages by default.

You *could* create/register a window inside a console app...but why would
you want to? In most cases, you're better off creating a simple 1 form
application and hiding the main form.

I threw together a possible way to do the hidden form approach below.

HTH
-sb

using System;
using System.Windows.Forms;

namespace MyApplication
{
static class Program
{
[STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
public class MyForm: Form
{
public MyForm()
{
this.ShowInTaskbar = false;
this.WindowState = FormWindowState.Minimized;
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
}
}
}


NickiC said:
I am trying to monitor incoming messages by overriding the
System.windows.form WndProc method. I have a radar device that sends
messages
via the Message parameter for the WndProc method. The program i am
developing
should be a console application but the radar only sends messages via the
wndproc method, so I am wondering if a window form has to be visible in
order
for the messages to be received? I would like to just create an object of
my
window class and use the methods I've created to manipulate my messages
but
it appears that this won't work or I'm doing something wrong. I would
appreciate any help. Thanks
 
G

Guest

"You *could* create/register a window inside a console app"

Do you have any example code on how to do this?
Thanks

NickiC said:
Actually, I guess my problem is that I have a loop that continues to monitor
input from the user and I created a separate thread for this loop to run on,
but it appears that as long as the loop is looping there are no window
messages that are coming accross. So i guess my question is now: as long as
a console is waiting for input will the WndProc method not receive messages?

NickiC said:
Thanks for your reply! Let me try to clarify my question. I am writing a
program that will be run on windows xp embedded. The only interface with the
radar will be via the console.

The radar was designed to send it's response to speeding cars to a
System.windows.form.Message via the WndProc method, but since this is a
console application i will not have a window open. I did write a test
application using a window form and I was able to receive the messages from
the radar fine but now I'm trying to write the actual program which will only
have a console to display information.

My main class is not a windows form, however, I did create another class
which is a windows form. I wanted to create an instance of the windows form
class so that I can get the messages from the wndproc method but this does
not seem to work unless I have a window open. I want to know if I can use my
windows form class without having the window to receive the messages from my
radar? If you understand this and there is a better way to do this I welcome
your suggestions.

sb said:
I'm not clear on your question but I will tell you a few things that may
help.

1) Windows do not have to be visible to receive/process messages sent to
their WndProc.
2) "Console Applications" lack any underlying window or message pump...so
they can't process Window messages by default.

You *could* create/register a window inside a console app...but why would
you want to? In most cases, you're better off creating a simple 1 form
application and hiding the main form.

I threw together a possible way to do the hidden form approach below.

HTH
-sb

using System;
using System.Windows.Forms;

namespace MyApplication
{
static class Program
{
[STAThread]
static void Main()
{
Application.Run(new MyForm());
}
}
public class MyForm: Form
{
public MyForm()
{
this.ShowInTaskbar = false;
this.WindowState = FormWindowState.Minimized;
}

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
}
}
}


I am trying to monitor incoming messages by overriding the
System.windows.form WndProc method. I have a radar device that sends
messages
via the Message parameter for the WndProc method. The program i am
developing
should be a console application but the radar only sends messages via the
wndproc method, so I am wondering if a window form has to be visible in
order
for the messages to be received? I would like to just create an object of
my
window class and use the methods I've created to manipulate my messages
but
it appears that this won't work or I'm doing something wrong. I would
appreciate any help. Thanks
 
S

sb

I could not find where someone had done this before in C# so I just wrote a
short class from scratch. This class creates a message-only window that you
may/may not be able to use/adapt to fit your needs. It's really rare that
anyone would ever need to do this but who knows :)

HTH
-sb

<MessageWindow.cs>
using System;
using System.Runtime.InteropServices;
namespace TestApplication
{
public class MessageWindow : IDisposable
{
#region DllImports
[DllImport("user32.dll")]
private static extern IntPtr CreateWindowEx(uint dwExStyle, string
lpClassName, string lpWindowName, uint dwStyle,
int x, int y, int nWidth, int nHeight, IntPtr hWndParent,
IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

[DllImport("user32.dll")]
private static extern bool DestroyWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex,
IntPtr dwNewLong);

[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,
IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion

private const int GWL_WNDPROC = -4;
private const int HWND_MESSAGE = -3;

private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg,
IntPtr wParam, IntPtr lParam);


private WndProcDelegate _WndProc;
private IntPtr _OldWndProc;
private IntPtr _hWnd;

public IntPtr Handle // public property
{
get { return _hWnd; }
}

public MessageWindow()
{
_hWnd = CreateWindowEx(0, "STATIC", "MyMessageOnlyWindow", 0, 0,
0, 0, 0,
new IntPtr(HWND_MESSAGE), IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero);
_WndProc = new WndProcDelegate(WndProc);
_OldWndProc = new IntPtr(SetWindowLong(_hWnd, GWL_WNDPROC,
Marshal.GetFunctionPointerForDelegate(_WndProc)));
}

protected IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam,
IntPtr lParam)
{
System.Diagnostics.Debug.WriteLine(msg); // let's see what was
sent
return CallWindowProc(_OldWndProc, hWnd, msg, wParam, lParam);
}

#region IDisposable Members
public void Dispose()
{
if (_hWnd != IntPtr.Zero)
{
DestroyWindow(_hWnd);
_hWnd = IntPtr.Zero;
}
}
#endregion
}
}



<Program.cs>

using System;
using System.Runtime.InteropServices;

namespace TestApplication
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr
wParam, IntPtr lParam);

static void Main(string[] args)
{
MessageWindow m = new MessageWindow();

SendMessage(m.Handle, 55, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
SendMessage(m.Handle, 77, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
}
}
}
 
S

Stoitcho Goutsev \(100\)

In order to start a mesage pump in a console applicatio what you need to do
is

SomeForm f = new SomeForm();
Application.Run(f);

once the Application.Run is called it starts the message loop which means
the call will block there until the form is not closed. The console window
will still be visible and all Console.WriteXXX calls will output to it.
If you don't want to block tha main console applcication thread that can be
done in a worker thread also.

BTW, WinXP and Win2K support message only windows

Those windows are not visible doesn't have Z order and are used merely for
sending and receiving messages
(http://msdn.microsoft.com/library/d...nterface/windowing/windows/windowfeatures.asp).

In .NET I believe they can be createed using NativeWindow

NativeWindow mwnd =null;

......
CreateParams cp = new CreateParams();
cp.Parent = new IntPtr(-3);
NativeWindow mwnd = new NativeWindow();
mwnd.CreateHandle(cp);

I must say that I've never used them. I created test application and can
verify that such windows is created (Spy++).
Just a reminder that message-only widnows still require message loop.


--
HTH
Stoitcho Goutsev (100)



sb said:
I could not find where someone had done this before in C# so I just wrote a
short class from scratch. This class creates a message-only window that
you may/may not be able to use/adapt to fit your needs. It's really rare
that anyone would ever need to do this but who knows :)

HTH
-sb

<MessageWindow.cs>
using System;
using System.Runtime.InteropServices;
namespace TestApplication
{
public class MessageWindow : IDisposable
{
#region DllImports
[DllImport("user32.dll")]
private static extern IntPtr CreateWindowEx(uint dwExStyle, string
lpClassName, string lpWindowName, uint dwStyle,
int x, int y, int nWidth, int nHeight, IntPtr hWndParent,
IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

[DllImport("user32.dll")]
private static extern bool DestroyWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex,
IntPtr dwNewLong);

[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,
IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion

private const int GWL_WNDPROC = -4;
private const int HWND_MESSAGE = -3;

private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg,
IntPtr wParam, IntPtr lParam);


private WndProcDelegate _WndProc;
private IntPtr _OldWndProc;
private IntPtr _hWnd;

public IntPtr Handle // public property
{
get { return _hWnd; }
}

public MessageWindow()
{
_hWnd = CreateWindowEx(0, "STATIC", "MyMessageOnlyWindow", 0,
0, 0, 0, 0,
new IntPtr(HWND_MESSAGE), IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero);
_WndProc = new WndProcDelegate(WndProc);
_OldWndProc = new IntPtr(SetWindowLong(_hWnd, GWL_WNDPROC,
Marshal.GetFunctionPointerForDelegate(_WndProc)));
}

protected IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam,
IntPtr lParam)
{
System.Diagnostics.Debug.WriteLine(msg); // let's see what was
sent
return CallWindowProc(_OldWndProc, hWnd, msg, wParam, lParam);
}

#region IDisposable Members
public void Dispose()
{
if (_hWnd != IntPtr.Zero)
{
DestroyWindow(_hWnd);
_hWnd = IntPtr.Zero;
}
}
#endregion
}
}



<Program.cs>

using System;
using System.Runtime.InteropServices;

namespace TestApplication
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr
wParam, IntPtr lParam);

static void Main(string[] args)
{
MessageWindow m = new MessageWindow();

SendMessage(m.Handle, 55, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
SendMessage(m.Handle, 77, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
}
}
}
 
G

Guest

Thanks sb, I'm trying to implement the example code you posted. I tried to
compile the code but am getting an error on this line of code:

_OldWndProc = new IntPtr(SetWindowLong(_hWnd, GWL_WNDPROC,
Marshal.GetFunctionPointerForDelegate(_WndProc)));

It's saying that Marshal does not contain a definition for
'GetFunctionPointerForDelegate'
I tried to look up another function that may be comparable but didn't see
anything.
Is there another way to get the pointer without using this function since
it's not defined.
Thanks for your help!

sb said:
I could not find where someone had done this before in C# so I just wrote a
short class from scratch. This class creates a message-only window that you
may/may not be able to use/adapt to fit your needs. It's really rare that
anyone would ever need to do this but who knows :)

HTH
-sb

<MessageWindow.cs>
using System;
using System.Runtime.InteropServices;
namespace TestApplication
{
public class MessageWindow : IDisposable
{
#region DllImports
[DllImport("user32.dll")]
private static extern IntPtr CreateWindowEx(uint dwExStyle, string
lpClassName, string lpWindowName, uint dwStyle,
int x, int y, int nWidth, int nHeight, IntPtr hWndParent,
IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);

[DllImport("user32.dll")]
private static extern bool DestroyWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex,
IntPtr dwNewLong);

[DllImport("user32.dll")]
private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc,
IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
#endregion

private const int GWL_WNDPROC = -4;
private const int HWND_MESSAGE = -3;

private delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg,
IntPtr wParam, IntPtr lParam);


private WndProcDelegate _WndProc;
private IntPtr _OldWndProc;
private IntPtr _hWnd;

public IntPtr Handle // public property
{
get { return _hWnd; }
}

public MessageWindow()
{
_hWnd = CreateWindowEx(0, "STATIC", "MyMessageOnlyWindow", 0, 0,
0, 0, 0,
new IntPtr(HWND_MESSAGE), IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero);
_WndProc = new WndProcDelegate(WndProc);
_OldWndProc = new IntPtr(SetWindowLong(_hWnd, GWL_WNDPROC,
Marshal.GetFunctionPointerForDelegate(_WndProc)));
}

protected IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam,
IntPtr lParam)
{
System.Diagnostics.Debug.WriteLine(msg); // let's see what was
sent
return CallWindowProc(_OldWndProc, hWnd, msg, wParam, lParam);
}

#region IDisposable Members
public void Dispose()
{
if (_hWnd != IntPtr.Zero)
{
DestroyWindow(_hWnd);
_hWnd = IntPtr.Zero;
}
}
#endregion
}
}



<Program.cs>

using System;
using System.Runtime.InteropServices;

namespace TestApplication
{
class Program
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr
wParam, IntPtr lParam);

static void Main(string[] args)
{
MessageWindow m = new MessageWindow();

SendMessage(m.Handle, 55, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
SendMessage(m.Handle, 77, IntPtr.Zero, IntPtr.Zero);
Console.ReadLine();
}
}
}
 
S

sb

My apologies...that method was added in version 2.0 of the framework.

You can make the following two changes to the code I posted and it should
work:

private static extern int SetWindowLong(IntPtr hWnd, int nIndex,
WndProcDelegate dwNewLong);

_OldWndProc = new IntPtr(SetWindowLong(_hWnd, GWL_WNDPROC, _WndProc));

-sb
 
S

sb

I just caught that you're using XP _Embedded_...so the dll name will
probably have to be changed to "coredll.dll" in all of the DLL import
lines...otherwise it should work fine.

-sb
 
G

Guest

sb, is there anyway I'd be able to IM you. I have a few more questions about
wndproc?

Thanks
Nicki
 
S

sb

Sure...but I won't be back on until tomorrow PM. Yahoo IM ("stormfire1") or
ICQ (1844767)

-sb
 

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