SetForegroundWindow from own app

Just starting out? Need help? Post your questions and find answers here.
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: SetForegroundWindow from own app

Post by Danilo »

TI-994A wrote:
Danilo wrote:Known problem with the IDE, we discussed it a hundred times with freak, search the forum for it. Do not use the IDE as foreground window when testing, use anything but the PB IDE.
You're right; very perculiar behaviour. Thanks for pointing that out.
Please read:
- I warned you: The dangers of attaching input queues
- Foreground activation permission is like love: You can't steal it, it has to be given to you

Looks like AttachThreadInput can lead to a Deadlock.

It is funny because my first code (SetForegroundWindowEx) is from MSDN/Microsoft and
they recommended to use AttachThreadInput together with SetForegroundWindow.
Later some guys realized it isn't a good idea, so DO NOT USE IT anymore. Although it works
most of the time, it can also lead to crashes. It happens with the PB IDE, and it could happen
with random other applications too.
TI-994A wrote:Even with this simple routine, the window pops right up to the front and gets the focus, regardless of what application window may be in the foreground; no flashing whatsoever.
You start a new program with your code and in this case it gets activated anyway.
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: SetForegroundWindow from own app

Post by Danilo »

Found another function: SwitchToThisWindow

But please note:
[This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]
:D

Code: Select all

;
; [This function is not intended for general use.
;  It may be altered Or unavailable in subsequent versions of Windows.]
;
; Applies to: desktop apps only
;
; Switches focus to the specified window and brings it To the foreground.
;
;
; http://msdn.microsoft.com/en-us/library/ms633553
;
;
Prototype proto_SwitchToThisWindow(hWnd.i,fAltTab.l)
;
Procedure SwitchToThisWindow(hWnd.i,fAltTab.l)
    ; hWnd:
    ;   A handle To the window.
    ;
    ; fAltTab:
    ;   A TRUE for this parameter indicates that the window is being switched to using
    ;   the Alt/Ctl+Tab key sequence. This parameter should be FALSE otherwise.
    ;
    ; This function does not return a value.
    ;
    Protected lib = OpenLibrary(#PB_Any,"user32.dll")
    If lib
        Protected func.proto_SwitchToThisWindow = GetFunction(lib,"SwitchToThisWindow")
        If func
            func(hWnd,fAltTab)
        EndIf
        CloseLibrary(lib)
    EndIf
EndProcedure


;
; Example program
;
Global myMsg = RegisterWindowMessage_("MyWindowMessage")

Procedure run(v.i)
    Protected program
    program = RunProgram("calc.exe","","",#PB_Program_Open)
    
    While ProgramRunning(program)
      Delay(100)
    Wend
    CloseProgram(program)
    PostMessage_(v,myMsg,0,0)
EndProcedure

Procedure winthread(v)
    Protected win
    win = OpenWindow(#PB_Any,100,100,500,300,"main")
    CreateThread(@run(),WindowID(win))
    Repeat
        Select WaitWindowEvent()
            Case #PB_Event_CloseWindow
               Break
            Case myMsg
                SwitchToThisWindow(WindowID(win),#True)
        EndSelect
    ForEver
    CloseWindow(win)
EndProcedure

Define t = CreateThread(@winthread(),0)
WaitThread(t)
Works without AttachThreadInput, so doesn't crash other programs. It emulates ALT+TAB switching with 2nd argument set to #True.
User avatar
TI-994A
Addict
Addict
Posts: 2751
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: SetForegroundWindow from own app

Post by TI-994A »

CORRECTION:
TI-994A wrote:...Even with this simple routine, the window pops right up to the front and gets the focus, regardless of what application window may be in the foreground; no flashing whatsoever.

Code: Select all

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 50, 50, 300, 100, "Set Foreground Test", wFlags)
Delay(3000)
SetForegroundWindow_(WindowID(0))
While WaitWindowEvent() ! #PB_Event_CloseWindow : CloseWindow : Wend
After further testing, I've noticed that the above example works only with a short delay, nothing more than Delay(5000); any longer than that and we get only the flashing taskbar button. Perhaps the delay maintains the window's foreground status for a while, afterwhich it falls to the background.

Hello again, Danilo! Thank you very much for your tireless help and elaborate examples; really great codes. And thanks for pointing out the SwitchToThisWindow() function, although I was not able to get it to work; upon closing the Calculator in your example, the "main" window only flashes in the taskbar.

In any case, thanks to yours and RASHAD's wonderful examples, I have pieced together this short routine, for the simple and express purpose of making an application bring itself to the foreground:

Code: Select all

;========================================
;
;  A workaround to SetForegroundWindow()
;  adapted from routines by PureBasic 
;  experts, RASHAD & Danilo. Thank you!
;   
;  by TI-994A  -  7th April, 2012
;
;========================================

Enumeration
  #MainWindow
  #sfwTimer
EndEnumeration

Global.i wSFW, tSFW, mSFW = RegisterWindowMessage_("mySetForegroundWindow")

Procedure SetMeForeground()
  PostMessage_(WindowID(wSFW), mSFW, 0, 0)
EndProcedure

Procedure pSFW(hWndParent)
  wSFW = OpenWindow(#PB_Any, 0, 0, 0, 0, "", #PB_Window_Invisible, hWndParent)
  Repeat
    Select WaitWindowEvent()
      Case mSFW
        BringWindowToTop_(hWndParent)
    EndSelect
  ForEver
EndProcedure 

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(#MainWindow, #PB_Any, #PB_Any, 400, 200, "SetForegroundWindow Workaround", wFlags) 
tSFW = CreateThread(@pSFW(), WindowID(#MainWindow))
AddWindowTimer(#MainWindow, #sfwTimer, 5000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      SetMeForeground()
    Case #PB_Event_CloseWindow
      appQuit = 1
      KillThread(tSFW)
  EndSelect
Until appQuit = 1
As a demonstration, this example uses a timer to bring the main window to the front every five seconds. So far, it's worked well on my machines, but it would be great to know if it works across a broader range.

Please do let me have some feedback if you test it. Thank you.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: SetForegroundWindow from own app

Post by Danilo »

Works here, Win7 64bit.

Very annoying, I hope you don't use it in a public program. :D
User avatar
TI-994A
Addict
Addict
Posts: 2751
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: SetForegroundWindow from own app

Post by TI-994A »

Danilo wrote:Works here, Win7 64bit.

Very annoying, I hope you don't use it in a public program. :D
That's good to know.

And you're right, it is very annoying when a pop-up interrupts your work, especially if it grabs the focus from the window you're working on. But in certain cases, like this single-instance example that I posted (6th post), it would be great for the running instance to bring itself to the foreground when the user attempts to launch a second instance.

Thanks for your help with this.
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Post Reply