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); }
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); }