WPF:MainWindow黑色背景

时间:2018-10-19 18:35:31

标签: c# wpf interprocess

如果应用程序已经在运行,并且用户尝试运行该程序的新实例(单个实例),我试图从系统托盘中打开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吗?

正常: Normal View

黑屏: enter image description here

3 个答案:

答案 0 :(得分:1)

我没有直接回答您的问题,但是我可以通过提出一种更简单的方法来解决您的问题,从而避免大多数WinForm,ptr处理程序和导入所有dll文件,从而间接地回答它。 这种方法将使您几乎只处理WPF代码,而我对此进行了测试,并且背景色问题不存在

首先:在MainWindow.xaml.cs

  1. 使MainWindow为单例
  2. 类似于您所做的,当用户尝试关闭MainWindow时,隐藏MainWindow而不是将其关闭。

您的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();
        }
    }
}
}

第二:从 App.xaml.cs

中删除以下代码
StartupUri="MainWindow.xaml"

第三:将以下引用添加到您的WPF项目中

  1. System.Drawing
  2. System.Windows.Forms

References Screenshot

第四:向资源添加图标

  1. 右键单击您的WPF项目,然后选择属性 OR 或双击WPF项目中的“属性”。
  2. 选择资源
  3. 选择图标
  4. 选择添加资源
  5. 选择添加现有文件... 从您的PC中选择选择添加新图标以创建新文件。
  6. 如果您使用其他图标,请确保将图标重命名为 Dapino-Summer-Holiday-Palm-tree.ico 或在 App.xaml.cs中的代码中进行更改 I got my test icon from this link

ICONS Screenshot

第五:向资源添加图像

  1. 遵循上面的相同说明(第四部分)
  2. 确保将图标更改为图片
  3. 如果您选择其他图像,请确保将其重命名为 palm-tree-icon.png ,或确保在 App.xaml.cs 中的代码中更改名称。强> I got my test icon from this link

enter image description here

第六名:App.xaml.cs

  1. 添加构造函数和Startup方法。
  2. 创建应用程序和应用程序托盘的实例
  3. 在任务栏中添加了两项(应用名称和退出)
  4. 其中一项带有图标,向您显示不知道怎么办。

您的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. 第一个实例,它将打开MainWindow
  2. 要在任务栏中进行选择,请右键单击该图标,然后选择(应用程序名称或退出)。
  3. 双击Icon将再次打开应用程序。 要将其更改为仅一键操作:将 App.xaml.cs 中的 notifyIcon.DoubleClick 更改为 notifyIcon.Click 事件>
  4. 我试图最小化更改,以使您更轻松地添加到项目中。
  5. 我希望您同意这比在codeproject.com中遵循的示例更简单,更好。

答案 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();
    }

这对我来说是个把戏。而且避免了长时间编码。