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); } }
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); }
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); }
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); }
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; }
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); } }
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; }
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; }
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; }
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(); } }
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)); }
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; }
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); }
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); }
private void _InitializeCaptionHeight() { Point ptCaption = new Point(0, NativeMethodsShell.GetSystemMetrics(SM.CYCAPTION)); WindowCaptionHeight = DpiHelper.DevicePixelsToLogical(ptCaption).Y; }
// 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(); }
private void _InitializeHighContrast() { HIGHCONTRAST hc = NativeMethodsShell.SystemParameterInfo_GetHIGHCONTRAST(); HighContrast = (hc.dwFlags & HCF.HIGHCONTRASTON) != 0; }
private void _InitializeSmallIconSize() { SmallIconSize = new Size( NativeMethodsShell.GetSystemMetrics(SM.CXSMICON), NativeMethodsShell.GetSystemMetrics(SM.CYSMICON)); }
private static object _DestroyWindow(IntPtr hwnd, string className) { Utility.SafeDestroyWindow(ref hwnd); NativeMethodsShell.UnregisterClass(className, NativeMethodsShell.GetModuleHandle(null)); return(null); }
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); } } } }