Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
353 views
in Technique[技术] by (71.8m points)

powershell - Sort listview checked items by order in which they were checked

I'm trying to use a powershell GUI to solve a simple problem: we often have to create quality reports for outgoing parts which involves looking through and inserting inspection photos, but we really only need to pick two photos that show the whole part (making seeking out the folder and trying to sort through dozens of photos seem like a silly way of going about it). So I am creating a GUI that will load all the pictures (icon-sized) in a listbox with checkboxes, with the ability to double-click on a picture to open a new window with the full-sized picture if needed. The user can check two images, click okay, and it will return the two images (eventually to another function that will insert them in the proper place without having to manually open an excel file and insert them using excel's GUI). I have all of this fully-functional in my test code. However, when the inspection photos are taken they are always taken in random order, and the reason we need two pictures is we need one of the top of the part and one of the bottom. I was thinking I could just have instructions to check the top image first, then check the bottom image, and I'll be able to sort the checked items in order of which one the user checked first. This is proving to be more difficult than I anticipated, can someone please assist me? So far I have:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing 
$objForm = New-Object System.Windows.Forms.Form

Add-Type -AssemblyName System.Drawing
$objForm.Text = "Outgoing Inspection Images"
$objForm.Height = 800
$objForm.Width = 1500
 
$imageList = new-Object System.Windows.Forms.ImageList 
$imageList.ImageSize = New-Object System.Drawing.Size(256,256) # Size of the pictures




$Testdir = '...Inspection Picturesoutgoing inspection pictures'
$Testpics = Get-ChildItem -Path $TestDir


$Testpics = $Testpics.FullName



for ($i=0; $i -lt $Testpics.Length; $i++){

$bitm=[System.Drawing.Image]::FromFile($testpics[$i]) 

$Testname = $testpics[$i]  -split "\" |Select-Object -Last 1

$imageList.Images.Add($Testname,$bitm) 




}
 

 
$listView1 = New-Object System.Windows.Forms.ListView
 
$listView1.View = 'Details'
$listView1.Height = 800
$listView1.Width = 800
$listView1.CheckBoxes = $true;
$ListView1.MultiSelect = $false;
$listview1.FullRowSelect = $true
 
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 12
 
$listView1.Location = $System_Drawing_Point
$listView1.Name = "listView1"
 
$listView1.Columns.Add('Inspection Picture',400)| Out-Null
 




for ($i=0; $i -lt $Testpics.Length; $i++){

$Testname = $testpics[$i]  -split "\" |Select-Object -Last 1

$listView1.SmallImageList = $imageList
$listView1.Items.Add($Testname,$i) 

 

}



    $OKButton = new-object System.Windows.Forms.Button
    $OKButton.Location = '850,200'
    $OKButton.Size = '100,40' 
    $OKButton.Text = 'OK'

 
    #Add a cancel button
    $CancelButton = new-object System.Windows.Forms.Button
    $CancelButton.Location = '1050,200'
    $CancelButton.Size = '100,40'
    $CancelButton.Text = "Cancel"
    $CancelButton.DialogResult=[System.Windows.Forms.DialogResult]::Cancel



$objForm.Controls.add($listView1)

$objForm.Controls.add($OKButton)

$OKButton.Add_Click{


    $x = $listView1.SelectedItems.Text
    write-host "Selected: "
    write-host $x

    $y = $listview1.CheckedItems.Text

    write-host "checked: "

    write-host $y

    if ($y.count -ne 2){

    write-warning -Message "Please check two images"

    }

if ($y.count -eq 2){



$Objform.DialogResult=[System.Windows.Forms.DialogResult]::OK
$listView1.Dispose()
$imageList.Dispose()
$objForm.Dispose()


return $y

    }


}

$objForm.Controls.add($cancelButton)
 




Function DoSomething()
{


    if($listview1.SelectedItems.Count -eq 1)
    {
    


$file = (-join($testdir, '/', $listview1.SelectedItems[0].Text))


$panel1 = New-Object Windows.Forms.Panel
$Panel1.AutoScroll = $true;



$win = New-Object Windows.Forms.Form
$box = New-Object Windows.Forms.PictureBox
$box.Image = [System.Drawing.Image]::FromFile($file)
$box.AutoSize = $true

$Panel1.controls.add($box)


$win.width = 1500
$win.height = 800
$Win.Text = $listview1.SelectedItems[0].Text


$panel1.width = ($win.width - 15)

$panel1.height = ($win.height -50)

$win.Controls.Add($panel1)




$win.ShowDialog()

}

}


