У кого-нибудь когда-нибудь возникали проблемы с запуском приложения 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?Большое спасибо за любые предложения.