I want to run an app inside a panel or something within my applicaiton. It's an emulator front end. You browse through games, then when you select one it launches the emulator. I found the following code and adapted it to my project
Public Class Form1
Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const WM_SYSCOMMAND As Integer = 274
Private Const SC_MAXIMIZE As Integer = 61488
Dim proc As Process
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
proc = Process.Start("C:\WINDOWS\notepad.exe")
proc.WaitForInputIdle()
SetParent(proc.MainWindowHandle, Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
End Sub
End Class
If I try it with notepad, or even zsnesw.exe it works okay, but if I try to pass some parameters to zsnesw it kind of freaks out and I have to reboot my computer (I can't switch applications or even open the task manager).
Also, even when it does work, the start menu pops up like I have switched to another app. This is kind of what I was trying to avoid in the first place as my app is full screen.
I got it working!
Dim proc As Process
proc = Process.Start(emuPath + "zsnesw", "-m """ + selGame.romPath + """")
proc.WaitForInputIdle()
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
Me.BringToFront()
Problem 1: I was passing the arguments incorrectly. I was trying to use Process.StartInfo.Arguments. Didn't work for some reason. Using a comma in Process.Start works fine.
Problem 2: I added Me.BringToFront() to hide the start menu again.
Use Thread.Sleep
;)
'Run Calc application inside Panel2 control
Dim proc As Process
proc = Process.Start("Calc.exe")
proc.WaitForInputIdle()
Thread.Sleep(1000)
SetParent(proc.MainWindowHandle, Me.Panel2.Handle)
Thread.Sleep(1000)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
Related
This question already has an answer here:
How to make a window active in vb.net
(1 answer)
Closed 5 years ago.
I'm writing a simple Visual Basic app to help me launch global hotkeys by the press of a taskbar button.
To do this, I basically set the app to minimize itself back to the taskbar. I then want to activate the taskbar itself (not the previously active program) so I can use SendKeys to do these keypresses. In my test, the keypresses get registered. Its just that I can't seem to find out how to actually activate the taskbar from my program.
If I use AppActivate, I need the processID or the window title.
So it seems best to use Windows API's to do it, but I'm not getting the result I'm after either and I must be doing something wrong.
Here's my code:
Public Class Form1
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Sub Form1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus
Me.WindowState = FormWindowState.Minimized
Dim intReturn As Integer = FindWindow("Shell_traywnd", "")
AppActivate(intReturn)
SendKeys.Send("%1")
MsgBox("test")
End Sub
End Class
The error I'm getting is that there's no process by this ID running.
FindWindow will return a hwnd handle, not a processID. You will need to use the function SetForegroundWindow to activate it.
Your code becomes as follows:
Public Class Form1
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Declare Function SetForegroundWindow Lib "user32.dll" (ByVal hwnd As Integer) As Integer
Private Sub Form1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.GotFocus
Me.WindowState = FormWindowState.Minimized
Dim intReturn As Integer = FindWindow("Shell_traywnd", "")
SetForegroundWindow(intReturn)
SendKeys.Send("%1")
MsgBox("test")
End Sub
End Class
I'm calling a vb.net exe from a program in java, and i want it to stay behind all of the already opened programs.
I read that you can kinda bring to front with TopMost set to true , but i find no way to put it in the back.
There's some workarounds, like setvisible=false the previous form and setting to true after that, but that isn't quite good with my application. Thank you!
Calling the form's SendToBack (Inherited from Control) method from the Shown event handler is the key.
Calling it from load for example, won't do anything since the window isn't "ready" yet anyway.
Private Sub Form1_Shown(sender As System.Object, e As System.EventArgs) Handles MyBase.Shown
SendToBack()
End Sub
Alternatively, use the SetWindowPos native function as defined in User32.dll.
Imports System.Runtime.InteropServices
...
'Signature source: http://pinvoke.net/default.aspx/user32/SetWindowPos.html
<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Boolean
End Function
...
Private Sub Form1_Shown(sender As System.Object, e As System.EventArgs) Handles MyBase.Shown
SetWindowPos(Handle, New IntPtr(1), Location.X, Location.Y, Width, Height, 0)
End Sub
The only thing I changed from the signature provided by PInvoke.net was that I changed the "uFlags" parameter type from "SetWindowPosFlags" (Also defined on the PInvoke.net) to an Integer.
Through a variety of reasons I am forced to use the incredibly frustrating vb.net DateTimePicker control, in the even more frustrating Citrix client, for an application. This isn't actually my main problem, the problem is, I have to make the datetimepicker automatically drop down when the user presses any button (besides tab, escape, etc).
I really need to get this to work, the users won't really take no for an answer. I would prefer to not get a new custom control, but if one exists that is easy to implement (and doesn't allow the user to type in the date) then I would be open to it.
This is what I've done so far, it works perfectly well outside of Citrix, but when it triggers in Citrix the DateTimePicker doesn't refresh when the user navigates around it. Meaning the square is over the current date, and the user can press arrow keys to their heart's content, but it never shows this to the user. (Even if the user uses the mouse to drop it down.)
Again outside of Citrix this works fine.
'Used to manually dropdown datetimepickers
Private dateTimePickerControl As DateTimePicker
Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Public Sub DropDownCalendar()
Const WM_LBUTTONDOWN As Int32 = &H201
Const WM_LBUTTONUP As Int32 = &H202
Dim x As Integer = Me.dateTimePickerControl.Width - 10
Dim y As Integer = CInt(Me.dateTimePickerControl.Height / 2)
Dim lParam As Integer = x + y * &H10000
'click down, and show the calendar
SendMessage(Me.dateTimePickerControl.Handle, WM_LBUTTONDOWN, CType(1, IntPtr), CType(lParam, IntPtr))
'Click-up, and activate the calendar (without this the calendar is shown, but is not active, and doesn't work as expected)
SendMessage(Me.dateTimePickerControl.Handle, WM_LBUTTONUP, CType(1, IntPtr), CType(lParam, IntPtr))
End Sub
Private Sub dteDate_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles dteDate.KeyDown
Try
If e.KeyCode = Keys.Delete Then
sender.customFormat = " "
e.Handled = True
ElseIf e.KeyCode <> Keys.Tab And e.KeyCode <> Keys.ShiftKey Then
sender.focus()
dateTimePickerControl = sender
DropDownCalendar()
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I'm completely at a loss. Is such a thing even possible in Citrix? In a previous attempt I used SendKeys("{F4}") which worked fine outside of Citrix, but in Citrix would just drop down a frozen white background.
Does anyone have any ideas that could help me out here?
Sometimes we've had to add DoEvents when sending messages like this in our VB app hosted on Citrix. See if this works for you:
Private Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
Private Sub DropDownCalendar(ctl As DateTimePicker)
Const WM_LBUTTONDOWN = &H201
Const WM_LBUTTONUP = &H202
If ctl Is Nothing Then
Exit Sub
End If
ctl.Select()
Dim lParam = (ctl.Width - 10) + (CInt(ctl.Height / 2) * &H10000)
'click down, and show the calendar
SendMessage(ctl.Handle, WM_LBUTTONDOWN, CType(1, IntPtr), CType(lParam, IntPtr))
Application.DoEvents()
'Click-up, and activate the calendar (without this the calendar is shown, but is not active, and doesn't work as expected)
SendMessage(ctl.Handle, WM_LBUTTONUP, CType(1, IntPtr), CType(lParam, IntPtr))
End Sub
Private Sub dteDate_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles dteDate.KeyDown
Try
If e.KeyCode = Keys.Delete Then
CType(sender, DateTimePicker).CustomFormat = " "
e.Handled = True
ElseIf e.KeyCode <> Keys.Tab And e.KeyCode <> Keys.ShiftKey Then
DropDownCalendar(CType(sender, DateTimePicker))
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
I have a bunch of related VB.NET console applications I've written for admin/management functions.
I now want to bring them together under a single Windows Forms application that works as a launcher, but instead of launching the apps as seperate programs, I want to embed the apps in the windows forms app, e.g. have a scrollable list of icons down the left hand side - clicking on one will launch the associated .exe in the right hand pane of the windows forms app.
For now I have a simple single form application with one panel, so I can test out if what I want to do is possible.
Having read around MSDN and SO, I've found other posts about this but none that seem to do what I want.
I don't want to intercept stin/stdout/stderr streams and attempt to emulate the console application, I want to actually run the compiled exe (which I can achieve) but have it run inside the windows form (which I can't achieve, it launches as a seperate process).
The main code for Form1 that I have right now is:
Public Class Form1
Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const WM_SYSCOMMAND As Integer = 274
Private Const SC_MAXIMIZE As Integer = 61488
Dim proc As Process
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
proc = Process.Start("\\fileserver\datashare\path\WIN_MGR.exe")
proc.WaitForInputIdle()
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
End Sub
End Class
Anyone able to put me in the right direction to actually run the .exe application windowed within the windows form?
Based on the comments, change your Form_Load as follows:
proc = Process.Start("\\fileserver\datashare\path\WIN_MGR.exe")
Thread.Sleep(1000) 'Possibly replace this with polling MainWindowHandle
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
WaitForInputIdle fails because the console application does not have a graphical interface. For a more accurate delay, Idle_Mind suggests polling MainWindowHandle in a while-loop until it returns a value other than IntPtr.Zero.
I have an application written in VB.net running on Windows 7 that opens a word document and inserts some values into it. This works fine, but on my client's machines(development works fine) Word is opening up behind my application. I've tried maximizing the document in code, but it's still opening behind my application on the client machines. Does anyone have any idea how I can fix this?
Things I've already tried:
maximizing word in my application
giving focus to word in my application
I've made sure the patches are up to date.
I've performed a repair on Office
Have you tried minimizing the application, as opposed to maximizing the document?
Me.WindowState = FormWindowState.Minimized will minimize the form that calls it (this is assuming that you are using a forms application).
You might need to bring Word to the forefront. This is a bit different from bringing a form in your app to the top.
You'll need to have a reference to two APIs, FindWindow and SetWindowPos - the first one can find the windows handle for another application that is running, and the second sends a message to the operating system to give an application focus (it uses the windows handle from FindWindow)
Here's some sample code.
Public Class Form1
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function FindWindow(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
End Function
<Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As Integer) As Boolean
End Function
Private Shared ReadOnly HWND_TOPMOST As New IntPtr(-1)
Private Shared ReadOnly HWND_NOTOPMOST As New IntPtr(-2)
Private Const SWP_NOSIZE As Integer = &H1
Private Const SWP_NOMOVE As Integer = &H2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Shell("calc.exe")
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim myHandle As IntPtr = FindWindow(Nothing, "Calculator")
SetWindowPos(myHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
SetWindowPos(myHandle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
End Sub
End Class
Clicking the first button will instantiate a copy of Calculator, the second button will make it topmost, then set it back to normal... so it will still be the top form, but the user can activate other windows as well.