代码之家  ›  专栏  ›  技术社区  ›  Simon Yo

除非在终端中粘贴变量,否则不会加载Winform objListBox

  •  0
  • Simon Yo  · 技术社区  · 6 年前

    我从来没有遇到过这样的问题。我试了很多方法来解决这个问题,但都解决不了。 除非在执行之前在powershell ise中键入$qlfile=“c:\ querylist”,否则无法填充此objlistbox。

    $QlFile = "C:\querylist.txt"
    
    Add-Type -assembly System.Windows.Forms
    [reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Size = New-Object System.Drawing.Size(850,550)
    $objForm.StartPosition = "WindowsDefaultLocation"
    $objForm.Text = "Query List"
    $objForm.AutoScroll = $True
    $objListBox = New-Object System.Windows.Forms.ListBox
    $objListBox.Location = New-Object System.Drawing.Size(10,40)
    $objListBox.Size = New-Object System.Drawing.Size(800,30)
    $objListBox.ScrollAlwaysVisible = $True
    $objListBox.Height = 250
    $objListBox.add_SelectedIndexChanged($SelectedFile)
    $objListBox.DrawMode = [System.Windows.Forms.DrawMode]::OwnerDrawFixed
    $objListBox.Add_DrawItem($objListBox_DrawItem)
    $objForm.Controls.Add($objListBox)
    $objTextBox = New-Object System.Windows.Forms.TextBox
    $objTextBox.Location = New-Object System.Drawing.Size(10,320)
    $objTextBox.Size = New-Object System.Drawing.Size(800,3000)
    $objtextBox.Height = 100
    $objtextBox.Multiline = $true
    $objForm.Controls.Add($objtextBox)
    # create label
    $labelz1 = New-Object system.Windows.Forms.Label
    $labelz1.Text = "Select a Query"
    $labelz1.Left=10
    $labelz1.Top= 20
    $labelz1.Font= "Verdana"
    
    $labelz2 = New-Object system.Windows.Forms.Label
    $labelz2.Text = "Edit Query"
    $labelz2.Left=10
    $labelz2.Top= 300
    $labelz2.Font= "Verdana"
    
    #add the label to the form
    $objForm.controls.add($labelz1)
    $objForm.controls.add($labelz2)
    
    $BigButton = New-Object System.Windows.Forms.Button
    $BigButton.Size = New-Object System.Drawing.Size(250,50)
    $BigButton.Location = New-Object System.Drawing.Size(10,450)
    $BigButton.Add_MouseHover({$BigButton.backcolor = [System.Drawing.Color]::CornflowerBlue
                $BigButton.Text = "CLICK ME!"})
    $BigButton.Add_MouseLeave({$BigButton.backcolor = [System.Drawing.Color]::DarkBlue
                $BigButton.Text = "Copy Text"})
    $BigButton.Text = "Copy Text"
    
    $BigButton.Add_Click({
        #$objtextBox.Text | Clip
        $WPFQuery_text.text = $objtextBox.Text
        })
    $objForm.controls.add($BigButton)
    
    $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
    # Populate list.
    Get-Content $QlFile | ForEach-Object {[void] $objListBox.Items.Add($_)}
    
    $objListBox_DrawItem={
     param(
      [System.Object] $sender,
      [System.Windows.Forms.DrawItemEventArgs] $e
     )
       #Suppose Sender de type Listbox
     if ($Sender.Items.Count -eq 0) {return}
    
       #Suppose item de type String
     $lbItem=$Sender.Items[$e.Index]
     if ( $lbItem.contains('Q:'))  
     {
        $Color=[System.Drawing.Color]::Orange      
        try
        {
          $brush = new-object System.Drawing.SolidBrush($Color)
          $e.Graphics.FillRectangle($brush, $e.Bounds)
        }
        finally
        {
          $brush.Dispose()
        }
       }
     $e.Graphics.DrawString($lbItem, $e.Font, [System.Drawing.SystemBrushes]::ControlText, (new-object System.Drawing.PointF($e.Bounds.X, $e.Bounds.Y)))
    }    
    
    
    $SelectedFile=
    {
    $objtextBox.Text = ($objListbox.SelectedItem)
    }
    
    
    $OnLoadForm_StateCorrection=
    {#Correct the initial state of the form to prevent the .Net maximized form issue
        $objForm.WindowState = $InitialFormWindowState
    }
    
    #Save the initial state of the form
    $InitialFormWindowState = $objForm.WindowState
    #Init the OnLoad event to correct the initial state of the form
    $objForm.add_Load($OnLoadForm_StateCorrection)
    #Show the Form
    
    [System.Windows.Forms.Application]::Run($objForm)
    #$objForm.ShowDialog()
    

    有趣的是,我甚至不需要按回车键。只需输入$qlfile然后删除它就可以了。
    没有任何意义。
    如果我右键单击.ps1文件,并使用powershell运行它将永远无法工作,因为它没有$qlfile目标存储在会话/线程中。

    我必须使用[system.windows.forms.application]::run($objform),因为我是在一个线程中与另一个wpf表单(上面没有显示)并排运行这个代码,所有这些代码都放在一个按钮中:$wpfbutton3.add掼click({}),但我将它作为一个单独的.ps1编写,以使它首先工作。
    我需要能够编辑和选择在同一时间。使用.showDialog无法执行此操作。

    我想解决办法是把变量$qlfile放在[system.windows.forms.application]::run()运行的同一个线程/作业中。

    你怎么做到的?

    我试过做:

    $ps = [powershell]::create()
    $ps.AddScript(
         {
         [System.Windows.Forms.Application]::Run($objForm)
         })
    $ps.Runspace.SessionStateProxy.SetVariable("form", $objForm)
    $ps.BeginInvoke()
    

    但它不起作用,因为它是一个后台进程,所以我根本看不到winform。

    谢谢你的阅读,请帮忙

    1 回复  |  直到 6 年前
        1
  •  1
  •   Jaykul    6 年前

    在使用事件处理程序之前,需要定义它们。移动的定义 $SelectedFile $OnLoadForm_StateCorrection 到顶端。

    这是我的版本:

    [CmdletBinding()]
    param(
        $SourceFile = "C:\querylist.txt"
    )
    Add-Type -Assembly System.Windows.Forms, System.Drawing
    
    $MainForm = [System.Windows.Forms.Form]@{
        Size          = New-Object System.Drawing.Size(850, 550)
        StartPosition = "WindowsDefaultLocation"
        Text          = "Query List"
        AutoScroll    = $True
    }
    
    $ListBox = [System.Windows.Forms.ListBox]@{
        Location            = New-Object System.Drawing.Size(10, 40)
        Size                = New-Object System.Drawing.Size(800, 30)
        ScrollAlwaysVisible = $True
        Height              = 250
        DrawMode            = "OwnerDrawFixed"
    }
    $MainForm.Controls.Add($ListBox)
    
    
    $TextBox = [System.Windows.Forms.TextBox]@{
        Location  = New-Object System.Drawing.Size(10, 320)
        Size      = New-Object System.Drawing.Size(800, 3000)
        Height    = 100
        Multiline = $true
    }
    $MainForm.Controls.Add($TextBox)
    
    $selectLabel = [System.Windows.Forms.Label]@{
        Text = "Select a Query"
        Left = 10
        Top  = 20
        Font = "Verdana"
    }
    $MainForm.Controls.add($selectLabel)
    
    $EditLabel = [System.Windows.Forms.Label]@{
        Text = "Edit Query"
        Left = 10
        Top  = 300
        Font = "Verdana"
    }
    $MainForm.Controls.add($EditLabel)
    
    $BigButton = [System.Windows.Forms.Button]@{
        Size     = New-Object System.Drawing.Size(250, 50)
        Location = New-Object System.Drawing.Size(10, 450)
        Text     = "Copy Text"
    }
    $MainForm.controls.add($BigButton)
    
    $ListBox.Add_SelectedIndexChanged( {
            $TextBox.Text = ($ListBox.SelectedItem)
        })
    
    # Hook up event handlers
    $ListBox.Add_DrawItem( {
        param(
            [System.Object] $sender,
            [System.Windows.Forms.DrawItemEventArgs] $e
        )
        #Suppose Sender de type Listbox
        if ($Sender.Items.Count -eq 0) {
            return
        }
    
        #Suppose item de type String
        $lbItem = $Sender.Items[$e.Index]
        if ( $lbItem.contains('Q:')) {
            $Color = [System.Drawing.Color]::Orange
            try {
                $brush = new-object System.Drawing.SolidBrush($Color)
                $e.Graphics.FillRectangle($brush, $e.Bounds)
            } finally {
                $brush.Dispose()
            }
        }
        $e.Graphics.DrawString($lbItem, $e.Font, [System.Drawing.SystemBrushes]::ControlText, (new-object System.Drawing.PointF($e.Bounds.X, $e.Bounds.Y)))
    })
    
    $BigButton.Add_MouseHover( {
        $BigButton.backcolor = [System.Drawing.Color]::CornflowerBlue
        $BigButton.Text = "CLICK ME!"
    })
    $BigButton.Add_MouseLeave( {
        $BigButton.backcolor = [System.Drawing.Color]::DarkBlue
        $BigButton.Text = "Copy Text"
    })
    $BigButton.Add_Click( {
        #$TextBox.Text | Clip
        $WPFQuery_text.text = $TextBox.Text
    })
    
    # Save the initial state of the form
    $InitialFormWindowState = $MainForm.WindowState
    # Init the OnLoad event to correct the initial state of the form
    $MainForm.Add_Load( {
        #Correct the initial state of the form to prevent the .Net maximized form issue
        $MainForm.WindowState = $InitialFormWindowState
    })
    
    # Populate list.
    Get-Content $SourceFile | ForEach-Object {[void] $ListBox.Items.Add($_)}
    
    #Show the Form
    [System.Windows.Forms.Application]::Run($MainForm)