问题提出:对于普通应用程序,我们很多时候会将窗口最小化到系统托盘。当我们点击这个托盘图标时,可能会弹出一些友好的提示界面,可以恰当的进行一些操作。
一般情况下,我们可能粗暴的将这个友好提示界面放置在桌面的右下角,对于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
- typedefstruct_AppBarData{
- DWORDcbSize;//Thesizeofthestructure,inbytes.
- HWNDhWnd;//Thehandletotheappbarwindow.
- UINTuCallbackMessage;//Anapplication-definedmessageidentifier.ThismemberisusedwhensendingtheABM_NEWmessage.
- UINTuEdge;//边界位置,有4种:ABE_BOTTOM、ABE_LEFT、ABE_RIGHT、ABE_TOP
- RECTrc;//任务栏的边界矩形位置。
- LPARAMlParam;//ThismemberisusedwiththeABM_SETAUTOHIDEBARandABM_SETSTATEmessages.
- }APPBARDATA,*PAPPBARDATA;
一个简单的C++代码:
- HWNDhwnd=FindWindow(L"Shell_TrayWnd",L"");
- if(hwnd!=NULL)
- {
- APPBARDATAabd={sizeof(APPBARDATA)};
- abd.hWnd=hwnd;
- BOOLbRt=SHAppBarMessage(ABM_GETTASKBARPOS,&abd);//此处能够获取位置和矩形
- UINTuState=(UINT)SHAppBarMessage(ABM_GETSTATE,&abd);//此处也可以使用ABM_GETAUTOHIDEBAR来获取
- if(0==uState)
- {
- //0:Taskbarisneitherintheauto-hidenoralways-on-topstate.
- //1:ABS_AUTOHIDEThetaskbarisintheauto-hidestate.
- //2:ABS_ALWAYSONTOPThetaskbarisinthealways-on-topstate.
- }
- ...
- }
C#代码:
功能:
1. 获取taskbar的位置
2. 计算出所放窗口的位置
- 首先需要引入API及相关宏和结构体:
- [DllImport("shell32.dll")]
- publicstaticexternIntPtrSHAppBarMessage(uintdwMessage,refAPPBARDATApData);
- publicenumAppBarMessages
- {
- 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)]
- publicstructRECT
- {
- publicint_Left;
- publicint_Top;
- publicint_Right;
- publicint_Bottom;
- }
- [StructLayout(LayoutKind.Sequential)]
- publicstructAPPBARDATA
- {
- publicintcbSize;
- publicIntPtrhWnd;
- publicuintuCallbackMessage;
- publicuintuEdge;
- publicRECTrc;
- publicintlParam;
- }
- publicenumAppBarStates
- {
- AutoHide=0x00000001,
- AlwaysOnTop=0x00000002
- }
- publicenumAppBarEdge
- {
- ABE_LEFT=0,
- ABE_TOP=1,
- ABE_RIGHT=2,
- ABE_BOTTOM=3
- }
- ///<summary>
- ///Retrievecurrenttaskbar'spositioninfo.
- ///</summary>
- ///<paramname="taskbarRect">Currenttaskbar'srectangle.</param>
- ///<paramname="eTaskbarEdge">Currenttaskbar'sedge.</param>
- ///<paramname="eTaskbarState">Currenttaskbar'sstate.</param>
- publicvoidGetTaskbarPosInfo(
- refRectangletaskbarRect,
- refWin32API.AppBarEdgeeTaskbarEdge,
- refWin32API.AppBarStateseTaskbarState)
- {
- eTaskbarState=Win32API.AppBarStates.AlwaysOnTop;//Initdefaultstate
- IntPtrhTaskBarWnd=Win32API.FindWindow("Shell_TrayWnd","");
- if(hTaskBarWnd!=null)
- {
- Win32API.APPBARDATAabd=newWin32API.APPBARDATA();
- abd.cbSize=Marshal.SizeOf(typeof(Win32API.APPBARDATA));
- Win32API.SHAppBarMessage((uint)(Win32API.AppBarMessages.GetTaskBarPos),refabd);
- eTaskbarEdge=(Win32API.AppBarEdge)(abd.uEdge);
- IntPtrhTmpWnd=Win32API.SHAppBarMessage((uint)(Win32API.AppBarMessages.GetAutoHideBar),refabd);
- if(0!=hTmpWnd.ToInt64())
- {
- eTaskbarState=Win32API.AppBarStates.AutoHide;
- }
- taskbarRect=Rectangle.FromLTRB(abd.rc._Left,abd.rc._Top,abd.rc._Right,abd.rc._Bottom);
- }
- }
- ///<summary>
- ///Initializethepopupwindow'sposition.
- ///</summary>
- ///<returns></returns>
- privatevoidInitialPosition()
- {
- RectangletaskbarRect=newRectangle();
- Win32API.AppBarEdgeeTaskbarEdge=newWin32API.AppBarEdge();
- Win32API.AppBarStateseTaskbarState=newWin32API.AppBarStates();
- Win32API.GetTaskbarPosInfo(reftaskbarRect,refeTaskbarEdge,refeTaskbarState);
- intnSceenWidth=(int)Math.Ceiling(SystemParameters.VirtualScreenWidth);
- intnSceenHeight=(int)Math.Ceiling(SystemParameters.VirtualScreenHeight);
- //WhethercurrentUIlanguageisMiddleEastcountrylanguage.
- //BecausetheMiddleEastcountry'userisrighthanded,sothepopupwindow'sposition
- //isdifferentwithnormalwhentaskbarisinTOPandBOTTOMstatus.
- boolisMiddleEastLanguage=IsMiddleEastLanguage();
- boolisTaskBarHide=(Win32API.AppBarStates.AutoHide==eTaskbarState)?true:false;
- switch(eTaskbarEdge)
- {
- caseWin32API.AppBarEdge.ABE_LEFT:
- this.Left=isTaskBarHide?taskbarRect.Left:(taskbarRect.Right);
- this.Top=nSceenHeight-this.Height;
- break;
- caseWin32API.AppBarEdge.ABE_TOP:
- this.Left=!isMiddleEastLanguage?(taskbarRect.Right-this.Width):taskbarRect.Left;
- this.Top=isTaskBarHide?taskbarRect.Top:(taskbarRect.Bottom);
- break;
- caseWin32API.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>
- ///WhetherthecurrentUIcultureismiddlecountryornot.
- ///</summary>
- ///<returns>Returntrueorfalse.</returns>
- privateboolIsMiddleEastLanguage()
- {
- stringcultureName=System.Globalization.CultureInfo.CurrentUICulture.Name;
- stringmainLanguage=cultureName.Substring(0,2);
- if(mainLanguage.Equals("ar")||mainLanguage.Equals("he"))
- {
- returntrue;
- }
- returnfalse;
- }