VB6 to VB.Net - How do I make my COM Addin form Always On Top of Excel?

How do I make a VB.Net (Visual Studio 2010) form topmost to a specific parent window (an Hwnd)?

In VB.Net, Form.TopMost makes a form topmost to every window on the desktop.

I need my form to be topmost to only Excel as the form is part of an Excel COM Addin.

What's the best way to do this in .NET?

I will be targeting x64 once Office 2010 is released and I'm not sure if I can continue to use the 32-bit SetWindowLong API call as I used to do in VB6 as follows:

Private Declare Function SetWindowLong Lib "user32" _
    Alias "SetWindowLongA" _
   (ByVal hwnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long
...
'frm is a Form with a Public ParentWindow as Long property.
'xlApp contains a reference to Excel.Application

Public Sub AlwaysOnTopOfExcel (frm as Object, bAlwaysOnTopOfExcel as Boolean)

If bAlwaysOnTopOfExcel Then
  ' set parent to xlApp.Hwnd and save current
  frm.ParentWindow = SetWindowLong(frm.hwnd, GWW_HWNDPARENT, xlApp.Hwnd)
Else
  If frm.ParentWindow <> 0 Then
     ' restore original parent
     Call SetWindowLong(frm.hwnd, GWW_HWNDPARENT, frm.ParentWindow)
  End If
End If

End Sub

This is related to another question that I asked about convernting an Hwnd to an IWin32Window.

http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_25691843.html

I can make frm.TopMost do what I want if I set its parent window when I show it with frm.Show(Win32Handle) but I can't figure out how to get the form on top of Excel after it has been shown. I need to toggle the state of always on top based on an "Always On Top" checkbox that resides on the form itself.
ou81aswellAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

13598Commented:
You could try using         Me.ShowDialog( hwnd)   where hwnd is the excel hook. that would make it the parent.
ou81aswellAuthor Commented:
Thanks. My problem is that I can't assume the window was initialy shown with the parent window set without having to delve a lot deeper into the code.

Is there a way to set the parent window after the form has been shown? BTW If it makes any difference, these forms are non-modal.
Corey ScheichDeveloperCommented:
You can use windows apis if you don't have full control of the form.


Imports Microsoft.Office.Interop
Public Class Form1

    Public Declare Function SetParent Lib "User32.dll" (ByVal ChildHwnd As IntPtr, ByVal ParentHwnd As IntPtr) As Integer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim excel As New Excel.Application
        excel.Visible = True
        SetParent(Me.Handle, excel.Hwnd)
    End Sub
End Class

Open in new window

Starting with Angular 5

Learn the essential features and functions of the popular JavaScript framework for building mobile, desktop and web applications.

ou81aswellAuthor Commented:
Thanks. Can I call SetParent after the form has been shown?

Does the declare for SetParent have to be changed for x64?
Corey ScheichDeveloperCommented:
You can call the setparent any time after both form's windows handles have been created.  

No on x64 when running as x64 windows uses C:\windows\System32  which are all the x64 dlls and when running as x86 it uses C:\windows\SysWOW64 which are all the x86 dlls so it shouldn't be a problem either way.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
13598Commented:
You can have two forms in your app. The initial form which doesn't have to show where on load you retrrieve the Excel hwnd and then open the 'real' form with the Showdialog.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.