Badly behaving window

Ask questions about creating Graphical User Interfaces (GUI) in PowerShell and using WinForms controls.
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
This topic is 7 years and 5 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked
User avatar
wartech
Posts: 52
Last visit: Wed Jan 03, 2024 9:09 am

Badly behaving window

Post by wartech »

Hi,
I've created a phonebook application with PowerShell Studio 2016 (single form with a datagridview, labels, text boxes & buttons).
The form behaves as expected until it has been maximised, then restored.
After a restore down, clicking on the title bar and trying to drag the window (even a tiny amount) causes it to maximise.
Then it can be moved around, but it won't restore to normal size.

Any suggestions?
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Badly behaving window

Post by jvierra »

And this is after you have changed the fonts to use pixels instead of points?

This is not behavior caused by Windows Forms but is due to a coding error or issues with your graphics hardware. We cannot guess at what is causing this.

Start by creating a simple version of your form with no code them add your code a logical step at a time to try and determine which code may be responsible.

Is this while trying to run it from PowerShell Studio? Do you have the latest version of PSS installed?
User avatar
wartech
Posts: 52
Last visit: Wed Jan 03, 2024 9:09 am

Re: Badly behaving window

Post by wartech »

This is while running from PowerShell Studio and when users run the .exe on their PCs (various makes & models) or on a Server 2008 R2 terminal server.
It's going to be tricky to figure out at what point this problem was introduced:
1. It's kind of grown organically as I worked out ways to add new features.
2. Adding the ability to maximize the windows was a recent addition.
3. Even after making the window maximizable I wasn't checking for this problem.

Until I get the time to rewrite from scratch (which is probably needed) I guess I'll just make the form fixed size.
Anyway - thanks for your advice, whatever the outcome it's been fun learning how to put my scripts into GUIs.
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Badly behaving window

Post by jvierra »

Windows have built in controls to maximize and minimize. You should not be writing code to do this.
User avatar
wartech
Posts: 52
Last visit: Wed Jan 03, 2024 9:09 am

Re: Badly behaving window

Post by wartech »

I really wouldn't know how to.
I just set the form's MaximizeBox property to True and corrected the anchor points for the datagridview etc. (all within the form designer window).
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Badly behaving window

Post by jvierra »

Then what is the issue? Forms don't change by themselves. Something you are doing is causing an issue or your graphics subsystem has issues. This can happen with hi-res adapters in gaming mode when the driver is not compatible with the OS.
User avatar
wartech
Posts: 52
Last visit: Wed Jan 03, 2024 9:09 am

Re: Badly behaving window

Post by wartech »

The I.T. dept doesn't qualify for expensive graphics cards! :(

I'd paste the script here - but I haven't figured out how to properly do that yet

