Beispiel #1
0
        private static Interop.RECT FixByEdge(Interop.APPBARDATA barData, Vector sizeInPixels)
        {
            switch ((ABEdge)barData.uEdge)
            {
            case ABEdge.Right:
            {
                barData.rc.left = barData.rc.right - (int)Math.Round(sizeInPixels.X);
                break;
            }

            case ABEdge.Left:
            {
                barData.rc.right = barData.rc.left + (int)sizeInPixels.X;
                break;
            }

            case ABEdge.Bottom:
            {
                barData.rc.top = barData.rc.bottom - (int)Math.Round(sizeInPixels.Y);
                break;
            }

            case ABEdge.Top:
            {
                barData.rc.bottom = barData.rc.top + (int)sizeInPixels.Y;
                break;
            }
            }

            return(barData.rc);
        }
        public static void SetAppBar(Window appbarWindow, ABEdge edge, FrameworkElement childElement = null, bool topMost = true)
        {
            var info = GetRegisterInfo(appbarWindow);

            info.Edge         = edge;
            info.ChildElement = childElement;

            var abd = new Interop.APPBARDATA();

            abd.cbSize = Marshal.SizeOf(abd);
            abd.hWnd   = new WindowInteropHelper(appbarWindow).Handle;

            int renderPolicy;

            if (edge == ABEdge.None)
            {
                if (info.IsRegistered)
                {
                    Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_REMOVE, ref abd);
                    info.IsRegistered = false;
                }
                RestoreWindow(appbarWindow);

                // Restore normal desktop window manager attributes
                renderPolicy = (int)Interop.DWMNCRenderingPolicy.UseWindowStyle;

                Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_EXCLUDED_FROM_PEEK, ref renderPolicy, sizeof(int));
                Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_DISALLOW_PEEK, ref renderPolicy, sizeof(int));

                return;
            }

            if (!info.IsRegistered)
            {
                info.IsRegistered    = true;
                info.CallbackId      = Interop.RegisterWindowMessage("AppBarMessage");
                abd.uCallbackMessage = info.CallbackId;

                var ret = Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_NEW, ref abd);

                var source = HwndSource.FromHwnd(abd.hWnd);
                source.AddHook(info.WndProc);
            }

            appbarWindow.WindowStyle = WindowStyle.None;
            appbarWindow.ResizeMode  = ResizeMode.NoResize;
            appbarWindow.Topmost     = topMost;

            // Set desktop window manager attributes to prevent window
            // from being hidden when peeking at the desktop or when
            // the 'show desktop' button is pressed
            renderPolicy = (int)Interop.DWMNCRenderingPolicy.Enabled;

            Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_EXCLUDED_FROM_PEEK, ref renderPolicy, sizeof(int));
            Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_DISALLOW_PEEK, ref renderPolicy, sizeof(int));

            ABSetPos(info, appbarWindow, childElement);
        }
        public static void SetAppBar(Window appbarWindow, ABEdge edge, FrameworkElement childElement = null)
        {
            var info = GetRegisterInfo(appbarWindow);
            info.Edge = edge;
            info.ChildElement = childElement;

            var abd = new Interop.APPBARDATA();
            abd.cbSize = Marshal.SizeOf(abd);
            abd.hWnd = new WindowInteropHelper(appbarWindow).Handle;

            int renderPolicy;

            if (edge == ABEdge.None)
            {
                if (info.IsRegistered)
                {
                    Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_REMOVE, ref abd);
                    info.IsRegistered = false;
                }
                RestoreWindow(appbarWindow);

                // Restore normal desktop window manager attributes
                renderPolicy = (int)Interop.DWMNCRenderingPolicy.UseWindowStyle;

                Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_EXCLUDED_FROM_PEEK, ref renderPolicy, sizeof(int));
                Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_DISALLOW_PEEK, ref renderPolicy, sizeof(int));

                return;
            }

            if (!info.IsRegistered)
            {
                info.IsRegistered = true;
                info.CallbackId = Interop.RegisterWindowMessage("AppBarMessage");
                abd.uCallbackMessage = info.CallbackId;

                var ret = Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_NEW, ref abd);

                var source = HwndSource.FromHwnd(abd.hWnd);
                source.AddHook(info.WndProc);
            }

            appbarWindow.WindowStyle = WindowStyle.None;
            appbarWindow.ResizeMode = ResizeMode.NoResize;
            appbarWindow.Topmost = true;

            // Set desktop window manager attributes to prevent window
            // from being hidden when peeking at the desktop or when
            // the 'show desktop' button is pressed
            renderPolicy = (int)Interop.DWMNCRenderingPolicy.Enabled;

            Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_EXCLUDED_FROM_PEEK, ref renderPolicy, sizeof(int));
            Interop.DwmSetWindowAttribute(abd.hWnd, (int)Interop.DWMWINDOWATTRIBUTE.DWMA_DISALLOW_PEEK, ref renderPolicy, sizeof(int));

            ABSetPos(info.Edge, appbarWindow, childElement);
        }
