SetForegroundWindow from own app
SetForegroundWindow from own app
Hi guys! I've been trying unsuccessfully to get SetForegroundWindow() to work, and noticed from previous threads that it is a known problem. Can anyone please confirm if it is confined to any particular version of Windows; I've tried only on Windows XP and 7. Also, most of the posts seem to be referring to problems calling SetForegroundWindow() from another application; is there any way to make an application bring itself to the foreground?
Thank you.
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 
Re: SetForegroundWindow from own app
StickyWindow(#Fenetre, Etat) ??
or
or
Code: Select all
Procedure SetWindowPos( WindowID , State) ; Permet de mettre la fenêtre en arrière, au premier plan,...
; #HWND_BOTTOM
; #HWND_TOPMOST
; #HWND_NOTOPMOST
; HWND_TOP
SetWindowPos_ ( WindowID , State, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE )
EndProcedure
Re: SetForegroundWindow from own app
Hi,
this works for me at XPBernd
P.S.: You have to change the WindowName of course.
Oh, sorry, I didn't read enough.
For your own PB program use StickyWindow(#Window, Status).
this works for me at XP
Code: Select all
WindowName.s = "Rechner"
hWnd = FindWindow_(#Null, WindowName)
If hWnd
ShowWindow_(hWnd, #SW_RESTORE)
SetForegroundWindow_(hWnd)
EndIfP.S.: You have to change the WindowName of course.
Oh, sorry, I didn't read enough.
For your own PB program use StickyWindow(#Window, Status).
Re: SetForegroundWindow from own app
dobro wrote:StickyWindow(#Fenetre, Etat) ??
orCode: Select all
SetWindowPos_(WindowID, State, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE)
Hi guys! Thanks for the quick replies.infratec wrote:For your own PB program use StickyWindow(#Window, Status).
StickyWindow() & SetWindowPos() with the #HWND_TOPMOST parameter works well, but I do not wish to have the window permanently topmost. I tried to make a double call to SetWindowPos(), once with #HWND_TOPMOST and then with #HWND_TOP and even #HWND_NOTOPMOST, but I can't seem to undo the Z-order.
Is it a Windows restriction, perhaps?
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 
Re: SetForegroundWindow from own app
I think that the next snippet is the best to bring any window to top
Feel free to test
Edit :Sorry I did not notice that you want to Bring a Window to top from that window itself
DoubleClick the SystemTray icon
Feel free to test
Code: Select all
;***************** Find the Handle of The External Window ******************
Repeat
hWnd = FindWindow_(0, "PureBasic Window")
Until hWnd
;***************************************************************************
OpenWindow(0,50,50,100,100,"Test 1",#PB_Window_SystemMenu)
ButtonGadget(0,10,10,50,25,"TEST 1")
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Q = 1
Case #PB_Event_Gadget
Select EventGadget()
Case 0
SendMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_HOTKEY, hWnd)
EndSelect
EndSelect
Until Q = 1
End
DoubleClick the SystemTray icon
Code: Select all
OpenWindow(0,50,50,100,100,"Test 1",#PB_Window_SystemMenu)
AddSysTrayIcon(0, WindowID(0),LoadImage(0, "g:\projects\icon\CdPlayer.ico"))
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Q = 1
Case #PB_Event_SysTray
Select EventType()
Case #PB_EventType_LeftDoubleClick
SendMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_HOTKEY, WindowID(0))
EndSelect
EndSelect
Until Q = 1
End
Last edited by RASHAD on Fri Apr 06, 2012 2:36 pm, edited 1 time in total.
Egypt my love
Re: SetForegroundWindow from own app
Just enable StickyWindow() then disable it. Recently had to do the same myself. 
www.posemotion.com
PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef
Even the vine knows it surroundings but the man with eyes does not.
PureBasic Tools for OS X: PureMonitor, plist Tool, Data Maker & App Chef
Even the vine knows it surroundings but the man with eyes does not.
Re: SetForegroundWindow from own app
Hi RASHAD! Thanks for the code example. It works well when calling another window to the foreground, but it doesn't work when calling itself. Same problem with SetWindowPos()/#HWND_TOP and SetForegroundWindow().RASHAD wrote:I think that the next snippet is the best to bring any window to top
Feel free to test![]()
Code: Select all
SendMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_HOTKEY, hWnd)
So far, this is the only workaround that does the job:
Thanks a lot J. Baker! I've unsuccessfully tried this trick by calling SetWindowPos() first with #HWND_TOPMOST then with #HWND_NOTOPMOST, but didn't think to try it with PurBasic's StickyWindow(). Works perfectly.J. Baker wrote:Just enable StickyWindow() then disable it. Recently had to do the same myself.
If anyone knows the answer to this mystery, I'd still like to know what causes this.
Thank you, and everyone else for all your help!
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 
Re: SetForegroundWindow from own app
I just updated the previous post while you was posting 
Egypt my love
Re: SetForegroundWindow from own app
Hello again, RASHAD. Thanks for the new example, which for some reason works when we click on the SysTray icon, but not programatically:
When we bring another window to the front, this window does not come back to the top after the timeout. This method works:
However, I've noticed that even after disabling the StickyWindow(), the window doesn't get pushed back by certain applications, like NotePad, Windows File Explorer, and even the PureBasic IDE. If this window pops-up on any one of these application windows, it will not be pushed behind by clicking on them. It has to be clicked on, or moved, before losing its topmost Z-order.
Code: Select all
OpenWindow(0, 50, 50, 100, 100, "Test 1", #PB_Window_SystemMenu)
Delay(3000)
SendMessage_(WindowID(0), #WM_SYSCOMMAND, #SC_HOTKEY, WindowID(0))
While WaitWindowEvent() ! #PB_Event_CloseWindow : CloseWindow : WendCode: Select all
OpenWindow(0, 50, 50, 100, 100, "Test 1", #PB_Window_SystemMenu)
Delay(3000)
StickyWindow(0, 1)
StickyWindow(0, 0)
While WaitWindowEvent() ! #PB_Event_CloseWindow : CloseWindow : WendTexas 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 
Re: SetForegroundWindow from own app
Code: Select all
Procedure ProcedureName(Parameter)
OpenWindow(1, 0, 0, 0, 0, "",#PB_Window_Invisible, WindowID(0))
AddWindowTimer(1,123,Parameter)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Timer
BringWindowToTop_(WindowID(0))
EndIf
Until Quit = 1
EndProcedure
OpenWindow(0, 50, 50, 100, 100, "Test 1", #PB_Window_SystemMenu)
Thread = CreateThread(@ProcedureName(), 5000)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Q = 1
EndSelect
Until Q = 1
Egypt my love
Re: SetForegroundWindow from own app
Hi RASHAD. Ingenious workaround, calling it from another thread. For some reason a window is just not able to bring itself to the foreground. Thanks for that.RASHAD wrote:Code: Select all
Thread = CreateThread(@ProcedureName(), 5000)
Earlier, I said that calling SetWindowPos() first with #HWND_TOPMOST then with #HWND_NOTOPMOST didn't work; actually it worked exactly as a double call to StickyWindow(). It too demonstrated the same erratic behaviour, maintaining its topmost Z-order even when the window immediately below it is clicked (except if Google Chrome is the window below it!).
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 
Re: SetForegroundWindow from own app
If another process is active, SetForegroundWindow_() does not disturb the user by just switchingTI-994A wrote:is there any way to make an application bring itself to the foreground?
windows. Instead it notifies the user with blinking taskbar entry.
So SetForegroundWindow_() only works if your own process and its threads is already active.
If you really want to disturb the user experience, you can use AttachThreadInput_() if another
process is currently in the foreground. Use SetForegroundWindowInternal().
Code: Select all
EnableExplicit
; http://msdn.microsoft.com/de-de/library/bb979463.aspx
;
; Verwenden Sie die Funktion SetForegroundWindowEx statt der
; API Funktion SetForegroundWindow ausschließlich, wenn das
; betroffene Fenster tatsächlich in den Vordergrund gebracht
; werden muss.
Procedure SetForegroundWindowEx(hWndWindow)
; Dient dem Setzen des Vordergrundfensters mit der Funktion
; SetForegroundWindow, die sich unter neueren Windows-Versionen
; anders verhält als unter Windows 95 und Windows NT 4.0.
; Der Rückgabewert ist True, wenn das Fenster erfolgreich in den
; Vordergrund gebracht werden konnte.
Protected SetForegroundWindowEx
Protected lThreadForeWin.l ; Thread-ID für das aktuelle Vordergrundfenster
Protected lThreadWindow.l ; Thread-ID für das in hWndWindow spezifizierte
; Fenster, das in den Vordergrund des Desktops
; gebracht werden soll.
; Falls das Fenster dem gleichen Thread wie das aktuelle
; Vordergrundfenster angehört, ist kein Workaround erforderlich:
lThreadWindow = GetWindowThreadProcessId_(hWndWindow, 0)
lThreadForeWin = GetWindowThreadProcessId_(GetForegroundWindow_(), 0)
If lThreadWindow = lThreadForeWin
; Vordergrundfenster und zu aktivierendes Fenster gehören zum
; gleichen Thread. SteForegroundWindow allein reicht aus:
SetForegroundWindowEx = SetForegroundWindow_(hWndWindow)
Else
; Das Vordergrundfenster gehört zu einem anderen Thread als das
; Fenster, das neues Vordergrundfenster werden soll. Mittels
; AttachThreadInput erhaten wir kurzzeitig Zugriff auf die
; Eingabeverarbeitung des Threads des Vordergrundfensters,
; so dass SetForegroundWindow wie erwartet arbeitet:
AttachThreadInput_(lThreadForeWin, lThreadWindow, #True)
SetForegroundWindowEx = SetForegroundWindow_(hWndWindow)
AttachThreadInput_(lThreadForeWin, lThreadWindow, #False)
EndIf
ProcedureReturn SetForegroundWindowEx
EndProcedure
; http://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo
;
Procedure SetForegroundWindowInternal(hWnd)
If Not IsWindow_(hWnd) : ProcedureReturn : EndIf
; relation time of SetForegroundWindow lock
Protected lockTimeOut.l = 0;
Protected hCurrWnd = GetForegroundWindow_()
Protected dwThisTID.l = GetCurrentThreadId_()
Protected dwCurrTID.l = GetWindowThreadProcessId_(hCurrWnd,0)
; we need To bypass some limitations from Microsoft :)
If (dwThisTID <> dwCurrTID)
AttachThreadInput_(dwThisTID, dwCurrTID, #True);
SystemParametersInfo_(#SPI_GETFOREGROUNDLOCKTIMEOUT,0,@lockTimeOut,0);
SystemParametersInfo_(#SPI_SETFOREGROUNDLOCKTIMEOUT,0,0,#SPIF_SENDWININICHANGE | #SPIF_UPDATEINIFILE);
#ASFW_ANY = -1
AllowSetForegroundWindow_(#ASFW_ANY);
EndIf
SetForegroundWindow_(hWnd);
;SetFocus_(hWnd)
If (dwThisTID <> dwCurrTID)
SystemParametersInfo_(#SPI_SETFOREGROUNDLOCKTIMEOUT,0,lockTimeOut,#SPIF_SENDWININICHANGE | #SPIF_UPDATEINIFILE);
AttachThreadInput_(dwThisTID, dwCurrTID, #False);
EndIf
EndProcedure
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
;SetForegroundWindowEx(WindowID(win))
SetForegroundWindowInternal(WindowID(win))
EndSelect
ForEver
CloseWindow(win)
EndProcedure
Define t
t = CreateThread(@winthread(),0)
WaitThread(t)For your own application just use the procedure SetForegroundWindowInternal().
Please use this only if you really need it. It is very disturbing for the user if (s)he is
doing some work and other windows bring itself into the foreground all the time.
That's the reason Microsoft changed the function - SetForegroundWindow was misused too often
and disturbed the user experience.
Last edited by Danilo on Sat Apr 07, 2012 6:57 am, edited 1 time in total.
Re: SetForegroundWindow from own app
Hi Danilo! Thanks for the great code. I've not had a chance to study it yet, but my initial tests had these results:Danilo wrote:If another process is active, SetForegroundWindow_() does not disturb the user by just switching windows. Instead it notifies the user with blinking taskbar entry.TI-994A wrote:is there any way to make an application bring itself to the foreground?
1. the code executed perfectly when compiled, but crashed on Windows XP Professional if run from the PureBasic IDE
2. SetForegroundWindow() works perfectly on Windows XP Professional, with no annoying blinking taskbar button.
Could anyone else please confirm 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 
Re: SetForegroundWindow from own app
Known problem with the IDE, we discussed it a hundred times with freak, search the forum for it.TI-994A wrote:1. the code executed perfectly when compiled, but crashed on Windows XP Professional if run from the PureBasic IDE
Do not use the IDE as foreground window when testing, use anything but the PB IDE.
Alternatively out-comment the first AttachThreadInput_(dwThisTID, dwCurrTID, #True) that causes the IDE crash.
It flashes only if the current foreground window is another process, see SetForegroundWindowTI-994A wrote:2. SetForegroundWindow() works perfectly on Windows XP Professional, with no annoying blinking taskbar button.
An application cannot force a window to the foreground while the user is working with another window. Instead, Windows flashes the taskbar button of the window to notify the user.
Re: SetForegroundWindow from own app
You're right; very perculiar behaviour. Thanks for pointing that out.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.
That's what it says, but here on my work computer, running Windows XP Professional SP3, I can't seem to get that behaviour. 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.Danilo wrote:It flashes only if the current foreground window is another process, see SetForegroundWindow
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 : WendIt'd be really great if someone else can confirm 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 




