I have a list of files displayed in a listbox.
when I select a file from the listbox i want the file to load into a panel on my form.
i.e. if its a word document word will open in the panel, if its a pdf reader wil open into the panel.
I can get the files to load externally using
Dim ProcStart As New ProcessStartInfo
ProcStart.FileName = ListBox1.SelectedItem
Process.Start(ProcStart)
however i am unsure of how to get it to then dock in my panel. I tried
Me.Panel1.Controls.Add(ProcStart)
but this is obviously wrong as I can't add a process as a control.
I did a bit of googleing and have tried to do it this way
<DllImport("user32.dll")>
Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As UInteger
End Function
Private Sub ListBox1_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles ListBox1.SelectedIndexChanged
Dim proc As Process
Dim AppPath As String
AppPath = lstDocs & ListBox1.SelectedItem
proc = Process.Start(AppPath)
proc.WaitForInputIdle()
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
End Sub
but the word application still opens outside my program and not in the panel!!
Any ideas? and thanks for looking!
Have you tried adding a button with code behind it to start the process?
'This is how i would start the process
this would be in your code that starts the control ( inserting )
Dim dep1 As (INSERT YOUR EVENT HERE)= New (INSERT YOUR EVENT HERE)
AddHandler dep.OnChange, AddressOf dep_onchange
the actuall button
Private Sub dep_onchange1(ByVal sender As System.Object, ByVal e As System.EventArgs)
' this event is run asynchronously so you will need to invoke to run on the UI thread(if required)
If Me.InvokeRequired Then
lbnoes.BeginInvoke(New MethodInvoker(AddressOf GetNoes))
Else
GetNoes()
End If
End Sub
Related
I have been able to run an external program using the following code.
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("user32.dll")> Public Shared Function SetParent(ByVal hwndChild As IntPtr, ByVal hwndNewParent As IntPtr) As Integer
End Function
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("notepad.exe")
PRO.Start()
Do Until PRO.WaitForInputIdle = True
'Nothing
Loop
SetParent(PRO.MainWindowHandle, Me.Handle)
PRO.Dispose()
End Sub
This works fine..... (for notepad that is)
However If I swich notepad for my own vb.net application it fails to launch that aplication inside the form but rather runs it outside of the form. I thought that the application I am trying to launch might of had somthing in it so I created a new application with nothing in it (as bare as I could get it) and run that instead of notepad but it also fails to launch within its "parent" form but rather it also triggers outside of the "parent" form insted?
Could someone please help me fix this?
You just need to wait a tiny bit longer for the MainWindowHandle property to be populated.
Here's a kludge that'll do it:
Private Async Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("C:\Users\mikes\Desktop\temp.exe")
PRO.Start()
Await Task.Run(Sub()
PRO.WaitForInputIdle()
While PRO.MainWindowHandle.Equals(IntPtr.Zero)
Threading.Thread.Sleep(10)
End While
End Sub)
SetParent(PRO.MainWindowHandle, Me.Handle)
End Sub
If you want a ten second fail-safe, and exceptions caught, then you could change it up to:
Private Async Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
Try
Dim PRO As Process = New Process
PRO.StartInfo.FileName = ("C:\Users\mikes\Desktop\temp.exe")
PRO.Start()
Await Task.Run(Sub()
Dim timeout As DateTime = DateTime.Now.AddSeconds(10)
While timeout > DateTime.Now AndAlso PRO.MainWindowHandle.Equals(IntPtr.Zero)
Threading.Thread.Sleep(10)
End While
End Sub)
If (Not PRO.MainWindowHandle.Equals(IntPtr.Zero)) Then
SetParent(PRO.MainWindowHandle, Me.Handle)
Else
MessageBox.Show("Timed out waiting for main window handle.", "Failed to Launch External Application")
End If
Catch ex As Exception
MessageBox.Show(ex.ToString, "Failed to Launch External Application")
End Try
End Sub
Here is my current code for the button click procedure. My module is called Summary.vb, and the modal form I am trying to open is frmSummary. The Form opens but nothing in my module is executed.
Private Sub btnSummary_Click(sender As Object, e As EventArgs) Handles btnSummary.Click
Dim frmSum As New frmSummary
Dim intScoreType As Integer = 1
frmSum.ShowDialog()
DisplaySummary(1, intSAT, Max_Size)
End Sub
And here is the first part of my module:
Sub DisplaySummary(ByVal intScoreType As Integer, ByVal intScores() As Integer, ByVal Max_Size As Integer)
Public Class Form1
Dim Iclick, submit
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Iclick.InvokeMember("click")
With WebBrowser1.Document
For l_index As Integer = 0 To ListBox1.Items.Count - 1
Dim l_text As String = CStr(ListBox1.Items(l_index))
.All("input").InnerText = l_text
System.Threading.Thread.Sleep(5000)
Next
'.All("input").InnerText = "http://wordpress.com"
End With
submit.InvokeMember("click")
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
WebBrowser1.Navigate("http://whatwpthemeisthat.com")
End Sub
Private Sub WebBrowser1_DocumentCompleted(ByVal sender As System.Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
Iclick = WebBrowser1.Document.GetElementById("input")
submit = WebBrowser1.Document.GetElementById("check")
End Sub
End Class
This is my code so far I have a ListBox with URLs I want to check using web browser which theme are they running (if they are wordpress) but the program seems to be bugged when I click START it is NOT responding, until the last element. It has to do something with the system.threading.thread.sleep line but I don't know what am I doing wrong? Thanks.
That's excactly what the Thread.Sleep() method is for. It freezes for 5 seconds.
Also you are replacing the input each time the For loop repeats. So it replaces, waits 5 seconds, replaces, waits 5 sec... and so on.
I guess you are trying to click the submit button for each of the elements, but that's not what you are doing. You have to hit the submit button each time the text has changed. However you really can't be sure about the loading time of the page.
I'd suggest you to place the submit-part inside the loop, then wait, then go into the next iteration. Maybe you could even try to run the website multiple times, one for each listbox item and then apply the right text to the controls in the webpage, hit the button and receive your result.
EDIT: Your best bet for the Thread.Sleep() would be creating a new thread in which you place the loop. This thread can be paused for 5 seconds, and your application will still respond. This is how you create one:
Imports System.Threading.Thread
Dim myThread as Thread
'//..........
'//Button1 is clicked ->
myThread = new Thread (AddressOf myLoop)
myThread.start()
'//..........
Private Sub myLoop ()
'// Loop goes here...
'Sleeping here will only affect the thread that runs this sub. Your form will still be available
End Sub
Hey all i am in need of some help getting my code working correctly like i am needing it to. Below is my code that when the user click on the textbox, it pops up a keyboard where they can click on any letter and it will type that letter into the textbox. Problem being is i can not seem to get the name of the text box to return so that it knows where to send the letters to.
Order in firing is:
TextBox1_MouseDown
keyboardOrPad.runKeyboardOrPad
kbOrPad.keyboardPadType
ClickLetters
Form1.putIntoTextBox
Form1
Private Sub TextBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
Call keyboardOrPad.runKeyboardOrPad("SHOW") 'Just shows the keyboard
Call kbOrPad.keyboardPadType("PAD", TextBox1)
End Sub
Public Sub putIntoTextBox(ByRef what2Put As String, ByRef whatBox As TextBox)
whatBox.Text = what2Put '<-- has error Object reference not set to an instance of an object. for the whatBox.text
End Sub
kbOrPad class
Dim theBoxName As TextBox = Nothing
Public Sub keyboardPadType(ByRef whatType As String, ByRef boxName As TextBox)
theBoxName = boxName '<-- shows nothing here
Dim intX As Short = 1
If whatType = "PAD" Then
Do Until intX = 30
Dim theButton() As Control = Controls.Find("Button" & intX, True)
theButton(0).Enabled = False
intX += 1
Loop
ElseIf whatType = "KEYB" Then
End If
End Sub
Private Sub ClickLetters(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim btn As Button = CType(sender, Button)
If btn.Text = "Backspace" Then
Else
Call Form1.putIntoTextBox(btn.Text, theBoxName) 'theBoxName taken from keyboardPadType
End If
End Sub
Some visuals for you:
Pastebin code: http://pastebin.com/4ReEnJB0
make sure that theBoxName is a Module scoped variable, then I would populate it like this giving you the flexibility of implementing a shared TextBox MouseDown Handler:
Private Sub TextBox1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
Dim tb As TextBox = CType(sender, TextBox)
Call keyboardPadType("PAD", tb)
End Sub
Try something like this
Public Class Form1
Dim myKborPad As New kbOrPad
Private Sub TextBox1_MouseDown(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
Dim tb As TextBox = CType(sender, TextBox)
Call myKborPad.keyboardPadType("PAD", tb)
End Sub
Edit Based on your PasteBin code.
I noticed you already have an instance of your keyboardPadType declared in your Module, use that instead of what I said earlier. That code should look like:
remove:
Dim myKborPad As New kbOrPad
and use the theKbOrPad that you created in your module like this:
Private Sub TextBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextBox1.MouseDown
Dim tb As TextBox = CType(sender, TextBox)
Call keyboardOrPad.runKeyboardOrPad("SHOW")
Call theKbOrPad.keyboardPadType("PAD", tb)
'Call kbOrPad.keyboardPadType("PAD", tb)
End Sub
Also about the current error your are getting, you are trying to use the default instance of your Form1 , it isn't the actual Form that you are running, you can code around this by making the method you are trying to use as shared. Like this:
Public Shared Sub putIntoTextBox(ByRef what2Put As String, ByRef whatBox As TextBox)
whatBox.Text = what2Put
End Sub
But however I would actually prefer to put it into your Module like this
Public Sub putIntoTextBox(ByRef what2Put As String, ByRef whatBox As TextBox)
whatBox.Text = what2Put
End Sub
and call it like this
Call putIntoTextBox(btn.Text, theBoxName)
after making above changes your code worked.
First, you should replace the ByRef with ByVal (anytime you don't know whether you should use one or the other, use ByVal).
Secondly, I believe you don't need the method, putIntoTextBox, I think you should be able to do that directly (might be threading problems that prevent it, but I don't think that's likely based on your description). You don't show where Form1 is set (or even if it is), and that's another potential problem.
Finally, the better way to call back into the other class is to use a delegate/lambada.
(I know, no code, but you don't provide enough context for a working response, so I'm just giving text).
ok here is the scenario.
1. i've create a project that has 1 form named form1.exe
2. i've also create a project that has 1 MDI form.
in this MDI Form. i'would like to call "form1.exe" act like / behave like MDI Form child.
i've tried using this code :
Public Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndParent As IntPtr) As IntPtr
End Function
Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripMenuItem.Click, NewToolStripButton.Click, NewWindowToolStripMenuItem.Click
Dim myProcess As Process = New Process()
myProcess.StartInfo.FileName = "D:\tesVB.exe"
myProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal
myProcess.Start()
myProcess.WaitForInputIdle()
SetParent(myProcess.MainWindowHandle, Me.Handle)
myProcess.WaitForExit()
End Sub
Above code is worked but that new child form(form1.exe) doesn't act like it should be! When i maximized or minimized it. it don't act like MDI Child Form.
Can anyone give me another better example code ? thx before.
hahaha.... found it my self. hope this solution would be good for others.
Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripMenuItem.Click, NewToolStripButton.Click, NewWindowToolStripMenuItem.Click
Dim eAssembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom("D:\form1.exe")
Dim eForm As Form = eAssembly.CreateInstance("form1.Form1", True)
Me.AddOwnedForm(eForm)
eForm.MdiParent = Me
eForm.Show()
End Sub
Private Sub ShowNewForm(ByVal sender As Object, ByVal e As EventArgs) Handles NewToolStripMenuItem.Click, NewToolStripButton.Click, NewWindowToolStripMenuItem.Click
Dim eAssembly As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom("D:\form1.exe")
Dim eForm As Form = eAssembly.CreateInstance("form1.Form1", True)
Me.AddOwnedForm(eForm)
eForm.MdiParent = Me
eForm.Show()
End Sub
Runtime error
eform is a form and eAssembly.CreateInstance("form1.Form1", True) returns an object