...OK try this:
  1. $formPhoneBookSearchDial_Load={
  2.    
  3. }
  4.  
  5. #region Control Helper Functions
  6. function Load-DataGridView
  7. {
  8.     <#
  9.     .SYNOPSIS
  10.         This functions helps you load items into a DataGridView.
  11.  
  12.     .DESCRIPTION
  13.         Use this function to dynamically load items into the DataGridView control.
  14.  
  15.     .PARAMETER  DataGridView
  16.         The DataGridView control you want to add items to.
  17.  
  18.     .PARAMETER  Item
  19.         The object or objects you wish to load into the DataGridView's items collection.
  20.    
  21.     .PARAMETER  DataMember
  22.         Sets the name of the list or table in the data source for which the DataGridView is displaying data.
  23.  
  24.     .PARAMETER AutoSizeColumns
  25.         Resizes DataGridView control's columns after loading the items.
  26.     #>
  27.     Param (
  28.         [ValidateNotNull()]
  29.         [Parameter(Mandatory = $true)]
  30.         [System.Windows.Forms.DataGridView]$DataGridView,
  31.         [ValidateNotNull()]
  32.         [Parameter(Mandatory = $true)]
  33.         $Item,
  34.         [Parameter(Mandatory = $false)]
  35.         [string]$DataMember,
  36.         [System.Windows.Forms.DataGridViewAutoSizeColumnMode]$AutoSizeColumns = 'None'
  37.     )
  38.     $DataGridView.SuspendLayout()
  39.     $DataGridView.DataMember = $DataMember
  40.    
  41.     if ($Item -is [System.Data.DataSet] -and $Item.Tables.Count -gt 0)
  42.     {
  43.         $DataGridView.DataSource = $Item.Tables[0]
  44.     }
  45.     elseif ($Item -is [System.ComponentModel.IListSource]`
  46.         -or $Item -is [System.ComponentModel.IBindingList] -or $Item -is [System.ComponentModel.IBindingListView])
  47.     {
  48.         $DataGridView.DataSource = $Item
  49.     }
  50.     else
  51.     {
  52.         $array = New-Object System.Collections.ArrayList
  53.        
  54.         if ($Item -is [System.Collections.IList])
  55.         {
  56.             $array.AddRange($Item)
  57.         }
  58.         else
  59.         {
  60.             $array.Add($Item)
  61.         }
  62.         $DataGridView.DataSource = $array
  63.     }
  64.    
  65.     if ($AutoSizeColumns -ne 'None')
  66.     {
  67.         $DataGridView.AutoResizeColumns($AutoSizeColumns)
  68.     }
  69.    
  70.     $DataGridView.ResumeLayout()
  71. }
  72.  
  73. function ConvertTo-DataTable
  74. {
  75.     <#
  76.         .SYNOPSIS
  77.             Converts objects into a DataTable.
  78.    
  79.         .DESCRIPTION
  80.             Converts objects into a DataTable, which are used for DataBinding.
  81.    
  82.         .PARAMETER  InputObject
  83.             The input to convert into a DataTable.
  84.    
  85.         .PARAMETER  Table
  86.             The DataTable you wish to load the input into.
  87.    
  88.         .PARAMETER RetainColumns
  89.             This switch tells the function to keep the DataTable's existing columns.
  90.        
  91.         .PARAMETER FilterWMIProperties
  92.             This switch removes WMI properties that start with an underline.
  93.    
  94.         .EXAMPLE
  95.             $DataTable = ConvertTo-DataTable -InputObject (Get-Process)
  96.     #>
  97.     [OutputType([System.Data.DataTable])]
  98.     param (
  99.         [ValidateNotNull()]
  100.         $InputObject,
  101.         [ValidateNotNull()]
  102.         [System.Data.DataTable]$Table,
  103.         [switch]$RetainColumns,
  104.         [switch]$FilterWMIProperties)
  105.    
  106.     if ($null -eq $Table)
  107.     {
  108.         $Table = New-Object System.Data.DataTable
  109.     }
  110.    
  111.     if ($InputObject -is [System.Data.DataTable])
  112.     {
  113.         $Table = $InputObject
  114.     }
  115.     elseif ($InputObject -is [System.Data.DataSet] -and $InputObject.Tables.Count -gt 0)
  116.     {
  117.         $Table = $InputObject.Tables[0]
  118.     }
  119.     else
  120.     {
  121.         if (-not $RetainColumns -or $Table.Columns.Count -eq 0)
  122.         {
  123.             #Clear out the Table Contents
  124.             $Table.Clear()
  125.            
  126.             if ($null -eq $InputObject) { return } #Empty Data
  127.            
  128.             $object = $null
  129.             #find the first non null value
  130.             foreach ($item in $InputObject)
  131.             {
  132.                 if ($null -ne $item)
  133.                 {
  134.                     $object = $item
  135.                     break
  136.                 }
  137.             }
  138.            
  139.             if ($null -eq $object) { return } #All null then empty
  140.            
  141.             #Get all the properties in order to create the columns
  142.             foreach ($prop in $object.PSObject.Get_Properties())
  143.             {
  144.                 if (-not $FilterWMIProperties -or -not $prop.Name.StartsWith('__')) #filter out WMI properties
  145.                 {
  146.                     #Get the type from the Definition string
  147.                     $type = $null
  148.                    
  149.                     if ($null -ne $prop.Value)
  150.                     {
  151.                         try { $type = $prop.Value.GetType() }
  152.                         catch { }
  153.                     }
  154.                    
  155.                     if ($null -ne $type) # -and [System.Type]::GetTypeCode($type) -ne 'Object')
  156.                     {
  157.                         [void]$table.Columns.Add($prop.Name, $type)
  158.                     }
  159.                     else #Type info not found
  160.                     {
  161.                         [void]$table.Columns.Add($prop.Name)
  162.                     }
  163.                 }
  164.             }
  165.            
  166.             if ($object -is [System.Data.DataRow])
  167.             {
  168.                 foreach ($item in $InputObject)
  169.                 {
  170.                     $Table.Rows.Add($item)
  171.                 }
  172.                 return @( ,$Table)
  173.             }
  174.         }
  175.         else
  176.         {
  177.             $Table.Rows.Clear()
  178.         }
  179.        
  180.         foreach ($item in $InputObject)
  181.         {
  182.             $row = $table.NewRow()
  183.            
  184.             if ($item)
  185.             {
  186.                 foreach ($prop in $item.PSObject.Get_Properties())
  187.                 {
  188.                     if ($table.Columns.Contains($prop.Name))
  189.                     {
  190.                         $row.Item($prop.Name) = $prop.Value
  191.                     }
  192.                 }
  193.             }
  194.             [void]$table.Rows.Add($row)
  195.         }
  196.     }
  197.    
  198.     return @( ,$Table)
  199. }
  200. #endregion
  201.  
  202. $crlf = [char]13 + [char]10
  203.  
  204. try
  205. {   # Download phonebook from Asterisk PBX server
  206.     $pb = [xml](New-Object System.Net.Webclient).Downloadstring("http://10.0.3.254:83/phonebook.xml")
  207. }
  208. catch
  209. {
  210.     $textboxError.Text = "Cannot download the phone book. Please check your proxy settings."
  211. }
  212. $grps = $pb.AddressBook.pbgroup
  213. $contacts = $pb.AddressBook.Contact
  214.  
  215. $script:numbers = $dNumbers = @($contacts |
  216.     Sort-Object -Property Group, LastName, FirstName |
  217.     Select-Object @{
  218.         Label = "Group"; Expression = { $grps.name[$_.Group] }
  219.     }, FirstName, LastName, Department, @{
  220.         Label = "Number"; Expression = { if ($null -eq $_.Phone[0].phonenumber) { $_.Phone.phonenumber }
  221.             else { $_.Phone[0].phonenumber } }
  222.     }
  223. )
  224.  
  225. Load-DataGridView -DataGridView $datagridview1 -Item $script:numbers
  226.  
  227. $dialCapable = $false
  228. # For terminal server users, the file with the IP address of their phone is stored in LocalAppData
  229. # PC users get this file from ProgData
  230. $ipFiles = @(($env:LocalAppData + '\Norbar\IP.txt'), ($env:ProgramData + '\Norbar\IP.txt'))
  231. foreach ($ipFile in $ipFiles)
  232. {
  233.     if ((Test-Path -Path $ipFile) -eq $true)
  234.     {
  235.         $ipAddr = @(Get-Content -Path $ipFile)[0]
  236.         $textboxDebugMsg.Text = "IP address: $ipAddr" + $crlf
  237.         if ([ipaddress]::TryParse($ipAddr, [ref]0) -eq $true)
  238.         {
  239.             $dialCapable = $true
  240.             break
  241.         }
  242.     }
  243. }
  244. $password = "secret"
  245. $fLineStatus = "http://" + $ipAddr + "/cgi-bin/api-get_line_status?passcode=" + $password
  246. $fSendKeys = "http://" + $ipAddr + "/cgi-bin/api-send_key?passcode=" + $password
  247.  
  248.  
  249. $buttonClose_Click={
  250.    
  251. }
  252.  
  253. $buttonReset_Click = {
  254.     $textbox2.Visible = $false
  255.     $labelNumber.Visible = $false
  256.     $buttonDial.Visible = $false
  257.     $script:numbers = $dNumbers
  258.     $textboxDebugMsg.Text = "$($script:numbers.Count) contacts found." + $crlf
  259.     $textbox1.Clear()
  260.     Load-DataGridView -DataGridView $datagridview1 -Item $script:numbers
  261.     $textbox1.Focus()
  262. }
  263.  
  264. $buttonSearch_Click={
  265.     $textbox2.Visible = $false
  266.     $labelNumber.Visible = $false
  267.     $buttonDial.Visible = $false
  268.     if ($null -ne $textbox1.Text)
  269.     {
  270.         $search = "*" + $textbox1.Text + "*"
  271.         $script:numbers = $script:numbers | Where-Object {
  272.             $_.Group -like $search -or
  273.             $_.FirstName -like $search -or
  274.             $_.LastName -like $search -or
  275.             $_.Department -like $search -or
  276.             $_.Number -like $search
  277.         }
  278.         $textboxDebugMsg.Text = "Search clicked. $($script:numbers.Count) contacts found" + $crlf
  279.         if ($script:numbers.Count -eq 0)
  280.         {
  281.             $script:numbers = New-Object PSobject
  282.             $script:numbers | Add-Member Group "Search returns no matches. Please reset"
  283.         }
  284.         Load-DataGridView -DataGridView $datagridview1 -Item $script:numbers
  285.     }
  286.     $textbox1.Focus()
  287.     $textbox1.SelectAll()
  288. }
  289.  
  290. $datagridview1_CellClick=[System.Windows.Forms.DataGridViewCellEventHandler]{
  291. #Event Argument: $_ = [System.Windows.Forms.DataGridViewCellEventArgs]
  292.     $name = $script:numbers[$_.RowIndex].FirstName + " " + $script:numbers[$_.RowIndex].LastName
  293.     $textboxDebugMsg.AppendText("$name selected." + $crlf)
  294.     $script:dialNumber = $script:numbers[$_.RowIndex].Number
  295.     if ($dialCapable -and $null -ne $script:dialNumber)
  296.     {
  297.         $textbox2.Text = $script:dialNumber
  298.         $labelNumber.Visible = $true
  299.         $textbox2.Visible = $true
  300.         $buttonDial.Visible = $true
  301.     }
  302.     $textbox1.Focus()
  303. }
  304.  
  305. $datagridview1_KeyDown = [System.Windows.Forms.KeyEventHandler]{
  306.     #Event Argument: $_ = [System.Windows.Forms.KeyEventArgs]
  307.     if ($_.KeyCode -eq 'Escape')
  308.     {
  309.         $buttonReset_Click.Invoke()
  310.     }
  311. }
  312.  
  313. $buttonDial_Click = {
  314.     $textboxDebugMsg.AppendText("Dial clicked." + $crlf)
  315.     $resultLine = Invoke-WebRequest -Uri $fLineStatus
  316.     if ($resultLine.Content.Length -eq 0)
  317.     {
  318.         $textboxDebugMsg.AppendText("Line status not returned: Your phone needs a firmware update." + $crlf)
  319.     }
  320.     $textboxDebugMsg.AppendText($resultLine.Content.Replace("{", $crlf) + $crlf)
  321. # This condition abandoned for the moment. A bug in some Grandstream firmware
  322. # versions prevents the phone from returning a line check
  323. #   if ($resultLine.Content -match '"line": 1, "state": "idle"')
  324. #   {
  325. #       $textboxDebugMsg.AppendText("Line OK." + $crlf)
  326.         $dialString = $fSendKeys + "&keys=" + ($script:dialNumber.ToCharArray() -Join (":")) + ":SEND"
  327.         $textboxDebugMsg.AppendText($dialString.Replace($password,"******") + $crlf)
  328.         $result = Invoke-WebRequest -Uri $dialString
  329.         $textboxDebugMsg.AppendText($result.Content)
  330. #   }
  331. }
  332.  
  333. $logo_DoubleClick = {
  334.     if ($textboxDebugMsg.Visible -eq $true)
  335.     {
  336.         $textboxDebugMsg.Visible = $false
  337.     }
  338.     else
  339.     {
  340.         $textboxDebugMsg.Visible = $true
  341.     }
  342. }
  343.  
  344. $textbox1_KeyDown=[System.Windows.Forms.KeyEventHandler]{
  345. #Event Argument: $_ = [System.Windows.Forms.KeyEventArgs]
  346.     if ($_.KeyCode -eq 'Enter')
  347.     {
  348.         $buttonSearch_Click.Invoke()
  349.     }
  350.     if ($_.KeyCode -eq 'Escape')
  351.     {
  352.         $buttonReset_Click.Invoke()
  353.     }
  354. }
  355.  
  356. $textboxDebugMsg_KeyDown=[System.Windows.Forms.KeyEventHandler]{
  357. #Event Argument: $_ = [System.Windows.Forms.KeyEventArgs]
  358.     if ($_.KeyCode -eq 'Enter')
  359.     {
  360.         $buttonSearch_Click.Invoke()
  361.     }
  362.     if ($_.KeyCode -eq 'Escape')
  363.     {
  364.         $buttonReset_Click.Invoke()
  365.     }
  366. }
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Badly behaving window

Post by jvierra »

you have a great amount of code that only exists outside of any event. This will likely cause very unpredictable behavior. All code in a form should be in an event.

If you are going to post code it should be attached as a PSF as there is no way to know how your form is set up with just the embedded custom script.
User avatar
wartech
Posts: 52
Last visit: Wed Jan 03, 2024 9:09 am

Re: Badly behaving window

Post by wartech »

Oops!

Am I right to guess that the non-event stuff goes into the form_Load section?
I had wondered what belongs in there.

Anyway - I've done that (attached), but it still doesn't like maximize, restore, followed by drag window.
I'm sure it must be something I've done - just can't see what.

Many thanks.
Attachments
Search-PhoneBook6.psf
Search the company phone book, pick a number & dial it
(137.46 KiB) Downloaded 126 times
jvierra
Posts: 15439
Last visit: Tue Nov 21, 2023 6:37 pm
Answers: 30
Has voted: 4 times
Been upvoted: 33 times

Re: Badly behaving window

Post by jvierra »

Your form has some fundamental mistakes or misunderstandings. As long as code is executing in an event the form will be frozen. To get a form to display we have the "load" vent which is mostly used to initialize values or do simple assignments to control. The "Activated" event fires after the form is displayed and allows a further opportunity to initialize the form. Any long running code will freeze the form until the event exits.

To understand this and learn how to design a form that is responsive read the following blog posts.

https://www.sapien.com/blog/?s=responsive+forms
https://www.sapien.com/blog/topics/user ... istrators/
This topic is 7 years and 5 months old and has exceeded the time allowed for comments. Please begin a new topic or use the search feature to find a similar but newer topic.
Locked