如何获取任务栏(taskbar)相关信息

问题提出:对于普通应用程序,我们很多时候会将窗口最小化到系统托盘。当我们点击这个托盘图标时,可能会弹出一些友好的提示界面,可以恰当的进行一些操作。
一般情况下,我们可能粗暴的将这个友好提示界面放置在桌面的右下角,对于XP,这是OK的,因为XP不允许我们将任务栏拖动到桌面的上、左、右三个方向,
只允许停靠下桌面的最下方,但是对于win7,我们便需要考虑到其它三个方向,再根据这个方向确定好提示界面放的位置。那么,如何获得任务栏的位置及相关信息?
windows提供了相关和API进行操作。

UINT_PTR SHAppBarMessage(
DWORD dwMessage,
PAPPBARDATA pData
);
其中
dwMessage为发送给system的消息。
pData为一个APPBARDATA结构体,用于存储发送或者返回的数据。

dwMessage只能为以下的其中一个值。
ABM_ACTIVATE:告知系统任务栏被激活。
ABM_GETAUTOHIDEBAR:查询任务栏是否是自动隐藏(前提是要给出任务栏停靠的位置)。
ABM_GETSTATE:查询任务栏自动隐藏和总是牌处于顶层的状态。
ABM_GETTASKBARPOS:获取任务栏的边界矩形位置。
ABM_QUERYPOS:请求任务栏的位置。(上、下、左、右)
其它状态略。
ABM_NEW、ABM_REMOVE、ABM_SETAUTOHIDEBAR、ABM_SETPOS、ABM_SETSTATE、ABM_WINDOWPOSCHANGED

typedef struct _AppBarData {
    DWORD cbSize;             // The size of the structure, in bytes. 
    HWND hWnd;                // The handle to the appbar window. 
    UINT uCallbackMessage;    // An application-defined message identifier.This member is used when sending the ABM_NEW message. 
    UINT uEdge;               // 边界位置,有4种:ABE_BOTTOM、ABE_LEFT、ABE_RIGHT、ABE_TOP
    RECT rc;                  // 任务栏的边界矩形位置。
    LPARAM lParam;            // This member is used with the ABM_SETAUTOHIDEBAR and ABM_SETSTATE messages. 
} APPBARDATA, *PAPPBARDATA;

一个简单的C++代码:

HWND hwnd = FindWindow(L"Shell_TrayWnd", L"");
    if (hwnd != NULL)
    {
        APPBARDATA abd = { sizeof(APPBARDATA) };
        abd.hWnd = hwnd;
        BOOL bRt = SHAppBarMessage(ABM_GETTASKBARPOS, &abd);    // 此处能够获取位置和矩形
        UINT uState = (UINT) SHAppBarMessage(ABM_GETSTATE, &abd);   // 此处也可以使用ABM_GETAUTOHIDEBAR来获取
        if (0 == uState)
        {
            // 0: Taskbar is neither in the auto-hide nor always-on-top state.
            // 1: ABS_AUTOHIDE The taskbar is in the auto-hide state. 
            // 2: ABS_ALWAYSONTOP The taskbar is in the always-on-top state. 
        }
        ...
    }

C#代码:

功能:
1. 获取taskbar的位置
2. 计算出所放窗口的位置

