RE: [fltk.general] Use worker thread to call Fl_Window and Fl_run - [General Use]

29 views
Skip to first unread message

MacArthur, Ian (Leonardo, UK)

unread,
Oct 1, 2020, 5:52:39 AM10/1/20
to fltkg...@googlegroups.com


From: fltkg...@googlegroups.com <fltkg...@googlegroups.com> On Behalf Of anmol....@gmail.com
Sent: 01 October 2020 10:08
To: fltk.general <fltkg...@googlegroups.com>
Subject: Re: [fltk.general] Use worker thread to call Fl_Window and Fl_run

> Forking a new process may be a bit heavyweight for my needs.
> Its more intensive on Windows than on *NIX.

Yes, and not necessary in this case anyway, I suggest.


<snip>

// Loop
AEC_progress = (int)(i * mult);
        Fl::check();
// End Loop


That's effectively Fl::run()... I'd have a little delay in that tight loop, if it were me, though!


> This works well with the bar indicator, but the text shows some junk.

Yes, it would do.
Your label is stored in a stack-automatic variable "char percent[10] = { "" };" and is going out of scope before it is used, so you get garbage.
If you know your label store is of transient persistence, as here, you should probably use copy_label() rather than label().



> Also, this window goes to the background.

> Any suggestions to force this window to the top of all other windows? My GUI (code that I cannot
> change) may be pushing a cmd window to the top as I am using popen/pclose and windows starts a cmd
> window when you use pipes.

OK - that's hard, since fltk is not in control of the z-order in your case... You could *try* calling show() on your window each time you check() it, but that might just cause hideous flickering as the windows fight over who is on top.

The alternative, if you are prepared to use platform specific code, is to modify the window attributes to make it always on top, but non-modal so it does not prevent events passing to your other windows (using the Windows terminology for this) and see if that helps. But that will not be portable of course.

Also, you can tell windows not to throw the CMD window at all for the pipe, though off-hand I can’t remember the magical invocation for that. It's a linker option though, IIRC. might be "-mwindows" with gcc, can't recall what VS uses...





Leonardo MW Ltd
Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL
A company registered in England & Wales. Company no. 02426132
********************************************************************
This email and any attachments are confidential to the intended
recipient and may also be privileged. If you are not the intended
recipient please delete it from your system and notify the sender.
You should not copy it or use it for any purpose nor disclose or
distribute its contents to any other person.
********************************************************************

Albrecht Schlosser

unread,
Oct 1, 2020, 6:07:38 AM10/1/20
to fltkg...@googlegroups.com
On 10/1/20 11:52 AM 'MacArthur, Ian' wrote:

> Also, you can tell windows not to throw the CMD window at all for the pipe, though off-hand I can’t remember the magical invocation for that. It's a linker option though, IIRC. might be "-mwindows" with gcc, can't recall what VS uses...

If it's /that/ linker option ("-mwindows") then it's likely
"/subsystem:windows" (as opposed to "/subsystem:console") with MSVC, but
don't rely on the exact syntax.

anmol....@gmail.com

unread,
Oct 1, 2020, 11:05:20 AM10/1/20
to fltk.general
copy_label() fixed the problem. Thanks!
Calling show() in the loop or changing /subsytem:windows in linker options did not work either.
Stackexchange tells me CreateProcess() is the only reliable way to stop the console window from starting.
But I'm not going that route.

Almost as if microsoft intended this to mess with our minds. Hmm..

I'll try the " modify the window attributes to make it always on top, but non-modal so it does not prevent events passing to your other windows" method and report back.

anmol....@gmail.com

unread,
Oct 1, 2020, 12:13:39 PM10/1/20
to fltk.general
I could not get set_non_modal to work. Perhaps I am missing something..

>>
Fl::add_timeout(2.0, Update_CB, (void*)&progress);
    win.set_non_modal();
    win.show();
>>

I found an old thread with some info, Greg - from 16 years ago.
>>
if you can obtain hWnd, than with WinAPI function SetWindowPos() you can set
it to be on top of all windows by something like:

SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS)
>>

Also,
>>
This was also covered in a previous thread from April:

Subject: How to make a window "Stay On Top"
>>
But I could not find that thread.

I will copy the code in case we lose that archive.

>>
//===============================================================================
#include <FL/Fl.H>
#include <FL/x.H>
#include <Fl/Fl_Window.H>
#include <windows.h>

