Well, I tried it myself - and I was wrong. PostMessage() can not be used in this way. Even though the message loop is running - it starves other messages from being processed - essentially making your message loop an infinite one.
SetTimer() can be used in this fashion, since WM_TIMER is the very last message to be processed by GetMessage(). Using a timeout of 0 will cause WM_TIMER to come in immediately - and the message loop won't ignore other messages as they come in.
Of course this method doesn't apply in all cases - and threading is bit more straight forward for doing something "in the background" while keeping your UI responsive.
Code:
#include <windows.h>
#include <iostream>
using namespace std;
#define DO_WORK_ID 42
LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);
int main()
{
const char *className = "WindowsApp";
WNDCLASSA wincl = {0};
wincl.hInstance = GetModuleHandle(0);
wincl.lpszClassName = className;
wincl.lpfnWndProc = WinProc;
wincl.style = CS_DBLCLKS;
wincl.hIcon = LoadIcon(0, IDI_APPLICATION);
wincl.hCursor = LoadCursor(0, IDC_ARROW);
wincl.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
if (!RegisterClassA(&wincl))
return 1;
HWND hwndParent;
hwndParent = CreateWindowA(className, "Windows App",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 100, HWND_DESKTOP, 0,
GetModuleHandle(0), 0);
if (!hwndParent)
return 1;
HWND hwndChild;
hwndChild = CreateWindowA("Button", "Button", WS_CHILD | WS_VISIBLE,
10, 10, 170, 50,
hwndParent, (HMENU)BUTTON_ID,
GetModuleHandle(0), 0);
if (!hwndChild)
return 1;
MSG msg;
BOOL bRet;
for (;;)
{
bRet = GetMessage(&msg, hwndParent, 0, 0);
if ((bRet == 0) || (bRet == -1))
break;
if (msg.message == WM_TIMER)
cout << "msg = WM_TIMER" << endl;
else
cout << "msg = " << msg.message << endl;
TranslateMessage(&msg);
DispatchMessage(&msg);
}//while
return (int)msg.wParam;
}//main
LRESULT CALLBACK WinProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
static int counter = 0;
static bool bRun = false;
switch(msg)
{
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}//case
case WM_COMMAND:
{
if (wParam == BUTTON_ID)
{
bRun = !bRun;
if (bRun)
{
cout << "bRun = true" << endl;
SetTimer(hwnd, DO_WORK_ID, 0, 0);
}//if
else
{
cout << "bRun = false" << endl;
KillTimer(hwnd, DO_WORK_ID);
}//else
return 0;
}//if
}//case
case WM_TIMER:
{
cout << "Do Work: " << ++counter << endl;
return 0;
}//case
}//switch
return DefWindowProc(hwnd, msg, wParam, lParam);
}//WinProc
gg