GUI freezes after few seconds in this little Dialog based apllication

Pages: 12
Hello,
im a beginner trying to understand the reason why the GUI freezes after very few seconds here.
Try run it and see what i mean..
Shouldn't it keep printing Hello1 Hello2 Hello3 Hello4 and Hello5 forever?
To be clear: it is SetWindowText() that stops doing the job, so it is the GUI that freezes.
What i mean is, the application keeps running, it is just the "show text" part, that crashes.
I know this because i debugged it before posting.
So what am i missing? Why is it freezing?
Do you know?
Thanks in advance

Here is main.cpp:
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
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resource.h"

using namespace std;

HINSTANCE hInst;

void sayHello(HWND handle)
{
    BOOL working = true;
    while (working)
    {
        SetWindowText(handle, "Hello1");
        SetWindowText(handle, "Hello2");
        SetWindowText(handle, "Hello3");
        SetWindowText(handle, "Hello4");
        SetWindowText(handle, "Hello5");
    }
}

BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
            return TRUE;

        case WM_CLOSE:
            EndDialog(hwndDlg, 0);
            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDC_BTN_QUIT:
                    EndDialog(hwndDlg, 0);
                    return TRUE;

                case IDC_BTN_TEST:
                    HWND handle = GetDlgItem(hwndDlg, 1003);
                    sayHello(handle);
                    return TRUE;
            }
    }

    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst = hInstance;

    return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);
}

Here is resource.h:
1
2
3
4
5
6
#include <windows.h>

#define DLG_MAIN 101
#define IDC_BTN_TEST 1001
#define IDC_BTN_QUIT 1002
#define ID_CONTROLSTATIC 1003 

Here is resource.rc:
1
2
3
4
5
6
7
8
9
10
11
#include "resource.h"

DLG_MAIN DIALOGEX 6, 5, 194, 106

CAPTION "Test Application"

BEGIN
  CONTROL "&Test", IDC_BTN_TEST, "Button", 0x10010000, 138,  5, 46, 15
  CONTROL "TEXT HERE", ID_CONTROLSTATIC, "Static", 0x10010000, 35, 35, 50, 8
  CONTROL "&Quit", IDC_BTN_QUIT, "Button", 0x10010000, 138, 29, 46, 15
END
Your while loop from myHello() function never breaks, this is the problem.
So how would you code it so that it doesn't freeze?
It depends on what you really want to do ...
For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void sayHello(HWND handle)
{
    BOOL working = true;
    size_t i = 0;
    while (working)
    {
        SetWindowText(handle, "Hello1");
        SetWindowText(handle, "Hello2");
        SetWindowText(handle, "Hello3");
        SetWindowText(handle, "Hello4");
        SetWindowText(handle, "Hello5");
        if (i > 10) {
             break;
       }
        i++;
    }
}
I want it to print continously Hello1 Hello2 Hello3 Hello4 and Hello5.
It shall never stop.
Of course sayHello() is a stand-in for a longer function.
Then the most simple way is to use a timer and handle WM_TIMER message.
How should it be implemented?
Please show some code.
Thanks
Maybe you could put this inside your loop:
 
UpdateWindow(handle);


Which would cause the window to update during your loop.
Last edited on
modoran, why do you use a size_t for the counter instead of an unsigned short?
unsigned short is limited to 0 - 65535 (suppose unsigned short = 2 bytes). It will work in this particular case, but for very large loops size_t is desirable.
Google up the SetTimer/KillTimer functions and you'll know how to use WM_TIMER as proposed by modoran, which would be the right approach here.
I tried
UpdateWindow(handle);
but it doesn't work.
I googled setTimer/KillTimer but don't know how it is supposed to be used here.
Can you explain?
In WM_CREATE:
UINT_PTR m_timer = SetTimer (NULL, 0, 1000, NULL);

In WM_TIMER:
// do the real job here, will be called every 1000 ms in this example

