简体   繁体   English

无窗托盘图标应用程序2

[英]Windowless tray icon application 2

This is the continuation of Windowless tray icon application 这是无窗托盘图标应用程序的延续

I finally got to do what I want with this tray icon that is: 1. icon in the tray 2. click open small tray windows 3. click on tray window open main window 我终于用这个托盘图标完成了我想要做的事情:1.托盘图标2.单击打开小托盘窗口3.单击托盘窗口打开主窗口

The only issue is that I want the small intermediate window start far away the tray. 唯一的问题是我希望中间的小窗口从托盘开始很远。 I would liket it to be near the tray icon who has launched it as shown in the following pic. 我希望它靠近已启动它的任务栏图标,如下图所示。

在此处输入图片说明

The code for the tray icon (launched from the mainwindow) is: 托盘图标(从主窗口启动)的代码为:

 var tim = new TrayIconMenuWindow.TrayIconMenuWindow();
 tim.WindowStartupLocation = WindowStartupLocation.CenterOwner;<------
 tim.ShowDialog();
 this.Visibility = Visibility.Visible;

I have tried all startuplocations but none helped. 我已经尝试了所有的启动位置,但是都没有帮助。 Thanx 感谢名单

If you want the window in the bottom right of the screen, you may use something like this: 如果您希望窗口位于屏幕的右下角,则可以使用以下方法:

Rectangle workingArea = Screen.GetWorkingArea(this);
this.Location = new Point(workingArea.Right - Size.Width,
                                  workingArea.Bottom - Size.Height);

Edit 编辑
I just realized you are working in WPF. 我刚刚意识到您正在使用WPF。 If that's the case,use this code: 如果是这样,请使用以下代码:

var screenSize = System.Windows.SystemParameters.WorkArea;
this.Left = screenSize.Right - this.Width;
this.Top = screenSize.Bottom - this.Height;

If you expect a window to show up next to the NotifyIcon like a ContextMenuStrip associated to the NotifyIcon, you will need to obtain the exact location of the NotifyIcon in the screen and then adjust the window's location. 如果您希望某个窗口像与该NotifyIcon关联的ContextMenuStrip一样出现在NotifyIcon旁边,则需要获取NotifyIcon在屏幕中的确切位置,然后调整该窗口的位置。 You can find an example in: 您可以在以下位置找到示例:

It's quite lengthy but the code to get the location of a NotifyIcon can be shorter like this: 它相当长,但是获取NotifyIcon位置的代码可以更短,如下所示:

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Forms;

public static class NotifyIconRect
{
    #region Win32

    [DllImport("Shell32.dll", SetLastError = true)]
    private static extern int Shell_NotifyIconGetRect(
        [In] ref NOTIFYICONIDENTIFIER identifier,
        out RECT iconLocation);

    [StructLayout(LayoutKind.Sequential)]
    private struct NOTIFYICONIDENTIFIER
    {
        public uint cbSize;
        public IntPtr hWnd;
        public uint uID;
        public GUID guidItem; // System.Guid can be used.
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct GUID
    {
        public uint Data1;
        public ushort Data2;
        public ushort Data3;

        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] Data4;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;

        public static implicit operator Rect(RECT rect)
        {
            if ((rect.right - rect.left < 0) || (rect.bottom - rect.top < 0))
                return Rect.Empty;

            return new Rect(
                rect.left,
                rect.top,
                rect.right - rect.left,
                rect.bottom - rect.top);
        }
    }

    #endregion

    public static Rect GetNotifyIconRect(NotifyIcon notifyIcon)
    {
        NOTIFYICONIDENTIFIER identifier;
        if (!TryGetNotifyIconIdentifier(notifyIcon, out identifier))
            return Rect.Empty;

        RECT iconLocation;
        int result = Shell_NotifyIconGetRect(ref identifier, out iconLocation);

        switch (result)
        {
            case 0: // 0 means S_OK.
            case 1: // 1 means S_FALSE.
                return iconLocation;
            default:
                return Rect.Empty;
        }
    }

    private static bool TryGetNotifyIconIdentifier(NotifyIcon notifyIcon, out NOTIFYICONIDENTIFIER identifier)
    {
        identifier = new NOTIFYICONIDENTIFIER { cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONIDENTIFIER))    };

        int id;
        if (!TryGetFieldValue(notifyIcon, "id", out id))
            return false;

        NativeWindow window;
        if (!TryGetFieldValue(notifyIcon, "window", out window))
            return false;

        identifier.uID = (uint)id;
        identifier.hWnd = window.Handle;
        return true;
    }

    private static bool TryGetFieldValue<T>(object instance, string fieldName, out T fieldValue)
    {
        fieldValue = default(T);

        var fieldInfo = instance.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
        if (fieldInfo == null)
            return false;

        var value = fieldInfo.GetValue(instance);
        if (!(value is T))
            return false;

        fieldValue = (T)value;
        return true;
    }
}

This code is a little tricky because it gets private field values of a NotifyIcon by reflection but I don't know any other way to accomplish this operation. 这段代码有些棘手,因为它通过反射来获取NotifyIcon的私有字段值,但是我不知道其他任何方式来完成此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM