The third installment in this PowerShell AI series explores how user queries are processed and answered using a RESTful API and JSON payloads, enabling seamless interaction with local AI models through a custom-built desktop interface.
So far I have shown you what my revised script looks like and I have talked about how the model name download process works and how the combo box is populated. Now, I want to talk about the query process.
The query process is tied to an event handler that is tied to the Submit button. When a user clicks the Submit button, the event handler executes. A lot of the code that exists within the event handler is used for output formatting, so I am going to omit quote a few lines of code from the code block below and show you the lines that actually control the query and response.
OK, so here you can see a pared down version of the event handler. The first thing that the event handler does is to write the user’s input (the text that they entered into the query box) to a variable called $UserInput. The name of the model that the user selected is written to a variable called $ModelName. There is also a line of code that checks to make sure that the user query is not empty before allowing the process to move forward.
At this point, the script writes the word "You:" to the output box and then appends the text contained within the $UserInput variable. At that point, the query box’s contents are cleared to make way for the next query.
The actual query process makes use of a RESTful API. That means two things. First, it means that the Ollama server is designed to accept Web requests (you don’t have to perform any special configuration to get Ollama to function as a Web server). The other thing that using a RESTful API means is that the query is going to need to be structured in JSON format.
The query body includes the name of the AI model to be used, the text that the user has entered, and a flag telling the server not to stream the output. A header variable defines the request as containing JSON data. Finally, the Invoke-RestMethod cmdlet is used to send the header and the body to a URL defined at the beginning of the script. You can see the body, header, and request below:
Because of the way that the Invoke-RestMethod command is constructed, the response to the request is going to be stored in a PowerShell variable called $Response. This variable contains a lot of unnecessary data, so I am setting up another variable called $ExtractedText, which contains only the data associated with the response’s Response field.
Even this extracted text contains some extra information. As such, I have created another variable called $TrimmedResponse, which I use to store a "trimmed" version of the response string. Specifically, I am deleting the first 11 characters and the last two characters of the response.
Finally, the script writes to the output pane the name of the model that is currently in use. The script then appends a colon and the trimmed response. At that point, both the query and the response are displayed within the output.
So as you can see, my script is both long and complex. As promised however, I want to conclude the series by providing you with the full source code. Here it is:
Add-Type -AssemblyName System.Windows.Forms
# Create the main form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Poseys Large Language Model Text Editor"
$Form.Size = New-Object System.Drawing.Size(1920, 1080)
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Set Remote Machine Details
$RemoteMachine = "147.100.100.240" # The Ollama Server's IP address
$RemoteOllama = "147.100.100.240:11434" # The Ollama Server's IP address combined with the Ollama port number
$URL = "http://147.100.100.240:11434/api/generate"
$Cred=Get-Credential
Invoke-Command -ComputerName $RemoteMachine -Credential $Cred -ScriptBlock {
powershell.exe -command "Ollama serve"}
#Get a list of the models that have been downloaded to the remote machine
$UneditedModelList = Invoke-Command -ComputerName $RemoteMachine -Credential $Cred -ScriptBlock {powershell.exe -command "Ollama list"} | Select-String "^\S+" | ForEach-Object { ($_ -split '\s+')[0] }
# Right now the $ModelList variable contains a list of the models. However, it also includes the word Name.
# We need to use a loop to get rid of the unwanted word in the first array position.
# I am initializing $ModelList as an empty array and then using a counter to add items
# from the unedited model list to the array.
$ModelList = @()
For ($Counter = 1; $Counter -lt $UneditedModelList.Length; $Counter++){
$ModelList += $UneditedModelList[$Counter]
}
#############################################################
## Input Panel (top panel) ##
#############################################################
# Create a top panel for the input box, model drop down, submit, and edit buttons
$TopPanel = New-Object System.Windows.Forms.Panel
$TopPanel.Location = New-Object System.Drawing.Point(10,10)
$TopPanel.Size = New-Object System.Drawing.Size(900,300)
# Create the input label
$InputLabel = New-Object System.Windows.Forms.Label
$InputLabel.Text = "Input and Model Selection"
$InputLabel.Location = New-Object System.Drawing.Point(0,0)
$InputLabel.Size = New-Object System.Drawing.Size(900, 50)
$InputLabel.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$InputLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$InputLabel.BackColor = [System.Drawing.Color]::LightBlue
$InputLabel.ForeColor = [System.Drawing.Color]::Black
# Create Model Combo Box
$ModelComboBox = New-Object System.Windows.Forms.ComboBox
$ModelComboBox.Location = New-Object System.Drawing.Point(10,55)
$ModelComboBox.Size = New-Object System.Drawing.Size(250,150)
$ModelComboBox.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$ModelComboBox.text = ""
# Define the array of choices and add them to the drop down
$ModelList | ForEach-Object {[void] $ModelComboBox.Items.Add($_)}
# Select the default choice
$ModelComboBox.SelectedIndex = 0
# Create the Submit Button
$SubmitButton = New-Object System.Windows.Forms.Button
$SubmitButton.Font = New-Object System.Drawing.Font("Arial", 12)
$SubmitButton.Location = New-Object System.Drawing.Point(300,55)
$SubmitButton.Size = New-Object System.Drawing.Size(75,30)
$SubmitButton.Text = "Submit"
# Create the Exit Button
$ExitButton = New-Object System.Windows.Forms.Button
$ExitButton.Font = New-Object System.Drawing.Font("Arial", 12)
$ExitButton.Location = New-Object System.Drawing.Point(400,55)
$ExitButton.Size = New-Object System.Drawing.Size(75,30)
$ExitButton.Text = "Exit"
$ExitButton.Add_Click({
$Form.Close()
})
# Create the User Input TextBox (Multiline for long text)
$InputBox = New-Object System.Windows.Forms.TextBox
$InputBox.Location = New-Object System.Drawing.Point(0,90)
$InputBox.Size = New-Object System.Drawing.Size(900, 160)
$InputBox.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$InputBox.Multiline = $True
$InputBox.ScrollBars = "Vertical"
# Create the output label
$OutputLabel = New-Object System.Windows.Forms.Label
$OutputLabel.Text = "AI Output"
$OutputLabel.Location = New-Object System.Drawing.Point(0,250)
$OutputLabel.Size = New-Object System.Drawing.Size(900, 50)
$OutputLabel.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$OutputLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$OutputLabel.BackColor = [System.Drawing.Color]::LightBlue
$OutputLabel.ForeColor = [System.Drawing.Color]::Black
# Event Handler for Submit Button
$SubmitButton.Add_Click({
$UserInput = $InputBox.Text
$ModelName = $ModelComboBox.SelectedItem
if ($UserInput -ne "") {
### Write the user's query to the output box
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 0
$OutputBox.SelectionColor = "#FF0000FF" #Set the text color to Blue
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 4 # So that I can format the word You and the colon after.
$OutputBox.SelectionFont = New-Object System.Drawing.Font($OutputBox.Font, [System.Drawing.FontStyle]::Bold)
[String]$OutputText = "You:"
$OutputBox.AppendText("`r`n$OutputText")
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 0
$OutputBox.SelectionFont = New-Object System.Drawing.Font($OutputBox.Font, [System.Drawing.FontStyle]::Regular)
$OutputText = $UserInput
$OutputBox.AppendText("$UserInput`r`n")
$InputBox.Clear() # Clear the input box to make room for the next query
## Perform the actual query
# Create the JSON payload
$Body = @{
model = "$ModelName"
prompt = "$UserInput"
stream = $false
} | ConvertTo-Json -Depth 3
# Set the headers
$Headers = @{
"Content-Type" = "application/json"
}
# Send the request and get the response
$Response = Invoke-RestMethod -Uri $Url -Method Post -Headers $Headers -Body $Body
# The response includes a number of different pieces of data. The $ExtractedText variable captures only the
# data that is a part of the actual response
[String]$ExtractedText=$Response | Select-Object Response
# The extracted text contains some unneeded characters before and after the response text.
# The trimmed response eleminates the first eleven characters and the last two characters.
[String]$TrimmedResponse = $ExtractedText[11..($ExtractedText.Length -2)] -Join ''
## Display the results from the query
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = $ModelName.Length + 1
$OutputBox.SelectionColor = "#FF000000" # Set the text color to black
$OutputBox.SelectionFont = New-Object System.Drawing.Font($OutputBox.Font, [System.Drawing.FontStyle]::Bold)
[String]$OutputText = $ModelName + ": "
$OutputBox.AppendText("`r`n$OutputText")
$OutputBox.SelectionStart = $OutputBox.TextLength
$OutputBox.SelectionLength = 0
$OutputBox.SelectionFont = New-Object System.Drawing.Font($OutputBox.Font, [System.Drawing.FontStyle]::Regular)
[String]$OutputText = $TrimmedResponse
$OutputBox.AppendText("$TrimmedResponse`r`n")
}
})
#Add the controls to the Right panel
$TopPanel.Controls.Add($InputLabel) | Out-Null
$TopPanel.Controls.Add($ModelComboBox) | Out-Null
$TopPanel.Controls.Add($SubmitButton) | Out-Null
$TopPanel.Controls.Add($ExitButton) | Out-Null
$TopPanel.Controls.Add($InputBox) | Out-Null
$TopPanel.Controls.Add($OutputLabel) | Out-Null
#############################################################
## Editor Label Panel (Blue Bar Above Editor ##
#############################################################
# Create a top panel for the input box, model drop down, submit, and edit buttons
$TopEditorPanel = New-Object System.Windows.Forms.Panel
$TopEditorPanel.Location = New-Object System.Drawing.Point(910,10)
$TopEditorPanel.Size = New-Object System.Drawing.Size(1050,50)
# Create the input label
$EditorLabel = New-Object System.Windows.Forms.Label
$EditorLabel.Text = "Text Editor"
$EditorLabel.Location = New-Object System.Drawing.Point(0,0)
$EditorLabel.Size = New-Object System.Drawing.Size(1050, 50)
$EditorLabel.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$EditorLabel.TextAlign = [System.Drawing.ContentAlignment]::MiddleCenter
$EditorLabel.BackColor = [System.Drawing.Color]::LightBlue
$EditorLabel.ForeColor = [System.Drawing.Color]::Black
#Add the controls to the Top Editor panel
$TopEditorPanel.Controls.Add($EditorLabel) | Out-Null
###########################################################
## Output Panel (Lower Left Box) ##
###########################################################
# Create a panel for the left text area (menu + textbox)
$OutputPanel = New-Object System.Windows.Forms.Panel
$OutputPanel.Location = New-Object System.Drawing.Point(10, 320)
$OutputPanel.Size = New-Object System.Drawing.Size(900, 750)
# Create the output (left) RichTextBox
$OutputBox = New-Object System.Windows.Forms.RichTextBox
$OutputBox.Multiline = $true
$OutputBox.Location = New-Object System.Drawing.Point(5,30) # Positioned below menu
$OutputBox.Size = New-Object System.Drawing.Size(890, 650)
$OutputBox.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$OutputBox.BackColor = "#FFFFFFFF"
$OutputBox.ReadOnly = $True
$OutputBox.Multiline = $True
$OutputBox.ScrollBars = "Vertical"
$OutputBox.Text = ""
# Create the menu for the output box
# Create MenuStrip
$OutputMenu = New-Object System.Windows.Forms.MenuStrip
$OutputMenu.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
# File Menu
$OutputFileMenu = New-Object System.Windows.Forms.ToolStripMenuItem("File")
$OutputSaveMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Save Conversation")
$OutputSaveMenuItem.Add_Click({
$OutputSaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$OutputSaveFileDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
If ($OutputSaveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$FileName = $OutputSaveFileDialog.FileName
$Extension = [System.IO.Path]::GetExtension($FileName).ToLower()
If ($Extension -eq ".txt"){
$OutputBox.Text | Set-Content -Path $OutputSaveFileDialog.FileName
}
}
})
$OutputExitMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Exit")
$OutputExitMenuItem.Add_Click({ $Form.Close() })
$OutputFileMenu.DropDownItems.Add($OutputSaveMenuItem) | Out-Null
$OutputFileMenu.DropDownItems.Add($OutputExitMenuItem) | Out-Null
$OutputMenu.Items.Add($OutputFileMenu) | Out-Null
# Output Edit Menu
$OutputEditMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Edit")
$OutputCopyMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Copy")
$OutputCopyMenuItem.Add_Click({ $OutputBox.Copy() })
# Add the "Find" functionality
$OutputFindMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Find")
$OutputFindMenuItem.Add_Click({
# Create a new dialog to ask for the search term
$FindDialogBox = New-Object System.Windows.Forms.Form
$FindDialogBox.Text = "Find"
$FindDialogBox.Width = 300
$FindDialogBox.Height = 150
$FindDialogBox.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$FindDialogBox.Location = $OutputBox.PointToScreen([System.Drawing.Point]::new(100, 100))
$FindLabel = New-Object System.Windows.Forms.Label
$FindLabel.Text = "Find what:"
$FindLabel.AutoSize = $True
$FindLabel.Location = New-Object System.Drawing.Point(10, 10)
$FindDialogBox.Controls.Add($FindLabel) | Out-Null
$FindtextBox = New-Object System.Windows.Forms.TextBox
$FindtextBox.Location = New-Object System.Drawing.Point(10, 40)
$FindtextBox.Width = 260
$FindTextBox.Text = ""
$findDialogBox.Controls.Add($FindtextBox) | Out-Null
$FindButton = New-Object System.Windows.Forms.Button
$FindButton.Text = "Find"
$FindButton.Location = New-Object System.Drawing.Point(10, 70)
$FindButton.Add_Click({
$SearchTerm = $FindtextBox.Text
If (![String]::IsNullOrWhiteSpace($SearchTerm)) {
# Clear previous highlights by resetting the text color and background
$OutputBox.SelectAll()
$OutputBox.SelectionBackColor = [System.Drawing.Color]::White
$OutputBox.DeselectAll()
# Search and highlight all occurrences of the search term
$Index = 0
While ($Index -ge 0) {
$Index = $OutputBox.Text.IndexOf($SearchTerm, $Index)
if ($Index -ge 0) {
$OutputBox.Select($Index, $SearchTerm.Length)
$OutputBox.SelectionBackColor = [System.Drawing.Color]::Yellow
$Index += $SearchTerm.Length
}
}
}
$FindDialogBox.Close()
})
$FindDialogBox.Controls.Add($FindButton) | Out-Null
# Show the find dialog
$FindDialogBox.ShowDialog() | Out-Null
})
# Add the "Clear Highlights" functionality
$OutputClearHighlightsItem = New-Object System.Windows.Forms.ToolStripMenuItem("Clear Highlights")
$OutputClearHighlightsItem.Add_Click({
# Clear previous highlights by resetting the text color and background
$OutputBox.SelectAll()
$OutputBox.SelectionBackColor = [System.Drawing.Color]::White
$OutputBox.DeselectAll()
})
# Add the "Clear Conversation" functionality
$OutputClearConversationItem = New-Object System.Windows.Forms.ToolStripMenuItem("Delete Conversation")
$OutputClearConversationItem.Add_Click({
# Display a Confirmation Message Box Prior to Deleting Anything
$Confirmation = [System.Windows.Forms.MessageBox]::Show(
"Are you sure you want to delete the current conversation?", # Message text
"Confirm Deletion", # Title
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Warning
)
# Only Proceed with Clearing the Conversation if the User Clicks Yes
If ($Confirmation -eq [System.Windows.Forms.DialogResult]::Yes) {
# Perform the deletion logic here
$OutputBox.Clear() # Clears the output box containing the conversation
}
})
$OutputEditMenu.DropdownItems.Add($OutputCopyMenuItem) | Out-Null
$OutputEditMenu.DropdownItems.Add($OutputFindMenuItem) | Out-Null
$OutputEditMenu.DropdownItems.Add($OutputClearHighlightsItem) | Out-Null
$OutputEditMenu.DropdownItems.Add($OutputClearConversationItem) | Out-Null
$OutputMenu.Items.Add($OutputEditMenu) | Out-Null
# Add MenuStrip to the Form
$Form.Controls.Add($OutputMenu) | Out-Null
# Add controls to left panel
$OutputPanel.Controls.Add($OutputMenu) | Out-Null
$OutputPanel.Controls.Add($OutputBox) | Out-Null
# Create the Context Menu (Right-Click Menu or Shortcut Menu) for the Output Box
$OutputContextMenu = New-Object System.Windows.Forms.ContextMenuStrip
# Add "Select All" Menu Item
$OutputSelectAllMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Select All")
$OutputSelectAllMenuItem.Add_Click({ $OutputBox.SelectAll() })
# Add "Copy" Menu Item
$CopyMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Copy")
$CopyMenuItem.Add_Click({ $OutputBox.Copy() })
#Add Menu Choices to the Shortcut Menu
$OutputContextMenu.Items.Add($OutputSelectAllMenuItem) | Out-Null
$OutputContextMenu.Items.Add($OutputCopyMenuItem) | Out-Null
# Assign the Shortcut Menu to the RichTextBox
$OutputBox.ContextMenuStrip = $OutputContextMenu
#####################################################
## Editor (Right Panel) ##
#####################################################
# Create a panel for the right text area (menu + textbox)
$EditorPanel = New-Object System.Windows.Forms.Panel
$EditorPanel.Location = New-Object System.Drawing.Point(910, 60)
$EditorPanel.Size = New-Object System.Drawing.Size(1000, 1000)
# Create the menu strip for the right RichTextBox
$OutputMenuRight = New-Object System.Windows.Forms.MenuStrip
$rightMenuItems = @("Copy", "Paste", "Undo")
# Create the editor's RichTextBox
$Editor = New-Object System.Windows.Forms.RichTextBox
$Editor.Location = New-Object System.Drawing.Point(5, 35) # Positioned below menu
$Editor.Size = New-Object System.Drawing.Size(970, 905)
$Editor.Text = ""
$Editor.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
$Editor.BackColor = "#FFFFFFFF"
$Editor.SelectionColor = [System.Drawing.Color]::Black
$Editor.ReadOnly = $False
$Editor.Multiline = $True
$Editor.ScrollBars = "Vertical"
# Populate the menu strip for the right editor box
# Create MenuStrip
$EditorMenu = New-Object System.Windows.Forms.MenuStrip
$EditorMenu.Font = New-Object System.Drawing.Font("Arial", 14) # Default font
# File Menu
$FileMenu = New-Object System.Windows.Forms.ToolStripMenuItem("File")
$OpenMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Open")
$OpenMenuItem.Add_Click({
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.Filter = "Text Files (*.txt)|*.txt| RTF File (*.rtf)|*.rtf|All Files|*.*"
$OpenFileDialog.Title = "Open File"
If ($OpenFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$FileName = $OpenFileDialog.FileName
$Extension = [System.IO.Path]::GetExtension($FileName).ToLower()
If ($Extension -eq ".txt") {
$Editor.Text = Get-Content $OpenFileDialog.FileName -Raw
}
ElseIf ($Extension -eq ".rtf") {
# Open RTF file
$Editor.LoadFile($fileName, [System.Windows.Forms.RichTextBoxStreamType]::RichText)
}
}
})
$SaveMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Save")
$SaveMenuItem.Add_Click({
$SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$SaveFileDialog.Filter = "RTF File (*.rtf)|*.rtf|Text Files (*.txt)|*.txt |All Files (*.*)|*.*"
If ($SaveFileDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$FileName = $SaveFileDialog.FileName
$Extension = [System.IO.Path]::GetExtension($fileName).ToLower()
If ($Extension -eq ".rtf") {
# Save as RTF
$Editor.SaveFile($FileName, [System.Windows.Forms.RichTextBoxStreamType]::RichText)
}
ElseIf ($Extension -eq ".txt"){
$Editor.Text | Set-Content -Path $SaveFileDialog.FileName
}
}
})
$ExitMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Exit")
$ExitMenuItem.Add_Click({ $Form.Close() })
$FileMenu.DropDownItems.Add($OpenMenuItem) | Out-Null
$FileMenu.DropDownItems.Add($SaveMenuItem) | Out-Null
$FileMenu.DropDownItems.Add($ExitMenuItem) | Out-Null
$EditorMenu.Items.Add($FileMenu) | Out-Null
# Edit Menu
$EditMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Edit")
$UndoMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Undo")
$UndoMenuItem.Add_Click({ $Editor.Undo() })
$CutMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Cut")
$CutMenuItem.Add_Click({ $Editor.Cut() })
$CopyMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Copy")
$CopyMenuItem.Add_Click({ $Editor.Copy() })
$PasteMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Paste")
$PasteMenuItem.Add_Click({ $Editor.Paste() })
# Add the "Find" functionality
$FindMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Find")
$FindMenuItem.Add_Click({
# Create a new dialog to ask for the search term
$FindDialogBox = New-Object System.Windows.Forms.Form
$FindDialogBox.Text = "Find"
$FindDialogBox.Width = 300
$FindDialogBox.Height = 150
$FindDialogBox.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$FindDialogBox.Location = $EditorPanel.PointToScreen([System.Drawing.Point]::new(100, 100))
$FindLabel = New-Object System.Windows.Forms.Label
$FindLabel.Text = "Find what:"
$FindLabel.AutoSize = $True
$FindLabel.Location = New-Object System.Drawing.Point(10, 10)
$FindDialogBox.Controls.Add($FindLabel) | Out-Null
$FindtextBox = New-Object System.Windows.Forms.TextBox
$FindtextBox.Location = New-Object System.Drawing.Point(10, 40)
$FindtextBox.Width = 260
$FindTextBox.Text = ""
$findDialogBox.Controls.Add($FindtextBox) | Out-Null
$FindButton = New-Object System.Windows.Forms.Button
$FindButton.Text = "Find"
$FindButton.Location = New-Object System.Drawing.Point(10, 70)
$FindButton.Add_Click({
$SearchTerm = $FindtextBox.Text
If (![String]::IsNullOrWhiteSpace($SearchTerm)) {
# Clear previous highlights by resetting the text color and background
$Editor.SelectAll()
$Editor.SelectionBackColor = [System.Drawing.Color]::White
$Editor.DeselectAll()
# Search and highlight all occurrences of the search term
$Index = 0
While ($Index -ge 0) {
$Index = $Editor.Text.IndexOf($SearchTerm, $Index)
if ($Index -ge 0) {
$Editor.Select($Index, $SearchTerm.Length)
$Editor.SelectionBackColor = [System.Drawing.Color]::Yellow
$Index += $SearchTerm.Length
}
}
}
$FindDialogBox.Close()
})
$FindDialogBox.Controls.Add($FindButton) | Out-Null
# Show the find dialog
$FindDialogBox.ShowDialog() | Out-Null
})
# Add the "Find and Replace" functionality
$FindReplaceMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Find and Replace")
$FindReplaceMenuItem.Add_Click({
# Create the Find and Replace dialog box
$FindReplaceDialogBox = New-Object System.Windows.Forms.Form
$FindReplaceDialogBox.Text = "Find and Replace"
$FindReplaceDialogBox.Width = 320
$FindReplaceDialogBox.Height = 200
$FindReplaceDialogBox.StartPosition = [System.Windows.Forms.FormStartPosition]::Manual
$FindReplaceDialogBox.Location = $EditorPanel.PointToScreen([System.Drawing.Point]::new(100, 100))
# Label for Find Field
$FindReplaceLabel = New-Object System.Windows.Forms.Label
$FindReplaceLabel.Text = "Text to Find:"
$FindReplaceLabel.AutoSize = $True
$FindReplaceLabel.Location = New-Object System.Drawing.Point(10, 10)
$FindReplaceDialogBox.Controls.Add($FindReplaceLabel) | Out-Null
# Textbox for Find Input
$FindReplaceTextBox = New-Object System.Windows.Forms.TextBox
$FindReplaceTextBox.Location = New-Object System.Drawing.Point(10, 30)
$FindReplaceTextBox.Width = 280
$FindReplaceDialogBox.Controls.Add($FindReplaceTextBox) | Out-Null
# Label for Replace Field
$ReplaceLabel = New-Object System.Windows.Forms.Label
$ReplaceLabel.Text = "Replace with:"
$ReplaceLabel.AutoSize = $True
$ReplaceLabel.Location = New-Object System.Drawing.Point(10, 60)
$FindReplaceDialogBox.Controls.Add($ReplaceLabel) | Out-Null
# Textbox for Replace Input
$ReplaceTextBox = New-Object System.Windows.Forms.TextBox
$ReplaceTextBox.Location = New-Object System.Drawing.Point(10, 80)
$ReplaceTextBox.Width = 280
$FindReplaceDialogBox.Controls.Add($ReplaceTextBox) | Out-Null
# "Replace All" button
$ReplaceAllButton = New-Object System.Windows.Forms.Button
$ReplaceAllButton.Text = "Replace All"
$ReplaceAllButton.Location = New-Object System.Drawing.Point(10, 120)
$ReplaceAllButton.Add_Click({
$SearchTerm = $FindReplaceTextBox.Text
$ReplaceTerm = $ReplaceTextBox.Text
If (![String]::IsNullOrWhiteSpace($SearchTerm)) {
# Replace all occurrences in the RichTextBox
$Editor.Text = $Editor.Text -replace [Regex]::Escape($SearchTerm), $ReplaceTerm
}
$FindReplaceDialogBox.Close()
})
$FindReplaceDialogBox.Controls.Add($ReplaceAllButton) | Out-Null
# Show the Find and Replace dialog
$FindReplaceDialogBox.ShowDialog()
})
# Add the "Clear Highlights" Functionality
$EditorClearHighlightsItem = New-Object System.Windows.Forms.ToolStripMenuItem("Clear Highlights")
$EditorClearHighlightsItem.Add_Click({
# Clear previous highlights by resetting the text color and background
$Editor.SelectAll()
$Editor.SelectionBackColor = [System.Drawing.Color]::White
$Editor.DeselectAll()
})
# Add the "Clear Notes" Functionality
$EditorDeleteEditsItem = New-Object System.Windows.Forms.ToolStripMenuItem("Delete All Text")
$EditorDeleteEditsItem.Add_Click({
# Display a Confirmation Message Box Prior to Deleting Anything
$Confirmation = [System.Windows.Forms.MessageBox]::Show(
"Are you sure you want to delete the text editor content?", # Message text
"Confirm Deletion", # Title
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Warning
)
# Only Proceed with Clearing the Conversation if the User Clicks Yes
If ($Confirmation -eq [System.Windows.Forms.DialogResult]::Yes) {
# Perform the deletion logic here
$Editor.Clear() # Clears the entire contents of the text editor
}
})
$EditMenu.DropDownItems.Add($UndoMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($CutMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($CopyMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($PasteMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($FindMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($FindReplaceMenuItem) | Out-Null
$EditMenu.DropDownItems.Add($EditorClearHighlightsItem) | Out-Null
$EditMenu.DropDownItems.Add($EditorDeleteEditsItem) | Out-Null
$EditorMenu.Items.Add($EditMenu) | Out-Null
# Format Menu
$FormatMenu = New-Object System.Windows.Forms.ToolStripMenuItem("Format")
$FontMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Font")
$FontMenuItem.Add_Click({
$FontDialog = New-Object System.Windows.Forms.FontDialog
$FontDialog.Font = $TextBox.Font
If ($FontDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
$Editor.SelectionFont = $FontDialog.Font
}
})
# Highlight menu item
$HighlightMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Highlight")
$HighlightMenuItem.Add_Click({
If ($Editor.SelectedText.Length -gt 0) {
$Editor.SelectionBackColor = [System.Drawing.Color]::Yellow }
})
# Create a menu item for choosing the text color
$ColorMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Text Color")
$ColorMenuItem.Add_Click({
# Open the Color dialog box to select a color
$ColorDialog = New-Object System.Windows.Forms.ColorDialog
If ($ColorDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
# Apply the selected color to the selected text in the RichTextBox
$Editor.SelectionColor = $ColorDialog.Color
}
})
$FormatMenu.DropDownItems.Add($FontMenuItem) | Out-Null
$FormatMenu.DropDownItems.Add($ColorMenuItem) | Out-Null
$FormatMenu.DropDownItems.Add($HighlightMenuItem) | Out-Null
$EditorMenu.Items.Add($FormatMenu) | Out-Null
# Add MenuStrip to the Form
$Form.Controls.Add($EditorMenu) | Out-Null
# Create the Context Menu (the Shortcut Menu or the Right-Click Menu)
$EditorContextMenu = New-Object System.Windows.Forms.ContextMenuStrip
# Add the "Undo" Menu Item
$EditorUndoMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Undo")
$EditorUndoMenuItem.Add_Click({ $Editor.Undo() })
# Add the "Cut" Menu Item
$EditorCutMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Cut")
$EditorCutMenuItem.Add_Click({ $Editor.Cut() })
# Add the "Copy" Menu Item
$EditorCopyMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Copy")
$EditorCopyMenuItem.Add_Click({ $Editor.Copy() })
# Add the "Paste" Menu Item
$EditorPasteMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Paste")
$EditorPasteMenuItem.Add_Click({ $Editor.Paste() })
# Add the "Select All" Menu Item
$EditorSelectAllMenuItem = New-Object System.Windows.Forms.ToolStripMenuItem("Select All")
$EditorSelectAllMenuItem.Add_Click({ $Editor.SelectAll() })
# Add the Menu Options to the Shortcut Menu
$EditorContextMenu.Items.Add($EditorUndoMenuItem) | Out-Null
$EditorContextMenu.Items.Add($EditorCutMenuItem) | Out-Null
$EditorContextMenu.Items.Add($EditorCopyMenuItem) | Out-Null
$EditorContextMenu.Items.Add($EditorPasteMenuItem) | Out-Null
$EditorContextMenu.Items.Add($EditorSelectAllMenuItem) | Out-Null
# Assign the Shortcut Menu to the Editor
$Editor.ContextMenuStrip = $EditorContextMenu
#Add the controls to the Right panel
$EditorPanel.Controls.Add($EditorMenu) | Out-Null
$EditorPanel.Controls.Add($Editor) | Out-Null
##########################################
## Display the GUI ##
##########################################
# Add panels to the form
$Form.Controls.Add($TopPanel) | Out-Null
$Form.Controls.Add($OutputPanel) | Out-Null
$Form.Controls.Add($TopEditorPanel) | Out-Null
$Form.Controls.Add($EditorPanel) | Out-Null
# Show the form
[Void]$Form.ShowDialog()