Exemple #1
0
        private void _InitializeWindowResizeBorderThickness()
        {
            Size frameSize = new Size(
                NativeMethodsShell.GetSystemMetrics(SM.CXSIZEFRAME),
                NativeMethodsShell.GetSystemMetrics(SM.CYSIZEFRAME));
            Size frameSizeInDips = DpiHelper.DeviceSizeToLogical(frameSize);

            WindowResizeBorderThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height, frameSizeInDips.Width, frameSizeInDips.Height);
        }
        public static void SafeDestroyIcon(ref IntPtr hicon)
        {
            IntPtr p = hicon;

            hicon = IntPtr.Zero;
            if (IntPtr.Zero != p)
            {
                NativeMethodsShell.DestroyIcon(p);
            }
        }
        public static void SafeDestroyWindow(ref IntPtr hwnd)
        {
            IntPtr p = hwnd;

            hwnd = IntPtr.Zero;
            if (NativeMethodsShell.IsWindow(p))
            {
                NativeMethodsShell.DestroyWindow(p);
            }
        }
        public static void SafeDisposeImage(ref IntPtr gdipImage)
        {
            IntPtr p = gdipImage;

            gdipImage = IntPtr.Zero;
            if (IntPtr.Zero != p)
            {
                NativeMethodsShell.GdipDisposeImage(p);
            }
        }
        public static void SafeDeleteObject(ref IntPtr gdiObject)
        {
            IntPtr p = gdiObject;

            gdiObject = IntPtr.Zero;
            if (IntPtr.Zero != p)
            {
                NativeMethodsShell.DeleteObject(p);
            }
        }
Exemple #6
0
 private static int _GetBitDepth()
 {
     if (s_bitDepth == 0)
     {
         using (SafeDC dc = SafeDC.GetDesktop())
         {
             s_bitDepth = NativeMethodsShell.GetDeviceCaps(dc, DeviceCap.BITSPIXEL) * NativeMethodsShell.GetDeviceCaps(dc, DeviceCap.PLANES);
         }
     }
     return(s_bitDepth);
 }
Exemple #7
0
        private void _InitializeWindowNonClientFrameThickness()
        {
            Size frameSize = new Size(
                NativeMethodsShell.GetSystemMetrics(SM.CXSIZEFRAME),
                NativeMethodsShell.GetSystemMetrics(SM.CYSIZEFRAME));
            Size   frameSizeInDips     = DpiHelper.DeviceSizeToLogical(frameSize);
            int    captionHeight       = NativeMethodsShell.GetSystemMetrics(SM.CYCAPTION);
            double captionHeightInDips = DpiHelper.DevicePixelsToLogical(new Point(0, captionHeight)).Y;

            WindowNonClientFrameThickness = new Thickness(frameSizeInDips.Width, frameSizeInDips.Height + captionHeightInDips, frameSizeInDips.Width, frameSizeInDips.Height);
        }
Exemple #8
0
        private static void _PostSystemCommand(Window window, SC command)
        {
            IntPtr hwnd = new WindowInteropHelper(window).Handle;

            if (hwnd == IntPtr.Zero || !NativeMethodsShell.IsWindow(hwnd))
            {
                return;
            }

            NativeMethodsShell.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr((int)command), IntPtr.Zero);
        }
