Hello I've got a list view that opens items inside a folder and displays them. I want to know if there is a way to have the list view display the icons aswell, maybe using shell32 or an imagelist. Here's the code:
Imports System.IO
Imports System.Xml
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
Public Class cv7import
Private Sub cv7import_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim caminho As String
caminho = "C:\Documents and Settings\Software\Ambiente de trabalho\1"
lstvicon.View = View.Details
lstvicon.GridLines = False
lstvicon.FullRowSelect = True
lstvicon.HideSelection = False
lstvicon.MultiSelect = True
lstvicon.Columns.Add("Nome")
lstvicon.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize)
Dim DI As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(caminho)
Dim files() As System.IO.FileInfo = DI.GetFiles
Dim file As System.IO.FileInfo
Dim li As ListViewItem
For Each file In files
li = lstvicon.Items.Add(file.Name)
li.Tag = file.FullName
Next
End Sub
End Class
Here's two images, of how it looks and how I want it to look, if it helps.
How I wanted: http://imageshack.us/photo/my-images/21/wantd.png/
How it looks: http://imageshack.us/photo/my-images/13/needk.png/
Well you need to find the extension of the file to start with:
Dim file As String = "C:\scratch\newfile.txt"
Dim ext as string = IO.Path.GetExtension(file)
Then you need to find this entry in the HKEY_CLASSES_ROOT section of the registry:
HKEY_CLASSES_ROOT\.txt
The default value in this key gives the file type associated with this file in my case txtfile (remember that different registries may have different values depending on what the user has set up and what programs are installed)
You then need to look up this values DefaultIcon key in HKEY_CLASSES_ROOT:
HKEY_CLASSES_ROOT\txtfile\DefaultIcon
The default value in here gives you the location of the icon and the icon number in my case:
%SystemRoot%\system32\imageres.dll,-102
From this point I think you may need to rely on the ExtractIconEX API
to extract the icon. This link may also be of use
ListViewItems have ImageList, ImageIndex and ImageKey properties. Add a ImageList control to your form (from the components group in the toolbox). You can add images to the ImageList by clicking "Choose images" below the property grid, when the image list is selected. Then assign the image list and an image index or an image key to your list items.
Related
I am trying to build this file copy utility in VB.Net, and I have this window:
The current folder button opens up a folder browser dialog, and I save the selected path from the dialog to a string variable which I then pass to a function. The function adds all files and directories present in that folder to the current folder listbox.
Now I need this filepath for the all files checkbox, which when triggered lists all the subdirectories and their contents in the currentfolder listbox.
Is there any way I can extract that filepath variable dynamically without hardcoding it? Or can I create custom event handlers and trigger them inside the current folder button handler?
Here is my code:
Public Class Form1
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim FB As FolderBrowserDialog = New FolderBrowserDialog()
Dim srcpath As String
Dim flag As Integer = 1
FB.ShowDialog()
FB.ShowNewFolderButton = True
If (DialogResult.OK) Then
srcpath = FB.SelectedPath()
End If
listfiles(srcpath)
End Sub
Public Function listfiles(srcpath As String)
Dim dir As DirectoryInfo = New DirectoryInfo(srcpath)
Dim dirs As DirectoryInfo() = dir.GetDirectories()
Dim d As DirectoryInfo
Dim files As FileInfo() = dir.GetFiles()
Dim file As FileInfo
For Each file In files
CurrentFolderListBox.Items.Add(file.Name)
Next
For Each d In dirs
CurrentFolderListBox.Items.Add(d)
Next
'If CheckBox1.Checked = True Then
' CheckBox1_CheckedChanged(sender, New System.EventArgs())
'End If
End Function
Public Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChange
Dim item As DirectoryInfo
For Each i As DirectoryInfo In CurrentFolderListBox.Items
item = i
Next
End Sub
Any help would be most appreciated.
Well, for the list side lbox, and the right side lbox?
Why not fill each list box with a data source? You can have 1, or 2, or even 5 columns of data. The ListBox can display TWO of the columns.
So, VERY often a list box will have two values. the "value" based on what you select (often a PK database row value), and then you have the "text" value for display.
from FoxPro, ms-access, vb.net, and even asp.net?
A list box traditional has had the ability to "store" a set of values for your selection.
So, why not just put out the file list to a on the fly "data structure". You can quite much use a struct, a class or whatever.
However, might as well use a data table, since listbox supports "binding" to a table.
So, in the ListBox settings, you have these two settings:
so above is our "display"
And then set the "value" to the FULL file name like this:
So now we can say create a form like this:
So, our code to select the "from folder" can look like this:
Private Sub cmdSelFrom_Click(sender As Object, e As EventArgs) Handles cmdSelFrom.Click
Dim f As New FolderBrowserDialog
If f.ShowDialog = DialogResult.OK Then
txtFromFolder.Text = f.SelectedPath
ListBox1.DataSource = GetFileData(txtFromFolder.Text)
End If
End Sub
Public Function GetFileData(sFolder As String) As DataTable
Dim rstData As New DataTable
rstData.Columns.Add("FullFile", GetType(String))
rstData.Columns.Add("FileName", GetType(String))
' get all files from this folder
Dim folder As New DirectoryInfo(sFolder)
Dim fList() As FileInfo = folder.GetFiles
For Each MyFile As FileInfo In fList
Dim OneRow As DataRow = rstData.NewRow
OneRow("FullFile") = MyFile.FullName
OneRow("FileName") = MyFile.Name
rstData.Rows.Add(OneRow)
Next
Return rstData
End Function
so, we setup a two column "thing" (in this case a data table).
We fill it with our two values (FileName and FullFile).
So, we now have this:
I have selected two files on the left side, and thus we get this:
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
For Each MySel As DataRowView In ListBox1.SelectedItems
Debug.Print(MySel.Item("FileName"))
Debug.Print(MySel.Item("FullFile"))
Next
End Sub
OutPut:
a.pdf
C:\Test2\a.pdf
b.pdf
C:\Test2\b.pdf
We could even include say file size in that table. But the "basic" concept here is that we can store + save data items into the list box, and that REALLY makes the code simple, since the list box now has JUST the file for display, but also enables us to have the full path name also.
The following code will print a Label with default text & QR Code image from saved image path on computer, but I need to add replace the text & QR image with a custom text & QR Image. I cannot find any examples online of the new SDK, there is a little reference on the GitHub but cant piece anything together to work.
I Installed NuGet package Dynmo.Connect.SDK
Imports DymoSDK.Implementations
Dim dymoSDKLabel As DymoSDK.Implementations.DymoLabel
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim SelectedPrinter As String = "DYMO LabelWriter 450"
Dim copies As Integer = 1
Dim barcodeGraphsQuality As Boolean = True
dymoSDKLabel = New DymoLabel()
dymoSDKLabel.LoadLabelFromFilePath("C:\Users\User\Documents\QR.dymo")
DymoPrinter.Instance.PrintLabel(dymoSDKLabel, SelectedPrinter, copies, barcodeGraphsQuality)
End Sub
I wanted to say that I figured out the answer to my own problem in case someone is wondering how. I created a label in Dymo Connect software program called label.dymo. I added a TextObject and a ImageObject to the label, positioned in the middle and saved the label. I installed a Free NuGet package called QRCoder and referenced it in this sample code below. The String Variable called id is coming from my database and is the row id for what was just created(last insert row id). The QrCode generates a QRCode matching my id variable and then converts it to base64string because that what format the Dymo ImageObject supports. You can replace the id variable with any number or text as you need for your project.
Imports DymoSDK.Implementations
Imports QRCoder
Dim dymoSDKLabel As DymoSDK.Implementations.DymoLabel
Dim LabelTextObject As DymoSDK.Interfaces.ILabelObject
Dim LabelQRObject As DymoSDK.Interfaces.ILabelObject
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Dim gen As New QRCodeGenerator
Dim data = gen.CreateQrCode(id, QRCodeGenerator.ECCLevel.Q)
Dim qrCode As New Base64QRCode(data)
Dim base64qrcode As String = qrCode.GetGraphic(20)
Dim SelectedPrinter As String = "DYMO LabelWriter 450"
Dim copies As Integer = 1
Dim barcodeGraphsQuality As Boolean = True
dymoSDKLabel = New DymoLabel()
dymoSDKLabel.LoadLabelFromFilePath("C:\Users\User\Documents\label.dymo")
LabelTextObject = dymoSDKLabel.GetLabelObject("TextObject")
dymoSDKLabel.UpdateLabelObject(LabelTextObject, id)
LabelQRObject = dymoSDKLabel.GetLabelObject("ImageObject")
dymoSDKLabel.UpdateLabelObject(LabelQRObject, base64qrcode)
DymoPrinter.Instance.PrintLabel(dymoSDKLabel, SelectedPrinter, copies, barcodeGraphsQuality)
End Sub
This code is intended to delete the actual files from the system when it is selected from the system:
Dim file As String()
file = System.IO.Directory.GetFiles("C:\Users\User\Desktop", "lalala.txt", IO.SearchOption.AllDirectories)
If ListBox1.SelectedIndex = -1 Then
MsgBox("No files selected")
Else
System.IO.File.Delete(ListBox1.Items(ListBox1.SelectedIndex).ToString())
ListBox1.Items.RemoveAt(ListBox1.SelectedIndex)
End If
However, only the items in the listbox are deleted. The actual file still exists. I am unsure where I should put the file into the Delete function.
I have referred to this but it has not helped me.
________UPDATE________
I have discovered where it went wrong: it is because only the file name is added to the listbox:
ListBox1.Items.Add(Path.GetFileName(fileFound))
Instead of Path.GetFullPath.
Anyhow, can I delete the file with GetFileName only?
The problem, as you realised, is that the filename only is not enough information to delete a file. You need the whole path to the file as well. So you need some way of storing the whole path but only showing the filename. This is also important because there might be two (or more) files with same name in separate directories.
A ListBox can have its Datasource property set to show items from "an object that implements the IList or IListSource interfaces, such as a DataSet or an Array."
Then you set the DisplayMember and ValueMember properties to tell it what to display and what to give as the value.
For example, I made up a class named "FileItem" which has properties for the full filename and for whatever you want to display it as, filled a list with instances of "FileItem", and told ListBox1 to display it:
Imports System.IO
Public Class Form1
Class FileItem
Property FullName As String
Property DisplayedName As String
Public Sub New(filename As String)
Me.FullName = filename
Me.DisplayedName = Path.GetFileNameWithoutExtension(filename)
End Sub
End Class
Private Sub PopulateDeletionList(dir As String, filter As String)
Dim files = Directory.EnumerateFiles(dir, filter, SearchOption.AllDirectories)
Dim fileNames = files.Select(Function(s) New FileItem(s)).ToList()
Dim bs As New BindingSource With {.DataSource = fileNames}
ListBox1.DataSource = bs
ListBox1.DisplayMember = "DisplayedName"
ListBox1.ValueMember = "FullName"
End Sub
Private Sub ListBox1_Click(sender As Object, e As EventArgs) Handles ListBox1.Click
Dim lb = DirectCast(sender, ListBox)
Dim sel = lb.SelectedIndex
If sel >= 0 Then
Dim fileToDelete = CStr(lb.SelectedValue)
Dim choice = MessageBox.Show("Do you really want to delete " & fileToDelete, "Confirm file delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If choice = DialogResult.Yes Then
Try
File.Delete(fileToDelete)
lb.DataSource.RemoveAt(sel)
Catch ex As Exception
MessageBox.Show("Could not delete " & fileToDelete & " because " & ex.Message)
End Try
End If
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PopulateDeletionList("C:\temp", "*.txt")
End Sub
End Class
Edited I had forgotten to delete the item from the ListBox. To do that, it needs to be tied to the DataSource through a BindingSource.
Extra feature Seeing as there could be more than one file with the same name, you might want to add a tooltip to the listbox items so that you can see which directory it is in. See how to add tooltips on winform list box items for an implementation which needs only minor adjustments to work, such as:
Dim toolTip As ToolTip = New ToolTip()
' ...
Private Sub ListBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseMove
Dim lb = DirectCast(sender, ListBox)
Dim index As Integer = lb.IndexFromPoint(e.Location)
If (index >= 0 AndAlso index < ListBox1.Items.Count) Then
Dim desiredTooltip = DirectCast(lb.Items(index), FileItem).FullName
If (toolTip.GetToolTip(lb) <> desiredTooltip) Then
toolTip.SetToolTip(lb, desiredTooltip)
End If
End If
End Sub
The most simple (and reliable) solution would be to create a custom data type and add that to the ListBox instead.
By overriding the ToString() method you can make it display only the file name, while the back-end object still contains the full path.
Public Structure FileEntry
Public FullPath As String 'A variable holding the full path to the file.
'Overriding the ToString() method, making it only return the file name.
Public Overrides Function ToString() As String
Return System.IO.Path.GetFileName(Me.FullPath)
End Function
Public Sub New(ByVal Path As String)
Me.FullPath = Path
End Sub
End Structure
Now whenever you want to add paths to the ListBox you've got to add a new instance of the FileEntry structure, instead of a regular string:
ListBox1.Items.Add(New FileEntry(fileFound))
And to delete you just cast the currently selected item into a FileEntry, and then pass its FullPath onto the File.Delete() method.
Dim Entry As FileEntry = DirectCast(ListBox1.Items(ListBox1.SelectedIndex), FileEntry)
System.IO.File.Delete(Entry.FullPath)
NOTE: For this to work every item in the list box must be a FileEntry.
Online test: https://dotnetfiddle.net/x2FuV3 (pardon the formatting, DotNetFiddle doesn't work very well on a cellphone)
Documentation:
How to: Declare a Structure (Visual Basic) - Microsoft Docs
Overriding the Object.ToString() method - MSDN
You can use Path.Combine.
Since you are going to search in C:\Users\User\Desktop, you can do this to delete:
System.IO.File.Delete(Path.COmbine("C:\Users\User\Desktop",ListBox1.Items(ListBox1.SelectedIndex).ToString())
Here, "C:\Users\User\Desktop" and the selected index's text will be combined to make a single path.
Edit:
I get it, you want to show the file name onlyy in the textbox but want to delete the file from the system too but can't do it, right?
Well you can do this:
Put two listbox and while you add a file to a listbox1, put it's path to the listbox2 whose visibility will be False, meaning it won't be shown in the runtime.
DOing this, while an item is selected in the listbox1, use the path.combine to make a path by adding the filename & path from the list with same index number.
Something like this:
System.IO.File.Delete(path.combine(ListBox1.Items(ListBox1.SelectedIndex).ToString(), ListBox2.Items(ListBox1.SelectedIndex).ToString())
I have a picture icon on my form. I would like to have it so when the user drags this icon to a windows explorer, desktop etc the associated file is written to that location.
I have the file path in a combo and as I said an image on the form for the user to drag. The image is just a general image not really associated with the actual file.
Can you help me out? I have no clue!
For the next guy....
Where pbDragger is the picture box.
It is important to note that the DataObject requires a string array even if you are only dragging one file.
Private Sub pbDragger_MouseMove(sender As Object, e As MouseEventArgs) Handles pbDragger.MouseMove
If ((e.Button And MouseButtons.Left) = MouseButtons.Left) Then
Dim strPath As String = cboRef.SelectedItem!Path.ToString ' Path of the file to be copied
Dim strArr() As String = {strPath} ' 'FileDrop requires an array of string!!
Dim oDraginfo As New DataObject(DataFormats.FileDrop, strArr)
Dim dropEffect As DragDropEffects = pbDragger.DoDragDrop(oDraginfo, DragDropEffects.Copy)
End If
End Sub
I am pretty new to VB and am compiling a program which contains several forms, each of which is populated with text boxes. The purpose of the program is for text to be dragged between boxes to move assets around. I've managed the drag and drop functionality but need to persist the text in the text boxes once the program is shut down so that when reopened, the last location of all moved text is still present.
Can anyone make any suggestions/supply sample code please?
I've tried the easiest to understand suggestion to get me started but when I build and publish the program it says that I do not have access to the file to save the values!! Can anyone help? Code below
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim txtpersist As IO.TextWriter = New IO.StreamWriter("C:\Users\HP\Documents\namestore")
txtpersist.WriteLine(TextBox1.Text)
txtpersist.WriteLine(TextBox2.Text)
txtpersist.WriteLine(TextBox3.Text)
txtpersist.Close()
Dim yourfile As IO.TextReader = New IO.StreamReader("C:\Users\HP\Documents\namestore")
TextBox1.Text = yourfile.ReadLine()
TextBox2.Text = yourfile.ReadLine()
TextBox3.Text = yourfile.ReadLine()
yourfile.Close()
End Sub
End Class
You can use the built in PropertyBinding to link your TextBox.Text to a Property. It will put it into your App.Config File which will allow you to edit it through MySettings as long as it is per user. If the settings are application level you would be better of using one of the other answers. You can also look at this article for some more information.
You should write the location of the textboxes to a persistent store on program exit, such as a file, a database, or the registry. On program load, you can retrieve the saved values and set the locations accordingly.
You could save each textbox's text inside of a file and re-open it at runtime.
Dim yourfile As TextWriter = New StreamWriter("pathtofile")
Say you had 3 textBoxes called textBox1, textBox2 and textBox3. You would save each one's status by simply writing each textbox's text property inside the file. Like so:
yourfile.WriteLine(textBox1.Text)
yourfile.WriteLine(textBox2.Text)
yourfile.WriteLine(textBox3.Text)
At the end, you just close the file.
yourfile.Close()
Loading the data back is just as simple.
Dim yourfile As TextReader = New StreamReader("pathtofile")
textBox1.Text = yourfile.ReadLine()
textBox2.Text = yourfile.ReadLine()
textBox3.Text = yourfile.ReadLine()
yourfile.Close()
Let me know if you have any questions or require further assistance. Be sure to import the System.IO namespace, to get access to the IO classes used here.
The most common method of persisting data is to store it in a database. Of course that adds more work to your project since you now have to create, update, and maintain a database. An easier solution is to use a file.
We'll create a new class in order to read & write data from the file. This way if you switch to a database later on, you only need to change the class. And since I'm sure at some point you'll want a database we'll make the class use datatables to minimize the changes needed to it. Here's our class:
Public Class TextBoxes
Private tbl As DataTable
Private filename As String
'Use constants for our column names to reduce errors
Private Const ctrlName As String = "CtrlName"
Private Const text As String = "Text"
Public Sub New(ByVal file As String)
'Create the definition of our table
tbl = New DataTable("TextBox")
tbl.Columns.Add(ctrlName, Type.GetType("System.String"))
tbl.Columns.Add(text, Type.GetType("System.String"))
'Save the filename to store the data in
Me.filename = file
End Sub
Public Sub Save(ByVal frm As Form)
Dim row As DataRow
'Loop through the controls on the form
For Each ctrl As Control In frm.Controls
'If the control is a textbox, store its name & text in the datatable
If TypeOf (ctrl) Is TextBox Then
row = tbl.NewRow
row.Item(ctrlName) = ctrl.Name
row.Item(text) = ctrl.Text
tbl.Rows.Add(row)
End If
Next
'Save the additions to the dataset and write it out as an XML file
tbl.AcceptChanges()
tbl.WriteXml(filename)
End Sub
Public Sub Load(ByVal frm As Form)
'Don't load data if we can't find the file
If Not IO.File.Exists(filename) Then Return
tbl.ReadXml(filename)
For Each row As DataRow In tbl.Rows
'If this control is on the form, set its text property
If frm.Controls.ContainsKey(row.Item(ctrlName)) Then
CType(frm.Controls(row.Item(ctrlName)), TextBox).Text = row.Item(text).ToString
End If
Next
End Sub
End Class
Next you'll want to use this fine class to read & write your data. The code for doing this is nice and simple:
Dim clsTextBoxes As New TextBoxes("C:\Txt.xml")
'Save the textboxes on this form
clsTextBoxes.Save(Me)
'Load the textboxes on this form
clsTextBoxes.Load(Me)
I would do it using either the Application settings as Mark Hall pointed out or like this...
Public Class MyTextBoxValueHolder
Public Property Value1 As String
Public Property Value2 As String
Public Property Value3 As String
Public Sub Save(Path As String)
Dim serializer As New XmlSerializer(GetType(MyTextBoxValueHolder))
Using streamWriter As New StreamWriter(Path)
serializer.Serialize(streamWriter, Me)
End Using
End Sub
Public Shared Function Load(Path As String) As MyTextBoxValueHolder
Dim serializer As New XmlSerializer(GetType(MyTextBoxValueHolder))
Using streamReader As New StreamReader(Path)
Return DirectCast(serializer.Deserialize(streamReader), MyTextBoxValueHolder)
End Using
End Function
End Class
So what you can then do is...
Dim myValues As MyTextBoxValueHolder = MyTextBoxValueHolder.Load("SomeFilePath.xml")
myTextBox1.Text = myValues.Value1
myTextBox2.Text = myValues.Value2
'And so on....
2 Save
Dim myValues As New MyTextBoxValueHolder
myValues.Value1 = myTextBox1.Text
myValues.Value2 = myTextBox2.Text
myValues.Save("SomeFilePath.xml")
'All saved
to maintain the values you can use stored user settings, see the following links.
http://msdn.microsoft.com/en-us/library/ms379611(v=vs.80).aspx
http://www.codeproject.com/KB/vb/appsettings2005.aspx
Regards.