Answer:
You have to leverage the Windows API, but it's a little more convoluted than using FindWindow() because the name and class of the Revit Window are not static. Here are the steps:
1. get the Desktop window using Win32.GetDesktopWindow()
2. get the top most window using Win32.GetTopWindow() of the Desktop
3. iterate through the windows using Win32.GetWindow() until you find a window with the name "Autodesk Revit..." using Win32.GetWindowText()
4. HOWEVER, you're not done--there might be a Ghost class of the "Autodesk Revit..." window present so you have to check the class name and make sure it starts with "Afx:..." using Win32.RealGetWindowClass()--once that is verified, you've got the Revit window handle
5. Finally, associate your control with the Revit window handle using Win32.SetParent()
For some reason, I'm not allowed to attach the Win32 C# file, so here it is, but it's probably not formatted correctly:
using System;
using System.Runtime.InteropServices;
namespace com.cadalytic.specificad.autodesk.revit
{
///
/// Summary description for Win32.
///
public class Win32
{
// The WM_COMMAND message is sent when the user selects a command item from a menu,
// when a control sends a notification message to its parent window, or when an
// accelerator keystroke is translated.
public const int WM_COMMAND = 0x111;
public const int GW_HWNDNEXT = 2;
public const int GW_HWNDPREV = 3;
public const int GW_CHILD = 5;
// need these functions too...
[DllImport("User32.dll")]
public static extern int GetDesktopWindow();
[DllImport("User32.dll")]
public static extern int GetTopWindow(int hwndParent);
[DllImport("User32.dll")]
public static extern int GetWindow(int hwndSibling, int wFlag);
[DllImport("User32.dll")]
public static extern int GetWindowText(int hWnd, System.Text.StringBuilder text, int count);
[DllImport("User32.dll")]
public static extern UInt32 RealGetWindowClass(int hWnd, System.Text.StringBuilder text, UInt32 count);
[DllImport("User32.dll")]
public static extern int SetParent(int hWndChild, int hWndNewParent);
// The FindWindow function retrieves a handle to the top-level window whose class name
// and window name match the specified strings. This function does not search child windows.
// This function does not perform a case-sensitive search.
// [DllImport("User32.dll")]
// public static extern int FindWindow(string strClassName, string strWindowName);
// The FindWindowEx function retrieves a handle to a window whose class name
// and window name match the specified strings. The function searches child windows, beginning
// with the one following the specified child window. This function does not perform a case-sensitive search.
// [DllImport("User32.dll")]
// public static extern int FindWindowEx(int hwndParent, int hwndChildAfter, string strClassName, string strWindowName);
// The SendMessage function sends the specified message to a
// window or windows. It calls the window procedure for the specified
// window and does not return until the window procedure has processed the message.
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
[MarshalAs(UnmanagedType.LPStr)] string lParam); // second message parameter
[DllImport("User32.dll")]
public static extern Int32 SendMessage(
int hWnd, // handle to destination window
int Msg, // message
int wParam, // first message parameter
int lParam); // second message parameter
public Win32()
{
}
~Win32()
{
}
}
}
Remember to change the namespace to something that makes sense to you 🙂
Cheer, Chuck