$listview1.Add_ItemActivate({DoSomething})

$result = $objForm.ShowDialog()

The problem is if I check for example "IMG_4949.JPG" and "IMG_4951.JPG", $y seems to always contain them sorted by name. I want to change this so that if I check the box by IMG_4951 first, this will be listed first in the output. Is there any way to achieve this?

question from:https://stackoverflow.com/questions/65853971/sort-listview-checked-items-by-order-in-which-they-were-checked

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The simplest thing is to handle the ItemCheck event and keep track of what's checked in what order.

One way of doing that would be to move the checked items to the top... That way they would be in order automatically.

using namespace System.Windows.Forms
using namespace System.Drawing

param($Path = "C:UsersJaykulOneDrive - PoshCodeDocumentsShareXScreenshots2021-01")

Add-Type -Assembly System.Windows.Forms
Add-Type -Assembly System.Drawing

$imageList = [ImageList]@{
    ImageSize = [Size]::new(256, 256)
}

$listView = [ListView]@{
    View           = 'Details'
    Location       = [Point]@{X = 12; Y = 12 }
    Height         = 800
    Width          = 800
    CheckBoxes     = $true;
    MultiSelect    = $false;
    FullRowSelect  = $true
    Name           = "listView"
    SmallImageList = $imageList
}

$null = $listView.Columns.Add('Inspection Picture', 400)
$TestPics = Get-ChildItem $Path
$i = 0
foreach($file in $TestPics) {
    $imageList.Images.Add([Image]::FromFile($file.FullName))
    $item = $listView.Items.Add($file.Name, $i++)
    # Use the tag to keep track of the extra information you really need
    $item.Tag = $file
}

$OKButton = [Button]@{
    Location = '850,200'
    Size = '100,40'
    Text = 'OK'
}

#Add a cancel button
$CancelButton = [Button]@{
    Location = '1050,200'
    Size = '100,40'
    Text = "Cancel"
    DialogResult = [System.Windows.Forms.DialogResult]::Cancel
}

$OKButton.Add_Click{
    if ($listView.CheckedItems.Count -ne 2) {
        $null = [MessageBox]::Show("Please check exactly two images","$($y.Count) of 2 selected", "OK", "Warning")
    } else {
        # Return things by sticking them in the tag:
        $mainForm.Tag = $listView.CheckedItems.Tag
        $listView.CheckedItems.Tag | Write-Output
        $mainForm.DialogResult = [System.Windows.Forms.DialogResult]::OK
        $listView.Dispose()
        $imageList.Dispose()
        $mainForm.Close()
    }
}

$mainForm = [Form]@{
    Text   = "Outgoing Inspection Images"
    Height = 800
    Width  = 1500
}

$mainForm.Controls.add($listView)
$mainForm.Controls.add($OKButton)
$mainForm.Controls.add($cancelButton)

$panel = [Panel]@{
    AutoScroll = $true;
}

$box = [PictureBox]@{
    AutoSize = $true
}

$panel.Controls.Add($box)

$Popup = [Form]@{
    Text = $listview.SelectedItems[0].Text
}

$Popup.Controls.Add($panel)

$listView.Add_ItemCheck({
    $count = $listView.CheckedItems.Count
    $item = $listView.Items[$_.Index]
    # They're checking a new item
    if ($_.Index -ne $count -and $_.CurrentValue -eq "Unchecked" -and $_.NewValue -eq "Checked") {
        $listView.Items.Remove($item)
        $item.Checked = $true
        $listView.Items.Insert($count, $item)
    } elseif ($_.Index -lt $count -and $_.NewValue -eq "Unchecked") {
        $listView.Items.Remove($item)
        $item.Checked = $false
        $listView.Items.Insert($count-1, $item)
    }
})
$listview.Add_ItemActivate({
    if ($listview.SelectedItems.Count -eq 1) {
        $file = Join-Path $Path $listview.SelectedItems[0].Text
        $box.Image = [System.Drawing.Image]::FromFile($file)
        $popup.Width = 15 + ($panel.Width = $box.Width)
        $popup.Height = 40 + ($panel.Height = $box.Height)
        $Popup.ShowDialog()
    }
})

$result = $mainForm.ShowDialog()
# Output the results before disposing the form
$mainForm.Tag
$mainForm.Dispose()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...