如果应用程序已经在运行,并且用户尝试运行该程序的新实例(单个实例),我试图从系统托盘中打开MainWindow
我正在关注本教程: https://www.codeproject.com/Articles/32908/C-Single-Instance-App-With-the-Ability-To-Restore
如果将MainWindow最小化,它会完美工作,但是,当我关闭刚刚隐藏的窗口并通过传递一条消息(使用主窗口处理程序)从新创建的实例重新打开它时,我得到了窗口打开,但它是黑屏。
关闭MainWindow:
private void main_Closing(object sender, System.ComponentModel.CancelEventArgs e) {
// If the window is visible, then hide it
if (IsVisible)
Visibility = Visibility.Hidden;
e.Cancel = true;
}
使用MainWinow处理程序显示MainWindow
public const int SW_SHOWNORMAL = 1;
[DllImportAttribute("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImportAttribute("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ShowToFront(IntPtr window) {
ShowWindow(window, SW_SHOWNORMAL);
SetForegroundWindow(window);
}
我如何在MainWindow.xaml.cs中称呼它
public void ShowWindow() {
WinApi.ShowToFront(new WindowInteropHelper(this).Handle);
}
我能够通过替换
来拥有普通窗口public void ShowWindow() {
WinApi.ShowToFront(new WindowInteropHelper(this).Handle);
}
与
public void ShowWindow() {
Visibility = Visibility.Visible;
WindowState = WindowState.Normal;
}
但是,我仍然想知道处理程序为什么用黑屏打开我的MainWindow吗?
答案 0 :(得分:1)
我没有直接回答您的问题,但是我可以通过提出一种更简单的方法来解决您的问题,从而避免大多数WinForm,ptr处理程序和导入所有dll文件,从而间接地回答它。 这种方法将使您几乎只处理WPF代码,而我对此进行了测试,并且背景色问题不存在
您的MainWindow.xml.cs应该看起来像这样,没有其他其他代码:
using System.Windows;
namespace WPFSystemTray
{
public partial class MainWindow : Window
{
private static MainWindow instance;
public static MainWindow Instance
{
get
{
if (instance == null)
{
instance = new MainWindow();
}
return instance;
}
}
private MainWindow()
{
InitializeComponent();
this.Closing += MainWindow_Closing;
}
private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (!App.IsExitApplication)
{
e.Cancel = true;
this.Hide();
}
}
}
}
StartupUri="MainWindow.xaml"
您的App.xaml.cs应该如下所示。
using System;
using System.Windows;
namespace WPFSystemTray
{
public partial class App : Application
{
public static bool IsExitApplication;
public App()
{
Startup += App_Startup;
}
private void App_Startup(object sender, StartupEventArgs e)
{
WPFSystemTray.MainWindow.Instance.Show();
System.Windows.Forms.NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon();
notifyIcon.DoubleClick += _notifyIcon_DoubleClick;
notifyIcon.Icon = WPFSystemTray.Properties.Resources.Dapino_Summer_Holiday_Palm_tree;
notifyIcon.Visible = true;
CreateContextMenu(notifyIcon);
}
private void _notifyIcon_DoubleClick(object sender, EventArgs e)
{
ShowMainWindow();
}
private void CreateContextMenu(System.Windows.Forms.NotifyIcon notifyIcon)
{
if (notifyIcon != null)
{
notifyIcon.ContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
notifyIcon.ContextMenuStrip.Items.Add("Application Name",
WPFSystemTray.Properties.Resources.palm_tree_icon).Click
+= NotifyIcon_ApplicationName_Click;
notifyIcon.ContextMenuStrip.Items.Add("Exit").Click += NotifyIcon_Exit_Click;
}
}
private void NotifyIcon_ApplicationName_Click(object sender, EventArgs e)
{
ShowMainWindow();
}
private void NotifyIcon_Exit_Click(object sender, EventArgs e)
{
IsExitApplication = true;
MainWindow.Close();
(sender as System.Windows.Forms.ToolStripItem).Owner.Dispose();
}
public void ShowMainWindow()
{
if (!MainWindow.IsVisible)
{
MainWindow.Show();
}
else
{
if (MainWindow.WindowState == WindowState.Minimized)
{
MainWindow.WindowState = WindowState.Normal;
}
MainWindow.Activate();
}
}
}
}
答案 1 :(得分:1)
我无法明确记住何时何地,但是隐藏窗口基本上可以结束其生命,例如模式窗口。当我需要做类似的事情时,我只是将Window的LEFT属性设置为一些淫秽的负值,而不是隐藏或使其可见,因此用户看不到。
例如,您的实际窗口尺寸为800x450。我可以将左位置设置为-900。由于我的窗口的最坏情况是800宽,因此,向-900左移将不会使其可见,也不会释放该窗口及其资源。因此,当您尝试重置其可见性时,只需将其左位置重新设置为0。现在,如果用户有多台显示器,那可能是另一个问题……也许将其左位置设置为-4000。
答案 2 :(得分:0)
对于WPF,这样做的方法非常简单。
只需将激活的功能添加到MainWindow或您喜欢的其他表单中即可。
并添加this.show();
public void Window_Activated(object sender, EventArgs e)
{
this.Show();
}
这对我来说是个把戏。而且避免了长时间编码。