简体   繁体   中英

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

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. 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. 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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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