itchley
Goto Top

Menü-Überschrift in einer GUI durch PowerShell

Moin zusammen,

mit PowerShell bin ich leider noch nicht so lange beschäftigt, da aufgrund von vielen Altlasten noch alles über Batch laufen musste. Nun kann ich die alten Skripte mit PowerShell erneuern und möchte das auch mit vernünftigen Aussehen machen.

Zu meinem Problem:
Der Benutzer muss an verschiedenen Stellen etwas Auswählen und ich wollte dies mit einer einfachen Klickoberfläche lösen; das klappt auch soweit bis auf die Formatierung der Überschrift. Diese ist unterschiedlich lang und mein Wunsch wäre es, wenn diese sich, wenn sie denn länger ist, nicht nach rechts ausbreitet sondern durch einen Zeilenumbruch nach unten erweitert und dabei die Schaltflächen nach unten schiebt.
Alle meine Versuche sind nicht erfolgreich...
demo


    # Create a listbox to select the region
    [System.Windows.Forms.Application]::EnableVisualStyles()
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  
    [void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")  

    # Menu Layout
    $MenuBox = New-Object System.Windows.Forms.Form
    #$MenuBox.Size = New-Object System.Drawing.Size @(650,250)
    $MenuBox.Text = 'Miau'  
    $MenuBox.StartPosition = "CenterScreen"  
    $MenuBox.AutoSize = $True
    $MenuBox.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D

    # Menu Header Text
    $MenuHeader = New-Object System.Windows.Forms.Label
    $MenuHeader.Font = New-Object System.Drawing.Font("Consolas",20,3,3,1)  
    $MenuHeader.Location = New-Object System.Drawing.Size(118,20)
    #$MenuHeader.Size = New-Object System.Drawing.Size(380,40)
    $MenuHeader.AutoSize = $True 
    $MenuHeader.Text = 'Eine nun etwas längere Überschrift'  
    $MenuHeader.TextAlign = [System.Drawing.ContentAlignment]::TopCenter
    $MenuBox.Controls.Add($MenuHeader)

    # Button Level 0
    
        $Button0 = New-Object System.Windows.Forms.Button
        $Button0.Location = New-Object System.Drawing.Size(62,60)
        $Button0.Size = New-Object System.Drawing.Size(500,30)
        $Button0.Add_Click({
            $global:ButtonResult = 'Ergebnis0'  
            $MenuBox.Close()
            })
        $Button0.Text = 'Text für Schaltfläche 0'  
        $Button0.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3,1)  
        $MenuBox.Controls.Add($Button0)
        

    # Button Level 1
  
        $Button1 = New-Object System.Windows.Forms.Button
        $Button1.Location = New-Object System.Drawing.Size(62,100)
        $Button1.Size = New-Object System.Drawing.Size(500,30)
        $Button1.Add_Click({
            $global:ButtonResult = 'Ergebnis1'  
            $MenuBox.Close()
            })
        $Button1.Text = 'Text für Schaltfläche 1'  
        $Button1.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3,1)  
        $MenuBox.Controls.Add($Button1)
        

    # Button Level 2
   
        $Button2 = New-Object System.Windows.Forms.Button
        $Button2.Location = New-Object System.Drawing.Size(62,140)
        $Button2.Size = New-Object System.Drawing.Size(500,30)
        $Button2.Add_Click({
            $global:ButtonResult = 'Ergebnis2'  
            $MenuBox.Close()
            })
        $Button2.Text = 'Text für Schaltfläche 2'  
        $Button2.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3,1)  
        $MenuBox.Controls.Add($Button2)
        

    # Button  Level 3
   
        $Button3 = New-Object System.Windows.Forms.Button
        $Button3.Location = New-Object System.Drawing.Size(62,180)
        $Button3.Size = New-Object System.Drawing.Size(500,30)
        $Button3.Add_Click({
            $global:ButtonResult = 'Ergebnis3'  
            $MenuBox.Close()
            })
        $Button3.Text = 'Text für Schaltfläche 3'  
        #$Button3.Text.MouseOverColor = [System.Drawing.Color]::red
        #$Button3.TextAlign = [System.Drawing.ContentAlignment]::TopCenter
        $Button3.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",12,0,3,1)  
        $MenuBox.Controls.Add($Button3)
        

    # Exit Button
    $ExitButton = New-Object System.Windows.Forms.Button
    $ExitButton.Location = New-Object System.Drawing.Size(540,220)
    $ExitButton.Size = New-Object System.Drawing.Size(75,23)
    $ExitButton.Text = "Exit"  
    $ExitButton.Font = New-Object System.Drawing.Font("Microsoft Sans Serif",11,0,3,1)  
    $ExitButton.Add_Click({
        #Remove-Item "$WorkingDirectory\Temp\*.*" -Force  
        $MenuBox.Close()
        })
    $MenuBox.Controls.Add($ExitButton)

    # Show Menu
    $MenuBox.Topmost = $True
    $MenuBox.Add_Shown({$MenuBox.Activate()})
    [void] $MenuBox.ShowDialog()
    $global:ButtonResult

