Issue with SHAppBarMessage for TaskBar Position on

2019-08-08 10:33发布

问题:

I am having a really strange issue with SHAppBarMessage, have been trying out different things for few hours now but i am not getting it. I am trying to get the TaskBar Position. It works fine on Windows 8 but on Windows Server the return value is SHAppBarMessage.

The following code from an answer works from fine on Windows 8, but on Windows 2008R2 it has a strange behavior.

    public static System.Drawing.Rectangle GetTaskbarPosition()
    {
        var data = new APPBARDATA();
        data.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(data);
        IntPtr retval = SHAppBarMessage(ABM_GETTASKBARPOS, ref data);
        if (retval == IntPtr.Zero) throw new Exception("Please re-install Windows");
        return new System.Drawing.Rectangle(data.rc.left, data.rc.top,
            data.rc.right - data.rc.left, data.rc.bottom - data.rc.top);
    }

    // P/Invoke goo:
    private const int ABM_GETTASKBARPOS = 5;
    [System.Runtime.InteropServices.DllImport("shell32.dll")]
    private static extern IntPtr SHAppBarMessage(int msg, ref APPBARDATA data);
    private struct APPBARDATA
    {
        public int cbSize;
        public IntPtr hWnd;
        public int uCallbackMessage;
        public int uEdge;
        public RECT rc;
        public IntPtr lParam;
    }
    private struct RECT
    {
        public int left, top, right, bottom;
    }

I am totally out of ideas. As it should work as it is. But i dont know why it is not working. Am i missing something?

回答1:

According to the documentation for ABM_GETTASKBARPOS:

fResult = (BOOL) SHAppBarMessage(ABM_GETTASKBARPOS, pabd);

pabd

A pointer to an APPBARDATA structure whose rc member receives the bounding rectangle, in screen coordinates, of the taskbar. You must specify the cbSize and hWnd when sending this message; all other members are ignored.

Emphasis mine.

This Delphi code sample suggests as much, it looks for a window by the name of Shell_TrayWnd:

// 'Shell_TrayWnd' is the name of the task bar's window
AppData.Hwnd := FindWindow('Shell_TrayWnd', nil);