Prevent App from Grabbing Focus - SYSTEM PROP:Hide Window

Clarion 11.0.13630

I have an application that START’s a hidden window. This window performs some actions and then closes. Works great.

However, if the app is running and I am working in another application, when that hidden window opens, that applications grabs focus and takes me away from the app I was working in.

Is there a way to prevent the hidden window app from getting focus?

Thank you!!!

Sounds like a result of the bug in Windows handling of the WM_SETREDRAW message. When the WPARAM value of this message is 0, Windows clears the WS_VISIBLE flag from styles of the window which handle is the first parameter of the message. While window has no WS_VISIBLE style, Windows does not posts the WM_PAINT message, just handles the window’s update region. When the WM_SETREDRAW message sent with the WPARAM equal 1, Windows adds the WS_VISIBLE flag to the window’s styles. As result, window becomes visible and Windows posts the WM_PAINT message to repaint the collected update region. The bug is that Windows sets the WS_VISIBLE style unconditionally without taking int account whether that flag was set when WM_SETREDRAW with WPARAM equal 0 was processed. Windows sends WM_SETREDRAW message internally quite actively, for example, if a window/control becomes completely overlapped.

Future Clarion version will solve this problem. At the moment, try to execute

SYSTEM{PROP:Hide} = TRUE

before opening your window.

1 Like

My naive question is whether or not the procedure even needs a window.

It does. The procedure uses a Capesoft NetWebClient object and needs the accept loop.

I tested in 11.1.13815 and this System property did Hide the Window. How to Unhide it? I tried SYSTEM{PROP:Hide}=False but the Window did not appear… Also tried WINDOW{PROP:Hide}=False but did not appear.

SimpleWindow   PROCEDURE
Window WINDOW('Scratch'),AT(,,400,200),CENTER,GRAY,IMM,SYSTEM,STATUS,FONT('Segoe UI',9),RESIZE
        BUTTON('Button1'),AT(155,180),USE(?Button1)
        BUTTON('Button2'),AT(206,180),USE(?Button2)
    END
    CODE
    SYSTEM{PROP:Hide}=TRUE  !Test @ALSO Hub post to prevent focus grab. It does Hide, how to Unhide?
    OPEN(WINDOW)                                                                                    
    !!! WINDOW{PROP:Hide}=TRUE  !Old way to prevent focus
    0{PROP:text}=clip(0{PROP:text}) &' - Library ' & system{PROP:LibVersion,2} &'.'& system{PROP:LibVersion,3}
    ACCEPT
        CASE EVENT()
        OF EVENT:OpenWindow   
           SYSTEM{PROP:Hide}=False  !Undo Hide=True
           WINDOW{PROP:Hide}=False  !Old way to prevent focus

If I do BOTH System and Window Hide=False then the window is visible, but is sort of a disabled window that is missing the 2 Button controls.

So it seems SYSTEM{PROP:Hide} = TRUE is Write Once and not reversible? That’s fine and useful, just need to know how it works?

There have been times I gave up trying to prevent my window from taking focus. One workaround is Before the code that I do NOT want to take focus I call GetForegroundWindow() so I know who had focus. Then when done call SetForegroundWindow() to be sure that program still has focus.

      GetForegroundWindow(),LONG,PASCAL,DLL(1)  !Use to try to fix Start focus issues
      SetForegroundWindow(LONG),BOOL,Proc,PASCAL,DLL(1)

B4runFGWHnd LONG

 CODE
 B4runFGWHnd = GetForegroundWindow() 

!...my window code that may take focus ...

 IF B4TotalFGWHnd AND GetForegroundWindow() <> B4runFGWHnd THEN !Did I change Focus? (We have met the enemy and he is us)
    SetForegroundWindow(B4TotalFGWHnd)
    DB('RunningXYZ called SetForegroundWindow=' & B4TotalFGWHnd )
 end

If a WINDOW was OPENed while SYSTEM{PROP:Hide} had value TRUE, its controls were configured to work in hidden mode. Setting SYSTEM{PROP:Hide} to FALSE can’t change their behavior.

2 Likes

Seems you reported that problem or similar on PTSS # 42549 "Open(Window) then HIDE causes focus loss and flicker on previous window "

From my code comments this “Foreground Fix” was also used for Run(Exe,1) where the target EXE would mess with focus and there was nothing I could do to prevent it. But I could fix it after RUN returned. These would be very quick runs.

I made a test program while trying SYSTEM Prop:Hide to see how it works. To see what would have if it was UnHide i.e. System and Window PROP:Hide=False would it grab focus. I know its not intended to be Unhide.

First it shows this message to let you run it 3 ways Show (normal), Hide, or UnHide which means it sets System Hide=True then later sets it to False to see what happens. As noted in the message there are command line switches to do the same. That way you can run from another program w/o the message which would take focus.

image

If you select Hide+UnHide it first does SYSTEM Hide=True, then in Event Open Window sets SYSTEM Hide=False plus unhides the Window. It also tries to unhide controls that were hidden but it does not work.

  IF HideIt THEN SYSTEM{PROP:Hide}=TRUE.
  OPEN(WINDOW)                                                                                    
  IF UnHideIt THEN SYSTEM{PROP:Hide}=FALSE.  ! Hide+UnHide
  ACCEPT
      CASE EVENT()
      OF EVENT:OpenWindow
         IF UnHideIt THEN                    ! Hide+UnHide
            SYSTEM{PROP:Hide}=FALSE
            Window{PROP:Hide}=False 
            UNHIDE(?CloseButton) ; UNHIDE(?RunHideBtn) ; UNHIDE(?RunHideBtn)  !Will unhide? NO
            UNHIDE(?FYI1) ; UNHIDE(?FYI2) ; UNHIDE(?RunHideBtn)  !Will unhide? NO
         END

In the below screen capture the Designer Window is on the Left showing all controls, and the runtime window is on the left. You see Button, String, Prompt do not unhide. The Progress control still works. The window is in a Disabled like state that nothing can be clicked, but the Escape key works.


System Prop:Hide Test Project

SystemHide_Test_Prj_20230612.zip (3.2 KB)


One thing I didn’t think to try was to Create() String or Prompt controls on the Window to see if they showed. Ok tried it and it worked! So you can have this System Hide window with a Working Progress, then Create strings to show other info:

This code is not in the attachment:

              st# = CREATE(0,CREATE:string)  !Create a Control on System HIDE window
              SETPOSITION(st#,1,1)
              st#{PROP:TExt}='I was CREATE(0,CREATE:string) SETPOSITION(st#,1,1)'  
              UNHIDE(st#)
1 Like

It’s possible to unhide a window created while SYSTEM{PROP:Hide} was TRUE and its controls. But it would be more easy and reliable to close such WINDOW and reopen it again. The primary goal of the SYSTEM{PROP:Hide}=TRUE was to run the “logical” part of the program while UI is on a remote computer.

1 Like