表单一旦丢失就无法获得焦点

发布于 2024-09-18 18:50:18 字数 804 浏览 2 评论 0原文

我已经为 Visual Studio 2008 创建了一个加载项,可以使用以下命令打开一个表单 Form1.Show(this);

如果(在表单打开时)用户打开/关闭 Visual Studio 对话框(例如程序集信息),则用户无法将注意力重新集中在由插件。

我是否缺少某些内容来允许用户返回表单?如果我使用 Form1.ShowDialog(this),则不会发生这种情况,但我希望用户在自定义表单打开时看到程序集信息。

该加载项使用

public System.IntPtr Handle
{
    get
    {
        return new System.IntPtr(_applicationObject.MainWindow.HWnd);
    }
}

编辑实现 IWin32Window:重现步骤

  • 创建 Visual Studio 外接程序项目
  • 添加对 System.Windows.Forms 的引用
  • 将以下内容添加到 public void Exec(...)

    System.Windows.Forms.Form f = new System.Windows.Forms.Form();
    f.Show();
    

  • 运行加载项,并在启动的 Visual Studio 实例中打开项目
  • 打开项目属性,转到“应用程序”选项卡,打开“程序集信息”,然后将其关闭。
  • I have created an Add-In for Visual Studio 2008 that opens up a form, using
    Form1.Show(this);

    If (while the form is open) the user opens/closes a Visual Studio dialog box, (such as Assembly Information) then the user cannot focus back on the form created by the addin.

    Is there something I'm missing to allow the user to return to the form? This doesn't occur if I use Form1.ShowDialog(this), but I would like the user to see the Assembly Information while my custom form is open.

    The add-in implements IWin32Window using

    public System.IntPtr Handle
    {
        get
        {
            return new System.IntPtr(_applicationObject.MainWindow.HWnd);
        }
    }
    

    EDIT: Steps to reproduce

  • Create a visual studio add-in project
  • Add a reference to System.Windows.Forms
  • Add the following to public void Exec(...)

    System.Windows.Forms.Form f = new System.Windows.Forms.Form();
    f.Show();
    
  • Run add-in, and open a project in the launched instance of visual studio
  • Open the project properties, go to the Application tab, open Assembly Information, and close it.
  • 如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

    扫码二维码加入Web技术交流群

    发布评论

    需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

    评论(2

    眼眸印温柔 2024-09-25 18:50:18

    感谢您的复制步骤。我能够重现您的问题。

    据我所知,Visual Studio IDE 使用控件而不是表单。

    不知道您的表单的预期功能是什么,我只是在下面添加了一个基本示例来开始。

    很容易有许多其他方法可以做到这一点。我不是插件开发人员,因此我在该领域的知识有限。

    用户控件

    首先,右键单击您的项目并添加一个新的用户控件。我在示例中将其命名为“MyForm”,并在其上放置了一个简单的按钮,单击时显示“Hello”。
    该用户控件将成为您的表单。

    namespace MyAddin1
    {
        public partial class MyForm : UserControl
        {
            public MyForm()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show("Hello");
            }
        }
    }
    

    创建表单

    我们需要使用托管您的外接程序和外接程序实例的应用程序。
    这两个都是已在您的 AddIn 项目中声明的成员:_applicationObject 和 _addInInstance。这些是在 OnConnection 事件中设置的。

    在下面的代码中,我创建了一个新的工具窗口,在其中托管我的用户控件。我正在使用 Windows2.CreateTooWindow2 方法来执行此操作。

    我已将示例代码添加到 Excec 事件中,如下所示。再说一次,我不确定这是否是合适的地方,但对于演示代码来说它应该足够了。

    /// <summary>Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.</summary>
    /// <param term='commandName'>The name of the command to execute.</param>
    /// <param term='executeOption'>Describes how the command should be run.</param>
    /// <param term='varIn'>Parameters passed from the caller to the command handler.</param>
    /// <param term='varOut'>Parameters passed from the command handler to the caller.</param>
    /// <param term='handled'>Informs the caller if the command was handled or not.</param>
    /// <seealso class='Exec' />
    public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
    {
        object tempObject = null;   // It's required but I'm not sure what one can do with it...
        Windows2 windows2 = null;   // Reference to the window collection displayed in the application host.
        Assembly asm = null;        // The assembly containing the user control.
        Window myWindow = null;     // Will contain the reference of the new Tool Window.
    
        try
        {
            handled = false;
    
            if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
            {
                if (commandName == "MyAddin1.Connect.MyAddin1")
                {
                    handled = true;
    
                    // Get a reference to the window collection displayed in the application host.
                    windows2 = (Windows2)_applicationObject.Windows;
    
                    // Get the executing assembly.
                    asm = Assembly.GetExecutingAssembly();
    
                    // Create the tool window and insert the user control.
                    myWindow = windows2.CreateToolWindow2(_addInInstance, asm.Location, "MyAddin1.MyForm", "My Tool Window", "{CB2AE2BD-2336-4615-B0A3-C55B9C7794C9}", ref tempObject);
    
                    // Set window properties to make it act more like a modless form.
                    myWindow.Linkable = false;  // Indicates whether the window can be docked with other windows in the IDE or not.
                    myWindow.IsFloating = true; // Indicates whether the window floats over other windows or not.
    
                    // Show the window.
                    myWindow.Visible = true;
    
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    

    我测试了该应用程序,它确实将我的外接程序添加到 IDE 的工具菜单中,当我单击我的外接程序时,它显示了该窗口并且它可以工作。显示装配对话框时也没有冻结、挂起或任何其他情况。

    Thank you for the reproduction steps. I was able to reproduce your issue.

    As far as I was able to find out, the Visual Studio IDE uses Controls rather than Forms.

    Not knowing what the intended functionality is of your form I simply added a basic example below to get started.

    There could easily be many other ways of doing this. I'm no AddIn developer and as such my knowledge is limited in that area.

    The User Control

    First, right-click your project and add a new user control. I named mine "MyForm" in my example and placed a simple button on it, displaying "Hello" when clicked.
    This user control is going to be your form.

    namespace MyAddin1
    {
        public partial class MyForm : UserControl
        {
            public MyForm()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                MessageBox.Show("Hello");
            }
        }
    }
    

    Creating the Form

    We need to use the application which is hosting your AddIn and the instance of your AddIn.
    Both those are members already declared in your AddIn project: _applicationObject and _addInInstance. Those are set in the OnConnection event.

    In the below code I create a new tool window, hosting my user control in it. I'm using the Windows2.CreateTooWindow2 Method to do that.

    I have added my sample code into the Excec event as seen below. Again, I'm not sure if that is the right place for it but for demonstrating the code it should suffice.

    /// <summary>Implements the Exec method of the IDTCommandTarget interface. This is called when the command is invoked.</summary>
    /// <param term='commandName'>The name of the command to execute.</param>
    /// <param term='executeOption'>Describes how the command should be run.</param>
    /// <param term='varIn'>Parameters passed from the caller to the command handler.</param>
    /// <param term='varOut'>Parameters passed from the command handler to the caller.</param>
    /// <param term='handled'>Informs the caller if the command was handled or not.</param>
    /// <seealso class='Exec' />
    public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)
    {
        object tempObject = null;   // It's required but I'm not sure what one can do with it...
        Windows2 windows2 = null;   // Reference to the window collection displayed in the application host.
        Assembly asm = null;        // The assembly containing the user control.
        Window myWindow = null;     // Will contain the reference of the new Tool Window.
    
        try
        {
            handled = false;
    
            if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
            {
                if (commandName == "MyAddin1.Connect.MyAddin1")
                {
                    handled = true;
    
                    // Get a reference to the window collection displayed in the application host.
                    windows2 = (Windows2)_applicationObject.Windows;
    
                    // Get the executing assembly.
                    asm = Assembly.GetExecutingAssembly();
    
                    // Create the tool window and insert the user control.
                    myWindow = windows2.CreateToolWindow2(_addInInstance, asm.Location, "MyAddin1.MyForm", "My Tool Window", "{CB2AE2BD-2336-4615-B0A3-C55B9C7794C9}", ref tempObject);
    
                    // Set window properties to make it act more like a modless form.
                    myWindow.Linkable = false;  // Indicates whether the window can be docked with other windows in the IDE or not.
                    myWindow.IsFloating = true; // Indicates whether the window floats over other windows or not.
    
                    // Show the window.
                    myWindow.Visible = true;
    
                    return;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
    

    I tested the application it did add my add-in to the tools menu of the IDE and when I clicked my Addin it showed the window and it worked. It also did not freeze, hang or anything when showing the Assembly Dialog.

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文