Drawing takes place when the draw code is called. And other things may also draw or partially draw directly when things happen. But in most cases drawing takes place on a paint event (WM_PAINT), this is because windows may need to be refreshed for many reasons. When you for example resize a window it will be invalidated and on the next WM_PAINT event the application should redraw the window in its new size.
Drawing out side WM_PAINT can make sense when you want to have some immediate GUI feedback for example when dragging a window divider, but the exact same drawing should also take place in the WM_PAINT event otherwise you may see that the divider disappears again.
Anyways, the problem is still the same the message window and most other controls and windows are (only) drawn in the WM_PAINT event and unless such one is handled no drawing will take place.
Therefore (and for many other reasons) event handling should be short so that other events will also be handled. But the WM_PAINT event is even more "delicate" Windows places this event on an applications event queue automatically, but only when the queue becomes empty. The idea is the application handles all kinds of events (mouse, keyboard, resize, etc.) and when things "settle" it refresh the graphical appearance of the window to reflect the changes caused by the various events.
Threads
Working with threads is both very simple and quite difficult, in the sense that it is very simple to create a new thread that does something it parallel with the other threads in the program and quite difficult because different threads can easily mess things up for each other.
In Windows nearly all GUI routines may only be called by the GUI thread, i.e. by the thread that run the message loop (aka message pump). The exceptions to this rule falls in two categories:
- Any thread can post a message to a window
- Certain (few) operations have a clear purpose to deal with "foreign" windows, but often they are just meant to locate such windows so that you can post a message to it.
So if you have a thread (other than the GUI thread itself) that want to influence the GUI, then it will have to do it indirectly by informing the GUI thread that the update should take place. I.e. the update will have to be shifted from the non-GUI thread to the GUI thread. Such shifting will have an asynchronous character, the non-GUI thread will "ask" for an update and eventually/later the GUI thread will perform it. If the non-GUI thread need to wait for the update to be effectuated you will have to use some other means to synchronize back from the GUI thread to the non-GUI thread.
The code you present does not make sense to put into a separate thread, because the code does very little except updating the GUI, and that have to be shifted back to the GUI thread anyway.
The code fragment you show should not run with highest possible intensity, it would seem silly to spend CPU cycles on running this code in a tight loop. So what I would suggest is to run this loop as a "delayCall" loop:
Code: Select all
predicates
updateStatus() :-
Heap=memory::getFreeHeap(),
Stack=memory::getFreeStack(),
Rem1=string::format("Flight #% Distance: % Min Distance %, Max Distance % Mean Distance % Stack size: % Heap size: % \n",itcount,round(Distance),round(minDistance),round(maxDistance),round(meanDistance),Stack, Heap),
%test show rem1 all over the shop
stdio::write(Rem1),
setText(Rem1),
formB::set_top_edit_ctl(Rem1),
formB::setPublicText(Rem1),
delayCall(50, updateStatus).
updateStatus will "update the status" and after 50 milliseconds it will do the same again. delayCall works by means of a WM_TIMER event, so this code will be scheduled into the event handling every 50 milliseconds, all the rest of the time the program can handle other events including WM_PAINT events which will actually make the GUI update the window.
The lines you mention they really should be drawn in the WM_PAINT/onPaint handler.