最近公司做一个考试系统,需要一个答题栏,要求:占用屏幕上方一部分区域,而且始终置顶,当其他窗口最大化时“答题栏”始终置前并且不遮挡最大化窗口的任何部分!就像windows任务栏一样。
最终效果图如下:
首先,我们必须声明所需的结构和常量。
我们声明RECT WINAPI结构如下:
[StructLayout(LayoutKind.Sequential)] struct RECT { public int left; public int top; public int right; public int bottom; }
我们声明APPBARDATA SHELLAPI结构如下:
[StructLayout(LayoutKind.Sequential)] struct APPBARDATA { public int cbSize; public IntPtr hWnd; public int uCallbackMessage; public int uEdge; public RECT rc; public IntPtr lParam; }
然后,我们声明AppBar用到的常量如下:
enum ABMsg : int { ABM_NEW=0, ABM_REMOVE, ABM_QUERYPOS, ABM_SETPOS, ABM_GETSTATE, ABM_GETTASKBARPOS, ABM_ACTIVATE, ABM_GETAUTOHIDEBAR, ABM_SETAUTOHIDEBAR, ABM_WINDOWPOSCHANGED, ABM_SETSTATE } enum ABNotify : int { ABN_STATECHANGE=0, ABN_POSCHANGED, ABN_FULLSCREENAPP, ABN_WINDOWARRANGE } enum ABEdge : int { ABE_LEFT=0, ABE_TOP, ABE_RIGHT, ABE_BOTTOM }
接下来,我们声明需要用到的WIN32和SHELL API接口:
[DllImport("SHELL32", CallingConvention = CallingConvention.StdCall)] static extern uint SHAppBarMessage(int dwMessage, ref APPBARDATA pData); [DllImport("USER32")] static extern int GetSystemMetrics(int Index); [DllImport("User32.dll", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint); [DllImport("User32.dll", CharSet = CharSet.Auto)] static extern int RegisterWindowMessage(string msg);
下一步,我们创建一个注册AppBar的方法。
private void RegisterBar() { APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.hWnd = this.Handle; if (!fBarRegistered) { uCallBack = RegisterWindowMessage("AppBarMessage"); abd.uCallbackMessage = uCallBack; uint ret = SHAppBarMessage((int)ABMsg.ABM_NEW, ref abd); fBarRegistered = true; ABSetPos(); } else { SHAppBarMessage((int)ABMsg.ABM_REMOVE, ref abd); fBarRegistered = false; } }
最后,我们创建一个设置AppBar位置的方法。
private void ABSetPos() { APPBARDATA abd = new APPBARDATA(); abd.cbSize = Marshal.SizeOf(abd); abd.hWnd = this.Handle; abd.uEdge = (int)ABEdge.ABE_TOP; if (abd.uEdge == (int)ABEdge.ABE_LEFT || abd.uEdge == (int)ABEdge.ABE_RIGHT) { abd.rc.top = 0; abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height; if (abd.uEdge == (int)ABEdge.ABE_LEFT) { abd.rc.left = 0; abd.rc.right = Size.Width; } else { abd.rc.right = SystemInformation.PrimaryMonitorSize.Width; abd.rc.left = abd.rc.right - Size.Width; } } else { abd.rc.left = 0; abd.rc.right = SystemInformation.PrimaryMonitorSize.Width; if (abd.uEdge == (int)ABEdge.ABE_TOP) { abd.rc.top = 0; abd.rc.bottom = Size.Height; } else { abd.rc.bottom = SystemInformation.PrimaryMonitorSize.Height; abd.rc.top = abd.rc.bottom - Size.Height; } } // Query the system for an approved size and position. SHAppBarMessage((int)ABMsg.ABM_QUERYPOS, ref abd); // Adjust the rectangle, depending on the edge to which the // appbar is anchored. switch (abd.uEdge) { case (int)ABEdge.ABE_LEFT: abd.rc.right = abd.rc.left + Size.Width; break; case (int)ABEdge.ABE_RIGHT: abd.rc.left = abd.rc.right - Size.Width; break; case (int)ABEdge.ABE_TOP: abd.rc.bottom = abd.rc.top + Size.Height; break; case (int)ABEdge.ABE_BOTTOM: abd.rc.top = abd.rc.bottom - Size.Height; break; } // Pass the final bounding rectangle to the system. SHAppBarMessage((int)ABMsg.ABM_SETPOS, ref abd); // Move and size the appbar so that it conforms to the // bounding rectangle passed to the system. MoveWindow(abd.hWnd, abd.rc.left, abd.rc.top, abd.rc.right - abd.rc.left, abd.rc.bottom - abd.rc.top, true); }
参考地址:http://www.codeproject.com/Articles/6741/AppBar-using-C
下载地址:http://pan.baidu.com/s/1qY4HX2c b7nv