In WM_DESTROY:
KillTimer (m_timer);


I hope you get the idea ...
I get what you mean now.
So you are basically telling me to slow it down. Well, i need it to be fast as possible.
But most importantly, i think it will not work because the freezing problem arises due to the GUI internals, and not because of the speed.
That is why i'm using this following solution (suggested on an other website):
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
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resource.h"

using namespace std;

HINSTANCE hInst;

void DoEvents()
{
  MSG msg; // <- this was missing

   while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
   {
      if(::GetMessage(&msg, NULL, 0, 0))
      {
          ::TranslateMessage(&msg);
          ::DispatchMessage(&msg);
      }
      else
          break;
   }
}

                                            

void sayHello(HWND handle)
{
    BOOL working = true;
    while (working)
    {
        SetWindowText(handle, "Hello1");
        SetWindowText(handle, "Hello2");
        SetWindowText(handle, "Hello3");
        SetWindowText(handle, "Hello4");
        SetWindowText(handle, "Hello5");

        DoEvents(); // <--- keeps the GUI going
    }
}

BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        case WM_INITDIALOG:
            return TRUE;

        case WM_CLOSE:
            EndDialog(hwndDlg, 0);
            return TRUE;

        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case IDC_BTN_QUIT:
                    EndDialog(hwndDlg, 0);
                    return TRUE;

                case IDC_BTN_TEST:
                    HWND handle = GetDlgItem(hwndDlg, 1003);
                    sayHello(handle);
                    return TRUE;
            }
    }

    return FALSE;
}


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
    hInst = hInstance;

    return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, (DLGPROC)DialogProc);
}
                                  
                                            

Thanks anyway
Your DoEvents() is incorrect because it fetches two messages but only processes one of them (the second one fetched).
You're right.
Corrected would then be:
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
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "resource.h"

using namespace std;

HINSTANCE hInst;

void DoEvents()
{
  MSG msg; // <- this was missing

   while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
   {
      if(::GetMessage(&msg, NULL, 0, 0))
      {
          ::TranslateMessage(&msg);
          ::DispatchMessage(&msg);
      }
      else
      {
          break;
      }
      ::TranslateMessage(&msg);
      ::DispatchMessage(&msg);
   }
}

Is that fine now? Or am i missing something else?
Thank you
Incorrect. The first message is lost as soon as GetMessage() fetches another one because it is the same variable, and if you were to correct this by using a second MSG variable, you would still be processing the message retrieved by PeekMessage() after the message retrieved by GetMessage(). You could, for example, get a WM_LMOUSEBUTTONUP before the corresponding WM_LMOUSEBUTTONDOWN, etc.

You just don't use GetMessage(). You just use PeekMessage() and I also think you need to limit the range of messages retrieved. I've never done it, but I would imagine you should limit DoEvents() to pumping UI messages.

But even if you were to get the message filters right, your window is a dialog box. Dialog box messages are usually processed by IsDialogMessage() and not a message pump, and I am actually unsure if this DoEvents() of yours is appropriate for dialog boxes. I don't really know that much to dictate whether this DoEvents() is safe for dialog boxes.

But really really, you shouldn't be doing this at all. If you want to do the work as fast as possible you can simply spawn a new thread and do the work in the new thread. You would then post update messages to the UI thread every now and then.
I thought of using a thread but then this guy posted this method to overcome the freezing problem and, since i have no idea where to start with threads (other than google obviously) i abandoned the idea of it.
Would you be so kind to show me how to use threads please?
What library should i/do you use?
Thanks a lot
You refuse to use SetTimer() as not being fast enough (do you know what 3rd argument do ???) and you want to use threads ??? Very interesting, to not say other words ... :)

So you are basically telling me to slow it down. Well, i need it to be fast as possible.
But most importantly, i think it will not work because the freezing problem arises due to the GUI internals, and not because of the speed.

Can anyone show how to implement CreateThread() in this application?
Pages: 12