Old school Win32 Message Only Window cannot receive messages - c++

I'm realize the console win32 app does not quit cleanly so I'm trying to switch to message only windows instead. I'm starting the app from another process and trying to kill it cleanly.
This is the win32 app, it spawns a calc.exe on startup and on clean shutdown, it should kill the calc.exe
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_USER: PostQuitMessage (0); break;
default: return DefWindowProc (hWnd, message, wParam, lParam);break;
}
return 0;
}
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int show)
{
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof (WNDCLASSEX);
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = L"WindowClass1";
RegisterClassEx (&wc);
HWND hWnd = CreateWindowEx (NULL,
L"WindowClass1", // name of the window class
L"Our First Windowed Program", // title of the window
0,
//WS_OVERLAPPEDWINDOW, // window style
300,300,500,400,
HWND_MESSAGE,
//NULL, // parent window, NULL
NULL, hInstance, NULL);
//ShowWindow (hWnd, SW_HIDE);
PROCESS_INFORMATION pi;
CreateWindowProcess (L"calc.exe", pi); // helper class to createprocess
MSG msg = { 0 };
while (true)
{
if (PeekMessage (&msg, 0, 0, 0, PM_REMOVE))
{
if (WM_QUIT == msg.message)
break;
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
// terminate the spawn process, this is not called cleanly
TerminateProcess (pi.hProcess, 0);
return (int)msg.wParam;
}
I made a c# program to start/kill the app cleanly (the calc.exe gets destroyed) by sending a WM_QUIT/WM_CLOSE/WM_USER message . The Win32 App does not receive messages unless the window is visible (WS_OVERLAPPED and ShowWindow true). PostMessage WM_QUIT is received but the calc.exe does not get destroyed, meaning it is not a clean exit.
How should I kill it cleanly from C# app?
class Program
{
[DllImport ("user32.dll")]
public static extern bool PostMessage (IntPtr hwnd, uint msg, int wparam, int lparam);
[DllImport ("User32.dll")]
public static extern int SendMessage (IntPtr hWnd, uint uMsg, int wParam, int lParam);
static void Main (string [] args)
{
try
{
Process myProcess;
myProcess = Process.Start ("My.exe");
// Display physical memory usage 5 times at intervals of 2 seconds.
for (int i = 0; i < 3; i++)
{
if (myProcess.HasExited) break;
else
{
// Discard cached information about the process.
myProcess.Refresh ();
Thread.Sleep (4000);
Console.WriteLine ("Sending Message");
const int WM_USER = 0x0400;
const int WM_CLOSE = 0xF060; // Command code for close window
const int WM_QUIT = 0x0012;
// Received only when windows is visible
//int result = SendMessage (myProcess.MainWindowHandle, WM_USER, 0, 0);
// not clean exit
PostMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
// doesn't receive
SendMessage (myProcess.MainWindowHandle, WM_QUIT, 0, 0);
}
}
}
}
}

Processes on Windows do not really have a "MainWindow". Process.MainWindowHandle is C# making a guess, and it guesses by looking to see if the process in question has a window with focus - which will only find visible windows. Use FindWindowEx to find the window handle you want to close.
Next, when a window closes, it does not automatically try to exit the current threads message loop. You need to handle WM_DESTROY to call PostQuitMessage.
In your message loop use GetMessage rather than PeekMessage if you are not doing any other work as PeekMessage returns immediately if there are no messages meaning the application thread will never have an opportunity to sleep.
With these changes in place you should be fine to simply post a WM_CLOSE to the valid window handle as it will be destroyed, post itself a WM-QUIT message to exit the message loop, and terminate the calc process properly.

Related

PostMessage not working with posting custom message

I used
PostMessage(NULL,WM_DUCKWND,0,0);
where
#define WM_DUCKWND (WM_USER +4)
to send user-defined msg to all windows in current thread.
DETAILS
this is straight in the main function
(DUCKPROC_CLASS_MSG_NAME and DUCKPROC_WINDOW_MSG_NAME are all user-defined macros)
//create message-only window
WNDCLASS wndc={};
wndc.lpfnWndProc = MsgWindowProc;
wndc.hInstance = hInstance;
wndc.lpszClassName = DUCKPROC_CLASS_MSG_NAME;
RegisterClass(&wndc);
auto hw=CreateWindowEx(NULL, DUCKPROC_CLASS_MSG_NAME, DUCKPROC_WINDOW_MSG_NAME, NULL, 0, 0, 0, 0, HWND_MESSAGE, NULL, hInstance, NULL);
//post
PostMessage(NULL,WM_DUCKWND,0,0);
//message loop
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
and used WindProc like this
LRESULT CALLBACK MsgWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
switch (uMsg)
{
case WM_DUCKWND:
[BREAKPOINT][BREAKPOINT][BREAKPOINT][BREAKPOINT]
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
However, the breakpoint isn't triggered as supposed.
How's that wrong?
"all windows in current thread."
No, that's not correct. HWND==NULL sends the message to the thread message queue. That's the message queue you process with your GetMessage(HWND==NULL) loop.
DispatchMessage is the function which looks at HWND in msg, and chooses the correct window proc. It does so by looking up the window class of that HWND.
Since HWND==NULL does not have a window class, it does not have a window proc either, and the message is not dispatched to any window.
If you want to send WM_DUCKWND(HWND==NULL) to all your windows, you'll have to dispatch it yourself. In this simple example, that's as simple as setting msg.hWnd=hw for msg.message==WM_DUCKWND && msg.hWnd==NULL.
Side note: it really should be WM_APP+4; the WM_USER range is for messages internal to a window class. The thread message queue is shared by windows, so you shouldn't post WM_USER messages to it.

Why is GetMessage exiting my program without sending any message?

here is my problem. I'm trying to create a windowless program that still uses trayIcon and Hooks, so I need to use messages (or not?) but when I use them, I don't know how to free my memory when I kill my process. Even classes's destructors aren't called. Here is a test main:
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR pCmdLine, int nCmdShow)
{
MSG msg;
OutputDebugStringW(L"Start.\n");
while (GetMessageW(&msg, NULL, NULL, NULL) > 0)
{
OutputDebugStringW(L"one.\n");
TranslateMessage(&msg);
OutputDebugStringW(L"two.\n");
DispatchMessage(&msg);
OutputDebugStringW(L"three.\n");
}
OutputDebugStringW(L"end.\n");
return 0;
}
As I saw in the doc, the GetMessage() call should return 0 or less to exit, but when I run it, and then shut it down, I get only the "Start." log, and I don't understand why. And if there is no way to get through this loop, then how can i call my destructors? I do have a window for my trayIcon that doesn't receive any message, maybe i should pass it as parameter to GetMessage()?
PS: my project uses trayIcons and Hooks, and when I run it with the same debug prints, it display once the 4 first strings, but nothing at shutdown, not even the "end." string.
EDIT: my (terrible) trayIcon creation:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
OutputDebugStringW(L"Message!\n");
switch (uMsg)
{
case WM_DESTROY:
OutputDebugStringW(L"Close message received\n");
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
case WM_RBUTTONUP:
{
OutputDebugStringW(L"Trying to open Context menu\n");
POINT const pt = { LOWORD(wParam), HIWORD(wParam) };
break;
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
bool CreateNotifyIcon(HINSTANCE& hInstance)
{
NOTIFYICONDATA notif = {};
static const wchar_t class_name[] = L"ExtendClass";
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = WindowProc;
wx.hInstance = hInstance;
wx.lpszClassName = class_name;
RegisterClassEx(&wx);
HWND win = CreateWindowEx(0, class_name, L"Windows Extend", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (win == NULL)
OutputDebugStringW(L"failed to create window\n");
ZeroMemory(&notif, sizeof(NOTIFYICONDATA));
notif.cbSize = sizeof(NOTIFYICONDATA);
notif.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
// Need to find a non-busy uID
notif.uID = 44421;
notif.hWnd = win;
StringCchCopy(notif.szTip, ARRAYSIZE(notif.szTip), L"Access Windows Extend options.");
StringCchCopy(notif.szInfo, ARRAYSIZE(notif.szInfo), L"Access Windows Extend options.");
StringCchCopy(notif.szInfoTitle, ARRAYSIZE(notif.szInfoTitle), L"Windows Extend");
notif.hIcon = (HICON)LoadImage(NULL, L"./Luma.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE);
if (!Shell_NotifyIcon(NIM_ADD, &notif))
{
OutputDebugStringW(L"failed to create notifIcon\n");
return false;
}
return true;
}
GetMessage() does not return until it receives a window/thread message, or has a message to synthesis. In the code you have shown, you are not creating any windows, not posting any thread messages to yourself, and not creating any hooks that require a message loop, so there is nothing for GetMessage() to do. It is blocked indefinitely. That is why you are only seeing your start message and nothing else happens until you forcibly kill the program.
Since you intend to display a system tray icon, you need a window for it, even if just a hidden window, in order to receive notifications about user interaction with the icon. Your GetMessage() loop will handle messages for all windows created in the same thread as the loop, since you are setting the hWnd parameter to NULL instead of a specific window. Once you create your tray icon window, the loop will receive messages for it just fine. You can then provide your tray icon with a popup menu that contains an item that will exit your message loop when clicked, thus allowing you to exit from WinMain() gracefully, invoke destructors, etc.
GetMessage returns -1 if an error occurs. So you should do while != 0 generally. But if you are not seeing "end", then your application is probably crashing.
https://msdn.microsoft.com/en-us/library/windows/desktop/ms644936(v=vs.85).aspx

Windows API wont quit

For some reason after I close this window my program wont exit and goes into an infinite loop. The solution to this problem seems to be changing GetMessage(&message, handel, 0, 0) to GetMessage(&message, NULL, 0, 0). However I don't understand why this is. Can somebody please explain. Also I don't see why I call UpdateWindow(handel) since the window will show without it.
#include <iostream>
#include <Windows.h>
using namespace std;
LRESULT CALLBACK EventHandler(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, PSTR args, int cmd)
{
MSG message;
HWND handel;
WNDCLASS win_class;
win_class.style = CS_HREDRAW | CS_VREDRAW;
win_class.cbClsExtra = 0;
win_class.cbWndExtra = 0;
win_class.lpszClassName = "Window";
win_class.hInstance = inst;
win_class.hbrBackground = GetSysColorBrush(COLOR_3DDKSHADOW);
win_class.lpszMenuName = NULL;
win_class.lpfnWndProc = EventHandler;
win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
RegisterClass(&win_class);
handel = CreateWindow(win_class.lpszClassName, "Window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 350, 250, NULL, NULL, inst, NULL);
ShowWindow(handel, cmd);
UpdateWindow(handel);
//Loop does not end.
while(GetMessage(&message, handel, 0, 0))
{
cout << "LOOP" << endl;
DispatchMessage(&message);
}
return WM_QUIT;
}
LRESULT CALLBACK EventHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static long long count = 0;
count++;
cout << "CALL #" << count << endl;
if(msg == WM_DESTROY)
{
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
WM_QUIT is not sent to any window, just placed in the thread's message queue with no HWND, that's why it doesn't match your filter.
Take a look at GetMessage and PostQuitMessage in MSDN
If the parameter hWnd of GetMessage function is NULL, GetMessage retrieves messages for any window that belongs to the current thread, and any messages on the current thread's message queue whose hwnd value is NULL.
The PostQuitMessage function posts a WM_QUIT message to the thread's message queue, not to the current window.
Here's a good opportunity to exercise your "search-the-MSDN-documentation" abilities:
First, let's look up the documentation for WM_QUIT:
Indicates a request to terminate an application, and is generated when
the application calls the PostQuitMessage function. This message
causes the GetMessage function to return zero.
...
The WM_QUIT message is not associated with a window and therefore will
never be received through a window's window procedure. It is retrieved
only by the GetMessage or PeekMessage functions.
Then, let's look up the documentation for GetMessage():
Retrieves a message from the calling thread's message queue. The
function dispatches incoming sent messages until a posted message is
available for retrieval.
...
hWnd [in, optional] Type: HWND
A handle to the window whose messages are to be retrieved. The window
must belong to the current thread.
If hWnd is NULL, GetMessage retrieves messages for any window that
belongs to the current thread, and any messages on the current
thread's message queue whose hwnd value is NULL (see the MSG
structure). Therefore if hWnd is NULL, both window messages and thread
messages are processed.
Therefore, you want to use NULL as the window handle for GetMessage(), not handel, since WM_QUIT is not associated with any window.
There's plenty more information about how Windows programs typically handle messages also from MSDN.
As the side note, the message for window close events is WM_CLOSE, which in turn causes your window to be destroyed by default. WM_DESTROY means your window is already on it's way to being destroyed. So if you want to intercept the close event (say to ask your user to save any changes), you would handle the WM_CLOSE event.
Also, as shown in the GetMessage() documentation, you should actually have your GetMessage() loop look like this:
BOOL bRet;
while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Because GetMessage() can actually return 1, 0, or -1 (despite it returning a BOOL).

WinAPI Window Closes Instantly

I have been experimenting with the WINAPI trying to learn it but the window I have created closes instantly. As you see when the W key is pressed or the left button is pressed it will close the program but when running it with no buttons being pressed it still closes.
#include <windows.h>
#include <windowsx.h>
// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam);
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
// register the window class
RegisterClassEx(&wc);
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
L"WindowClass1", // name of the window class
L"Game", // title of the window
WS_OVERLAPPEDWINDOW, // window style
1, // x-position of the window
1, // y-position of the window
1800, // width of the window
1000, // height of the window
NULL, // we have no parent window, NULL
NULL, // we aren't using menus, NULL
hInstance, // application handle
NULL); // used with multiple windows, NULL
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
// enter the main loop:
// this struct holds Windows event messages
MSG msg;
// wait for the next message in the queue, store the result in 'msg'
while (GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch (message)
{
// this message is read when the window is closed
case WM_MOUSEMOVE:
{
// Retrieve mouse screen position
int x = (short)LOWORD(lParam);
int y = (short)HIWORD(lParam);
// Check to see if the left button is held down:
bool leftButtonDown = wParam & MK_LBUTTON;
// Check if right button down:
bool rightButtonDown = wParam & MK_RBUTTON;
if (leftButtonDown == true)
{
//left click
//example lets close the program when press w
PostQuitMessage(0);
return 0;
}
}
case WM_KEYDOWN:
{
switch (wParam)
{
case 'W':
//w pressed
//example lets close the program when press w
PostQuitMessage(0);
return 0;
}
}
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
}
default:
break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);
}
You're missing some break statements in your switch, so for example, if you get the WM_MOUSEMOVE message and the leftButtonDown != true, execution will fall through to WM_KEYDOWN, etc.
Eventually you get to case WM_DESTROY:, which will Post you a lovely QuitMessage.
As an aside, this would be very easy to spot by stepping through, statement-by-statement, in a debugger.
There is no break in your switch statement.
You end up exetuting
PostQuitMessage(0);
You could do something like this:
case WM_FOO:
{
if ( bar ) {
return 0;
}
break;
}
Don't detect clicks via the WM_MOUSEMOVE message, use the WM_MOUSEDOWN instead.
The problem is that your code is probably launched by you clicking on something, so when your window gets its first WM_MOUSEMOVE message, the button is still actually pressed. Code runs much faster than fingers..

Broadcasting to owned window with PostMessage vs. SendNotifyMessage

Recently I came about a strange difference between the two Win32 API calls "PostMessage" and "SendNotifyMessage" (at least noticed on Win7 64bit SP1):
An owned top-level window of another process seems not to receive messages broadcasted (HWND_BROADCAST) with "PostMessage" while it receives messages broadcasted with "SendNotifyMessage" in its WndProc.
The sent message have been registered with the help of a call to "RegisterWindowMessage".
Even using Spy++, I cannot see the message arriving when using "PostMessage". In addition, I want to mention, that if I send the message directly to the specific HWND with "PostMessage", it arrives as expected. So it looks like the windows-internal implementation of "PostMessage" just skips my window when iterating for execution of the broadcast.
Reading the respective MSDN documentation, I cannot see any statement about this difference and I am wondering if this is a bug in PostMessage or in SendNotifyMessage and if I can rely on SendNotifyMessage to continue to show this behavior in future versions of Windows.
So does someone have a plausible explanation why the both functions treat the broadcasts differently in this situation?
In addition, I would want to ask if there is any way to still use PostMessage to broadcast to an owned top-level window, because I would prefer to post the message because I would prefer to not skip the message queue (which is what SendNotifyMessage does).
In case you are curious why I want to reach a top-level owned window: in WPF, windows are hidden from the taskbar (Window.ShowInTaskbar property) by making them owned top-level windows with a hidden owner window.
Thanks a lot in advance for any ideas or comments on this topic.
Attachment: here a sample showing the behavior ... simply build it, and start it two times ... the second process should make a message show up in the first one.
Here is also a link to the complete solution including a build EXE: Link to the complete VS solution
#include <windows.h>
#include <stdio.h>
#include <string>
#include <vector>
HWND hwndMain = NULL;
HWND ownerHwnd = NULL;
std::vector<std::string> theOutput;
UINT MyRegisteredMessage1 = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc = NULL;
if (message == MyRegisteredMessage1 && wParam != (WPARAM) hwndMain)
{
if (lParam == (LPARAM) 1)
theOutput.push_back("Got a 'MyRegisteredMessage1' via PostMessage");
if (lParam == (LPARAM) 2)
theOutput.push_back("Got a 'MyRegisteredMessage1' via SendNotifyMessage");
InvalidateRect(hwndMain, NULL, TRUE);
}
switch (message)
{
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for(size_t i = 0, pos = 0; i < theOutput.size(); ++i, pos += 20)
TextOutA(hdc, 0, pos, theOutput[i].c_str(), theOutput[i].size());
EndPaint (hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WndProcHidden(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
MSG msg;
BOOL bRet;
WNDCLASSA wc;
UNREFERENCED_PARAMETER(lpszCmdLine);
if (!hPrevInstance)
{
wc.style = 0;
wc.lpfnWndProc = (WNDPROC) WndProcHidden;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);;
wc.lpszMenuName = "MainMenu";
wc.lpszClassName = "MyOwnerWindowClass";
if (!RegisterClassA(&wc))
return FALSE;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.lpszClassName = "MyOwnedWindowClass";
if (!RegisterClassA(&wc))
return FALSE;
}
ownerHwnd = CreateWindowA("MyOwnerWindowClass", "OwnerWindow",
WS_OVERLAPPEDWINDOW, 0, 0, 800, 400, (HWND) NULL,
(HMENU) NULL, hInstance, (LPVOID) NULL);
hwndMain = CreateWindowA("MyOwnedWindowClass", "OwnedWindow",
WS_OVERLAPPEDWINDOW, 0, 0, 800, 400, ownerHwnd,
(HMENU) NULL, hInstance, (LPVOID) NULL);
// only show the "real" window
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
MyRegisteredMessage1 = RegisterWindowMessageA("MyRegisteredMessage1");
char infoText[256];
_snprintf_s(infoText, 256,
"HWND = %X, registered message code for 'MyRegisteredMessage1' = %d",
hwndMain, MyRegisteredMessage1);
theOutput.push_back(infoText);
InvalidateRect(hwndMain, NULL, TRUE);
PostMessage(HWND_BROADCAST, MyRegisteredMessage1, (WPARAM) hwndMain, (LPARAM) 1);
Sleep(1000);
SendNotifyMessageA(HWND_BROADCAST, MyRegisteredMessage1, (WPARAM) hwndMain, (LPARAM) 2);
while( (bRet = ::GetMessage( &msg, NULL, 0, 0 )) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
You may need to register your message using RegisterWindowMessage() -- see the Remarks section of this MSDN article
Just adding this here for info..
I was able to get around this issue in c# by registering an IMessageFilter object on the Application level. PreFilterMessage on this object will receive the message and I can handle it from there.
public class FooMessageFilter : IMessageFilter
{
uint UM_FOO = 0;
public event EventHandler OnFoo;
public FooMessageFilter()
{
UM_FOO = Win32.RegisterWindowMessage("UM_FOO");
}
public bool PreFilterMessage(ref Message m)
{
if(m.Msg == UM_FOO)
{
if(OnFoo != null)
OnFoo(this, new EventArgs());
return true;
}
return false;
}
}
I then added this message filter to the Application context in my owned top-level form's constructor.
public partial class Form1 : Form
{
private FooMessageFilter fooFilter = new FooMessageFilter();
public Form1()
{
InitializeComponent();
// Register message filter
Application.AddMessageFilter(fooFilter);
// Subscribe to event
fooFilter.OnFoo += HandleFoo;
}
private void HandleFoo(object o, EventArgs e)
{
MessageBox.Show("Foo!");
}
}
From there it was just a matter of hooking up events in my top-level window to the message filter. This was necessary because of the need to adhere to current architecture, and the message originating from a third party process.
The documentation page(s) for PostMessage() mention that integrity level restrictions apply:
Starting with Windows Vista, message posting is subject to UIPI. The thread of a process can post messages only to message queues of threads in processes of lesser or equal integrity level.
There is no mention of such restrictions on SendNotifyMessage(). Since you don't check the return value of either, you could be running into that, and you wouldn't know it.