//----------------------------------------------------------------------------
void Show_Topmost(Fl_Window* pWindow)
{
HWND hWnd= fl_xid(pWindow);
ShowWindow(hWnd, SW_SHOWNORMAL);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

//----------------------------------------------------------------------------
bool Is_Topmost(Fl_Window* pWindow)
{
HWND hWnd= fl_xid(pWindow);
WINDOWINFO pwi;
if (GetWindowInfo(hWnd, &pwi)) return pwi.dwExStyle & WS_EX_TOPMOST;
else return false;
}

//----------------------------------------------------------------------------
void Clear_Topmost(Fl_Window* pWindow)
{
HWND hWnd= fl_xid(pWindow);
ShowWindow(hWnd, SW_SHOWNORMAL);
SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

//----------------------------------------------------------------------------
void Show_Foreground(Fl_Window* pWindow)
{
HWND hWnd= fl_xid(pWindow);
ShowWindow(hWnd, SW_SHOWNORMAL);
if (GetForegroundWindow() != hWnd)
{
DWORD fgwpid = GetWindowThreadProcessId(GetForegroundWindow(),NULL);
DWORD mypid = GetWindowThreadProcessId(hWnd, NULL);
AttachThreadInput(mypid, fgwpid, TRUE);
BringWindowToTop(hWnd);
SetForegroundWindow(hWnd);
AttachThreadInput(mypid, fgwpid, FALSE);
}
}

//----------------------------------------------------------------------------
bool Is_Foreground(Fl_Window* pWindow)
{
return GetForegroundWindow()== fl_xid(pWindow);
}

//----------------------------------------------------------------------------
void Show_Background(Fl_Window* pWindow)
{
HWND hWnd= fl_xid(pWindow);
ShowWindow(hWnd, SW_SHOWNORMAL);
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

Manolo

unread,
Oct 1, 2020, 12:35:16 PM10/1/20
to fltk.general
On Thursday, October 1, 2020 at 6:13:39 PM UTC+2 anmol....@gmail.com wrote:
I could not get set_non_modal to work. Perhaps I am missing something..

>>
Fl::add_timeout(2.0, Update_CB, (void*)&progress);
    win.set_non_modal();
    win.show();
>>

Member function Fl_Window::set_non_modal() has an effect only on the relationship
between the non-modal-ized window and other FLTK windows. It has no efffect whatsoever relatively to
non-FLTK windows. [That's under the Windows platform].

anmol....@gmail.com

unread,
Oct 1, 2020, 2:36:48 PM10/1/20
to fltk.general

Nothing seems to stop that console window. set_non_modal does not work.
And even the windows specific code does not work.

    win.end();

    Fl::add_timeout(2.0, Update_CB, (void*)&progress);
    win.set_non_modal();
    win.show();
    Fl::check();
    //Sleep(500);
    Show_Topmost(&win);

And
>>
//----------------------------------------------------------------------------
void Show_Topmost(Fl_Window* pWindow) {
    HWND hWnd = fl_xid(pWindow);

Ian MacArthur

unread,
Oct 1, 2020, 4:19:20 PM10/1/20
to fltkg...@googlegroups.com
On 1 Oct 2020, at 19:36, anmol.mishra wrote:
>
>
> Nothing seems to stop that console window. set_non_modal does not work.
> And even the windows specific code does not work.
>
> win.end();
> Fl::add_timeout(2.0, Update_CB, (void*)&progress);
> win.set_non_modal();
> win.show();
> Fl::check();
> //Sleep(500);
> Show_Topmost(&win);


As Manolo pointed out earlier, win.set_non_modal(); is not going to work because it operates relative to other fltk windows, which is not the issue here.

When I said you should set the window to be non-modal, I was specifically referring to the MS terminology for this (calling a window "non-modal” is a MS’ism) and suggesting that you do that whilst also modifying the topmost attribute.

I was not meaning to suggest you use the fltk method by that name, as it is unlikely to work in this context, as noted before.

The other thing you need to know is that you can not always meaningfully change the attributes of a shown window under the MS way of doing things, so you probably need to set the topmost attribute before you first show the window, or at least hide it before changing the attribute...

We are some way beyond the bounds of fltk at this stage, so you might want to have a little browse around the MSDN docs to see how that all hangs together - they may well explain it more lucidly than I can!






anmol....@gmail.com

unread,
Oct 3, 2020, 3:47:43 AM10/3/20
to fltk.general
Found it. This method is a hack but it works consistently and the progress bar pops up - which is IMO a benefit.

#ifdef _OS_WIN

//----------------------------------------------------------------------------
void Show_Topmost(Fl_Window* pWindow) {
    HWND hWnd = fl_xid(pWindow);
    ShowWindow(hWnd, SW_MINIMIZE);
    ShowWindow(hWnd, SW_RESTORE);
    ShowWindow(hWnd, SW_SHOWNORMAL);
    SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

// Progress callback updates label
void Topmost_CB(void* userdata) {
    Fl_Progress* progress = (Fl_Progress*)userdata;
    int val;
    val = AEC_progress;
    progress->value((float)val);              // update progress bar with 0.0 ~ 100 value
    char percent[10] = { "" };
    sprintf_s(percent, "%d%%", val);
    progress->copy_label(percent);
    Show_Topmost(progress->window());

    Fl::repeat_timeout(2.0, Update_CB, (void*)progress);
}
#endif

And in main code,

    win.end();
#ifdef _OS_WIN
    Fl::add_timeout(2.0, Topmost_CB, (void*)&progress);
#else
    Fl::add_timeout(2.0, Callback_CB, (void*)&progress);
#endif
    win.set_non_modal();
    win.show();
    AEC_progress = 0;
    Fl::check();

Ian MacArthur

unread,
Oct 3, 2020, 7:37:52 AM10/3/20
to fltkg...@googlegroups.com
On 3 Oct 2020, at 08:47, anmol.mishra wrote:
>
> Found it. This method is a hack but it works consistently and the progress bar pops up - which is IMO a benefit.
>


Good, glad you found something that worked.

That said, if you are OK with using platform specific code, I do think you should look at Greg’s suggestion of using CreatePipe on Windows rather than the MS popen implementation, which can be “less good” sometimes...
Greg uses the popen/CreatePipe stuff in his work and knows what he’s talking about!

That should also get rid of the spurious console too, thus obviating the need for this hack at all!



anmol....@gmail.com

unread,
Oct 5, 2020, 8:03:24 AM10/5/20
to fltk.general
I did look at that - the problem is portability. popen works on OSX and Linux, so if I get this to work, its easier to port.

I will revisit this later as someone suggested named pipes are much faster than piping to stdin as I am doing currently.
Reply all
Reply to author
Forward
0 new messages