Gah! Windows! (What's windows message 0x031f?)

Started by
4 comments, last by Narf the Mouse 12 years ago
I added some Mouse input and an Input class to my engine. Now, the first thing my Window object does when HandleMessage() is called is get "msg #799". I'm not even using the new input classes in the code!

This nulls the functions' "this" Window object.

My Window object contains a System.Windows.Forms object (the displayForm whos' handle is being passed). It is *Not* a System.Windows.Forms object, nor is its handle passed.

public void HandleMessages()
{
System.Windows.Forms.Message message;
// "this" exists in the local context.
while (!Closed && PeekMessage(out message, displayForm.Handle, 0, 0, 1) != -1)
// "this" does not exist in the local context.
{
GetMessage(out message, displayForm.Handle, 0, 0); // Can't find "this.displayForm"; exits with NullReferenceException.
if (!displayForm.PreProcessMessage(ref message))
DispatchMessage(out message);
}
}

However, only the function-local "this" pointer is nulled; there seems to be no effect on the ability to call functions of my Window class. (Although I haven't tested outside of watching Window.Dispose() running just fine)
Advertisement
Hmm...

Orphaned files exist on the volume but could not be recovered because no more new names could be created in the recovery directory. Files must be moved from the recovery directory.
[/quote]
The number you gave is WM_DWMNCRENDERINGCHANGED. Doesn't seem to be input related at all.

Windows will send all kind of messages to a window. Do never expect any set series of messages to appear during startup. Or the series to stay as is on different versions of Windows. Just handle the messages that are of interest and pass the rest on to DefWindowProc (if that applies to your Windows.Forms/Win32 API mixture)

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Ninja'd

What looks a bit screwy is the PeekMessage. If that's a P/Invoke call you almost certainly need to describe the native MSG structure too and use that rather than System.Windows.Forms.Message. P/Invoke.net explicitly warns against using that as the first parameter.

You may be intending this, but just in case, if your PeekMessage finds a message it's dropped completely. To just check if there's a message, the last parameter to PeekMessage is 0 (PM_NOREMOVE)

DispatchMessage could also be retyped as taking a ref parameter instead of out, if for nothing else than clearer intent and code doc.

The number you gave is WM_DWMNCRENDERINGCHANGED. Doesn't seem to be input related at all.

Windows will send all kind of messages to a window. Do never expect any set series of messages to appear during startup. Or the series to stay as is on different versions of Windows. Just handle the messages that are of interest and pass the rest on to DefWindowProc (if that applies to your Windows.Forms/Win32 API mixture)

The relevant code:

/// <summary>
/// Handles incoming windows messages automatically.
/// Returns when done.
/// </summary>
public void HandleMessages()
{
System.Windows.Forms.Message message;
while (PeekMessage(out message, displayForm.Handle, 0, 0, 0) != -1)
{
GetMessage(out message, displayForm.Handle, 0, 0);
if (!displayForm.PreProcessMessage(ref message))
DispatchMessage(out message);
}
}


/// <summary>
/// Peeks at the next message for a windows object.
/// </summary>
/// <param name="msg"></param>
/// <param name="hWnd"></param>
/// <param name="messageFilterMin"></param>
/// <param name="messageFilterMax"></param>
/// <param name="flags"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int PeekMessage(out System.Windows.Forms.Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
/// <summary>
/// Gets the next message for a windows object.
/// </summary>
/// <param name="msg"></param>
/// <param name="hWnd"></param>
/// <param name="messageFilterMin"></param>
/// <param name="messageFilterMax"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int GetMessage(out System.Windows.Forms.Message msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax);
/// <summary>
/// Dispatches a message.
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int DispatchMessage(out System.Windows.Forms.Message msg);

Aside from changing them to return int, not bool, that's what I originally had - Changing PeekMessage to remove the message was done to see if it would change the error I got. On second thought, doing so doesn't make sense.

Any idea why I'd be getting that message and/or why it would result in the error I saw?

Ninja'd

What looks a bit screwy is the PeekMessage. If that's a P/Invoke call you almost certainly need to describe the native MSG structure too and use that rather than System.Windows.Forms.Message. P/Invoke.net explicitly warns against using that as the first parameter.

You may be intending this, but just in case, if your PeekMessage finds a message it's dropped completely. To just check if there's a message, the last parameter to PeekMessage is 0 (PM_NOREMOVE)

DispatchMessage could also be retyped as taking a ref parameter instead of out, if for nothing else than clearer intent and code doc.

So, I'd need to replicate the structure shown here: Link? What's a good match in C# for HWND, WPARAM, LPARAM and Point? I'm thinking a uint, dunno, dunno, and maybe just a custom struct containing an integer X and Y. *Google* Ok, so if I set the HWND, WPARAM and LPARAM to be IntPtrs, they should automatically size to the size the platform (32-bit or 64-bit) expects - But would they work with what the Peek/Get/DispatchMessage functions expect?

Any idea why it's nulling stuff or why I'm seeing the message?
Alright, I don't know if it was this refactoring or not, but I'm not seeing the message or null-exception anymore.

struct tagMSG
{
public UIntPtr hwnd;
public uint message;
public UIntPtr wParam;
public UIntPtr lParam;
public uint time;
public POINT pt;
}


struct POINT
{
public long x;
public long y;
}


/// <summary>
/// Handles incoming windows messages automatically.
/// Returns when done.
/// </summary>
public void HandleMessages()
{
if (!Closed)
{
tagMSG message;
int ret;
while ((ret = PeekMessage(out message, displayForm.Handle, 0, 0, 0)) != 0)
{
if (ret == -1)
throw new Exception("Unknown error in message handling.");
ret = GetMessage(out message, displayForm.Handle, 0, 0);
if (ret == -1)
throw new Exception("Unknown error in message handling.");
{
System.Windows.Forms.Message messageTemp = new System.Windows.Forms.Message();
messageTemp.HWnd = (IntPtr)(int)(uint)message.hwnd;
messageTemp.LParam = (IntPtr)(int)(uint)message.lParam;
messageTemp.Msg = (int)message.message;
messageTemp.WParam = (IntPtr)(int)(uint)message.wParam;
if (!displayForm.PreProcessMessage(ref messageTemp))
{
if (Closed)
break;
ret = DispatchMessage(ref message);
if (ret == -1)
throw new Exception("Unknown error in message handling.");
}
}
if (Closed)
break;
}
}
}


/// <summary>
/// Peeks at the next message for a windows object.
/// </summary>
/// <param name="msg"></param>
/// <param name="hWnd"></param>
/// <param name="messageFilterMin"></param>
/// <param name="messageFilterMax"></param>
/// <param name="flags"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int PeekMessage(out tagMSG msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax, uint flags);
/// <summary>
/// Gets the next message for a windows object.
/// </summary>
/// <param name="msg"></param>
/// <param name="hWnd"></param>
/// <param name="messageFilterMin"></param>
/// <param name="messageFilterMax"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int GetMessage(out tagMSG msg, IntPtr hWnd, uint messageFilterMin, uint messageFilterMax);
/// <summary>
/// Dispatches a message.
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
[System.Security.SuppressUnmanagedCodeSecurity] // We won't use this maliciously
[System.Runtime.InteropServices.DllImport("User32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern int DispatchMessage(ref tagMSG msg);

This topic is closed to new replies.

Advertisement