Exemple #9
0
        private void _InitializeCaptionButtonLocation()
        {
            // There is a completely different way to do this on XP.
            if (!Utility.IsOSVistaOrNewer || !NativeMethodsShell.IsThemeActive())
            {
                _LegacyInitializeCaptionButtonLocation();
                return;
            }

            var tbix = new TITLEBARINFOEX {
                cbSize = Marshal.SizeOf(typeof(TITLEBARINFOEX))
            };
            IntPtr lParam = Marshal.AllocHGlobal(tbix.cbSize);

            try
            {
                Marshal.StructureToPtr(tbix, lParam, false);
                // This might flash a window in the taskbar while being calculated.
                // WM_GETTITLEBARINFOEX doesn't work correctly unless the window is visible while processing.
                NativeMethodsShell.ShowWindow(_messageHwnd.Handle, SW.SHOW);
                NativeMethodsShell.SendMessage(_messageHwnd.Handle, WM.GETTITLEBARINFOEX, IntPtr.Zero, lParam);
                tbix = (TITLEBARINFOEX)Marshal.PtrToStructure(lParam, typeof(TITLEBARINFOEX));
            }
            finally
            {
                NativeMethodsShell.ShowWindow(_messageHwnd.Handle, SW.HIDE);
                Utility.SafeFreeHGlobal(ref lParam);
            }

            // TITLEBARINFOEX has information relative to the screen.  We need to convert the containing rect
            // to instead be relative to the top-right corner of the window.
            RECT rcAllCaptionButtons = RECT.Union(tbix.rgrect_CloseButton, tbix.rgrect_MinimizeButton);

            // For all known themes, the RECT for the maximize box shouldn't add anything to the union of the minimize and close boxes.
            Assert.AreEqual(rcAllCaptionButtons, RECT.Union(rcAllCaptionButtons, tbix.rgrect_MaximizeButton));

            RECT rcWindow = NativeMethodsShell.GetWindowRect(_messageHwnd.Handle);

            // Reorient the Top/Right to be relative to the top right edge of the Window.
            var deviceCaptionLocation = new Rect(
                rcAllCaptionButtons.Left - rcWindow.Width - rcWindow.Left,
                rcAllCaptionButtons.Top - rcWindow.Top,
                rcAllCaptionButtons.Width,
                rcAllCaptionButtons.Height);

            Rect logicalCaptionLocation = DpiHelper.DeviceRectToLogical(deviceCaptionLocation);

            WindowCaptionButtonsLocation = logicalCaptionLocation;
        }
Exemple #10
0
        static DpiHelper()
        {
            using (SafeDC desktop = SafeDC.GetDesktop())
            {
                // Can get these in the static constructor.  They shouldn't vary window to window,
                // and changing the system DPI requires a restart.
                int pixelsPerInchX = NativeMethodsShell.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSX);
                int pixelsPerInchY = NativeMethodsShell.GetDeviceCaps(desktop, DeviceCap.LOGPIXELSY);

                _transformToDip = Matrix.Identity;
                _transformToDip.Scale(96d / (double)pixelsPerInchX, 96d / (double)pixelsPerInchY);
                _transformToDevice = Matrix.Identity;
                _transformToDevice.Scale((double)pixelsPerInchX / 96d, (double)pixelsPerInchY / 96d);
            }
        }
Exemple #11
0
        private void _LegacyInitializeCaptionButtonLocation()
        {
            // This calculation isn't quite right, but it's pretty close.
            // I expect this is good enough for the scenarios where this is expected to be used.
            int captionX = NativeMethodsShell.GetSystemMetrics(SM.CXSIZE);
            int captionY = NativeMethodsShell.GetSystemMetrics(SM.CYSIZE);

            int frameX = NativeMethodsShell.GetSystemMetrics(SM.CXSIZEFRAME) + NativeMethodsShell.GetSystemMetrics(SM.CXEDGE);
            int frameY = NativeMethodsShell.GetSystemMetrics(SM.CYSIZEFRAME) + NativeMethodsShell.GetSystemMetrics(SM.CYEDGE);

            Rect captionRect = new Rect(0, 0, captionX * 3, captionY);

            captionRect.Offset(-frameX - captionRect.Width, frameY);

            WindowCaptionButtonsLocation = captionRect;
        }
Exemple #12
0
        private void _InitializeGlassColor()
        {
            bool isOpaque;
            uint color;

            NativeMethodsShell.DwmGetColorizationColor(out color, out isOpaque);
            color |= isOpaque ? 0xFF000000 : 0;

            WindowGlassColor = Utility.ColorFromArgbDword(color);

            var glassBrush = new SolidColorBrush(WindowGlassColor);

            glassBrush.Freeze();

            WindowGlassBrush = glassBrush;
        }
