How to close parent form and open child? - vb.net

Hey guys before I was just hiding the parent form, but now when I try to read from the parent file it says it can't because it's already running in a process. I followed some tutorial and it said to go to the project properties and have the application stop running when all the forms are closed.
But now since I did that it says the directory can't be found probably because I am reading the input from the parent form. Anyways here is my code
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" + frmLogin.txtUser.Text))
How should I go about doing this?
Edit:
Private Sub btnHunter_Click(sender As System.Object, e As System.EventArgs) Handles btnHunter.Click
selection = "Hunter"
writeData.classSelection()
End Sub
This is what I have when the button is clicked.
Here is the classSelection sub:
Public Sub classSelection()
If frmClass.selection = "Hunter" Then
writeFile1.WriteLine(frmClass.selection)
End If
If frmClass.selection = "Gatherer" Then
writeFile1.WriteLine(frmClass.selection)
End If
If frmClass.selection = "Farmer" Then
writeFile1.WriteLine(frmClass.selection)
End If
writeFile1.Close()
End Sub
The error points to this line:
If frmClass.selection = "Hunter" Then
Saying part of the file path cannot be found.

If you want to read input textbox in closed parent form, you have to declare public var
Make a new module in your project .. and add this
public sLogin as String
And before you hide or close frmLogin .. add this
sLogin = txtUser.Text
So, you could change your code with
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & sLogin))

matzone has given you a good hint. And to check exactly what your path is, just add a MessageBox using variables :
Dim writePath1 As String
Dim writeFile1 As StreamWriter
writePath1 = "C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & sLogin
If MessageBox.Show(writePath1, "Continue ?", MessageBoxButtons.YesNo) = DialogResult.Yes Then
writeFile1 = New StreamWriter(File.OpenWrite(writePath1))
' ...
writeFile1.Close() ' Very important ! Adrian pointed it out.
End If
^^ and if it works, you can discard the Dialog test or replace it by some test code like If File.Exists(...)
However, I don't understand wether you want to close the parent Form or hide it. It's different !
Closing the parent Form will discard any access to parent Form members, including txtUser.Text.
If you want to close the parent Form, the ChildForm should not be a child of that parent you are trying to close, or you must just hide the parent Form :
frmLogin.Hide() ' Not frmLogin.Close()
If you close frmLogin, frmLogin.txtUser won't be accessible, or use sLogin provided by matzone instead. Alternatively, you should pass frmLogin.txtUser.Text value to a custom property of ChildForm.
Imports System.IO
Public Partial Class ChildForm1
' Inherits System.Windows.Form
' ...
Private _txtUserFile As String
Public WriteOnly Property TxtUserFile() As String
Set(ByVal NewFileName As String)
_txtUserFile = NewFileName
End Set
End Property
Public Sub LoadFile()
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" & txtUserFile))
' ...
writeFile1.Close()
End sub
' ...
End Class
Then use this in parent Form :
MyChildForm.TxtUserFile = Me.txtUser.Text
' Me.Close() ' This will definately KILL Form1 (the parent one)
Me.Hide() ' Always use Hide() until you'll terminate your Application
MyChildForm.Show()
MyChildForm.LoadFile()
^^ but this is not a good code either ! Your problem remains unclear (at least for me)
"Still saying it can't find part of the path", then check the path..
Does the file actually exists ?
Does the path contains glitch ? (use the provided MessageBox test)
Does your account can access that directory ? (Windows configuration and account levels)

