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.
Related
I have made a custom task pane using a user control.
Every time I resize it I raise a method called SuspendDrawing the reason I do this is because the buttons on my custom task pane flicker when I resize it therefore I need to suspend it. I add these buttons using the designer
This works like a treat but then I need to call a method called ResumeDrawing when the user stops resizing however I don't know what event I should use to call the ResumeDrawing method as there is no ResizeEnd event for a user control.
Any suggestions would be appreciated as I'm out of ideas.
My code is as follows
Public Property Resizing As Boolean
<DllImport("user32.dll", EntryPoint:="SendMessageA", ExactSpelling:=True, CharSet:=CharSet.Ansi, SetLastError:=True)>
Private Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
End Function
Public Shared Sub SuspendDrawing(ByVal target As Control)
SendMessage(target.Handle, WM_SETREDRAW, 0, 0)
End Sub
Public Shared Sub ResumeDrawing(ByVal target As Control)
ResumeDrawing(target, True)
End Sub
Public Shared Sub ResumeDrawing(ByVal target As Control, ByVal redraw As Boolean)
SendMessage(target.Handle, WM_SETREDRAW, 1, 0)
If redraw Then
target.Refresh()
End If
End Sub
Private Sub SideBarPowerPoint_Resize(sender As Object, e As EventArgs) Handles MyBase.Resize
SuspendDrawing(Me)
End Sub
My Custom Task Pane
Dim taskPaneView = New PowerPointCommon.SideBarPowerPoint
sideBarTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(taskPaneView, " ")
If sideBarTaskPane.Visible = True Then
sideBarTaskPane.Visible = False
End If
sideBarTaskPane.Visible = True
sideBarTaskPane.DockPosition = Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionRight
sideBarTaskPane.Width = 100
I have a vb.net application which will be minimized to task bar or notification area. Is there any way for me to maximize/focus on that application when user presses a key (even if the user is using any other application).
Tried windows hot key but doesn't focus the app when it is already open.Please help
You require global hotkeys. First, add these functions to your application.
Private Declare Function GetKeyPress Lib "user32" Alias "GetAsyncKeyState" (ByVal key As Integer) As Integer
<DllImport("user32.dll", EntryPoint:="FindWindow", SetLastError:=True)> _
Private Shared Function FindWindow(lpClassName As String, lpWindowName As String) As IntPtr
End Function
<DllImport("user32.dll")> _
Private Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Boolean
End Function
<DllImport("user32.dll")> _
Private Shared Function SetForegroundWindow(hWnd As IntPtr) As Integer
End Function
Next, add a Timer and in its Timer.Tick Event, use this function like this:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
If GetKeyPress(Keys.LControlKey) And GetKeyPress(Keys.A) Then
Dim Handle As IntPtr = Process.GetProcessById(2916).MainWindowHandle
ShowWindow(Handle, 9)
SetForegroundWindow(Handle)
End If
End Sub
Set the Timer Interval to 150 to avoid repeated keypresses and make sure to enable the timer in the Form Load event.
I am working in vb with visual studio 2010.
The app AnyOrder is no longer supported and I am trying to make an app where our users can type in info and then have the info populate into AnyOrder (and also other sites - they have to populate a lot of redundant info) but I am having no luck at all getting the child windows of any order to populate once the data is in the VB window app.
I can get the parent window handle just fine but can't seem to get a child window handle to save my life. I can't even get the first level down and the blanks that I will need to populate are great grand-children of the parent window.
It won't let me post a screencap of the spy++ since I just signed up and don't have the 10 rep but here is a link to the capture.
Thank you in advance for any assistance that you can provide.
Figured out the answer somehow.
#Region "functions"
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Int32
Public Delegate Function EnumWindowProcess(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
<DllImport("User32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function EnumChildWindows(ByVal WindowHandle As IntPtr, ByVal Callback As EnumWindowProcess, ByVal lParam As IntPtr) As Boolean
End Function
Private Shared Function EnumWindow(ByVal Handle As IntPtr, ByVal Parameter As IntPtr) As Boolean
Dim ChildrenList As List(Of IntPtr) = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
ChildrenList = CType(GCHandle.FromIntPtr(Parameter).Target, Global.System.Collections.Generic.List(Of Global.System.IntPtr))
If ChildrenList Is Nothing Then Throw New Exception("GCHandle Target could not be cast as List(Of IntPtr)")
ChildrenList.Add(Handle)
Return True
End Function
Private Shared Function GetChildWindows(ByVal ParentHandle As IntPtr) As IntPtr()
Dim ListHandle As GCHandle = GCHandle.Alloc(ChildrenList)
Try
EnumChildWindows(ParentHandle, AddressOf EnumWindow, GCHandle.ToIntPtr(ListHandle))
Finally
If ListHandle.IsAllocated Then ListHandle.Free()
End Try
Return ChildrenList.ToArray
End Function
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
iParentHandle = FindWindow(vbNullString, AOParentName)
GetChildWindows(FindWindow(vbNullString, AOParentName))
Dim Childlist As String = String.Join(". ", ChildrenList)
MsgBox("list of child windows: " & Childlist)
End Sub
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.
I used to change the Form shape in VB 6.0 using the following code:
Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long, ByVal X3 As Long, ByVal Y3 As Long) As Long
Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long
Private Sub MakeRoundObject(objObject As Object, Value As Long)
Static lngHeight, lngLong, lngReturn, lngWidth As Long
lngWidth = objObject.Width / Screen.TwipsPerPixelX
lngHeight = objObject.Height / Screen.TwipsPerPixelY
SetWindowRgn objObject.hWnd, CreateRoundRectRgn(10, 50, lngWidth, lngHeight, Value + 10, Value), True
End Sub
Private Sub Form_Load()
Call MakeRoundObject(Form1, 50)
End Sub
In the same way I used VB.NET code as follows:
Imports Microsoft.VisualBasic.Compatibility
Public Class Form1
Private Declare Function CreateRoundRectRgn Lib "gdi32" (ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer, ByVal X3 As Integer, ByVal Y3 As Integer) As Integer
Private Declare Function ReleaseCapture Lib "user32" () As Integer
Private Declare Function SetWindowRgn Lib "user32" (ByVal hWnd As Integer, ByVal hRgn As Integer, ByVal bRedraw As Boolean) As Integer
Private Sub MakeRoundObject(ByRef objObject As Object, ByRef Value As Integer)
Static lngLong, lngHeight, lngReturn As Object
Static lngWidth As Integer
lngWidth = objObject.Width / VB6.TwipsPerPixelX
lngHeight = objObject.Height / VB6.TwipsPerPixelY
SetWindowRgn(objObject.hWnd, CreateRoundRectRgn(0, 0, lngWidth, lngHeight, Value, Value), True)
End Sub
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
MakeRoundObject(Me, 20)
End Sub
End Class
But in the latter case, I receive an error message - "Public member 'hWnd' on type 'Form1' not found."
What I do?
You don't have to use P/Invoke to do this. The Form.Region property was designed for this. A simple example:
Public Class Form1
Public Sub New()
InitializeComponent()
Dim path As New Drawing2D.GraphicsPath()
path.AddEllipse(0, 0, Me.Width, Me.Height)
Me.Region = New Region(path)
End Sub
End Class
The property is Handle now, not hWnd.
If you turned option strict on then the compiler would have told you hWnd didn't exist anymore. Also in .NET you should use ByVal not ByRef unless you NEED the ability for the caller to see changes made to that parameter, there is no longer a performance penalty for passing ByVal. You should also change the types of your parameters for the MakeRoundObject Sub to be correct datatypes instead of Object.
Maybe another way of getting a non-rectangular form shape you might not have thought about: set a transparent background color on the form and work with that.
I often do the following for things like About screens in .NET: set background color to something not used in the actual form (like deep purple) and use GDI+ to draw a filled shape inside the form boundaries in the color you want it to have.
Not actually changing the form region from a rectangle to something else, but it does work. And is often easier with "disjoined shapes" for the form.
Another way is to set TransparencyKey to a color like Magenta or any other not used on the form. Then set a BackgroundImage property to some image on which magenta color will represent transparent areas.
With that procedure, you can get any shape with minimum effort.