Exemple #13
0
        private void _InitializeWindowCornerRadius()
        {
            // The radius of window corners isn't exposed as a true system parameter.
            // It instead is a logical size that we're approximating based on the current theme.
            // There aren't any known variations based on theme color.
            Assert.IsNeitherNullNorEmpty(UxThemeName);

            // These radii are approximate.  The way WPF does rounding is different than how
            //     rounded-rectangle HRGNs are created, which is also different than the actual
            //     round corners on themed Windows.  For now we're not exposing anything to
            //     mitigate the differences.
            var cornerRadius = default(CornerRadius);

            // This list is known to be incomplete and very much not future-proof.
            // On XP there are at least a couple of shipped themes that this won't catch,
            // "Zune" and "Royale", but WPF doesn't know about these either.
            // If a new theme was to replace Aero, then this will fall back on "classic" behaviors.
            // This isn't ideal, but it's not the end of the world.  WPF will generally have problems anyways.
            switch (UxThemeName.ToUpperInvariant())
            {
            case "LUNA":
                cornerRadius = new CornerRadius(6, 6, 0, 0);
                break;

            case "AERO":
                // Aero has two cases.  One with glass and one without...
                if (NativeMethodsShell.DwmIsCompositionEnabled())
                {
                    cornerRadius = new CornerRadius(8);
                }
                else
                {
                    cornerRadius = new CornerRadius(6, 6, 0, 0);
                }
                break;

            case "CLASSIC":
            case "ZUNE":
            case "ROYALE":
            default:
                cornerRadius = new CornerRadius(0);
                break;
            }

            WindowCornerRadius = cornerRadius;
        }
Exemple #14
0
        public MessageWindow(CS classStyle, WS style, WS_EX exStyle, Rect location, string name, WndProc callback)
        {
            // A null callback means just use DefWindowProc.
            _wndProcCallback = callback;
            _className       = "MessageWindowClass+" + Guid.NewGuid().ToString();

            var wc = new WNDCLASSEX
            {
                cbSize        = Marshal.SizeOf(typeof(WNDCLASSEX)),
                style         = classStyle,
                lpfnWndProc   = s_WndProc,
                hInstance     = NativeMethodsShell.GetModuleHandle(null),
                hbrBackground = NativeMethodsShell.GetStockObject(StockObject.NULL_BRUSH),
                lpszMenuName  = "",
                lpszClassName = _className,
            };

            NativeMethodsShell.RegisterClassEx(ref wc);

            GCHandle gcHandle = default(GCHandle);

            try
            {
                gcHandle = GCHandle.Alloc(this);
                IntPtr pinnedThisPtr = (IntPtr)gcHandle;

                Handle = NativeMethodsShell.CreateWindowEx(
                    exStyle,
                    _className,
                    name,
                    style,
                    (int)location.X,
                    (int)location.Y,
                    (int)location.Width,
                    (int)location.Height,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    pinnedThisPtr);
            }
            finally
            {
                gcHandle.Free();
            }
        }
Exemple #15
0
        private IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam)
        {
            // Don't do this if called within the SystemParameters2 constructor
            if (_UpdateTable != null)
            {
                List <_SystemMetricUpdate> handlers;
                if (_UpdateTable.TryGetValue(msg, out handlers))
                {
                    Assert.IsNotNull(handlers);
                    foreach (var handler in handlers)
                    {
                        handler(wParam, lParam);
                    }
                }
            }

            return(NativeMethodsShell.DefWindowProc(hwnd, msg, wParam, lParam));
        }
Exemple #16
0
        private void _InitializeThemeInfo()
        {
            if (!NativeMethodsShell.IsThemeActive())
            {
                UxThemeName  = "Classic";
                UxThemeColor = "";
                return;
            }

            string name;
            string color;
            string size;

            NativeMethodsShell.GetCurrentThemeName(out name, out color, out size);

            // Consider whether this is the most useful way to expose this...
            UxThemeName  = System.IO.Path.GetFileNameWithoutExtension(name);
            UxThemeColor = color;
        }