Beispiel #4
0
        private static void ABSetPos(RegisterInfo info, Window appbarWindow, FrameworkElement childElement)
        {
            var edge    = info.Edge;
            var barData = new Interop.APPBARDATA();

            barData.cbSize = Marshal.SizeOf(barData);
            barData.hWnd   = new WindowInteropHelper(appbarWindow).Handle;
            barData.uEdge  = (int)edge;
            var screen       = System.Windows.Forms.Screen.FromHandle(barData.hWnd);
            var screenBounds = screen.Bounds;

            // Transforms a coordinate from WPF space to Screen space
            var toPixel = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformToDevice;
            // Transforms a coordinate from Screen space to WPF space
            var toWpfUnit = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformFromDevice;

            // Transform window size from wpf units (1/96 ") to real pixels, for win32 usage
            var sizeInPixels = (childElement != null ?
                                toPixel.Transform(new Vector(childElement.ActualWidth, childElement.ActualHeight)) :
                                toPixel.Transform(new Vector(appbarWindow.ActualWidth, appbarWindow.ActualHeight)));

            var screenSizeInPixels = toPixel.Transform(new Vector(screenBounds.Width, screenBounds.Height));

            barData.rc = GetRectBounds(screenBounds);
            barData.rc = FixByEdge(barData, sizeInPixels);

            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_QUERYPOS, ref barData);
            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_SETPOS, ref barData);

            // transform back to wpf units, for wpf window resizing in DoResize.
            var location  = toWpfUnit.Transform(new Point(barData.rc.left, barData.rc.top));
            var dimension = toWpfUnit.Transform(new Vector(barData.rc.right - barData.rc.left,
                                                           barData.rc.bottom - barData.rc.top));

            var rect = new Rect(location, new Size(dimension.X, dimension.Y));

            //This is done async, because WPF will send a resize after a new appbar is added.
            //if we size right away, WPFs resize comes last and overrides us.
            appbarWindow.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                                                new ResizeDelegate(DoResize), appbarWindow, rect);
        }
        private static void ABSetPos(RegisterInfo info, Window appbarWindow, FrameworkElement childElement)
        {
            var edge    = info.Edge;
            var barData = new Interop.APPBARDATA();

            barData.cbSize = Marshal.SizeOf(barData);
            barData.hWnd   = new WindowInteropHelper(appbarWindow).Handle;
            barData.uEdge  = (int)edge;

            // Transforms a coordinate from WPF space to Screen space
            var toPixel = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformToDevice;
            // Transforms a coordinate from Screen space to WPF space
            var toWpfUnit = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformFromDevice;

            // Transform window size from wpf units (1/96 ") to real pixels, for win32 usage
            var sizeInPixels = (childElement != null ?
                                toPixel.Transform(new Vector(childElement.ActualWidth, childElement.ActualHeight)) :
                                toPixel.Transform(new Vector(appbarWindow.ActualWidth, appbarWindow.ActualHeight)));
            // Even if the documentation says SystemParameters.PrimaryScreen{Width, Height} return values in
            // "pixels", they return wpf units instead.
            var actualWorkArea     = GetActualWorkArea(info);
            var screenSizeInPixels =
                toPixel.Transform(new Vector(actualWorkArea.Width, actualWorkArea.Height));
            var workTopLeftInPixels =
                toPixel.Transform(new Point(actualWorkArea.Left, actualWorkArea.Top));
            var workAreaInPixelsF = new Rect(workTopLeftInPixels, screenSizeInPixels);

            if (barData.uEdge == (int)ABEdge.Left || barData.uEdge == (int)ABEdge.Right)
            {
                barData.rc.top    = (int)workAreaInPixelsF.Top;
                barData.rc.bottom = (int)workAreaInPixelsF.Bottom;
                if (barData.uEdge == (int)ABEdge.Left)
                {
                    barData.rc.left  = (int)workAreaInPixelsF.Left;
                    barData.rc.right = (int)Math.Round(sizeInPixels.X);
                }
                else
                {
                    barData.rc.right = (int)workAreaInPixelsF.Right;
                    barData.rc.left  = barData.rc.right - (int)Math.Round(sizeInPixels.X);
                }
            }
            else
            {
                barData.rc.left  = (int)workAreaInPixelsF.Left;
                barData.rc.right = (int)workAreaInPixelsF.Right;
                if (barData.uEdge == (int)ABEdge.Top)
                {
                    barData.rc.top    = (int)workAreaInPixelsF.Top;
                    barData.rc.bottom = (int)Math.Round(sizeInPixels.Y);
                }
                else
                {
                    barData.rc.bottom = (int)workAreaInPixelsF.Bottom;
                    barData.rc.top    = barData.rc.bottom - (int)Math.Round(sizeInPixels.Y);
                }
            }

            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_QUERYPOS, ref barData);
            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_SETPOS, ref barData);

            // transform back to wpf units, for wpf window resizing in DoResize.
            var location  = toWpfUnit.Transform(new Point(barData.rc.left, barData.rc.top));
            var dimension = toWpfUnit.Transform(new Vector(barData.rc.right - barData.rc.left,
                                                           barData.rc.bottom - barData.rc.top));

            var rect = new Rect(location, new Size(dimension.X, dimension.Y));

            info.DockedSize = rect;

            //This is done async, because WPF will send a resize after a new appbar is added.
            //if we size right away, WPFs resize comes last and overrides us.
            appbarWindow.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                                                new ResizeDelegate(DoResize), appbarWindow, rect);
        }
        private static void ABSetPos(ABEdge edge, Window appbarWindow, FrameworkElement childElement)
        {
            var barData = new Interop.APPBARDATA();
            barData.cbSize = Marshal.SizeOf(barData);
            barData.hWnd = new WindowInteropHelper(appbarWindow).Handle;
            barData.uEdge = (int)edge;

            // Transforms a coordinate from WPF space to Screen space
            var toPixel = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformToDevice;
            // Transforms a coordinate from Screen space to WPF space
            var toWpfUnit = PresentationSource.FromVisual(appbarWindow).CompositionTarget.TransformFromDevice;

            // Transform window size from wpf units (1/96 ") to real pixels, for win32 usage
            var sizeInPixels = (childElement != null ?
                toPixel.Transform(new Vector(childElement.ActualWidth, childElement.ActualHeight)) :
                toPixel.Transform(new Vector(appbarWindow.ActualWidth, appbarWindow.ActualHeight)));
            // Even if the documentation says SystemParameters.PrimaryScreen{Width, Height} return values in
            // "pixels", they return wpf units instead.
            var screenSizeInPixels =
                toPixel.Transform(new Vector(SystemParameters.WorkArea.Width, SystemParameters.WorkArea.Height));

            if (barData.uEdge == (int)ABEdge.Left || barData.uEdge == (int)ABEdge.Right)
            {
                barData.rc.top = 0;
                barData.rc.bottom = (int)screenSizeInPixels.Y;
                if (barData.uEdge == (int)ABEdge.Left)
                {
                    barData.rc.left = 0;
                    barData.rc.right = (int)Math.Round(sizeInPixels.X);
                }
                else {
                    barData.rc.right = (int)screenSizeInPixels.X;
                    barData.rc.left = barData.rc.right - (int)Math.Round(sizeInPixels.X);
                }
            }
            else
            {
                barData.rc.left = 0;
                barData.rc.right = (int)screenSizeInPixels.X;
                if (barData.uEdge == (int)ABEdge.Top)
                {
                    barData.rc.top = 0;
                    barData.rc.bottom = (int)Math.Round(sizeInPixels.Y);
                }
                else {
                    barData.rc.bottom = (int)screenSizeInPixels.Y;
                    barData.rc.top = barData.rc.bottom - (int)Math.Round(sizeInPixels.Y);
                }
            }

            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_QUERYPOS, ref barData);
            Interop.SHAppBarMessage((int)Interop.ABMsg.ABM_SETPOS, ref barData);

            // transform back to wpf units, for wpf window resizing in DoResize.
            var location = toWpfUnit.Transform(new Point(barData.rc.left, barData.rc.top));
            var dimension = toWpfUnit.Transform(new Vector(barData.rc.right - barData.rc.left,
                barData.rc.bottom - barData.rc.top));

            var rect = new Rect(location, new Size(dimension.X, dimension.Y));

            //This is done async, because WPF will send a resize after a new appbar is added.
            //if we size right away, WPFs resize comes last and overrides us.
            appbarWindow.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle,
                new ResizeDelegate(DoResize), appbarWindow, rect);
        }