0

My MFC dialog's ON_CHECKED... event handler calls a dialog member "doit" that calls SetWindowText onto a dialog static textbox (cMyStatic). Only the 1st and last Set..text data appears in the textbox. I have tried with cMyStatic.Invalidate() and with UpdateData(). It appears that my SetWindowText is being blocked. The sequential code in that same member AFTER the request for SetWindowText does 2 sequential CreateProcess calls, and those processes run perfectly (they do nothing with the dialog - i.e., no user interaction). There is only ONE dialog, created in VS2019, with System Modal set to FALSE. Clearly, I am missing some understanding of the communication between members called from an ON_ unit and the dialog itself, but I have found no references that make it clear what is wrong or how to properly insert text into a dialog's textbox when an ON_ unit for that dialog is running. Can anyone offer suggestions? I suspect I may need to start an independent thread to do the Set..Text, but before I try do that, I'm hoping someone with nmore experience can give me some guidance.

Constantine Georgiou
  • 2,412
  • 1
  • 13
  • 17
DocDJ
  • 31
  • 5
  • 1
    So, there's a loop in your `ON_CHECKED...` handler, right? While that loop is running, no messages are being dispatched. Messages continue being dispatched once the message handler runs to completion. Throwing more threads at a problem is a knee-jerk reaction. There's likely a superior solution, though, without a [mcve] that solution cannot even be envisioned. – IInspectable Apr 11 '23 at 17:02
  • Please clarify your question. [From this](https://stackoverflow.com/questions/75942762/changing-static-text-in-dialog-box-at-runtime-without-calling-updatedata/75945115), in the comments, it seems you want a process to run, maybe getting info from the standard output, and avoid blocking the main thread. Say all that if that is what you are up to. – lakeweb Apr 11 '23 at 17:21
  • What is an `ON_ unit`. Please post some code that shows what you are up to, what sequence of events you are doing. – lakeweb Apr 11 '23 at 19:00
  • 1
    Furthermore, `ON_CHECKED` doesn't seem to an existing MFC message-handler macro... Do you mean `ON_BN_CLICKED`? And what is that control exactly, a pushbutton, a check-box maybe? – Constantine Georgiou Apr 11 '23 at 20:01
  • Is the `SetWindowText()` function called by the same thread that owns the dialog (and the static control) or by another one? – Constantine Georgiou Apr 12 '23 at 15:54

1 Answers1

0

Sounds like the calling/owning thread is busy between the SetWindowText() calls. SetWindowText() doesn't paint the window immediately (check the documentation), the changes will become visible when the WM_PAINT message will be processed, which is low-prioritry message, processed just before the thread is about to enter the idle state. You may just be receiving a single WM_PAINT message as the result of multiple SetWindowText() calls.

Try calling UpdateWindow() (for the static control, and all other controls you want to be updated immediately, or else "synchronously"), just after calling SetWindowText() or UpdateData(FALSE), this bypasses the message-queue and updates the control.

And this has nothing to do with calling these from inside the ON_CHECKED... handler.


EDIT:

I made a small test, but couldn't reproduce your problem. Here is some code:

for (int i = 0; i < 5; i++)
{
    CString s;
    s.Format(_T(" Count: %d"), i+1);
    cMyStatic.SetWindowText(s);
    //cMyStatic.UpdateWindow();
    Sleep(1000);
}

It is called from the one and only thread of the project, the main (UI) thread, which owns all windows. This works, even without calling UpdateWindow()! Same behavior even if I replace Sleep(1000) with a loop calling GetTickCount() until the time elapses. That is, for a static control SetWindowText() updates the control immediately. You mentioned a "static textbox", is this a static control or a disabled edit control? In my test I used a static control:

    LTEXT "",IDC_MYSTATIC,94,34,72,12,0,WS_EX_CLIENTEDGE

Tested with VS2022, Windows SDK Version: 10.0 (latest installed version)

Again, there is no ON_CHECKED... handler, as far as I know.

There must be something wrong with you project, make a copy and start removing stuff, until it is reduced to a MRE...

Constantine Georgiou
  • 2,412
  • 1
  • 13
  • 17
  • The op is not being clear. [From this...](https://stackoverflow.com/questions/75942762/changing-static-text-in-dialog-box-at-runtime-without-calling-updatedata/75945115). The main thread is sitting on a `WaitForSingleObject`, it is blocked. Read through the comments. – lakeweb Apr 11 '23 at 17:11
  • UpdateWindow() worked perfectly, but only if I followed it with a MessageBox. – DocDJ Apr 11 '23 at 17:39
  • The WaitForSIngleObject is MUCH later in the code than the SetWindowText. – DocDJ Apr 11 '23 at 17:41
  • @DocDJ *"UpdateWindow() worked perfectly, but only if I followed it with a MessageBox."* - Besides showing a UI, `MessageBox` *also* spins up a message loop, dispatching messages for you. Make sure to read through [this comment](https://stackoverflow.com/questions/75987819/mfc-event-handler-calls-setwindowtext-for-main-dialog-textbox-only-1st-and-last#comment134022159_75987819) carefully. I won't be surprised if that is spot-on. – IInspectable Apr 11 '23 at 18:12
  • I found this reference [link](https://forums.codeguru.com/showthread.php?435731-MFC-UpdateWindow()-doesn-t-work) which says that the bypass doesn't really happen. But I don't understand why there is ANY blocking. Do ON_ handlers run in uninterruptable mode, just like kernel routines? Except that my FIRST and LAST messages work. – DocDJ Apr 11 '23 at 20:10
  • Neither UpdateData nor UpdateWindow work, without a MessageBox. So "something" is causing blocking, but at the time of running the Set..Text, nothing else is running. The entire program is (currently) run from inside the ON_CHECKED... handler. – DocDJ Apr 11 '23 at 20:50
  • 1
    @DocDJ "The entire program is (currently) run from inside the ON_CHECKED... handler."* - That doesn't sound like a tractable solution. If you aren't *continuously* dispatching messages for your thread, then the application will appear to be unresponsive (and indeed literally is). Do you understand how a Windows program works? If not, that should be your immediate goal (start [here](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows) unless you have Petzold's book). – IInspectable Apr 12 '23 at 00:12
  • @IInspectable - Thanks for your advice. MY design is this: the main window is geared to gather (and display) setup info for my worker code. When the user has finished, he clicks on a checkbox. The ON_CHECKED handler gets control and starts the worker code. I think I understand how dialogs work, except I DON'T see any other way to start the work, And yes, the main window DOES appear to be blocked, because I can't click on the CANCEL button. I understand multi-threading, message-loops and CallBack functions (I've written several Win32 apps and a couple simple MFC apps). – DocDJ Apr 12 '23 at 11:33
  • 1
    @DocDJ The core principle is that the entire behavior of an application is run from a message loop. As messages are being dispatched, the system calls into callbacks, either provided by the system itself or by the client. All of that is synchronous, and as long as control is inside a callback, that thread isn't dispatching any messages (with a few exceptions). You will have to return from your callback as soon as possible. If you need to wait for completion of an operation, don't do it while in the callback. – IInspectable Apr 12 '23 at 11:52
  • So if I understand correctly, I should put a wait for the checkbox, inside my OnInitDIalog code and call my worker code when it succeeds? The system will detect the check, run the ON_CHECK member which does nothing, then my OnInitDIalog will succeed and my worker can run? – DocDJ Apr 12 '23 at 13:01
  • @DocDJ That sounds very awkward. You'll have higher chances of getting a response that is immediately applicable to your use case if you provide a [mcve]. – IInspectable Apr 12 '23 at 13:22
  • You're right. It won't work. Haven't found anything online on how to run a function in OnInitDialog AFTER a checkbox is checked. And can't do a wait in OnInitDialog because the dialog doesn't get drawn. I will have to create a minimal version, to get more help. – DocDJ Apr 12 '23 at 14:43