Bring VB.Net window on top of all windows

manjulapra picture manjulapra · Dec 17, 2011 · Viewed 18.1k times · Source

I have a window which should stay on top of Power point slide shows. So it should be on top of all the windows. I did this easily using VB 6 using Lib "user32", but it seems to be difficut with VB.net.

Me.TopMost = True

This does not seem to work as it works only within the program.

  Private Declare Function BringWindowToTop Lib "user32" Alias "BringWindowToTop" (ByVal hwnd As Long) As Long
    Private Sub frmTmr_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
        BringWindowToTop(Me.Handle)
    End Sub

This also gives a error! Any help is greatly appreciated! Thanks in advance,

Regards

Manjula

Answer

Cody Gray picture Cody Gray · Dec 17, 2011

If you want a window in your application to always appear on top of a window of a different application, then the BringWindowToTop function is definitely not what you want. For starters, as you've noticed, you have to repeatedly call the function using a timer. That should be your first clue that it's the wrong API. Another problem is that it's only bringing your window to the top of the Z order for its process, not all of the other processes running on the system. As the documentation explains,

Calling this function is similar to calling the SetWindowPos function to change a window's position in the Z order. BringWindowToTop does not make a window a top-level window.

That last sentence should indicate that there is a better way. Windows has built-in support for top-level windows (i.e., those that should always appear on top of other windows): these are called top-most windows. This is exactly what you want. Top-most windows always appear above non-topmost windows.

Raymond Chen attempts to explain some of the confusion on his blog. Note that in this case, HWND_TOP is equivalent to BringWindowToTop. Instead, you want HWND_TOPMOST.

The simplest way of making a window top-most is to specify the WS_EX_TOPMOST flag when you create the window. The .NET Framework hides most of the window creation work behind the scenes, but you can customize the parameters when you need to by overriding the CreateParams property of your form class.

Here's some sample code to make a form always top-most:

Protected Overrides ReadOnly Property CreateParams() As CreateParams
    Get
        Const WS_EX_TOPMOST As Integer = &H00000008

        Dim cp As CreateParams = MyBase.CreateParams
        cp.ExStyle = cp.ExStyle Or WS_EX_TOPMOST
        Return cp
    End Get
End Property

This won't work if you want to toggle the top-most state of the window at run-time. To do that, you're going to have to P/Invoke the SetWindowPos function. P/Invoke is similar to what you used to do in VB6 with the Declare statement, but the semantics have changed slightly for the .NET world—that's why you can't use your old VB6 Declare statements in VB.NET.

Here's what that code might look like for VB.NET:

<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 Const SWP_NOSIZE As Integer = &H1
Private Const SWP_NOMOVE As Integer = &H2

Private Shared ReadOnly HWND_TOPMOST As New IntPtr(-1)
Private Shared ReadOnly HWND_NOTOPMOST As New IntPtr(-2)

Public Function MakeTopMost()
    SetWindowPos(Me.Handle(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
End Function

Public Function MakeNormal()
    SetWindowPos(Me.Handle(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
End Function