function Set-DeployCenterButtonStyle { param( [Parameter(Mandatory=$true)][System.Windows.Forms.Button]$Button, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [ValidateSet('Button','PrimaryButton','DangerButton')][string]$Role = 'Button' ) $style = $Theme[$Role] $Button.BackColor = $style.Background $Button.ForeColor = $style.Foreground $Button.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat $Button.UseVisualStyleBackColor = $false $Button.FlatAppearance.BorderSize = 1 $Button.FlatAppearance.BorderColor = $style.Border $Button.FlatAppearance.MouseOverBackColor = $style.HoverBackground $Button.FlatAppearance.MouseDownBackColor = $style.PressedBackground if (-not $Button.Enabled) { $Button.BackColor = $style.DisabledBackground $Button.ForeColor = $style.DisabledForeground } } function New-DeployCenterComboBox { param( [Parameter(Mandatory=$true)][string]$Name, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font, [Parameter(Mandatory=$true)][AllowEmptyCollection()][string[]]$Items ) $comboBox = New-Object System.Windows.Forms.ComboBox $comboBox.Name = $Name $comboBox.DropDownStyle = [System.Windows.Forms.ComboBoxStyle]::DropDownList $comboBox.FlatStyle = [System.Windows.Forms.FlatStyle]::Flat $comboBox.BackColor = $Theme.PanelAlt $comboBox.ForeColor = $Theme.Text $comboBox.Font = $Font $comboBox.IntegralHeight = $false $comboBox.MaxDropDownItems = 12 foreach ($item in $Items) { [void]$comboBox.Items.Add($item) } return $comboBox } function Set-DeployCenterComboBoxTheme { param( [Parameter(Mandatory=$true)][System.Windows.Forms.ComboBox]$ComboBox, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme ) $ComboBox.BackColor = $Theme.PanelAlt $ComboBox.ForeColor = $Theme.Text } function New-DeployCenterPartitionProfileSelector { param( [Parameter(Mandatory=$true)][System.Windows.Forms.GroupBox]$Parent, [Parameter(Mandatory=$true)][string[]]$ProfileNames, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font ) $label = New-Object System.Windows.Forms.Label $label.Text = 'Profil de partitionnement' $label.Size = New-Object System.Drawing.Size(240, 17) $label.ForeColor = $Theme.Text $label.BackColor = [System.Drawing.Color]::Transparent $label.Font = $Font $comboBox = New-DeployCenterComboBox -Name 'cmbPartitionProfile' -Theme $Theme -Font $Font -Items $ProfileNames $Parent.Controls.Add($label) $Parent.Controls.Add($comboBox) Set-DeployCenterPartitionProfileSelectorLayout -Label $label -ComboBox $comboBox -Width ($Parent.ClientSize.Width - 24) return [pscustomobject]@{ Label = $label; ComboBox = $comboBox } } function Set-DeployCenterPartitionProfileSelectorLayout { param( [Parameter(Mandatory=$true)][System.Windows.Forms.Label]$Label, [Parameter(Mandatory=$true)][System.Windows.Forms.ComboBox]$ComboBox, [Parameter(Mandatory=$true)][int]$Width ) $Label.Location = New-Object System.Drawing.Point(12, 139) $ComboBox.Location = New-Object System.Drawing.Point(12, 157) $ComboBox.Size = New-Object System.Drawing.Size([Math]::Max(250, $Width), 26) } function New-DeployCenterDeploymentControls { param( [Parameter(Mandatory=$true)][System.Windows.Forms.GroupBox]$Parent, [Parameter(Mandatory=$true)][string[]]$ProfileNames, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font ) $diskLabel = New-Object System.Windows.Forms.Label $diskLabel.Text = 'Disque physique' $diskLabel.Location = New-Object System.Drawing.Point(12, 20) $diskLabel.Size = New-Object System.Drawing.Size(220, 18) $diskLabel.Font = $Font $diskLabel.ForeColor = $Theme.Text $diskLabel.BackColor = [System.Drawing.Color]::Transparent $diskCombo = New-DeployCenterComboBox -Name 'cmbDisk' -Theme $Theme -Font $Font -Items @() $diskCombo.Location = New-Object System.Drawing.Point(12, 39) $diskCombo.Size = New-Object System.Drawing.Size([Math]::Max(250, $Parent.ClientSize.Width - 24), 26) $diskCombo.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right $systemLabel = New-Object System.Windows.Forms.Label $systemLabel.Text = 'Système à installer' $systemLabel.Location = New-Object System.Drawing.Point(12, 71) $systemLabel.Size = New-Object System.Drawing.Size(240, 18) $systemLabel.Font = $Font $systemLabel.ForeColor = $Theme.Text $systemLabel.BackColor = [System.Drawing.Color]::Transparent $chooseSystemButton = New-Object System.Windows.Forms.Button $chooseSystemButton.Name = 'btnChooseWindows' $chooseSystemButton.Text = 'Choisir…' $chooseSystemButton.Size = New-Object System.Drawing.Size(132, 28) $chooseSystemButton.Location = New-Object System.Drawing.Point([Math]::Max(12, $Parent.ClientSize.Width - 144), 67) $chooseSystemButton.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right Set-DeployCenterButtonStyle -Button $chooseSystemButton -Theme $Theme -Role 'Button' $selectedSystemLabel = New-Object System.Windows.Forms.Label $selectedSystemLabel.Name = 'lblSelectedWindows' $selectedSystemLabel.Text = 'Aucun système sélectionné' $selectedSystemLabel.Location = New-Object System.Drawing.Point(12, 98) $selectedSystemLabel.Size = New-Object System.Drawing.Size([Math]::Max(250, $Parent.ClientSize.Width - 24), 22) $selectedSystemLabel.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right $selectedSystemLabel.Font = $Font $selectedSystemLabel.AutoEllipsis = $true $selectedSystemLabel.ForeColor = $Theme.Secondary $selectedSystemLabel.BackColor = [System.Drawing.Color]::Transparent $profileSelector = New-DeployCenterPartitionProfileSelector -Parent $Parent -ProfileNames $ProfileNames -Theme $Theme -Font $Font $profileSelector.ComboBox.Enabled = $false $hostLabel = New-Object System.Windows.Forms.Label $hostLabel.Text = "Nom d’hôte" $hostLabel.Location = New-Object System.Drawing.Point(12, 190) $hostLabel.Size = New-Object System.Drawing.Size(220, 24) $hostLabel.Font = $Font $hostLabel.ForeColor = $Theme.Text $hostLabel.BackColor = [System.Drawing.Color]::Transparent $hostTextBox = New-Object System.Windows.Forms.TextBox $hostTextBox.Name = 'txtHostName' $hostTextBox.Location = New-Object System.Drawing.Point([Math]::Max(244, $Parent.ClientSize.Width - 202), 187) $hostTextBox.Size = New-Object System.Drawing.Size(190, 26) $hostTextBox.MaxLength = 15 $hostTextBox.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right $hostTextBox.BackColor = $Theme.PanelAlt $hostTextBox.ForeColor = $Theme.Text $hostTextBox.Font = $Font $Parent.Controls.AddRange(@($diskLabel, $diskCombo, $systemLabel, $chooseSystemButton, $selectedSystemLabel, $hostLabel, $hostTextBox)) return [pscustomobject]@{ DiskComboBox = $diskCombo ChooseSystemButton = $chooseSystemButton SelectedSystemLabel = $selectedSystemLabel PartitionProfileLabel = $profileSelector.Label PartitionProfileComboBox = $profileSelector.ComboBox HostNameTextBox = $hostTextBox } } function Set-DeployCenterDeploymentControlsLayout { param( [Parameter(Mandatory=$true)][System.Windows.Forms.GroupBox]$Parent, [Parameter(Mandatory=$true)]$Controls ) $width = [Math]::Max(250, $Parent.ClientSize.Width - 24) $Controls.DiskComboBox.Size = New-Object System.Drawing.Size($width, 26) $Controls.ChooseSystemButton.Location = New-Object System.Drawing.Point([Math]::Max(12, $Parent.ClientSize.Width - 144), 67) $Controls.SelectedSystemLabel.Size = New-Object System.Drawing.Size($width, 22) Set-DeployCenterPartitionProfileSelectorLayout -Label $Controls.PartitionProfileLabel -ComboBox $Controls.PartitionProfileComboBox -Width $width $Controls.HostNameTextBox.Location = New-Object System.Drawing.Point([Math]::Max(244, $Parent.ClientSize.Width - 202), 187) $Controls.HostNameTextBox.Size = New-Object System.Drawing.Size(190, 26) } function New-DeployCenterLogWindow { param( [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font ) $form = New-Object System.Windows.Forms.Form $form.Text = 'Journal DeployCenter' $form.StartPosition = 'CenterParent' $form.Size = New-Object System.Drawing.Size(900, 500) $form.MinimumSize = New-Object System.Drawing.Size(560, 300) $form.ShowInTaskbar = $false $form.BackColor = $Theme.Background $form.ForeColor = $Theme.Text $form.Font = $Font $textBox = New-Object System.Windows.Forms.TextBox $textBox.Name = 'txtLog' $textBox.Location = New-Object System.Drawing.Point(12, 12) $textBox.Size = New-Object System.Drawing.Size(860, 440) $textBox.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right $textBox.Multiline = $true $textBox.ReadOnly = $true $textBox.WordWrap = $false $textBox.ScrollBars = [System.Windows.Forms.ScrollBars]::Both $textBox.BackColor = $Theme.PanelAlt $textBox.ForeColor = $Theme.Text $textBox.BorderStyle = [System.Windows.Forms.BorderStyle]::FixedSingle $textBox.Font = [System.Drawing.Font]::new('Consolas', [single]9, [System.Drawing.FontStyle]::Regular) $form.Controls.Add($textBox) $form.Add_FormClosing({ if ($_.CloseReason -eq [System.Windows.Forms.CloseReason]::UserClosing) { $_.Cancel = $true; $form.Hide() } }.GetNewClosure()) return [pscustomobject]@{ Form = $form; TextBox = $textBox } } function Show-DeployCenterPartitionSizingDialog { param( [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Profile, [Parameter(Mandatory=$true)][double]$AvailableGB, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font, [System.Windows.Forms.Form]$Owner = $null, [System.Collections.IDictionary]$InitialValues = @{} ) $inputs = @($Profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'UserInputGB' }) $remainder = @($Profile.Partitions | Where-Object { [string]$_.Size.Policy -eq 'RemainderAfterInputs' })[0] if ($inputs.Count -eq 0 -or $null -eq $remainder) { return $null } $minimumRemainder = [double]$remainder.Size.MinimumGB $minimumInputs = 0.0 foreach ($inputDefinition in $inputs) { $minimumInputs += [double]$inputDefinition.Size.MinimumGB } if ($AvailableGB -lt ($minimumInputs + $minimumRemainder)) { Show-DeployCenterMessage ` -Message "L'espace disponible sur ce disque est insuffisant pour le profil '$($Profile.Name)'." ` -Title 'Partitionnement impossible' -Icon Warning -Owner $Owner -Theme $Theme -Font $Font return $null } $dialog = New-Object System.Windows.Forms.Form $dialog.Text = 'Tailles des partitions' $dialog.StartPosition = if ($Owner) { 'CenterParent' } else { 'CenterScreen' } $dialog.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $dialog.ShowInTaskbar = $false $dialog.MinimizeBox = $false $dialog.MaximizeBox = $false $dialog.BackColor = $Theme.Background $dialog.ForeColor = $Theme.Text $dialog.Font = $Font $dialog.ClientSize = New-Object System.Drawing.Size(470, (152 + ($inputs.Count * 42))) $capacityLabel = New-Object System.Windows.Forms.Label $capacityLabel.Location = New-Object System.Drawing.Point(18, 16) $capacityLabel.Size = New-Object System.Drawing.Size(430, 34) $capacityLabel.Text = "Capacité estimée après réservation EFI, MSR et WinRE : {0:N1} Go.`r`nLa taille WinRE exacte sera recalculée lors du partitionnement." -f $AvailableGB $capacityLabel.ForeColor = $Theme.Text $capacityLabel.BackColor = [System.Drawing.Color]::Transparent $capacityLabel.Font = $Font $dialog.Controls.Add($capacityLabel) $inputControls = [System.Collections.Generic.List[object]]::new() for ($i = 0; $i -lt $inputs.Count; $i++) { $definition = $inputs[$i] $rowY = 60 + ($i * 42) $label = New-Object System.Windows.Forms.Label $label.Location = New-Object System.Drawing.Point(18, ($rowY + 4)) $label.Size = New-Object System.Drawing.Size(250, 26) $label.Text = [string]$definition.Size.Label $label.ForeColor = $Theme.Text $label.BackColor = [System.Drawing.Color]::Transparent $label.Font = $Font $dialog.Controls.Add($label) $otherMinimums = 0.0 for ($j = 0; $j -lt $inputs.Count; $j++) { if ($j -ne $i) { $otherMinimums += [double]$inputs[$j].Size.MinimumGB } } $maximum = [math]::Floor($AvailableGB - $minimumRemainder - $otherMinimums) $minimum = [double]$definition.Size.MinimumGB $numeric = New-Object System.Windows.Forms.NumericUpDown $numeric.Location = New-Object System.Drawing.Point(292, $rowY) $numeric.Size = New-Object System.Drawing.Size(150, 28) $numeric.Minimum = [decimal]$minimum $numeric.Maximum = [decimal]$maximum $numeric.DecimalPlaces = 0 $numeric.Increment = 1 $numeric.BackColor = $Theme.PanelAlt $numeric.ForeColor = $Theme.Text $numeric.Font = $Font $initialValue = $null if ($InitialValues.Contains([string]$definition.Role)) { $initialValue = [double]$InitialValues[[string]$definition.Role] } if ($null -eq $initialValue) { $initialValue = [math]::Floor($AvailableGB * ([double]$definition.Size.DefaultPercent / 100)) } $initialValue = [math]::Max($minimum, [math]::Min($maximum, $initialValue)) $numeric.Value = [decimal]$initialValue $inputControls.Add([pscustomobject]@{ Role = [string]$definition.Role; Control = $numeric }) $dialog.Controls.Add($numeric) } $remainderLabel = New-Object System.Windows.Forms.Label $remainderLabel.Location = New-Object System.Drawing.Point(18, (62 + ($inputs.Count * 42))) $remainderLabel.Size = New-Object System.Drawing.Size(430, 26) $remainderLabel.ForeColor = $Theme.Secondary $remainderLabel.BackColor = [System.Drawing.Color]::Transparent $remainderLabel.Font = $Font $dialog.Controls.Add($remainderLabel) $buttonPanel = New-Object System.Windows.Forms.Panel $buttonPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom $buttonPanel.Height = 58 $buttonPanel.BackColor = $Theme.PanelAlt $dialog.Controls.Add($buttonPanel) $cancelButton = New-Object System.Windows.Forms.Button $cancelButton.Text = 'Annuler' $cancelButton.Location = New-Object System.Drawing.Point(258, 10) $cancelButton.Size = New-Object System.Drawing.Size(92, 36) $cancelButton.Font = $Font $cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel Set-DeployCenterButtonStyle -Button $cancelButton -Theme $Theme -Role 'Button' $buttonPanel.Controls.Add($cancelButton) $validateButton = New-Object System.Windows.Forms.Button $validateButton.Text = 'Valider' $validateButton.Location = New-Object System.Drawing.Point(358, 10) $validateButton.Size = New-Object System.Drawing.Size(92, 36) $validateButton.Font = $Font Set-DeployCenterButtonStyle -Button $validateButton -Theme $Theme -Role 'PrimaryButton' $buttonPanel.Controls.Add($validateButton) $dialog.Tag = [pscustomobject]@{ InputControls = $inputControls; AvailableGB = $AvailableGB } $updateRemainder = { $sum = 0.0 foreach ($inputControl in $dialog.Tag.InputControls) { $inputValue = [double]$inputControl.Control.Value $typedValue = 0.0 if ([double]::TryParse([string]$inputControl.Control.Text, [ref]$typedValue)) { $inputValue = $typedValue } $sum += $inputValue } $remainingGB = $dialog.Tag.AvailableGB - $sum $remainderDrive = [string]$remainder.DriveLetter $remainderName = if ($remainderDrive) { "$remainderDrive`:" } else { [string]$remainder.Name } $remainderLabel.Text = "{0} : {1:N1} Go (espace restant)" -f $remainderName, $remainingGB $remainderLabel.ForeColor = if ($remainingGB -lt $minimumRemainder) { $Theme.Danger } else { $Theme.Secondary } $validateButton.Enabled = ($remainingGB -ge $minimumRemainder) }.GetNewClosure() foreach ($inputControl in $inputControls) { $inputControl.Control.Add_ValueChanged($updateRemainder) $inputControl.Control.Add_TextChanged($updateRemainder) } & $updateRemainder $validateButton.Add_Click({ $inputValues = @{} foreach ($inputControl in $dialog.Tag.InputControls) { $inputValues[$inputControl.Role] = [double]$inputControl.Control.Value } $sum = 0.0 foreach ($value in $inputValues.Values) { $sum += [double]$value } $dialog.Tag = [pscustomobject]@{ Inputs = $inputValues RemainderRole = [string]$remainder.Role RemainderGB = [math]::Round(($dialog.Tag.AvailableGB - $sum), 1) AvailableGB = $dialog.Tag.AvailableGB } $dialog.DialogResult = [System.Windows.Forms.DialogResult]::OK $dialog.Close() }) $dialog.AcceptButton = $validateButton $dialog.CancelButton = $cancelButton if ($Owner) { $result = $dialog.ShowDialog($Owner) } else { $result = $dialog.ShowDialog() } $selection = if ($result -eq [System.Windows.Forms.DialogResult]::OK) { $dialog.Tag } else { $null } $dialog.Dispose() return $selection } function Show-DeployCenterMessage { param( [Parameter(Mandatory=$true)][string]$Message, [Parameter(Mandatory=$true)][string]$Title, [ValidateSet('Information','Warning','Error')][string]$Icon = 'Information', [System.Windows.Forms.Form]$Owner = $null, [Parameter(Mandatory=$true)][System.Collections.IDictionary]$Theme, [Parameter(Mandatory=$true)][System.Drawing.Font]$Font ) $messageForm = New-Object System.Windows.Forms.Form $messageForm.Text = $Title $messageForm.StartPosition = if ($Owner) { 'CenterParent' } else { 'CenterScreen' } $messageForm.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedDialog $messageForm.ShowInTaskbar = $false $messageForm.MinimizeBox = $false $messageForm.MaximizeBox = $false $messageForm.BackColor = $Theme.Background $messageForm.ForeColor = $Theme.Text $messageForm.Font = $Font $messageWidth = 390 $textSize = [System.Windows.Forms.TextRenderer]::MeasureText( $Message, $Font, (New-Object System.Drawing.Size($messageWidth, 0)), [System.Windows.Forms.TextFormatFlags]::WordBreak ) $messageHeight = [Math]::Max(42, $textSize.Height + 8) $messageForm.ClientSize = New-Object System.Drawing.Size(470, ($messageHeight + 94)) $iconLabel = New-Object System.Windows.Forms.Label $iconLabel.Location = New-Object System.Drawing.Point(18, 24) $iconLabel.Size = New-Object System.Drawing.Size(34, 34) $iconLabel.Text = if ($Icon -eq 'Information') { 'i' } else { '!' } $iconLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter $iconLabel.Font = New-Object System.Drawing.Font('Segoe UI', [single]16, [System.Drawing.FontStyle]::Bold) $iconLabel.ForeColor = if ($Icon -eq 'Error') { $Theme.Danger } else { $Theme.Accent } $iconLabel.BackColor = [System.Drawing.Color]::Transparent $messageForm.Controls.Add($iconLabel) $messageLabel = New-Object System.Windows.Forms.Label $messageLabel.Location = New-Object System.Drawing.Point(64, 20) $messageLabel.Size = New-Object System.Drawing.Size($messageWidth, $messageHeight) $messageLabel.Text = $Message $messageLabel.ForeColor = $Theme.Text $messageLabel.BackColor = [System.Drawing.Color]::Transparent $messageLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleLeft $messageLabel.Font = $Font $messageForm.Controls.Add($messageLabel) $buttonPanel = New-Object System.Windows.Forms.Panel $buttonPanel.Dock = [System.Windows.Forms.DockStyle]::Bottom $buttonPanel.Height = 58 $buttonPanel.BackColor = $Theme.PanelAlt $messageForm.Controls.Add($buttonPanel) $okButton = New-Object System.Windows.Forms.Button $okButton.Text = 'OK' $okButton.Location = New-Object System.Drawing.Point(362, 10) $okButton.Size = New-Object System.Drawing.Size(92, 36) $okButton.Font = $Font $okButton.Cursor = [System.Windows.Forms.Cursors]::Hand $okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK Set-DeployCenterButtonStyle -Button $okButton -Theme $Theme -Role 'PrimaryButton' $buttonPanel.Controls.Add($okButton) $messageForm.AcceptButton = $okButton $messageForm.CancelButton = $okButton if ($Owner) { [void]$messageForm.ShowDialog($Owner) } else { [void]$messageForm.ShowDialog() } $messageForm.Dispose() } Export-ModuleMember -Function Set-DeployCenterButtonStyle, New-DeployCenterComboBox, Set-DeployCenterComboBoxTheme, New-DeployCenterPartitionProfileSelector, Set-DeployCenterPartitionProfileSelectorLayout, New-DeployCenterDeploymentControls, Set-DeployCenterDeploymentControlsLayout, New-DeployCenterLogWindow, Show-DeployCenterPartitionSizingDialog, Show-DeployCenterMessage