gpt4 book ai didi

c# - 尝试运行第二个实例时激活隐藏的 wpf 应用程序

转载 作者:太空狗 更新时间:2023-10-29 22:37:33 24 4
gpt4 key购买 nike

我正在开发一个 wpf 应用程序,当用户关闭按钮时我没有退出应用程序,而是将它最小化到托盘(类似于 google talk)。

    void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;

this.Hide();
}

我需要的是,如果用户忘记了应用程序的一个实例并尝试打开一个新实例,我必须关闭第二个实例并将我的应用程序设置为前台应用程序。如果应用程序处于最小化状态(未隐藏),我可以执行此操作。我正在使用以下代码

      protected override void OnStartup(StartupEventArgs e)
{

Process currentProcess = Process.GetCurrentProcess();


var runningProcess = (from process in Process.GetProcesses()
where
process.Id != currentProcess.Id &&
process.ProcessName.Equals(
currentProcess.ProcessName,
StringComparison.Ordinal)
select process).FirstOrDefault();
if (runningProcess != null)
{
Application.Current.Shutdown();

ShowWindow(runningProcess.MainWindowHandle, 5);

ShowWindow(runningProcess.MainWindowHandle, 3);
}

}

[DllImport("user32.dll")]
private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

当应用程序最小化时,它有一些独特的 MainWindowHandle 值。当我隐藏应用程序时,runningProcess 的 MainWindowHandle 显示为 0。我认为这就是为什么我的应用程序在处于隐藏状态时无法打开,但不知道如何修复它。

如果我需要发布更多代码或澄清任何内容,请告诉我。提前谢谢你。

最佳答案

When I hide the app, the MainWindowHandle of runningProcess is showing as 0

你是对的。如果进程没有与之关联的图形界面(隐藏/最小化),则 MainWindowHandle 值为零。

作为解决方法,您可以尝试通过使用 EnumDesktopWindows 函数枚举所有打开的窗口来获取隐藏窗口的 HANDLE,并将其进程 ID 与隐藏/最小化窗口的进程进行比较编号。

更新

WPF 的 WIN32 窗口与标准 WIN32 窗口的行为略有不同。它具有由单词 HwndWrapper 组成的类名、创建它的 AppDomain 的名称以及一个唯一的随机 Guid(每次启动时都会更改),例如 < em>HwndWrapper[WpfApp.exe;;4d426cdc-31cf-4e4c-88c7-ede846ab6d44]。

更新 2

当使用 Hide() 方法隐藏 WPF 的窗口时,它会在内部调用 UpdateVisibilityProperty(Visibility.Hidden),后者依次为 UIElement 为 false。当我们调用WPFWindowShow()方法时,UpdateVisibilityProperty(Visibility.Visible)被调用,的内部可见性标志>UIElement 已切换。

当我们使用 ShowWindow() 显示 WPF 窗口时,不会触发 UpdateVisibilityProperty() 方法,因此内部可见性标志不会被反转(这会导致以黑色背景显示的窗口)。

通过查看 WPF Window 内部实现,这是切换内部可见性标志的唯一方法,无需调用 Show()Hide() 方法,是通过发送 WM_SHOWWINDOW 消息。

const int GWL_EXSTYLE = (-20);
const uint WS_EX_APPWINDOW = 0x40000;

const uint WM_SHOWWINDOW = 0x0018;
const int SW_PARENTOPENING = 3;

[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll")]
private static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumWindowsProc ewp, int lParam);

[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);

[DllImport("user32.dll")]
private static extern uint GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern uint GetWindowText(IntPtr hWnd, StringBuilder lpString, uint nMaxCount);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern bool GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);

delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);

static bool IsApplicationWindow(IntPtr hWnd) {
return (GetWindowLong(hWnd, GWL_EXSTYLE) & WS_EX_APPWINDOW) != 0;
}

static IntPtr GetWindowHandle(int pid, string title) {
var result = IntPtr.Zero;

EnumWindowsProc enumerateHandle = delegate(IntPtr hWnd, int lParam)
{
int id;
GetWindowThreadProcessId(hWnd, out id);

if (pid == id) {
var clsName = new StringBuilder(256);
var hasClass = GetClassName(hWnd, clsName, 256);
if (hasClass) {

var maxLength = (int)GetWindowTextLength(hWnd);
var builder = new StringBuilder(maxLength + 1);
GetWindowText(hWnd, builder, (uint)builder.Capacity);

var text = builder.ToString();
var className = clsName.ToString();

// There could be multiple handle associated with our pid,
// so we return the first handle that satisfy:
// 1) the handle title/ caption matches our window title,
// 2) the window class name starts with HwndWrapper (WPF specific)
// 3) the window has WS_EX_APPWINDOW style

if (title == text && className.StartsWith("HwndWrapper") && IsApplicationWindow(hWnd))
{
result = hWnd;
return false;
}
}
}
return true;
};

EnumDesktopWindows(IntPtr.Zero, enumerateHandle, 0);

return result;
}

使用示例

...
if (runningProcess.MainWindowHandle == IntPtr.Zero) {
var handle = GetWindowHandle(runningProcess.Id, runningProcess.MainWindowTitle);
if (handle != IntPtr.Zero) {
// show window
ShowWindow(handle, 5);
// send WM_SHOWWINDOW message to toggle the visibility flag
SendMessage(handle, WM_SHOWWINDOW, IntPtr.Zero, new IntPtr(SW_PARENTOPENING));
}
}
...

关于c# - 尝试运行第二个实例时激活隐藏的 wpf 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21154693/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com