Exemple #17
0
        private static IntPtr _WndProc(IntPtr hwnd, WM msg, IntPtr wParam, IntPtr lParam)
        {
            IntPtr        ret         = IntPtr.Zero;
            MessageWindow hwndWrapper = null;

            if (msg == WM.CREATE)
            {
                var      createStruct = (CREATESTRUCT)Marshal.PtrToStructure(lParam, typeof(CREATESTRUCT));
                GCHandle gcHandle     = GCHandle.FromIntPtr(createStruct.lpCreateParams);
                hwndWrapper = (MessageWindow)gcHandle.Target;
                s_windowLookup.Add(hwnd, hwndWrapper);
            }
            else
            {
                if (!s_windowLookup.TryGetValue(hwnd, out hwndWrapper))
                {
                    return(NativeMethodsShell.DefWindowProc(hwnd, msg, wParam, lParam));
                }
            }
            Assert.IsNotNull(hwndWrapper);

            WndProc callback = hwndWrapper._wndProcCallback;

            if (callback != null)
            {
                ret = callback(hwnd, msg, wParam, lParam);
            }
            else
            {
                ret = NativeMethodsShell.DefWindowProc(hwnd, msg, wParam, lParam);
            }

            if (msg == WM.NCDESTROY)
            {
                hwndWrapper._Dispose(true, true);
                GC.SuppressFinalize(hwndWrapper);
            }

            return(ret);
        }
Exemple #18
0
        internal static void ShowSystemMenuPhysicalCoordinates(Window window, Point physicalScreenLocation)
        {
            const uint TPM_RETURNCMD  = 0x0100;
            const uint TPM_LEFTBUTTON = 0x0;

            Verify.IsNotNull(window, "window");
            IntPtr hwnd = new WindowInteropHelper(window).Handle;

            if (hwnd == IntPtr.Zero || !NativeMethodsShell.IsWindow(hwnd))
            {
                return;
            }

            IntPtr hmenu = NativeMethodsShell.GetSystemMenu(hwnd, false);

            uint cmd = NativeMethodsShell.TrackPopupMenuEx(hmenu, TPM_LEFTBUTTON | TPM_RETURNCMD, (int)physicalScreenLocation.X, (int)physicalScreenLocation.Y, hwnd, IntPtr.Zero);

            if (0 != cmd)
            {
                NativeMethodsShell.PostMessage(hwnd, WM.SYSCOMMAND, new IntPtr(cmd), IntPtr.Zero);
            }
        }
        public static IShellItem2 GetShellItemForPath(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                // Internal function.  Should have verified this before calling if we cared.
                return(null);
            }

            Guid    iidShellItem2 = new Guid(IID.ShellItem2);
            object  unk;
            HRESULT hr = NativeMethodsShell.SHCreateItemFromParsingName(path, null, ref iidShellItem2, out unk);

            // Silently absorb errors such as ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND.
            // Let others pass through
            if (hr == (HRESULT)Win32Error.ERROR_FILE_NOT_FOUND || hr == (HRESULT)Win32Error.ERROR_PATH_NOT_FOUND)
            {
                hr  = HRESULT.S_OK;
                unk = null;
            }

            hr.ThrowIfFailed();

            return((IShellItem2)unk);
        }
Exemple #20
0
        private void _InitializeCaptionHeight()
        {
            Point ptCaption = new Point(0, NativeMethodsShell.GetSystemMetrics(SM.CYCAPTION));

            WindowCaptionHeight = DpiHelper.DevicePixelsToLogical(ptCaption).Y;
        }
Exemple #21
0
        // Most properties exposed here have a way of being queried directly
        // and a way of being notified of updates via a window message.
        // This region is a grouping of both, for each of the exposed properties.

        private void _InitializeIsGlassEnabled()
        {
            IsGlassEnabled = NativeMethodsShell.DwmIsCompositionEnabled();
        }
Exemple #22
0
        private void _InitializeHighContrast()
        {
            HIGHCONTRAST hc = NativeMethodsShell.SystemParameterInfo_GetHIGHCONTRAST();

            HighContrast = (hc.dwFlags & HCF.HIGHCONTRASTON) != 0;
        }
