Активируйте свернутую winform в Citrix с помощью функций user32 - PullRequest
0 голосов
/ 06 декабря 2018

У кого-нибудь когда-нибудь возникали проблемы с запуском приложения C # Winforms в Citrix с использованием функций user32 при активации свернутой немодальной формы?

Я пытаюсь сделать это в событии активации немодальной формыпроверьте, есть ли доступная модальная форма, и если да, выведите ее на передний план и активируйте.

Из-за системных ограничений нашего приложения я не могу использовать Application.OpenForms, чтобы определить, какие типы форм доступны (или использовать любое из свойств формы, чтобы активировать или установить windowstate в форму), поэтому яиспользуя методы User32 GetWindow & SetActiveWindow (или SetForegroundWindow) и используя значение MainWindowHandle приложения, чтобы определить дескриптор модальной формы, вывести его на передний план и активировать.

Вот код:

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-OE-TRE OTIDE OTTER BIDE Citrix с помощью следующих шагов:
1) открыть немодальную форму, нажав на кнопку «открыть немодальное окно» 2) свернуть немодальную форму3) открыть модальную форму, нажав кнопку «Открыть модальное окно». 4) активировать немодальную форму, щелкнув значок на панели инструментов

. Приведенный выше код выведет модальную форму на передний план инемодальная форма будет за этим.Я также заметил, что значение newPtr (результат SetActiveWindow) является дескриптором NonModalForm.

Если я запускаю этот exe-файл WITHIN citrix с теми же шагами, немодальная форма остается на переднем плане, а значение newPtr равно 0.

Если немодальная формане минимизируется, и я пытаюсь активировать ее, затем модальная форма выводится на передний план.

Является ли лучший (рекомендуемый) способ заставить эти шаги работать в Citrix?Большое спасибо за любые предложения.

...