There are a few things to bear in mind when changing the cursor. The cursor may only be set in the thread to which the window that processes the messages belongs. When working on a long operation, a thread is usually started to keep the interface usable for the user so that he can continue to press the stop button, for example. Considering this, there is another problem, because the cursor is automatically reset to the normal appearance when it is moved over the window and thus triggers other events.
The solution is a status variable that stores the status of the long operation. The cursor can then be continuously set to the wait cursor in the WM_SETCURSOR message as long as the long operation is running.
Overall, it could look like this:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool g_LongOpRunning = false;
switch (message) {
case WM_START_LONG_OPERATION: {
g_LongOpRunning = true;
SetCursor(LoadCursor(NULL, IDC_WAIT));
std::thread(ThreadFunction, hWnd).detach();
}
break;
case WM_LONG_OPERATION_COMPLETE:
g_LongOpRunning = false;
break;
case WM_SETCURSOR:
if (g_LongOpRunning) {
SetCursor(LoadCursor(NULL, IDC_WAIT));
return TRUE;
}
break;