Seite 1 von 2
Window back on the Top - Gadget
Verfasst: 04.10.2011 13:49
von X360 Andy
Hallo Zusammen,
Ich hoffe ich habe eine Anfänger Frage.
Meine Software startet eine externe Anwendung, der Benutzer muss hier ein paar Sachen klicken.
[Mein Programm verliert hier den Focus]
Nachdem der Benutzer fertig ist [diese Abfrage bekomme vom Programm] soll meine Software wieder den Focus bekommen, und "setactiveGadget()" aufgrufen werden, leider bringt mir das ohne Focus nichts.
Wie kann ich nun in der Z-Order von Windows rumspielen und mein Programm/Fenster nach ganz oben bekommen.
Super wäre es wenn mir jemand helfen kann.
Gruß´Andreas
Re: Window back on the Top - Gadget
Verfasst: 04.10.2011 14:15
von Kiffi
SetActiveWindow()?
Grüße ... Kiffi
Re: Window back on the Top - Gadget
Verfasst: 04.10.2011 14:21
von ts-soft
Re: Window back on the Top - Gadget
Verfasst: 04.10.2011 18:06
von X360 Andy
Funktioniert leider nicht.
Was ich nun gerade getestet habe
Code: Alles auswählen
SetForegroundWindow_(WindowID(#Window_0))
SetActiveWindow(#Window_0)
SetActiveWindow_(WindowID(#Window_0))
SetWindowPos_(WindowID(#Window_0), #HWND_TOPMOST, 0, 0, 0, 0, #SWP_NOSIZE | #SWP_NOMOVE)
SetActiveGadget(GetRightGadget(#_1String_1, #_2String_1, #_3String_1, #_4String_1))
SetWindowPos_ funktioniert teilweise, nur nicht unter allen System [hab 2 getestet], unter WIN Server 2008 läufts, auf Windows 7 nicht.
[Und das auch nicht immer]
Als Info
Alle Befehle werden in einer externem Thread abgebearbeitet
Vereinfachtest Beispiel
Code: Alles auswählen
Procedure Alive_System(Para)
Repeat
Select Befehl
Case 1
; Hier kommen Befehle die auf die Daten von anderen Programm warten , hier verliert das Programm den Focus
; Hier sollte es den Focus es wieder bekommen, damit der Benutzer sofort weiterarbeiten kann
Befehl = 0
Case 2
Befehl = 0
Endselect
delay(10)
Until Exit = 1
Endprocedure
Re: Window back on the Top - Gadget
Verfasst: 04.10.2011 19:02
von Danilo
Probiere mal diese Funktion von MSDN:
Fenster in den Desktop-Vordergrund bringen
Code: Alles auswählen
; 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
Oder noch etwas erweitert von dort:
How to bring window to top with SetForegroundWindow()
Code: Alles auswählen
Procedure SetForegroundWindowInternal(hWnd)
If Not IsWindow_(hWnd) : ProcedureReturn : EndIf
; relation time of SetForegroundWindow lock
lockTimeOut.l = 0;
hCurrWnd = GetForegroundWindow_();
dwThisTID.l = GetCurrentThreadId_()
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);
If (dwThisTID <> dwCurrTID)
SystemParametersInfo_(#SPI_SETFOREGROUNDLOCKTIMEOUT,0,lockTimeOut,#SPIF_SENDWININICHANGE | #SPIF_UPDATEINIFILE);
AttachThreadInput_(dwThisTID, dwCurrTID, #False);
EndIf
EndProcedure
Re: Window back on the Top - Gadget
Verfasst: 04.10.2011 22:21
von X360 Andy
Klappt leider auch nicht.
Ich werde morgen mal schauen ob ich ein Code hinkriege der das Problem ausführbar zeigt.
Die Software hat aktuell etwa 7.000 selbstgeschrieben Zeilen Code sowie müssen viele Extra Programme auf dem Rechner sein.
Gruß
Re: Window back on the Top - Gadget
Verfasst: 05.10.2011 00:05
von Sicro
Hat bei mir bis jetzt immer geklappt:
Code: Alles auswählen
SetForegroundWindow_(WindowID(#Window_Main))
BringWindowToTop_(WindowID(#Window_Main))
Re: Window back on the Top - Gadget
Verfasst: 05.10.2011 08:29
von Danilo
X360 Andy hat geschrieben:Klappt leider auch nicht.
Mach mal aus diesem Code eine .exe mit Compileroption threadsafe:
Code: Alles auswählen
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)
Funktioniert hier. Das Fenster kommt immer in den Vordergrund,
sobald Calc beendet wurde. Aber als EXE kompilieren und diese
ohne geöffnete PB IDE testen.
Re: Window back on the Top - Gadget
Verfasst: 05.10.2011 16:27
von X360 Andy
Klappt in meinem Beispiel alles nicht.
Hier ein einfaches Beispiel wie es funktionieren sollte
- Hier funktioniert es nicht
[Egal welchen Befehl ich einsetze vor dem SetActiveGadget()]
Code: Alles auswählen
Global Exit
Global Befehl
#W1=1
#G1=2
#G2=3
Procedure A1(P)
Repeat
Select Befehl
Case 1
Debug "Befehl 1"
Befehl=0
Case 2
Debug "Befehl 2 ---"
Debug "Run Calc.exe"
program=RunProgram("calc.exe", "", "", #PB_Program_Open)
While ProgramRunning(program)
Delay(100)
Wend
CloseProgram(program)
Debug "Calc Closed"
SetActiveGadget(#G1)
Debug "SetActiveGadget State to G1"
Debug "realy ?"
Befehl=0
EndSelect
Delay(10)
Until Exit=1
Exit=2
EndProcedure
OpenWindow(#W1, 100, 100, 200, 200, "Main")
StringGadget(#G1, 10, 10, 100, 20, "ABC")
ButtonGadget(#G2, 10, 40, 100, 20, "Klick mich")
CreateThread(@A1(), 1)
Repeat
event=WaitWindowEvent(50)
Select event
Case #PB_Event_Gadget
Select EventGadget()
Case #G1
Befehl=1
Case #G2
Befehl=2
EndSelect
Case #PB_Event_CloseWindow
Select GetActiveWindow()
Case #W1
Exit=1
EndSelect
EndSelect
Until Exit=2
Re: Window back on the Top - Gadget
Verfasst: 05.10.2011 17:08
von HeX0R
Aus einem Thread heraus ist meistens schlecht, probier es mal so:
Code: Alles auswählen
Global Exit
Global Befehl
#W1=1
#G1=2
#G2=3
Procedure A1(P)
Repeat
Select Befehl
Case 1
Debug "Befehl 1"
Befehl=0
Case 2
Debug "Befehl 2 ---"
Debug "Run Calc.exe"
program=RunProgram("calc.exe", "", "", #PB_Program_Open)
While ProgramRunning(program)
Delay(100)
Wend
CloseProgram(program)
Debug "Calc Closed"
PostMessage_(WindowID(#W1), #WM_APP, 1, 1)
Befehl=0
EndSelect
Delay(10)
Until Exit=1
Exit=2
EndProcedure
OpenWindow(#W1, 100, 100, 200, 200, "Main")
StringGadget(#G1, 10, 10, 100, 20, "ABC")
ButtonGadget(#G2, 10, 40, 100, 20, "Klick mich")
CreateThread(@A1(), 1)
Repeat
event=WaitWindowEvent(50)
Select event
Case #WM_APP
SetActiveWindow(#W1)
SetActiveGadget(#G1)
Case #PB_Event_Gadget
Select EventGadget()
Case #G1
Befehl=1
Case #G2
Befehl=2
EndSelect
Case #PB_Event_CloseWindow
Select GetActiveWindow()
Case #W1
Exit=1
EndSelect
EndSelect
Until Exit=2
[Edit]
Oder gleich aus dem Thread ein
aufrufen.