Besten Dank schonmal

Gruß
Itchley

Content-ID: 7513461852

Url: https://administrator.de/forum/menue-ueberschrift-in-einer-gui-durch-powershell-7513461852.html

Ausgedruckt am: 05.04.2025 um 19:04 Uhr

7426148943
7426148943 13.06.2023 aktualisiert um 19:53:32 Uhr
Goto Top
Kannst du bspw. mit einem FlowLayoutPanel machen

https://www.philosophicalgeek.com/2008/12/12/an-easy-stack-layout-panel- ...

Und der Eigenschaft WordWrap auf $true festlegen
https://learn.microsoft.com/de-de/dotnet/api/system.windows.forms.textbo ...

Zeppel
mbehrens
mbehrens 13.06.2023 um 22:32:15 Uhr
Goto Top
Ich sehe da zwei Ansätze:

  • an geeigneter Stelle ein `n einfügen
  • AutoSize deaktivieren und Height/Width gewünscht setzen
TK1987
Lösung TK1987 13.06.2023, aktualisiert am 14.06.2023 um 00:39:33 Uhr
Goto Top
Moin,

Zitat von @Itchley:
Zu meinem Problem:
Der Benutzer muss an verschiedenen Stellen etwas Auswählen und ich wollte dies mit einer einfachen Klickoberfläche lösen; das klappt auch soweit bis auf die Formatierung der Überschrift. Diese ist unterschiedlich lang und mein Wunsch wäre es, wenn diese sich, wenn sie denn länger ist, nicht nach rechts ausbreitet sondern durch einen Zeilenumbruch nach unten erweitert und dabei die Schaltflächen nach unten schiebt.
kein Problem, einfach die MaximumSize-Eigenschaft mit einer gewünschten Breite versehen, z.B.:
$MenuHeader.MaximumSize = "100,1000"  

AutoSize würde ich persönlich niemals deaktivieren. Bei mir hat jedes Fenster AutoSize und ich hatte noch nie Probleme damit.
Damit sich die Elemente automatisch verschieben benutze ich immer ein TableLayoutPanel.

Ich habe dir den Code mal ein bisschen umgeschrieben (wie ich finde einfach übersichtlicher, aber das ist natürlich auch ein Stück weit geschmackssache):
#region Settings
  using namespace System.Windows.Forms
  using namespace System.Drawing
  Add-Type -a System.Windows.Forms
  [Application]::EnableVisualStyles()
  $Font = @{
    cons = [Font]::New("Consolas",20,[FontStyle]"Bold,Italic")  
    mss  = [Font]::New("Microsoft Sans Serif",12)  
  }
#endregion Settings

#region Controls
  $MenuBox = [Form]@{Text='Miau'; StartPosition="CenterScreen"; AutoSize=$True; FormBorderStyle="Fixed3D"; Font=$Font.mss; Padding="10,10,10,10"; TopMost=$true}  
  $TLP = [TableLayoutPanel]@{Dock="Fill"; AutoSize=$true}  
  $MenuHeader = [Label]@{AutoSize=$true; Font=$Font.cons; Text='Eine nun etwas längere Überschrift'; Anchor="Bottom"; MaximumSize="400,500"; TextAlign="MiddleCenter"}  
  $Buttons = @(
    [Button]@{Name="Button0"; Size="500,30"; Text='Text für Schaltfläche 0'; Margin="10,10,10,10"}  
    [Button]@{Name="Button1"; Size="500,30"; Text='Text für Schaltfläche 1'; Margin="10,10,10,10"}  
    [Button]@{Name="Button2"; Size="500,30"; Text='Text für Schaltfläche 2'; Margin="10,10,10,10"}  
    [Button]@{Name="Button3"; Size="500,30"; Text='Text für Schaltfläche 3'; Margin="10,10,10,10"}  
    [Button]@{Name="Exit"; Anchor="Bottom"; Size="75,23"; Text='Exit'; Margin="10,10,10,10"}  
  )
#endregion Controls

#region Events
  $Buttons.Add_Click({
    $this.TopLevelControl.tag = $this.Name
    $this.TopLevelControl.Hide()
  })
#endregion Events
    
#region Layout
  $TLP.Controls.Add($MenuHeader)
  $TLP.Controls.AddRange($Buttons)
  $MenuBox.Controls.Add($TLP)
#endregion Layout

#region run
  [void]$MenuBox.ShowDialog()
#endregion run

#region result
  $MenuBox.Tag
#endregion result

Gruß Thomas
Itchley
Itchley 14.06.2023 um 23:46:54 Uhr
Goto Top
Moin zusammen

@7426148943
nach Deinem Beitrag habe ich mich an den Vorschlägen ein paar Stunden versucht und bin leider kläglich gescheitert
Trotzdem Danke

@mbehrens
Ohne es zu getestet zu haben, glaube ich das 'n ein manueller Zeilenumbruch ist...wenn nein, sorry das ich es nicht versucht habe...wenn ja, unpraktikabel, da ich diese und auch noch andere "Klickfenster" noch sehr oft in mehreren Sprachen vorhalten möchte und da ist mir der Arbeitseinsatz dafür zu hoch face-wink - Vielleicht hätte ich erwähnen sollen, das die Texte von der Überschrift bis zum Exit-Button aus Variablen gefüllt werden - nochmal sorry wenn es undeutlich war
Wie in meinem Code zu sehen hatte ich in Zeile 8 eine alternative zu AutoSize, nur leider war das Ergebnis nicht wie gewünscht
Auch Dir danke ich trotzdem für deine Unterstützung

@TK1987
MenuBox.Size und MenuBox.AutoSize bringst Du mir das Ding MaximumSize - damit Funktioniert auch mein "unübersichtlicher" Code, aber Deiner ist schon deutlich eleganter...nur versteh ich den weniger als mein Konstrukt...möchte den aber gerne weil deutlich eleganter nutzen.
Allein in einer eigenen Reiterkarte in ISE läufts, bei mir im Skript im Austausch zur alten Version musste ich Zeile 2&3 rausschmeißen und egal was ich Auswähle, diese Box kommt in Dauerschleife, also ob ich über die Titelleiste "X" drücke oder den "Exit-Button" betätige, es schließt nicht sondern kommt wieder oder ich wähle einen der vier Button, das Fenster kommt wieder face-sad - dabei sollte eigentlich das nächste Fenster (alte Art) kommen - tausche diese erst wenn ich den Code allein für das Kapitel 30 mal einfügen kann.

Hab es wie folgt angepasst
                    # Variablen
                    $Frage = Get-Content "C:\Itchley\BedSpr\032.de"  
                    $Ueber = $032
                    $Lev0 = $033
                    $Lev1 = $034
                    $Lev2 = $035
                    $Lev3 = $036
                    $Ziel = "C:\Itchley\QMAT\W000100.txt"  

                    #region Settings
                      #using namespace System.Windows.Forms
                      #using namespace System.Drawing
                      Add-Type -a System.Windows.Forms
                      [Application]::EnableVisualStyles()
                      $Font = @{
                        cons = [Font]::New("Consolas",20,[FontStyle]"Bold,Italic")  
                        mss  = [Font]::New("Microsoft Sans Serif",12)  
                      }
                    #endregion Settings
                    #region Controls
                      $MenuBox = [Form]@{Text=$031; StartPosition="CenterScreen"; AutoSize=$True; FormBorderStyle="Fixed3D"; Font=$Font.mss; Padding="10,10,10,10"; TopMost=$true}  
                      $TLP = [TableLayoutPanel]@{Dock="Fill"; AutoSize=$true}  
                      $MenuHeader = [Label]@{AutoSize=$true; Font=$Font.cons; Text=$Ueber; Anchor="Bottom"; MaximumSize="600,600"; TextAlign="MiddleCenter"}  
                      $Buttons = @(
                        [Button]@{Name="$Frage Level 0 ______________________________________ Nicht Einsatzbereit"; Size="600,30"; Text=$Lev0; Margin="10,10,10,10"}  
                        [Button]@{Name="$Frage Level 1 ______________________________________ Nicht Einsatzbereit"; Size="600,30"; Text=$Lev1; Margin="10,10,10,10"}  
                        [Button]@{Name="$Frage Level 2 ______________________________________ Bedingt Einsatzbereit"; Size="600,30"; Text=$Lev2; Margin="10,10,10,10"}  
                        [Button]@{Name="$Frage Level 3 ______________________________________ Einsatzbereit; PlatformCard vorhanden"; Size="600,30"; Text=$Lev3; Margin="10,10,10,10"}  
                        [Button]@{Name="Exit"; Anchor="Bottom"; Size="95,23"; Text=$002; Margin="10,10,10,10"}  
                      )
                    #endregion Controls
                    #region Events
                      $Buttons.Add_Click({
                        $this.TopLevelControl.tag = $this.Name
                        $this.TopLevelControl.Hide()
                      })
                    #endregion Events
                    #region Layout
                      $TLP.Controls.Add($MenuHeader)
                      $TLP.Controls.AddRange($Buttons)
                      $MenuBox.Controls.Add($TLP)
                    #endregion Layout
                    #region run
                      [void]$MenuBox.ShowDialog()
                    #endregion run

                    # Ausgabe in Datei
                    Write-Output $MenuBox.Tag | Out-File -FilePath $Ziel
Dir definitiv ein dickes Danke, mein oben geschildertes Problem hast Du definitv gelöst aber leider versteh ich nicht, warum das Teil nicht schließt bzw. eine Dauerschleife auslöst face-confused

Beste Grüße
Itchley
TK1987
TK1987 15.06.2023 aktualisiert um 00:52:36 Uhr
Goto Top
Zitat von @Itchley:
@TK1987
Deiner ist schon deutlich eleganter...nur versteh ich den weniger als mein Konstrukt...
es ist im Prinzip genau das Selbe.

Du hast bisher zuerst ein Objekt einer Klasse erzeugt, dieses in einer Variable gespeichert und diesem dann nach und nach die Eigenschaftswerte zugewiesen... z.B.:
$MenuBox = New-Object System.Windows.Forms.Form
$MenuBox.Text = 'Miau'  
$MenuBox.StartPosition = "CenterScreen"  
$MenuBox.AutoSize = $True
ich hingegen habe die Werte schon bei der Erstellung übergeben...
$MenuBox = [System.Windows.Forms.Form]@{
  Text = 'Miau'  
  StartPosition = "CenterScreen"  
  AutoSize = $true
}
statt Zeilenümbrüche kann man die Zeilen halt auch mit Semikolons trennen und so ein Objekt in einer Zeile statt über meherere Zeilen hinweg schreiben.

Allein in einer eigenen Reiterkarte in ISE läufts
Von der Nutzung der ISE kann ich persönlich nur abraten. Nicht nur, das diese einige Bugs enthält, bei der Ausführung in der ISE laufen Sachen teils ganz anders ab als bei der normalen Ausführung.

Falls du unbedingt eine IDE benötigst, rate ich dir eher zu Visual Studio Code mit Powershell-Plugin.

Ich persönlich schreibe alle Powershell-Skripte mit Notepad++.
Dort kann man sich auch einen Befehl abspeichern (und mit Tastenkombi versehen), um Powershell-Skripte von Notepad++ aus ausführen zu können.

bei mir im Skript im Austausch zur alten Version musste ich Zeile 2&3 rausschmeißen und egal was ich Auswähle, diese Box kommt in Dauerschleife
Seltsam, dass das dann überhaupt noch funktioniert (vermutlich auch wieder eine Eigenart der ISE).

using-Zeilen müssen immer ganz am Anfang des Skripts stehen, also bitte nicht rausschmeissen, sondern einfach nach ganz oben setzen, dann funktioniert es face-wink

Wofür sind die Zeilen gut? Sie Sorgen einfach dafür, das du nicht immer den kompletten Paketpfad (System.Windows.Forms) zur Klasse angeben musst.

Du kannst dann also z.B. statt
New-Object System.Windows.Forms.Form
einfach
New-Object Form
sagen. Oder, wie ich es gemacht habe, einfach
[Form]@{}

Ohne die using-Zeilen dürfte der Code daher eigentlich gar nicht funktionieren, da die Klassen nicht gefunden werden können.

Gruß Thomas
Itchley
Itchley 15.06.2023 um 08:46:44 Uhr
Goto Top
Von der Nutzung der ISE kann ich persönlich nur abraten. Nicht nur, das diese einige Bugs enthält, bei der Ausführung in der ISE laufen Sachen teils ganz anders ab als bei der normalen Ausführung.
Na toll, aber kein Problem...meine Batch-Dinger habe ich auch alle in Notepad++ gemacht, von daher nehm ich dann hierfür auch wieder den und das starten über Tastenkombi hab ich auch schon drin.

Die using-Zeilen sind nun ganz oben und machen keine Probleme
Die Dauerschleife habe ich nun auch raus. War noch ein "Fragment" meiner verzweifelten Versuche gestern Abend übrig geblieben.

Daher besten Dank für Deine Hilfe und die echt gute Erklärung dazu
Gruß
Itchley