首页 > 代码库 > 利用C# Winform做Windows系统任务栏

利用C# Winform做Windows系统任务栏

最近公司做一个考试系统,需要一个答题栏,要求:占用屏幕上方一部分区域,而且始终置顶,当其他窗口最大化时“答题栏”始终置前并且不遮挡最大化窗口的任何部分!就像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

利用C# Winform做Windows系统任务栏