Well !
In fact, the problem could be somewhere else.
For example, I was able to reproduce your exception by providing an empty string [""] as the value of, either :
frmLogin.txtUser.Text ' = ""
' or
sLogin ' = ""
' or
txtUserFile ' = ""
In fact, I get the "Could not find a part of the path..." exception because the StreamWriter couldn'd read/write to a File, as I didn't provided a valid FileName for that file. As the filename parameter was an empty string "", the provided path for StreamWriter was just representing a directory instead of a file and an exception was raised.
Now, you should check wether you have a valid path before building a new instance of StreamWriter to get sure you are actually pointing to a File ?
Dim writeFile1 As StreamWriter
Dim MyEntirePath As String = "C:\Users\...\Accounts\" + frmLogin.txtUser.Text
MessageBox.Show(MyEntirePath) ' would be enough to be sure your path is correct
' Some test code here...
If everythingOK then ' create the StreamWriter...
writeFile1 = New StreamWriter(MyEntirePath)
' ...
' ...
Also, it's not a good idea to create your streamwriter, and use it in another part/method of your code. You never known if one day, you'll change your code, and forget to make the link between
Dim writeFile1 As StreamWriter = New StreamWriter(File.OpenWrite("C:\Users\Nick\Documents\Visual Studio 2010\Projects\LoginFixed\Accounts\" + frmLogin.txtUser.Text))
' plus
Private Sub btnHunter_Click(sender As System.Object, e As System.EventArgs)
...
End Sub
' plus
Public Sub classSelection()
...
writeFile1.Close()
End Sub
^^ too much "here and there"...
You'll obviously also get an exception if you try to click btnHunter twice.. I don't know what is the purpose of your code nor how it works, it looks like a game.. But I would use File.Exist(..) checks, create the file before, if none, and put that in a Try/Catch to check if I eventually don't have administrator rights to write to that directory. Otherwise, make a code that allow user to read/write files to a custom folder. Andalso, you have :
Application.StartupPath
^^ Very usefull, like :
Dim MyFilePath As String = Application.StartupPath + "\Datas\MyText.txt"
After two weeks of coding, I usually forget where I put those "C:\blabla.." or "D:\gnagna\" or what classes actually uses those absolute reference paths. I've dropped this way of getting directories long ago since the day I moved to Win7 on another computer and all such applications I developped using that approach was doomed...

Related

VB.Net RecycleBin is not declared

I refer to this post How to retrieve the 'Deletion Date' property of an Item stored in the Recycle Bin using Windows API Code Pack?
I refer to the answer by #ElektroStudios. I am trying to run that code. My knowledge of VB.net is very little.
Imports Microsoft.WindowsAPICodePack.Shell
Imports System.Text
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim RecycledFiles As ShellFile() = RecycleBin.MasterBin.Files
Dim sb As StringBuilder
' Loop through the deleted Items.
For Each Item As ShellFile In RecycledFiles
' Append the full name
sb.AppendLine(Item.Name)
' Append the DateDeleted.
sb.AppendLine(Item.Properties.GetProperty("DateDeleted").ValueAsObject.ToString)
MsgBox(sb.ToString)
sb.Clear()
Next Item
End Sub
End Class
However, I get a compiler error that RecycleBin is not declared. at
RecycleBin.MasterBin.Files
I am not too sure how to make this work. What is it that I am missing here? Is that a correct code ? Am I missing any Imports or any references?
I have already installed
nuget\Install-Package WindowsAPICodePack-Core
nuget\Install-Package WindowsAPICodePack-Shell
Note - I have already succeeded in accessing the RecycleBin using
SH.NameSpace(Shell32.ShellSpecialFolderConstants.ssfBITBUCKET)
I am specifically interested in that above piece of code. Thanks
To get the deletion date for items in the Recycle Bin, you don't need any extra libraries, you can use the Shell Objects for Scripting and Microsoft Visual Basic library (which I understand you already found in your last sentences) and the ExtendedProperty method.
Here is some code that dumps items in the recycle bin and their deletion date:
Sub Main()
Dim shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"))
Const ssfBITBUCKET As Integer = 10
Dim folder = shell.Namespace(ssfBITBUCKET)
For Each item In folder.Items
' dump some standard properties
Console.WriteLine(item.Path)
Console.WriteLine(item.ModifyDate)
' dump extended properties (note they are typed, here as a Date)
Dim dd As Date = item.ExtendedProperty("DateDeleted")
Console.WriteLine(dd)
' same but using the "canonical name"
' see https://learn.microsoft.com/en-us/windows/win32/api/propsys/nf-propsys-psgetpropertydescriptionbyname#remarks
Console.WriteLine(item.ExtendedProperty("System.Recycle.DateDeleted"))
Next
End Sub

How do I select specific variables based on checkbox state as I iterate through a For Each

I'm working on a project that requires I iterate through a list of controls on a tabpage to find all of the checkboxes. Then depending on the state of the box (checked or unchecked) select individual variables (filenames) to then perform either a batch rename or delete of files on the filesystem (cb.checked = perform action).
I have managed to create the "for each" for the iteration of the controls (thanks google) but I'm struggling to figure out how to pick the variables. They are all named differently, obviously, as are the checkboxes. Also the checkboxes are statically assigned to the form/tabpage. Here's what I have at the moment.
Public Sub delBut_code(ByRef fname As String)
If (Sanity = 1) Then
For Each cb As Control In Form1.Controls
If TypeOf cb Is CheckBox AndAlso DirectCast(cb,
CheckBox).Checked Then
If My.Computer.FileSystem.FileExists(fname) Then
My.Computer.FileSystem.DeleteFile(fname)
End If
End If
Next
MessageBox.Show("All Actions Completed Successfully")
Else
MessageBox.Show("Please select a File To Delete")
End If
End Sub
and here is an example of some of the variables:
Dim castle As String = selPath & "\zm_castle_loadingmovie.txt"
Dim factory As String = selPath &
"\zm_factory_load_factoryloadingmovie.txt"
Dim island As String = selPath & "\zm_island_loadingmovie.txt"
N.B selpath collects a user entered folder path and can be ignored here
I would really appreciate any pointers.
First, you can do much better with the loop:
Public Sub delBut_code(ByRef fname As String)
If Sanity <> 1 Then
MessageBox.Show("Please select a File To Delete")
Exit Sub
End If
Dim checked = Form1.Controls.OfType(Of CheckBox)().Where(Function(c) c.Checked)
For Each box As CheckBox in checked
Try
'A file not existing is only one reason among many this could fail,
' so it needs to be in a Try/Catch block.
' And once you're using a Try/Catch block anyway,
' the FileExists() check becomes a slow and unnecessary extra trip to the disk.
My.Computer.FileSystem.DeleteFile(fname)
Catch
'Do something here to let the user know it failed for this file
End Try
Next
MessageBox.Show("All Actions Completed")
End Sub
But now you need to know how have the right value in that fname variable. There's not enough information in the question for us to fully answer this, but we can give some suggestions. There a number of ways you could do this:
Set the Tag property in the Checkboxes when you build the string variables. Then fname becomes DirectCast(box.Tag, String).
Inherit a custom control from CheckBox to use instead of a normal Checkbox that has an additional String property for the file name. Set this property when you build the string variables.
Name your string variables in a way that you can derive the string variable name from the CheckBox variable name, and then use a Switch to pick the right string variable from each box.Name.
Keep a Dictionary(Of CheckBox, String) that maps the Checkboxes to the right string values.
But without knowing more context of the application, I hesitate to recommend any of these over the others as best for your situation.

VB.Net Handling Multiple Forms into Panel

I have tried to find an answer to this already, but cannot find one that answers this question.
I have a Master Form which contains two panels. In the master Form I am trying to write a subroutine to handle the loading of a form into one of the panels.
One panel always contains the same form and the code which works for this is:
'Configure Toolbar Import
Dim toolbarHandler As _pnl_header = New _pnl_header()
toolbarHandler.Size = pnlHeader.Size
toolbarHandler.TopLevel = False
pnlHeader.Controls.Add(toolbarHandler)
toolbarHandler.Show()
The panel successfully shows the form _pnl_header as expected.
The second panel will change the displayed form depending on user input, so rather than having to write the above code for every eventuality i would like one Public Sub to handle them all...
I've started writing a sub along the lines of:
Public Sub LoadContentPanel(WhichForm As Form)
Try
Dim contentHandler As WhichForm = New WhichForm()
contentHandler.Size = pnlContent.Size
contentHandler.TopLevel = False
pnlContent.Controls.Add(contentHandler)
contentHandler.Show()
Catch ex As Exception
MsgBox("Unable to Handle Content Panel Change. Error: " & ex.Message, vbOKOnly + vbCritical, "Load Error")
End Try
End Sub
However this fails as 'WhichForm' is not defined - how is best to correct this? or is there a better alternative?
Thanks
Without going into what you are doing I can explain where the error comes from.
Here you declare argument variable WhichForm of type Form
Public Sub LoadContentPanel(WhichForm As Form)
. . . . .
Code is incorrect in the next declaration line. WhichForm is a variable and not a type. Hence
Dim contentHandler As WhichForm = New WhichForm()
is invalid at As WhichForm. Because after As you need a type name. If you did
Dim contentHandler As Form = New Form()
it would work.
It seems that all you need to do is remove Dim contentHandler As WhichForm... and rename argument WhichForm to contentHandler.

" A Sharing Violation occured" error when editing images in Paint using VB.NET

I have written a program in VB.NET to monitor file changes to recent saved screenshots taken from the tool.
I have a custom FileSystemWatcher class written (shared by someone on the internet,just customized) and have an instance invoked in my program.
The basic issue or objective is that when i capture a screen area using my program, I want it to immediately copy it over to clipboard. There are times when I would want to edit the captured image, in which case any editing made and saved, after saving the edited image must automatically be copied over to clipboard.
I use the below code to copy the image over to clipboard
'Subroutine to Copy the captured screenshot
'Added 15/09/2014
Sub CopyImageCapture(ByVal ImgPath)
Dim ThreadA As Thread
ThreadA = New Thread(AddressOf Me.MyAsyncTask)
'Setting ApartmentState.STA as this is needed for Clipboard related functionalities
ThreadA.SetApartmentState(ApartmentState.STA)
ThreadA.Start(ImgPath)
End Sub
'Threading to handle the Clipboard copy function
'Copy the screenshot to Clipboard
'Added 15/09/2014
Private Sub MyAsyncTask(ByVal ImgPath)
Clipboard.Clear()
Clipboard.SetImage(ImgPath)
End Sub
And when i choose to edit the image, the below code takes care to monitor the file changes
Sub MonitorFileChange(ByVal FolderPath, ByVal ItemName)
Try
Dim sFolder As String
Dim sFile As String
sFolder = FolderPath
sFile = ItemName
If IO.Directory.Exists(sFolder) Then
objWatcher.FolderToMonitor = sFolder
objWatcher.FileToMonitor = sFile
'objWatcher.NotifyFilter = (NotifyFilters.FileName Or NotifyFilters.Size)
objWatcher.StartWatch()
Else
MessageBox.Show("Folder does not exist!")
End If
Catch ex As Exception
MsgBox("Encountered an exception in MonitorFileChange subroutine. Details - " + ex.Message)
End Try
End Sub
'Subrountine to capture FileChanged events (esp. when captured image is edited in Paint and Saved)
'Works in sync with custom class 'clsFSW' for this purpose.
'ADDED: 15/09/2014
Private Sub objWatcher_FileChanged(ByVal FullPath As String) Handles objWatcher.FileChanged
'Try
Dim lastWriteTime As DateTime
lastWriteTime = File.GetLastWriteTime(FullPath)
Debug.Print(lastWriteTime)
If (lastWriteTime <> lastRead) Then
objWatcher.EnableRaisingEvents = False
'QuickCopy for changes files. BUG FIX
If (QuickSaveToolStripMenuItem.Checked) Then
Debug.Print("File Changed: " & FullPath & vbCrLf)
Dim tempI As System.Drawing.Bitmap = New System.Drawing.Bitmap(FullPath)
Dim tempI2 As System.Drawing.Bitmap = New System.Drawing.Bitmap(tempI, tempI.Width, tempI.Height)
CopyImageCapture(tempI2)
tempI.Dispose()
End If
lastRead = lastWriteTime
End If
'Catch ex As Exception
' MsgBox("Encountered an exception in objWatcher_FileChanged subrountine. Details - " + ex.Message)
' 'Finally
' 'objWatcher.EnableRaisingEvents = True
'End Try
End Sub
The problem is sometimes when I open the captured image and make quick saves or press save a couple of times real quick I get a "A Sharing violation occured" error
Can anyone help resolve the above issue? Which part of the code or logic is causing this to happen?
Also, if you check the above snippet, sometimes (havent seen any particular pattern) but the catch block in objWatcher_FileChanged is triggered and the error is "Parameter not found"
Can someone please help into this too?
Thanks in advance! Please let me know if any info more is required.
EDIT: Please note, the sharing violation error seems invoked from the Paint application itself and not my program, but why does it happen randomly, is a mystery to me. Is there nay loophole in the logic? Any alternative logic to what I want to achieve?
Try disposing tempI2. Windows may be locking the file used with tempI, and keeping it locked since it is assigned to tempI2. If so, it may remain locked until tempI2 is disposed.

How to get all forms in a VB.net (VS08) project in an array?

Alright, so I need a method that traverses all the forms inside a VB.net project under Visual Studio 2008, and create an array of type form with references to all the forms inside it, so that the array looks like this (pseudocode)
FormsArray() = [Form1, Form2, Form3, Form4]
However, I don't have a clue as to how to begin.
You have to adjust the function to put the result of msgbox in a array
Public Sub getallforms(ByVal sender As Object)
Dim Forms As New List(Of Form)()
Dim formType As Type = Type.GetType("System.Windows.Forms.Form")
For Each t As Type In sender.GetType().Assembly.GetTypes()
If UCase(t.BaseType.ToString) = "SYSTEM.WINDOWS.FORMS.FORM" Then
MsgBox(t.Name)
End If
Next
End Sub
You must call the function from any form in the application like this (getallforms(me))
Here is how you would do this using Reflection, assuming that the class where you placed this code was in the same assembly that you wanted to iterate over. If not, then you'll need to change the Me.GetType().Assembly in the For Each loop into something else to account for loading the assembly in a different manner.
Dim Forms As New List(Of Form)()
Dim formType As Type = Type.GetType("System.Windows.Forms.Form")
For Each t As Type In Me.GetType().Assembly.GetTypes()
If t.IsSubclassOf(formType) = True Then
Forms.Add(CType(Activator.CreateInstance(t), Form))
End If
Next
Hey this is what I did to get the list of forms in my vb project, how ever this in not in code but you could write system.io code fragment to do just that.
open cmd prompt
go to project folder
run a dir /s/b *.designer.vb >> list.txt
use notepad or sublimetext and edit it to get the list ordered as you like it.
:) hope this helped!
I could not get this version to work:
Dim Forms As New List(Of Form)()
Dim formType As Type = Type.GetType("System.Windows.Forms.Form")
For Each t As Type In Me.GetType().Assembly.GetTypes()
If t.IsSubclassOf(formType) = True Then
Forms.Add(CType(Activator.CreateInstance(t), Form))
End If
Next
In VB2010 formType is always Nothing
So I dumped the formType line and simply modified your 'IF' statement to check the BaseType instead. Here is the New Version
Dim Forms As New List(Of Form)()
For Each t As Type In Me.GetType().Assembly.GetTypes()
If t.BaseType.Name = "Form" Then
Forms.Add(CType(Activator.CreateInstance(t), Form))
End If
Next
You need to either write a VS macro or an Addin.
In it, from a DTE or DTE2 instance, you can write:
Public Sub GetForms(ByVal host As DTE2)
Dim project As Project = host.ActiveDocument.ProjectItem.ContainingProject
For Each ce As CodeElement In project.CodeModel.CodeElements
If ce.Kind = vsCMElement.vsCMElementClass Then
Dim cl As CodeClass = CType(ce, CodeClass)
If cl.IsDerivedFrom("System.Windows.Forms) Then
'do something
End If
End If
Next
End Sub
2 options
I would load the actual project file into a XML reader. Then iterate all the nodes looking for all Form SubTypes and store the linked files in an array. If the name of file matches the name of the form class, you can create your FormsArray from that list. Otherwise you have to load each file and look for the public class definition of the file to get the list.
Using Reflection, examine the project using Assembly.GetTypes. Find all the System.Windows.Forms.Form Types and store them in a list. Then write out the Type.Name.