Create a dockable window in Visio

180 Views Asked by At

I created a Visio Add-In in Visual Studio 2022. I need create a dockable window, however i can't see a way for create it.

Right now the only way I found was via a window form like:

myCustomForm = new Form();
myCustomForm.Text = "My (not) Integrated Window."
myCustomForm.Show();

but I'm not satisfied.

I also followed (without success) this:

https://learn.microsoft.com/it-it/office/vba/api/Visio.Windows.Add

Does anyone have any suggestions?

2

There are 2 best solutions below

4
Nikolay On BEST ANSWER

The method you point out in the question is the correct one. That is, you should use Window.Windows.Add to add dockable windows in Visio. Please share the issue you are facing when trying to use it.

There is also a project template (installable via Visual Studio "extensions" menu) with dockable window out of the box I've created many years ago, bit it should still be functional (i.e. works fine with VS2022 and the latest Visio version), you can check it out here: https://marketplace.visualstudio.com/items?itemName=NikolayBelyh.ExtendedVisioAddinProject2017

If you decide to go with it, don't forget to give me a star :)

The source code is open on the GitHub (please check the above link for it)

2
Node defender On
  1. If you want to use winforms to open Visio directly, you can first drag a Button on Form1, then double-click the Button, and put the following code in the click event of the Button:

      private void button1_Click(object sender, EventArgs e) {
    
          Process jcam = new Process();
          jcam.StartInfo.FileName = @"C:\Users\Administrator\Desktop\Testnotepad.exe"; //The path to your Visio.exe
          ProcessStartInfo pr = jcam.StartInfo;
          pr.UseShellExecute = true;
          jcam.Start();
      }
    
  2. If you want Visio to be displayed on the Form, first drag a paint onto the Form and set its dock to full (that is, the largest rectangle in the middle). code show as below:

     /// <summary>
     /// Embed external exe
     /// </summary>
     public class EmbeddedExeTool
     {
         [DllImport("User32.dll", EntryPoint = "SetParent")]
         private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
         [DllImport("user32.dll", EntryPoint = "ShowWindow")]
         private static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
    
         [DllImport("user32.dll", SetLastError = true)]
         private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
    
         [DllImport("user32.dll")]
         private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
         [DllImport("user32.dll")]
         private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
         [DllImport("user32.dll", SetLastError = true)]
         private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
         IntPtr WindowHandle = IntPtr.Zero;
         private const int WS_THICKFRAME = 262144;
         private const int WS_BORDER = 8388608;
         private const int GWL_STYLE = -16;
         private const int WS_CAPTION = 0xC00000;
         private Process proApp = null;
         private Control ContainerControl = null;
    
         private const int WS_VISIBLE = 0x10000000;
         [DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
         private static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, int dwNewLong);
         [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
         private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, int dwNewLong);
    
         private IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong) {
             if (IntPtr.Size == 4)
             {
                 return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
             }
             return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
         }
         /// <summary>
         /// Load an external exe program into the program container
         /// </summary>
         /// <param name="control">To display the container control of the exe</param>
         /// <param name="exepath">The full absolute path of the exe</param>
         public void LoadEXE(Control control, string exepath) {
             ContainerControl = control;
             control.SizeChanged += Control_SizeChanged;
             ProcessStartInfo info = new ProcessStartInfo(exepath);
             info.WindowStyle = ProcessWindowStyle.Minimized;
             info.UseShellExecute = false;
             info.CreateNoWindow = false;
             proApp = Process.Start(info);
             Application.Idle += Application_Idle;
             EmbedProcess(proApp, control);
    
         }
         /// <summary>
         /// Load an external exe program into the program container
         /// </summary>
         /// <param name="form">The form to display the exe</param>
         /// <param name="exepath">The full absolute path of the exe</param>
         public void LoadEXE(Form form, string exepath) {
             ContainerControl = form;
             form.SizeChanged += Control_SizeChanged;
             proApp = new Process();
             proApp.StartInfo.UseShellExecute = false;
             proApp.StartInfo.CreateNoWindow = false;
             proApp.StartInfo.WindowStyle = ProcessWindowStyle.Minimized;
             proApp.StartInfo.FileName = exepath;
             proApp.StartInfo.Arguments = Process.GetCurrentProcess().Id.ToString();
             proApp.Start();
             Application.Idle += Application_Idle;
             EmbedProcess(proApp, form);
         }
         /// <summary>
         /// Make sure the application embeds this container
         /// </summary>
         /// <param name="sender"></param>
         /// <param name="e"></param>
         private void Application_Idle(object sender, EventArgs e) {
             if (this.proApp == null || this.proApp.HasExited)
             {
                 this.proApp = null;
                 Application.Idle -= Application_Idle;
                 return;
             }
             if (proApp.MainWindowHandle == IntPtr.Zero) return;
             Application.Idle -= Application_Idle;
             EmbedProcess(proApp, ContainerControl);
         }
         /// <summary>
         /// Embed the specified program into the specified control
         /// </summary>
         private void EmbedProcess(Process app, Control control) {
             // Get the main handle
             if (app == null || app.MainWindowHandle == IntPtr.Zero || control == null) return;
             try
             {
                 // Put it into this form
                 SetParent(app.MainWindowHandle, control.Handle);
                 // Remove border and whatnot               
                 SetWindowLong(new HandleRef(this, app.MainWindowHandle), GWL_STYLE, WS_VISIBLE);
                 ShowWindow(app.MainWindowHandle, (int)ProcessWindowStyle.Maximized);
                 MoveWindow(app.MainWindowHandle, 0, 0, control.Width, control.Height, true);
             }
             catch (Exception ex3)
             {
                 Console.WriteLine(ex3.Message);
             }
         }
    
    
         /// <summary>
         /// Embed container resize event
         /// </summary>
         private void Control_SizeChanged(object sender, EventArgs e) {
             if (proApp == null)
             {
                 return;
             }
    
             if (proApp.MainWindowHandle != IntPtr.Zero && ContainerControl != null)
             {
                 MoveWindow(proApp.MainWindowHandle, 0, 0, ContainerControl.Width, ContainerControl.Height, true);
             }
         }
     }
    
     private void button1_Click(object sender, EventArgs e) {
    
         EmbeddedExeTool exetool = new EmbeddedExeTool();
    
         exetool.LoadEXE(panel1, @"C:\Program Files\Google\Chrome\Application\chrome.exe");  //The specific path to embed the external exe
         //Process jcam = new Process();
         //jcam.StartInfo.FileName = @"C:\Users\Administrator\Desktop\Testnotepad.exe";  //The path to your Visio.exe
         //ProcessStartInfo pr = jcam.StartInfo;
         //pr.UseShellExecute = true;
         //jcam.Start();
     }
    
     /// <summary>
     /// The dock of the panel needs to be set to full
     /// </summary>
     /// <param name="sender"></param>
     /// <param name="e"></param>
     private void panel1_Paint(object sender, PaintEventArgs e) {
    
    
     }
    
     private void Form1_Load(object sender, EventArgs e) {
    
         EmbeddedExeTool exetool = new EmbeddedExeTool();
    
         exetool.LoadEXE(panel1, @"C:\Program Files\your.exe");  //The specific path to embed the external exe
    
     }