通过user32函数在Citrix中激活最小化的winform

时间:2018-12-06 20:04:47

标签: c# citrix user32

在激活最小化的非模式形式时,是否有人在使用USER32函数在Citrix中运行C#Winforms应用程序时遇到问题?

我试图做的是在非模式形式的Activate事件中,检查是否有可用的模式形式,如果有,将其带到前台并激活它。

由于我们的应用程序存在系统限制,因此我无法使用Application.OpenForms来检测可用的表单类型(或使用任何表单属性来激活窗口状态或将窗口状态设置为表单),因此我使用的是User32方法GetWindow和SetActiveWindow(或SetForegroundWindow),并使用Application的MainWindowHandle值确定Modal窗体的句柄,将其置于前台并激活。

代码如下:

using System.Runtime.InteropServices;
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms.VisualStyles;

namespace WindowsFormsApp
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern IntPtr GetWindow(IntPtr hWnd, UInt32 wCmd);
        [DllImport("user32.dll")]
        static extern IntPtr SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, UInt32 uFlags);
        [DllImport("user32.dll")]
        static extern Boolean ShowWindow(IntPtr hWnd, UInt32 wCmd);
        [DllImport("user32.dll")]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int GetWindowTextLength(IntPtr hWnd);
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern IntPtr SetActiveWindow(IntPtr hWnd);
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern IntPtr GetActiveWindow();
        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(800, 450);
            this.Text = "Form1";
            var nonModalButton = new Button() { Text = "Open non-modal window", Width = 200, Height = 30, Top = 10, Left = 10 };
            var modalButton = new Button() { Text = "Open modal window", Width = 200, Height = 30, Top = 50, Left = 10 };
            UInt32 GW_ENABLEDPOPUP = 6;

            // click event for modalButton
            modalButton.Click += (s, e) =>
            {
                var modalWindow = new Form() { Text = "Modal Window"};
                var newModalWindowButton = new Button() { Text = "Open child modal window", Width = 200, Height = 30, Top = 50, Left = 10 };
                // add click event to newModalWindowButton to show as a modal
                newModalWindowButton.Click += (s1, e1) => { (new Form() { Text = "Child Modal Window" }).ShowDialog(); };
                // add to list of controls for modalWindow Form
                modalWindow.Controls.Add(newModalWindowButton);
                // open new ModalWindow as a modal form
                modalWindow.ShowDialog((IWin32Window)s);
                //modalWindow.ShowDialog();
            };
            // click event for non-modalButton
            nonModalButton.Click += (s, e) =>
            {
                var nonModalWindow = new Form() { Text = "Non-Modal Window" };
                var newModalWindowButton = new Button() { Text = "Test", Width = 200, Height = 30, Top = 50, Left = 10 };
                nonModalWindow.Controls.Add(newModalWindowButton);
                // when non-modalWindow form is activated, find any active modal windows and activate the last one in the form collection
                nonModalWindow.Activated += (sender, ev) =>
                {
                    Form nonModalForm = sender as Form;
                    if (!nonModalForm.CanFocus)
                    {
                        var mainWindowHandlePtr = Process.GetCurrentProcess().MainWindowHandle;

                        var modalPopupPtr = GetWindow(mainWindowHandlePtr, GW_ENABLEDPOPUP);
                        var NewPtr = SetActiveWindow(modalPopupPtr);

                        if (NewPtr == IntPtr.Zero)
                        {
                            SetForegroundWindow(modalPopupPtr);
                        }
                    }
                };
                nonModalWindow.Show((IWin32Window)s);
            };
            this.Controls.AddRange(new Control[] { modalButton, nonModalButton });
            this.Show();
        }
        #endregion
    }
}

如果我以exe身份运行此文件,请按照以下步骤在citrix的范围之外:
    1)通过单击“打开非模态窗口”按钮来打开非模态表单     2)最小化非模态形式     3)通过单击“打开模态窗口”按钮来打开模态表单     4)通过点击工具栏中的图标来激活非模式表单

上面的代码会将模态形式带到前台,而非模态形式将在它后面。我还注意到newPtr值(SetActiveWindow的结果)是NonModalForm的句柄。

如果我使用相同的步骤在citrix中运行此exe,则非模式形式仍保留在前台,并且newPtr的值为0。

如果未将非模态形式最小化,而我尝试将其激活,则会将模态形式带到前台。

使这些步骤在Citrix中起作用的更好(推荐)方法吗?非常感谢您的任何建议。

0 个答案:

没有答案