TI-994A wrote:is there any way to make an application bring itself to the foreground?
If another process is active, SetForegroundWindow_() does not disturb the user by just switching
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)
The example starts calc.exe and when it is finished, it activates your own window.
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.