Portare in primo piano un'applicazione Windows Forms già avviata

giovedì 31 luglio 2008 - 09.47

shakermaker Profilo | Newbie

Salve a tutti. Ho un problema in VB.NET.
Ho una applicazione che desidero si apra una sola volta, perciò se si tenta di aprire l'exe una seconda volta, deve essere portata in primo piano la finestra dell'applicazione già avviata e non avviata una seconda istanza.
Ho scritto questo semplice codice nella form:

Private Const SW_SHOWMAXIMIZED As Integer = 3
Private Const SW_SHOWDEFAULT As Integer = 10
Private Const SW_SHOWNORMAL As Integer = 1
Private Const SW_RESTORE As Integer = 9
Private Const SW_SHOW As Integer = 5
Private Declare Function ShowWindow Lib "user32" (ByVal handle As IntPtr, ByVal nCmdShow As Integer) As Integer
Private Declare Function SetForegroundWindow Lib "user32" (ByVal handle As IntPtr) As Integer

Private Sub MaximizeExeByName(ByVal ExeNameWithoutPathOrExtension As String)
Dim ps() As Process = Process.GetProcessesByName(ExeNameWithoutPathOrExt ension)
If ps.Length > 0 Then
ShowWindow(ps(0).MainWindowHandle, SW_RESTORE)
'ShowWindow(ps(0).MainWindowHandle, SW_SHOW)
MsgBox("")
SetForegroundWindow(ps(0).MainWindowHandle)
End If
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If PrevInstance() Then
MaximizeExeByName("TestFocus")
Process.GetCurrentProcess().Kill()
End If
End Sub

Private Function PrevInstance() As Boolean
If UBound(Diagnostics.Process.GetProcessesByName(Diag nostics.Process.GetCurrentProcess.ProcessName)) > 0 Then
Return True
Else
Return False
End If
End Function

La cosa strana è che io provo ad aprire l'exe e a volte funziona (la form viene riportata in primo piano) e a volte no... del tutto casuale... avete qualche idea?

aiedail92 Profilo | Expert

Ciao

L'approccio che hai usato non è forse uno dei migliori. Infatti quando chiami MaximizeExeByName, se ci sono due processi attivi rischi di portare in rilievo l'applicazione che successivamente viene chiusa, rendendo inutile la chiamata. Ti consiglio invece di usare un altro approccio, quello dei Mutex. Trovi un esempio qui:

http://www.p2pforum.it/forum/showthread.php?t=165986

Per portare in rilievo la finestra principale poi non ti conviene usare la proprietà MainWindowHandle, perchè il processo potrebbe non avere una MainWindow associata. Per ottenere la finestra che ti serve usa FindWindow passando Nothing come primo argomento e il titolo della finestra come secondo:

Private Declare Unicode Function FindWindowW Lib "user32" _ (ByVal className As String, ByVal windowTitle As String) As IntPtr

Edit: Il codice del link non è del tutto corretto, controllate l'ultimo post per il codice giusto

Luca

shakermaker Profilo | Newbie

Ciao Luca, grazie per l'aiuto. Ho provato a inserire questo codice seguendo i tuoi 2 consigli:

Try
mut = Mutex.OpenExisting(IST_NAME)
Catch ex As WaitHandleCannotBeOpenedException
' Niente
Catch ex As Exception

End Try
If mut Is Nothing Then
Else
' mando in primo piano il processo esistente
FindWindowW("", "Sms Scheduler")
Process.GetCurrentProcess().Kill()
Exit Sub
End If

Il mutex però è sempre Nothing e mi si aprono più istanze... cosa ho sbagliato?

aiedail92 Profilo | Expert

Ciao

Se hai copiato il codice dal link che ti ho dato, mi sono accorto ora che nel codice completo manca l'istruzione per creare il Mutex se non è già stato creato (quindi alla prima istanza). Modifica il codice così (Ho già inserito anche il metodo che porta in primo piano la finestra corretta):

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Luca
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5