Question [Functions]API Windows-gestion de fenêtre
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
La dernière version du package des API Windows, ce trouve ici .
Fonctions implémentées :
function ShowWindowAsync([IntPtr] $hWnd, [Int32] $nCmdShow)
function SetActiveWindow([IntPtr] $hWnd)
function SendMessage([IntPtr] $hWnd, [Int32] $message, [Int32] $wParam, [Int32] $lParam)
function GetConsoleWindow()
function BringWindowToTop([IntPtr] $hWnd)
function SetWindowPos([IntPtr] $hWnd, [IntPtr] $hWndInsertAfter, [Int32] $X, [Int32] $Y, [Int32] $cx, [Int32] $cy, [UInt32] $uFlags)
function SetFocus([IntPtr] $hWnd)
function SwitchToThisWindow([IntPtr] $hWnd, [Boolean] $fAltTab=$false)
function SetForegroundWindow([IntPtr] $hWnd)
function GetWindowRect([IntPtr] $hWnd, [REF] $lpRect)
function FindWindow([String] $lpClassName, [string] $lpWindowName)
function MoveWindow([IntPtr] $hWnd, [Int32] $X, [Int32] $Y, [Int32] $nWidth, [Int32] $nHeight,[Int32] $bRepaint)
Tools :
function Set-ForegroundWindow ([IntPtr] $MyHandle=$((Get-Process –id $pid).MainWindowHandle))
Function Set-ConsoleIcon([string] $iconFile)
function Show-PowerShell() ! Utilise un variable globale
function Hide-PowerShell() ! Utilise un variable globale
function Minimize-PowerShell() ! Utilise un variable globale
Exemples :
[code:1]
#Exemple 1
#Cache la fenêtre de PowerShell
$myWindowHandle = (Get-Process -Id $pid).MainWindowHandle
#Cache la fenêtre PowerShell
Hide-PowerShell
sleep 2
#Restaure la fenêtre PowerShell
Show-PowerShell;
#Exemple 2
#exécute un process qui se place au premier plan en prenant le focus
$MyHandle=(Get-Process –id $pid).MainWindowHandle
Start-process \"C:\dev\DebugView\Dbgview.exe\" -WindowStyle Minimized
#Restaure la fenêtre de PowerShell au premier plan
SetActiveWindow $MyHandle
SetForegroundWindow $MyHandle
SwitchToThisWindow $MyHandle $true
#Exemple 2-1
#Sans minimiser la fenêtre du nouveau processus.
&\"C:\dev\DebugView\Dbgview.exe\"
start-sleep -m 200
Set-ForegroundWindow
#Exemple 2-2
#On minimise la fenêtre du nouveau processus.
$psi = new-object system.diagnostics.processStartInfo
$psi.FileName=\"C:\dev\DebugView\Dbgview.exe\"
$psi.Arguments=\"\"
$psi.LoadUserProfile=$false
$psi.UseShellExecute=$True
$psi.WindowStyle=[System.Diagnostics.ProcessWindowStyle]::Minimized
$proc = [system.diagnostics.process]::«»start($psi)
Set-ForegroundWindow
#Exemple 2-3
#On utilise un cmdlet dédié qui minimise la fenêtre du nouveau processus.
$MyHandle=(Get-Process –id $pid).MainWindowHandle
if ($PscxVersion -eq \"1.1.1.0\"«»)
{
Start-process \"C:\dev\DebugView\Dbgview.exe\" -WindowStyle Minimized >$null
Set-ForegroundWindow #$MyHandle
}
else
{ cmd.exe /C Start www.codeplex.com/PowerShellCX}
#Exemple 3
#On crée un nouveau shell PS
$MyHandle=([diagnostics.process]::«»start(\"PowerShell.exe\", $null)).id
#On démarre un process qui prend le \"focus\"
Start-process \"C:\dev\DebugView\Dbgview.exe\" -WindowStyle Minimized >$null
#On place cette fois ci le focus sur la nouvelle session PS précédement créée.
Set-ForegroundWindow $MyHandle
#Exemple 3-1
$MyHandle=([diagnostics.process]::«»start(\"PowerShell.exe\", $null)).id
#On démarre, en lui donnant une taille de fenêtre maximum, un process qui prend le \"focus\"
Start-process \"C:\dev\DebugView\Dbgview.exe\" -WindowStyle Maximized
#On place le focus sur la nouvelle session PS précédement créée.
Set-ForegroundWindow $MyHandle
#Certaines applications peuvent mémoriser leur position, comme le fait Dbgview.exe, dans ce cas le paramètre
#-WindowStyle peut sembler ne pas avoir le comportement adéquate. C'est l'application qui une fois chargée se redessine
# avec les anciennes coordonnées mémorisées (dans la registry ou dans un fichier de configuration).
#Dans ce cas on appel la fonction Minimize-PowerShell()
[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 30/05/10 18:01
Tutoriels PowerShell
Pièces jointes :
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
[code:1]
# -- Menu
function GetSystemMenu([IntPtr] $hWnd, [Boolean] $bRevert)
{ #Obtient le handle du menu system d'une fenêtre
$parameterTypes = [IntPtr],[Boolean]
$parameters = $hWnd,$bRevert
Invoke-Win32 \"user32.dll\" ([IntPtr]) \"GetSystemMenu\" $parameterTypes $parameters
}
function GetMenuItemCount([IntPtr] $hMenu)
{ #Renvoi le nombre d'items dans le menu spécifié
$parameterTypes = [IntPtr]
$parameters = $hMenu
Invoke-Win32 \"user32.dll\" ([Int32]) \"GetMenuItemCount\" $parameterTypes $parameters
}
function AppendMenu([IntPtr] $hMenu, [UInt32] $uFlags, [UInt32] $uIDNewItem,[String] $lpNewItem)
{ #Supprime une entrée de menu.
$parameterTypes = [IntPtr], [UInt32], [UInt32],[String]
$parameters = $hMenu, $uFlags, $uIDNewItem, $lpNewItem
Invoke-Win32 \"user32.dll\" ([Boolean]) \"AppendMenu\" $parameterTypes $parameters
# $MF_STRING = 0
# $MF_BITMAP = 4
# $MF_OWNERDRAW = 256
}
function RemoveMenu([IntPtr] $hMenu, [Int32] $uPosition, [Int32] $uFlags)
{ #Supprime une entrée de menu.
$parameterTypes = [IntPtr],[Int32],[Int32]
$parameters = $hMenu,$uPosition,$uFlags
Invoke-Win32 \"user32.dll\" ([Boolean]) \"RemoveMenu\" $parameterTypes $parameters
#Valeur des menus, il est possible de les utiliser pour $uPosition
# $SC_SIZE = 61440;
# $SC_MOVE = 61456;
# $SC_MINIMIZE = 61472;
# $SC_MAXIMIZE = 61488;
# $SC_RESTORE = 61728;
# $SC_SEPARATOR = 61455;
# $SC_CLOSE = 61536;
# Menu \"Modifier\"
# $SC_DEFAULT = 61792;
# Menu \"Propriétés\"
#Valeur de Uflags
# $MF_BYCOMMAND = 0
# $MF_BYPOSITION = 1024
}
[/code:1]
Permet de supprimer puis de recréer le menu système \"Fermer\" d'une fenêtre, l'instruction PowerShell exit reste valide :
[code:1]
#Struct menuinfo: msdn.microsoft.com/en-us/library/ms647578(VS.85).aspx
#Constante utilsées par les API de gestion des menus
$MF_BYCOMMAND = 0
$MF_BYPOSITION = 1024
$SC_CLOSE = 61536
#Récupère le handle de la fenêtre de PS
$MyHandle=(Get-Process –id $pid).MainWindowHandle
#Récupère le handle du menu system de PS
$hSystemMenuPS= GetSystemMenu $MyHandle $False
#Récupère le nombre d'entrées du menu système de PS
$NbMenuItem= GetMenuItemCount $hSystemMenuPS
#Supprime le menu Close par sa position, s'il n'y a eu aucune modification
#RemoveMenu $hSystemMenuPS ($NbMenuItem - 4) $MF_BYPOSITION
#Supprime le menu Close par son nom
#RemoveMenu $hSystemMenuPS $SC_CLOSE $MF_BYCOMMAND
#Supprime le premier menu
#RemoveMenu $hSystemMenuPS ($NbMenuItem - 1) $MF_BYPOSITION
#Supprime le menu Close par son nom
#Le bouton \"X\" semble rester valide mais ce n'est pas le cas,
# un refresh de la fenêtre le redessinera grisé.
Remove-CloseMenu $hSystemMenuPS
# fait qq chose ...
#Ajoute, en fin de liste, une entrée de menu appelant
#l'event Close ( WM_SYSCOMMAND Notification)
Add-CloseMenu $hSystemMenuPS
[/code:1]
[edit]
Une nouveauté de la version 2 facilite les appels Win32 :
www.leeholmes.com/blog/PowerShellPInvokeWalkthrough.aspx
Message édité par: Laurent Dardenne, à: 21/01/09 17:14
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
[code:1]#Nouvelles fonctions
#Functions Windows
function GetWindowLong([IntPtr] $hWnd, [Int32] $nIndex)
function SetWindowLong([IntPtr] $hWnd, [Int32] $nIndex, [Int32] $dwNewLong)
#Functions Menu
function GetMenuState([IntPtr] $hMenu, [UInt32] $uId, [UInt32] $uFlags)
function InsertMenu([IntPtr] $hMenu,[UInt32] $Position, [UInt32] $Flags, [UInt32] $NewId,[String] $Item )
function DestroyMenu([IntPtr] $hMenu)
function DrawMenuBar([IntPtr] $hMenu)
#Function Tools
function Remove-MinimizeMenu([IntPtr] $hMenu)
function Add-MinimizeMenu([IntPtr] $hMenu)
function StayOnTop([IntPtr] $hWnd, [switch] $OFF)[/code:1]
Modifications:
-le handle de la fenêtre de PS est désormais en constante et est automatiquement déclaré lors du
chargement en dotsource du package : . .\packageWindowsFunctions.
Set-Variable PSWindowHandle -value ((Get-Process -Id $pid).MainWindowHandle) -option Constant
-La fonction Set-cstApiWindows est automatiquement déclarée lors du chargement en dotsource du package.
Elle contient de nouvelles constantes.
Deux nouveaux membres ont été ajoutés, une fonction Add et une propriété Name
La fonction Add facilite la saisie au lieu de
[code:1]
$cApiWindows.SWP_NOSIZE + $cApiWindows.SWP_NOMOVE + $cApiWindows.SWP_NOZORDER + $cApiWindows.SWP_NOACTIVATE + $cApiWindows.SWP_SHOWWINDOW
#On a
$cApiWindows.Add(\"SWP_NOSIZE\",\"SWP_NOMOVE\",\"SWP_NOZORDER\",\"SWP_NOACTIVATE\",\"SWP_SHOWWINDOW\"«»)[/code:1]
La propriété Name contient le nom de la variable d'origine car $this à pour nom \"this\".
[code:1]
...
$Code=\"`$obj| add-member -memberType Scriptproperty -Name Name -value {`\"$VariableName`\"} -SecondValue {Throw `\"La propriété $VariableName est en lecture seule.`\"}\"
invoke-expression $Code
...
[/code:1]
On ne peut donc pas en cas d'erreur dans un traitement indiqué quelle variable est concernée :
[code:1]
...
if ($this.\"$_\" -eq $null)
{Throw \"Le nom de propriété $_ n'existe pas pour la variable $($this.Name).\"}
...
[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 24/03/09 19:25
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
- Messages : 6311
- Remerciements reçus 68
[code:1][System.Runtime.InteropServices.Marshal]::GetLastWin32Error()[/code:1]
Ne fonctionne pas avec le script Invoke-Win32, car par défaut ce script construit l'attribut DllImportAttribute avec la valeur par défaut pour le champ SetLastError :
Comme dans ce ce cas la valeur n'est pas mise en cache on récupére n'importe quoi comme code erreur.true pour indiquer que l'appelé appellera SetLastError ; sinon false. La valeur par défaut est false, sauf en Visual Basic.
Le marshaleur runtime appelle GetLastError et met en mémoire cache la valeur retournée pour empêcher qu'elle soit remplacée par d'autres appels API. Pour récupérer le code d'erreur, vous pouvez appeler GetLastWin32Error.
J'ai essayé de modifier le script d'origine mais sans résultat probant
De plus dans l'appel suivant
[code:1] $ret=SetActiveWindow $WindowHandle
If ($ret -eq $null)
...
[/code:1]
$ret contient un pointeur qui ne peut être comparé avec la valeur $Null de PowerShell mais seulement avec [intPtr]::Zero ou 0.
Dans ce contexte le $null de PowerShell n'est pas identique au null du C#.
Donc la gestion des erreurs Win32 avec un script PS V1 n'est pas pour le moment possible.
Et vous en conviendrez c'est un peu gênant.
[edit]
Voir aussi : blogs.msdn.com/b/oldnewthing/archive/2015/08/19/10636096.aspx
Message édité par: Laurent Dardenne, à: 22/08/15 15:53
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Contributions à la communauté
- [Functions]API Windows-gestion de fenêtre