Exemple #23
0
 private void _InitializeSmallIconSize()
 {
     SmallIconSize = new Size(
         NativeMethodsShell.GetSystemMetrics(SM.CXSMICON),
         NativeMethodsShell.GetSystemMetrics(SM.CYSMICON));
 }
Exemple #24
0
 private static object _DestroyWindow(IntPtr hwnd, string className)
 {
     Utility.SafeDestroyWindow(ref hwnd);
     NativeMethodsShell.UnregisterClass(className, NativeMethodsShell.GetModuleHandle(null));
     return(null);
 }
Exemple #25
0
        public static IntPtr GenerateHICON(ImageSource image, Size dimensions)
        {
            if (image == null)
            {
                return(IntPtr.Zero);
            }

            // If we're getting this from a ".ico" resource, then it comes through as a BitmapFrame.
            // We can use leverage this as a shortcut to get the right 16x16 representation
            // because DrawImage doesn't do that for us.
            var bf = image as BitmapFrame;

            if (bf != null)
            {
                bf = GetBestMatch(bf.Decoder.Frames, (int)dimensions.Width, (int)dimensions.Height);
            }
            else
            {
                // Constrain the dimensions based on the aspect ratio.
                var drawingDimensions = new Rect(0, 0, dimensions.Width, dimensions.Height);

                // There's no reason to assume that the requested image dimensions are square.
                double renderRatio = dimensions.Width / dimensions.Height;
                double aspectRatio = image.Width / image.Height;

                // If it's smaller than the requested size, then place it in the middle and pad the image.
                if (image.Width <= dimensions.Width && image.Height <= dimensions.Height)
                {
                    drawingDimensions = new Rect((dimensions.Width - image.Width) / 2, (dimensions.Height - image.Height) / 2, image.Width, image.Height);
                }
                else if (renderRatio > aspectRatio)
                {
                    double scaledRenderWidth = (image.Width / image.Height) * dimensions.Width;
                    drawingDimensions = new Rect((dimensions.Width - scaledRenderWidth) / 2, 0, scaledRenderWidth, dimensions.Height);
                }
                else if (renderRatio < aspectRatio)
                {
                    double scaledRenderHeight = (image.Height / image.Width) * dimensions.Height;
                    drawingDimensions = new Rect(0, (dimensions.Height - scaledRenderHeight) / 2, dimensions.Width, scaledRenderHeight);
                }

                var            dv = new DrawingVisual();
                DrawingContext dc = dv.RenderOpen();
                dc.DrawImage(image, drawingDimensions);
                dc.Close();

                var bmp = new RenderTargetBitmap((int)dimensions.Width, (int)dimensions.Height, 96, 96, PixelFormats.Pbgra32);
                bmp.Render(dv);
                bf = BitmapFrame.Create(bmp);
            }

            // Using GDI+ to convert to an HICON.
            // I'd rather not duplicate their code.
            using (MemoryStream memstm = new MemoryStream())
            {
                BitmapEncoder enc = new PngBitmapEncoder();
                enc.Frames.Add(bf);
                enc.Save(memstm);

                using (var istm = new ManagedIStream(memstm))
                {
                    // We are not bubbling out GDI+ errors when creating the native image fails.
                    IntPtr bitmap = IntPtr.Zero;
                    try
                    {
                        Status gpStatus = NativeMethodsShell.GdipCreateBitmapFromStream(istm, out bitmap);
                        if (Status.Ok != gpStatus)
                        {
                            return(IntPtr.Zero);
                        }

                        IntPtr hicon;
                        gpStatus = NativeMethodsShell.GdipCreateHICONFromBitmap(bitmap, out hicon);
                        if (Status.Ok != gpStatus)
                        {
                            return(IntPtr.Zero);
                        }

                        // Caller is responsible for freeing this.
                        return(hicon);
                    }
                    finally
                    {
                        Utility.SafeDisposeImage(ref bitmap);
                    }
                }
            }
        }