首先需要引入API及相关宏和结构体:
        [DllImport("shell32.dll")]
        public static extern IntPtr SHAppBarMessage(uint dwMessage, ref APPBARDATA pData);

        public enum AppBarMessages
        {
            New              = 0x00000000,
            Remove           = 0x00000001,
            QueryPos         = 0x00000002,
            SetPos           = 0x00000003,
            GetState         = 0x00000004,
            GetTaskBarPos    = 0x00000005,
            Activate         = 0x00000006,
            GetAutoHideBar   = 0x00000007,
            SetAutoHideBar   = 0x00000008,
            WindowPosChanged = 0x00000009,
            SetState         = 0x0000000a
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int _Left;
            public int _Top;
            public int _Right;
            public int _Bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct APPBARDATA
        {
            public int    cbSize;
            public IntPtr hWnd;
            public uint   uCallbackMessage;
            public uint   uEdge;
            public RECT   rc;
            public int    lParam;
        }

        public enum AppBarStates
        {
            AutoHide    = 0x00000001,
            AlwaysOnTop = 0x00000002
        }

        public enum AppBarEdge
        {
            ABE_LEFT    = 0,
            ABE_TOP     = 1,
            ABE_RIGHT   = 2,
            ABE_BOTTOM  = 3
        }

        /// <summary>
        /// Retrieve current task bar's position info.
        /// </summary>
        /// <param name="taskbarRect">Current task bar's rectangle.</param>
        /// <param name="eTaskbarEdge">Current task bar's edge.</param>
        /// <param name="eTaskbarState">Current task bar's state.</param>
        public void GetTaskbarPosInfo(
            ref Rectangle taskbarRect, 
            ref Win32API.AppBarEdge eTaskbarEdge,
            ref Win32API.AppBarStates eTaskbarState)
        {
            eTaskbarState = Win32API.AppBarStates.AlwaysOnTop;  // Init default state

            IntPtr hTaskBarWnd = Win32API.FindWindow("Shell_TrayWnd", "");
            if (hTaskBarWnd != null)
            {
                Win32API.APPBARDATA abd = new Win32API.APPBARDATA();
                abd.cbSize = Marshal.SizeOf(typeof(Win32API.APPBARDATA));
                Win32API.SHAppBarMessage((uint)(Win32API.AppBarMessages.GetTaskBarPos), ref abd);
                eTaskbarEdge = (Win32API.AppBarEdge)(abd.uEdge);

                IntPtr hTmpWnd = Win32API.SHAppBarMessage((uint)(Win32API.AppBarMessages.GetAutoHideBar), ref abd);
                if (0 != hTmpWnd.ToInt64())
                {
                    eTaskbarState = Win32API.AppBarStates.AutoHide;
                }

                taskbarRect = Rectangle.FromLTRB(abd.rc._Left, abd.rc._Top, abd.rc._Right, abd.rc._Bottom);
            }
        }

        /// <summary>
        /// Initialize the popup window's position. 
        /// </summary>
        /// <returns></returns>
        private void InitialPosition()
        {
            Rectangle taskbarRect = new Rectangle();
            Win32API.AppBarEdge eTaskbarEdge = new Win32API.AppBarEdge();
            Win32API.AppBarStates eTaskbarState = new Win32API.AppBarStates();
            Win32API.GetTaskbarPosInfo(ref taskbarRect, ref eTaskbarEdge, ref eTaskbarState);

            int nSceenWidth = (int)Math.Ceiling(SystemParameters.VirtualScreenWidth);
            int nSceenHeight = (int)Math.Ceiling(SystemParameters.VirtualScreenHeight);

            // Whether current UI language is Middle East country language.
            // Because the Middle East country' user is right handed, so the popup window's position 
            // is different with normal when task bar is in TOP and BOTTOM status.
            bool isMiddleEastLanguage = IsMiddleEastLanguage();
            bool isTaskBarHide = (Win32API.AppBarStates.AutoHide == eTaskbarState) ? true : false;

            switch (eTaskbarEdge)
            {
                case Win32API.AppBarEdge.ABE_LEFT:
                    this.Left = isTaskBarHide ? taskbarRect.Left : (taskbarRect.Right);
                    this.Top = nSceenHeight - this.Height;
                    break;
                case Win32API.AppBarEdge.ABE_TOP:
                    this.Left = !isMiddleEastLanguage ? (taskbarRect.Right - this.Width) : taskbarRect.Left;
                    this.Top = isTaskBarHide ? taskbarRect.Top : (taskbarRect.Bottom);
                    break;
                case Win32API.AppBarEdge.ABE_RIGHT:
                    this.Left = isTaskBarHide ? (taskbarRect.Right - this.Width) : (taskbarRect.Left - this.Width);
                    this.Top = (nSceenHeight - this.Height)/*(1 == rightHanded) ? (nSceenHeight - this.Height) : (0)*/;
                    break;
                default:
                    this.Left = !isMiddleEastLanguage ? (taskbarRect.Right - this.Width) : taskbarRect.Left;
                    this.Top = isTaskBarHide ? (taskbarRect.Bottom - this.Height) : (taskbarRect.Top - this.Height);
                    break;
            }
        }

        /// <summary>
        /// Whether the current UI culture is middle country or not.
        /// </summary>
        /// <returns>Return true or false.</returns>
        private bool IsMiddleEastLanguage()
        {
            string cultureName = System.Globalization.CultureInfo.CurrentUICulture.Name;
            string mainLanguage = cultureName.Substring(0, 2);
            if (mainLanguage.Equals("ar") || mainLanguage.Equals("he"))
            {
                return true;
            }
            return false;
        }


 

 

展开阅读全文

没有更多推荐了,返回首页