How to pause a for loop

I want to make a system that counts up to 5 on a win32 screen but my issue is I cant figure out a way to pause just the for loop because everything I try just pauses the whole window and everything not just the for loop. Any Ideas how to fix it?
Last edited on
Do you have the code you wrote to attempt this? You might be using a less-than-optimal idea, especially if you aren't using a timer.
This is what I am doing
1
2
3
4
5
6
    for (int i = 1; i <= 5; ++i) {
        cout << i << " ";


        Sleep(5000);
    }


but the issue is it pauses the whole script including the window and I dont want that I just want it to pause the for loop. Can you help?
Sleep, as you found out, is a blocking function. Don't use it in a WinAPI app if you want the app to be responsive at all times. Use a timer instead.

Here's some generic WinAPI code for using a timer, it doesn't count the number of times it fires, it fires every second until the app is closed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>

#define ID_TIMER    1

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
VOID    CALLBACK TimerProc(HWND, UINT, UINT_PTR, DWORD);

int WINAPI wWinMain(_In_     HINSTANCE hInstance,
                    _In_opt_ HINSTANCE hPrevInstance,
                    _In_     PWSTR     pCmdLine,
                    _In_     int       nShowCmd)
{
   UNREFERENCED_PARAMETER(hPrevInstance);
   UNREFERENCED_PARAMETER(pCmdLine);

   static WCHAR szAppName[] = L"Timer";
   HWND         hwnd;
   MSG          msg;
   WNDCLASSW    wndclass;

   wndclass.style         = CS_HREDRAW | CS_VREDRAW;
   wndclass.lpfnWndProc   = WndProc;
   wndclass.cbClsExtra    = 0;
   wndclass.cbWndExtra    = 0;
   wndclass.hInstance     = hInstance;
   wndclass.hIcon         = (HICON)   LoadImageW(NULL, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
   wndclass.hCursor       = (HCURSOR) LoadImageW(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED);
   wndclass.hbrBackground = (HBRUSH)  (COLOR_WINDOW + 1);
   wndclass.lpszMenuName  = NULL;
   wndclass.lpszClassName = szAppName;

   if (!RegisterClassW(&wndclass))
   {
      MessageBoxW(NULL, L"Program requires Windows NT or later!",
                  szAppName, MB_ICONERROR);
      return 0;
   }

   hwnd = CreateWindowW(szAppName, L"Timer Demo",
                        WS_OVERLAPPEDWINDOW,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        CW_USEDEFAULT, CW_USEDEFAULT,
                        NULL, NULL, hInstance, NULL);

   ShowWindow(hwnd, nShowCmd);
   UpdateWindow(hwnd);

   while (GetMessageW(&msg, NULL, 0, 0))
   {
      TranslateMessage(&msg);
      DispatchMessageW(&msg);
   }
   return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
   switch (message)
   {
   case WM_CREATE:
      SetTimer(hwnd, ID_TIMER, 1000, TimerProc);
      return 0;

   case WM_DESTROY:
      KillTimer(hwnd, ID_TIMER);
      PostQuitMessage(0);
      return 0;
   }
   return DefWindowProcW(hwnd, message, wParam, lParam);
}

VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT_PTR iTimerID, DWORD dwTime)
{
   UNREFERENCED_PARAMETER(message);
   UNREFERENCED_PARAMETER(iTimerID);
   UNREFERENCED_PARAMETER(dwTime);

   static BOOL fFlipFlop = FALSE;
   HBRUSH      hBrush;
   HDC         hdc;
   RECT        rc;

   MessageBeep(-1);
   fFlipFlop = !fFlipFlop;

   GetClientRect(hwnd, &rc);

   hdc    = GetDC(hwnd);
   hBrush = CreateSolidBrush(fFlipFlop ? RGB(255, 0, 0) : RGB(0, 0, 255));

   FillRect(hdc, &rc, hBrush);
   ReleaseDC(hwnd, hdc);
   DeleteObject(hBrush);
}

You will likely want to have a static variable in your timer procedure function, and when the timer fires increment the variable. When the variable reaches your cut-off point destroy the timer. You can create a new timer later if you need it.

This code can be compiled as either C or C++ code, as long as you target it for the Windows subsystem instead of console mode.
I am relatively new and I am just wondering is there a way to call a function after the timer has finished? Thanks for helping I have been trying to fix that issue for so long
What exactly do you mean by "call a function after the timer has finished"?

You simply recreate the timer to reuse the timer procedure in some part of your window procedure. HOW you do that depends on a lot of factors you need to analyze where, when and how.

Windows apps are not like console mode apps, everything you deal with is event driven.

If you are unfamiliar with Windows cooperative processing a tutorial with examples I can recommend is:

theForger's Win32 API Tutorial - Winprog
http://www.winprog.org/tutorial/

If you are unfamiliar with C/C++ console mode programming you should spend some time learning that with a free online tutorial at Learn C++:

https://www.learncpp.com/

I don't know what your compiler/IDE is, but I really do recommend Visual Studio 2022 Community. It is free to use for non-businesses and is very feature rich. I used it to slap that code snippet above together.

https://visualstudio.microsoft.com/vs/community/

At this time VS is the only compiler that is 100% C++20 compliant. For me that is a big deal.
The WinAPI has evolved considerably over the years, the current idea of Windows apps now is they don't use the WinAPI Desktop model. The style of code used in my code snippet above.

I'm an ol' fart who prefers using the desktop model. The newer technologies do a lot more hand-holding and hiding the nitty-gritty details from you.
you can also just move the for loop into its own function as a thread. This will sleep only that thread, not the main thread, so your windows will remain responsive while the loop does its tick and nap stuff.
this would actually be much, much less complexity, weirdness, and code than doing it the windows way. The windows example is great, though and you need to see it, because more complicated problems may not be so easily resolved (where there is a real gui interaction that a simple thread won't do exactly what you need).

you should also take note of this behavior -- surely you have seen programs 'lock up' before? This is caused by a long running loop that was not stuffed into some construct (thread/timer/other) that allowed the main thread to keep going to process mouse/draw/etc tasks. You don't want to go overboard on it, but you also don't want your program to be the one that always goes out to lunch when you click 'go' or 'open a file' or the like :)
Topic archived. No new replies allowed.