зеркало из https://github.com/dotnet/winforms.git
Remove most usages of WIndowsGraphicsWrapper (#3532)
- Refactor DpiHelper a bit, adding new API to avoid DC creation (using new GetDpiForSystem()) - Add PaintEvent HDC wrapper to favor getting the natvie HDC if the Graphics wrapper hasn't been created - Extend DeviceContextHdcScope to support WindowsGraphicsWrapper migration - Change HDC property on PaintEventArgs - Add DrawLine to HDC extensions (from WindowsGraphics) - Graphics.DpiX is no different than normal device DPI, removed from CheckableControlBaseAdapter.cs - Remove Graphics from CheckBoxPopupAdapter.PaintPopupLayout - Add SetBkMode scope
This commit is contained in:
Родитель
6f85a5d9c7
Коммит
e45b38a61c
|
@ -281,7 +281,7 @@ namespace System.Windows.Forms.Design
|
|||
/// </summary>
|
||||
public static void DrawGrabHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
|
||||
{
|
||||
using var hDC = new DeviceContextHdcScope(graphics);
|
||||
using var hDC = new DeviceContextHdcScope(graphics, applyGraphicsState: false);
|
||||
|
||||
// Set our pen and brush based on primary selection
|
||||
using var brushSelection = new Gdi32.SelectObjectScope(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
|
||||
|
@ -296,7 +296,7 @@ namespace System.Windows.Forms.Design
|
|||
/// </summary>
|
||||
public static void DrawNoResizeHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
|
||||
{
|
||||
using var hDC = new DeviceContextHdcScope(graphics);
|
||||
using var hDC = new DeviceContextHdcScope(graphics, applyGraphicsState: false);
|
||||
|
||||
// Set our pen and brush based on primary selection
|
||||
using var brushSelection = new Gdi32.SelectObjectScope(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
|
||||
|
@ -311,7 +311,7 @@ namespace System.Windows.Forms.Design
|
|||
/// </summary>
|
||||
public static void DrawLockedHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
|
||||
{
|
||||
using var hDC = new DeviceContextHdcScope(graphics);
|
||||
using var hDC = new DeviceContextHdcScope(graphics, applyGraphicsState: false);
|
||||
|
||||
using var penSelection = new Gdi32.SelectObjectScope(hDC, s_grabHandlePenPrimary);
|
||||
|
||||
|
@ -440,7 +440,7 @@ namespace System.Windows.Forms.Design
|
|||
gDest.Clear(SystemColors.Control);
|
||||
}
|
||||
|
||||
using var destDC = new DeviceContextHdcScope(gDest);
|
||||
using var destDC = new DeviceContextHdcScope(gDest, applyGraphicsState: false);
|
||||
|
||||
// Perform our bitblit operation to push the image into the dest bitmap
|
||||
Gdi32.BitBlt(
|
||||
|
@ -580,7 +580,7 @@ namespace System.Windows.Forms.Design
|
|||
int fontHeight = 0;
|
||||
|
||||
using Graphics g = ctrl.CreateGraphics();
|
||||
using var dc = new DeviceContextHdcScope(g);
|
||||
using var dc = new DeviceContextHdcScope(g, applyGraphicsState: false);
|
||||
using var hFont = new Gdi32.ObjectScope(ctrl.Font.ToHFONT());
|
||||
using var hFontOld = new Gdi32.SelectObjectScope(dc, hFont);
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@ internal static partial class Interop
|
|||
internal static partial class Gdi32
|
||||
{
|
||||
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
|
||||
public static extern BOOL LineTo(IntPtr hdc, int x, int y);
|
||||
public static extern BOOL LineTo(HDC hdc, int x, int y);
|
||||
|
||||
public static BOOL LineTo(IHandle hdc, int x, int y)
|
||||
{
|
||||
BOOL result = LineTo(hdc.Handle, x, y);
|
||||
BOOL result = LineTo((HDC)hdc.Handle, x, y);
|
||||
GC.KeepAlive(hdc);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ internal static partial class Interop
|
|||
internal static partial class Gdi32
|
||||
{
|
||||
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
|
||||
public unsafe static extern BOOL MoveToEx(IntPtr hdc, int x, int y, Point* lppt);
|
||||
public unsafe static extern BOOL MoveToEx(HDC hdc, int x, int y, Point* lppt);
|
||||
|
||||
public unsafe static BOOL MoveToEx(IHandle hdc, int x, int y, Point* lppt)
|
||||
{
|
||||
BOOL result = MoveToEx(hdc.Handle, x, y, lppt);
|
||||
BOOL result = MoveToEx((HDC)hdc.Handle, x, y, lppt);
|
||||
GC.KeepAlive(hdc);
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class Gdi32
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper to scope selecting a given background mix mode into a HDC. Restores the original
|
||||
/// mix mode into the HDC when disposed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use in a <see langword="using" /> statement. If you must pass this around, always pass by
|
||||
/// <see langword="ref" /> to avoid duplicating the handle and resetting multiple times.
|
||||
/// </remarks>
|
||||
internal ref struct SetBkModeScope
|
||||
{
|
||||
private readonly BKMODE _previousMode;
|
||||
private readonly HDC _hdc;
|
||||
|
||||
/// <summary>
|
||||
/// Selects <paramref name="bkmode"/> into the given <paramref name="hdc"/>.
|
||||
/// </summary>
|
||||
public SetBkModeScope(HDC hdc, BKMODE bkmode)
|
||||
{
|
||||
_previousMode = SetBkMode(hdc, bkmode);
|
||||
|
||||
// If we didn't actually change the mode, don't keep the HDC so we skip putting back the same state.
|
||||
_hdc = _previousMode == bkmode ? default : hdc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (!_hdc.IsNull)
|
||||
{
|
||||
SetBkMode(_hdc, _previousMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,13 +26,18 @@ internal static partial class Interop
|
|||
/// </summary>
|
||||
public SetRop2Scope(HDC hdc, R2 rop2)
|
||||
{
|
||||
_hdc = hdc;
|
||||
_previousRop = SetROP2(hdc, rop2);
|
||||
|
||||
// If we didn't actually change the ROP, don't keep the HDC so we skip putting back the same state.
|
||||
_hdc = _previousRop == rop2 ? default : hdc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
SetROP2(_hdc, _previousRop);
|
||||
if (!_hdc.IsNull)
|
||||
{
|
||||
SetROP2(_hdc, _previousRop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
internal static partial class Interop
|
||||
{
|
||||
internal static partial class User32
|
||||
{
|
||||
// This is only available on Windows 1607 and later. Avoids needing a DC to get the DPI.
|
||||
[DllImport(Libraries.User32, ExactSpelling = true)]
|
||||
public static extern uint GetDpiForSystem();
|
||||
}
|
||||
}
|
|
@ -10,13 +10,24 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern unsafe HRESULT DrawThemeBackground(IntPtr hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, ref RECT pRect, RECT* pClipRect);
|
||||
public static extern unsafe HRESULT DrawThemeBackground(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pRect,
|
||||
RECT* pClipRect);
|
||||
|
||||
public static unsafe HRESULT DrawThemeBackground(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, ref RECT pRect, RECT* pClipRect)
|
||||
public static unsafe HRESULT DrawThemeBackground(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pRect,
|
||||
RECT* pClipRect)
|
||||
{
|
||||
HRESULT hr = DrawThemeBackground(hTheme.Handle, (Gdi32.HDC)hdc.Handle, iPartId, iStateId, ref pRect, pClipRect);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ internal static partial class Interop
|
|||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT DrawThemeEdge(
|
||||
IntPtr hTheme,
|
||||
IntPtr hdc,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pDestRect,
|
||||
|
@ -22,7 +22,7 @@ internal static partial class Interop
|
|||
|
||||
public static HRESULT DrawThemeEdge(
|
||||
IHandle hTheme,
|
||||
IHandle hdc,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pDestRect,
|
||||
|
@ -30,9 +30,8 @@ internal static partial class Interop
|
|||
User32.BF uFlags,
|
||||
ref RECT pContentRect)
|
||||
{
|
||||
HRESULT hr = DrawThemeEdge(hTheme.Handle, hdc.Handle, iPartId, iStateId, ref pDestRect, uEdge, uFlags, ref pContentRect);
|
||||
HRESULT hr = DrawThemeEdge(hTheme.Handle, hdc, iPartId, iStateId, ref pDestRect, uEdge, uFlags, ref pContentRect);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT DrawThemeParentBackground(IntPtr hwnd, IntPtr hdc, ref RECT prc);
|
||||
public static extern HRESULT DrawThemeParentBackground(IntPtr hwnd, Gdi32.HDC hdc, ref RECT prc);
|
||||
|
||||
public static HRESULT DrawThemeParentBackground(IHandle hwnd, IHandle hdc, ref RECT prc)
|
||||
public static HRESULT DrawThemeParentBackground(IHandle hwnd, Gdi32.HDC hdc, ref RECT prc)
|
||||
{
|
||||
HRESULT hr = DrawThemeParentBackground(hwnd.Handle, hdc.Handle, ref prc);
|
||||
HRESULT hr = DrawThemeParentBackground(hwnd.Handle, hdc, ref prc);
|
||||
GC.KeepAlive(hwnd);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ internal static partial class Interop
|
|||
[DllImport(Libraries.UxTheme, ExactSpelling = true, CharSet = CharSet.Unicode)]
|
||||
public static extern HRESULT DrawThemeText(
|
||||
IntPtr hTheme,
|
||||
IntPtr hdc,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
string pszText,
|
||||
|
@ -23,7 +23,7 @@ internal static partial class Interop
|
|||
|
||||
public static HRESULT DrawThemeText(
|
||||
IHandle hTheme,
|
||||
IHandle hdc,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
string pszText,
|
||||
|
@ -32,9 +32,8 @@ internal static partial class Interop
|
|||
uint dwTextFlags2,
|
||||
ref RECT pRect)
|
||||
{
|
||||
HRESULT hr = DrawThemeText(hTheme.Handle, hdc.Handle, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, ref pRect);
|
||||
HRESULT hr = DrawThemeText(hTheme.Handle, hdc, iPartId, iStateId, pszText, iCharCount, dwTextFlags, dwTextFlags2, ref pRect);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,24 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT GetThemeBackgroundContentRect(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pBoundingRect, out RECT pContentRect);
|
||||
public static extern HRESULT GetThemeBackgroundContentRect(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pBoundingRect,
|
||||
out RECT pContentRect);
|
||||
|
||||
public static HRESULT GetThemeBackgroundContentRect(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, ref RECT pBoundingRect, out RECT pContentRect)
|
||||
public static HRESULT GetThemeBackgroundContentRect(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pBoundingRect,
|
||||
out RECT pContentRect)
|
||||
{
|
||||
HRESULT hr = GetThemeBackgroundContentRect(hTheme.Handle, hdc.Handle, iPartId, iStateId, ref pBoundingRect, out pContentRect);
|
||||
HRESULT hr = GetThemeBackgroundContentRect(hTheme.Handle, hdc, iPartId, iStateId, ref pBoundingRect, out pContentRect);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT GetThemeBackgroundExtent(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pContentRect, out RECT pExtentRect);
|
||||
public static extern HRESULT GetThemeBackgroundExtent(IntPtr hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, ref RECT pContentRect, out RECT pExtentRect);
|
||||
|
||||
public static HRESULT GetThemeBackgroundExtent(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, ref RECT pContentRect, out RECT pExtentRect)
|
||||
public static HRESULT GetThemeBackgroundExtent(IHandle hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, ref RECT pContentRect, out RECT pExtentRect)
|
||||
{
|
||||
HRESULT hr = GetThemeBackgroundExtent(hTheme.Handle, hdc.Handle, iPartId, iStateId, ref pContentRect, out pExtentRect);
|
||||
HRESULT hr = GetThemeBackgroundExtent(hTheme.Handle, hdc, iPartId, iStateId, ref pContentRect, out pExtentRect);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,24 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT GetThemeBackgroundRegion(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, ref RECT pRect, out IntPtr pRegion);
|
||||
public static extern HRESULT GetThemeBackgroundRegion(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pRect,
|
||||
out Gdi32.HRGN pRegion);
|
||||
|
||||
public static HRESULT GetThemeBackgroundRegion(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, ref RECT pRect, out IntPtr pRegion)
|
||||
public static HRESULT GetThemeBackgroundRegion(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
ref RECT pRect,
|
||||
out Gdi32.HRGN pRegion)
|
||||
{
|
||||
HRESULT hr = GetThemeBackgroundRegion(hTheme.Handle, hdc.Handle, iPartId, iStateId, ref pRect, out pRegion);
|
||||
HRESULT hr = GetThemeBackgroundRegion(hTheme.Handle, hdc, iPartId, iStateId, ref pRect, out pRegion);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public static extern HRESULT GetThemeFont(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, int iPropId, out User32.LOGFONTW pFont);
|
||||
public static extern HRESULT GetThemeFont(IntPtr hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, int iPropId, out User32.LOGFONTW pFont);
|
||||
|
||||
public static HRESULT GetThemeFont(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, int iPropId, out User32.LOGFONTW pFont)
|
||||
public static HRESULT GetThemeFont(IHandle hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, int iPropId, out User32.LOGFONTW pFont)
|
||||
{
|
||||
HRESULT result = GetThemeFont(hTheme.Handle, hdc.Handle, iPartId, iStateId, iPropId, out pFont);
|
||||
HRESULT result = GetThemeFont(hTheme.Handle, hdc, iPartId, iStateId, iPropId, out pFont);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,26 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public unsafe static extern HRESULT GetThemeMargins(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, int iPropId, RECT* prc, out MARGINS pMargins);
|
||||
public unsafe static extern HRESULT GetThemeMargins(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
int iPropId,
|
||||
RECT* prc,
|
||||
out MARGINS pMargins);
|
||||
|
||||
public unsafe static HRESULT GetThemeMargins(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, int iPropId, RECT* prc, out MARGINS pMargins)
|
||||
public unsafe static HRESULT GetThemeMargins(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
int iPropId,
|
||||
RECT* prc,
|
||||
out MARGINS pMargins)
|
||||
{
|
||||
HRESULT hr = GetThemeMargins(hTheme.Handle, hdc.Handle, iPartId, iStateId, iPropId, prc, out pMargins);
|
||||
HRESULT hr = GetThemeMargins(hTheme.Handle, hdc, iPartId, iStateId, iPropId, prc, out pMargins);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,26 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public unsafe static extern HRESULT GetThemePartSize(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, RECT* prc, ThemeSizeType eSize, out Size psz);
|
||||
public unsafe static extern HRESULT GetThemePartSize(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
RECT* prc,
|
||||
ThemeSizeType eSize,
|
||||
out Size psz);
|
||||
|
||||
public unsafe static HRESULT GetThemePartSize(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, RECT* prc, ThemeSizeType eSize, out Size psz)
|
||||
public unsafe static HRESULT GetThemePartSize(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
RECT* prc,
|
||||
ThemeSizeType eSize,
|
||||
out Size psz)
|
||||
{
|
||||
HRESULT hr = GetThemePartSize(hTheme.Handle, hdc.Handle, iPartId, iStateId, prc, eSize, out psz);
|
||||
HRESULT hr = GetThemePartSize(hTheme.Handle, hdc, iPartId, iStateId, prc, eSize, out psz);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,13 +10,40 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
public unsafe static extern HRESULT GetThemeTextExtent(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, string pszText, int cchCharCount, uint dwTextFlags, RECT* pBoundingRect, out RECT pExtentRect);
|
||||
public unsafe static extern HRESULT GetThemeTextExtent(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
string pszText,
|
||||
int cchCharCount,
|
||||
uint dwTextFlags,
|
||||
RECT* pBoundingRect,
|
||||
out RECT pExtentRect);
|
||||
|
||||
public unsafe static HRESULT GetThemeTextExtent(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, string pszText, int cchCharCount, uint dwTextFlags, RECT* pBoundingRect, out RECT pExtentRect)
|
||||
public unsafe static HRESULT GetThemeTextExtent(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
string pszText,
|
||||
int cchCharCount,
|
||||
uint dwTextFlags,
|
||||
RECT* pBoundingRect,
|
||||
out RECT pExtentRect)
|
||||
{
|
||||
HRESULT hr = GetThemeTextExtent(hTheme.Handle, hdc.Handle, iPartId, iStateId, pszText, cchCharCount, dwTextFlags, pBoundingRect, out pExtentRect);
|
||||
HRESULT hr = GetThemeTextExtent(
|
||||
hTheme.Handle,
|
||||
hdc,
|
||||
iPartId,
|
||||
iStateId,
|
||||
pszText,
|
||||
cchCharCount,
|
||||
dwTextFlags,
|
||||
pBoundingRect,
|
||||
out pExtentRect);
|
||||
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,12 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public unsafe static extern HRESULT GetThemeTextMetrics(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, out TextMetrics ptm);
|
||||
public unsafe static extern HRESULT GetThemeTextMetrics(IntPtr hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, out TextMetrics ptm);
|
||||
|
||||
public unsafe static HRESULT GetThemeTextMetrics(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, out TextMetrics ptm)
|
||||
public unsafe static HRESULT GetThemeTextMetrics(IHandle hTheme, Gdi32.HDC hdc, int iPartId, int iStateId, out TextMetrics ptm)
|
||||
{
|
||||
HRESULT hr = GetThemeTextMetrics(hTheme.Handle, hdc.Handle, iPartId, iStateId, out ptm);
|
||||
HRESULT hr = GetThemeTextMetrics(hTheme.Handle, hdc, iPartId, iStateId, out ptm);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,30 @@ internal static partial class Interop
|
|||
public static partial class UxTheme
|
||||
{
|
||||
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
|
||||
public unsafe static extern HRESULT HitTestThemeBackground(IntPtr hTheme, IntPtr hdc, int iPartId, int iStateId, uint dwOptions, ref RECT pRect, IntPtr hrgn, Point ptTest, out ushort pwHitTestCode);
|
||||
public unsafe static extern HRESULT HitTestThemeBackground(
|
||||
IntPtr hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
uint dwOptions,
|
||||
ref RECT pRect,
|
||||
IntPtr hrgn,
|
||||
Point ptTest,
|
||||
out ushort pwHitTestCode);
|
||||
|
||||
public unsafe static HRESULT HitTestThemeBackground(IHandle hTheme, IHandle hdc, int iPartId, int iStateId, uint dwOptions, ref RECT pRect, IntPtr hrgn, Point ptTest, out ushort pwHitTestCode)
|
||||
public unsafe static HRESULT HitTestThemeBackground(
|
||||
IHandle hTheme,
|
||||
Gdi32.HDC hdc,
|
||||
int iPartId,
|
||||
int iStateId,
|
||||
uint dwOptions,
|
||||
ref RECT pRect,
|
||||
IntPtr hrgn,
|
||||
Point ptTest,
|
||||
out ushort pwHitTestCode)
|
||||
{
|
||||
HRESULT hr = HitTestThemeBackground(hTheme.Handle, hdc.Handle, iPartId, iStateId, dwOptions, ref pRect, hrgn, ptTest, out pwHitTestCode);
|
||||
HRESULT hr = HitTestThemeBackground(hTheme.Handle, hdc, iPartId, iStateId, dwOptions, ref pRect, hrgn, ptTest, out pwHitTestCode);
|
||||
GC.KeepAlive(hTheme);
|
||||
GC.KeepAlive(hdc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,21 +11,21 @@ namespace System.Windows.Forms
|
|||
[Flags]
|
||||
internal enum ApplyGraphicsProperties
|
||||
{
|
||||
None = 0x00000000,
|
||||
None = 0x0000_0000,
|
||||
|
||||
/// <summary>
|
||||
/// Apply clipping region.
|
||||
/// </summary>
|
||||
Clipping = 0x00000001,
|
||||
Clipping = 0x0000_0001,
|
||||
|
||||
/// <summary>
|
||||
/// Apply coordinate transformation.
|
||||
/// </summary>
|
||||
TranslateTransform = 0x00000002,
|
||||
TranslateTransform = 0x0000_0002,
|
||||
|
||||
/// <summary>
|
||||
/// Apply all supported Graphics properties.
|
||||
/// </summary>
|
||||
All = Clipping | TranslateTransform
|
||||
All = Clipping | TranslateTransform
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,27 @@ namespace System.Windows.Forms
|
|||
hbrush);
|
||||
}
|
||||
|
||||
internal static void DrawLine(this DeviceContextHdcScope hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
|
||||
=> DrawLine(hdc.HDC, pen, x1, y1, x2, y2);
|
||||
|
||||
internal static void DrawLine(this Gdi32.CreateDcScope hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
|
||||
=> DrawLine(hdc.HDC, pen, x1, y1, x2, y2);
|
||||
|
||||
internal static void DrawLine(this User32.GetDcScope hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
|
||||
=> DrawLine(hdc.HDC, pen, x1, y1, x2, y2);
|
||||
|
||||
internal unsafe static void DrawLine(this Gdi32.HDC hdc, Gdi32.HPEN pen, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
using var ropScope = new Gdi32.SetRop2Scope(hdc, Gdi32.R2.COPYPEN);
|
||||
using var bkScope = new Gdi32.SetBkModeScope(hdc, Gdi32.BKMODE.TRANSPARENT);
|
||||
using var selection = new Gdi32.SelectObjectScope(hdc, pen);
|
||||
|
||||
Point oldPoint = new Point();
|
||||
Gdi32.MoveToEx(hdc, x1, y1, &oldPoint);
|
||||
Gdi32.LineTo(hdc, x2, y2);
|
||||
Gdi32.MoveToEx(hdc, oldPoint.X, oldPoint.Y, &oldPoint);
|
||||
}
|
||||
|
||||
internal static Color GetNearestColor(this DeviceContextHdcScope hdc, Color color)
|
||||
=> GetNearestColor(hdc.HDC, color);
|
||||
|
||||
|
@ -63,5 +84,17 @@ namespace System.Windows.Forms
|
|||
internal static Graphics CreateGraphics(this Gdi32.HDC hdc) => Graphics.FromHdcInternal(hdc.Handle);
|
||||
internal static Graphics CreateGraphics(this Gdi32.CreateDcScope hdc) => Graphics.FromHdcInternal(hdc.HDC.Handle);
|
||||
internal static Graphics CreateGraphics(this User32.GetDcScope hdc) => Graphics.FromHdcInternal(hdc.HDC.Handle);
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of pixels per logical inch along the device width. In a system with multiple display
|
||||
/// monitors, this value is always from the primary display.
|
||||
/// </summary>
|
||||
internal static int GetDpiX(this Gdi32.HDC hdc) => Gdi32.GetDeviceCaps(hdc, Gdi32.DeviceCapability.LOGPIXELSX);
|
||||
|
||||
/// <summary>
|
||||
/// Get the number of pixels per logical inch along the device (screen) height. In a system with multiple
|
||||
/// display monitors, this value is always from the primary display.
|
||||
/// </summary>
|
||||
internal static int GetDpiY(this Gdi32.HDC hdc) => Gdi32.GetDeviceCaps(hdc, Gdi32.DeviceCapability.LOGPIXELSY);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,59 +19,52 @@ namespace System.Windows.Forms
|
|||
/// Use in a <see langword="using" /> statement. If you must pass this around, always pass by+
|
||||
/// <see langword="ref" /> to avoid duplicating the handle and risking a double release.
|
||||
/// </remarks>
|
||||
internal ref struct DeviceContextHdcScope
|
||||
internal readonly ref struct DeviceContextHdcScope
|
||||
{
|
||||
public readonly Gdi32.HDC HDC { get; }
|
||||
public IDeviceContext DeviceContext { get; }
|
||||
public int _savedState;
|
||||
public Gdi32.HDC HDC { get; }
|
||||
|
||||
private readonly int _savedHdcState;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Gdi32.HDC"/> from the the given <paramref name="deviceContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="saveState">When true, saves the state.</param>
|
||||
public DeviceContextHdcScope(IDeviceContext deviceContext, bool saveState = true)
|
||||
{
|
||||
DeviceContext = deviceContext;
|
||||
HDC = (Gdi32.HDC)deviceContext.GetHdc();
|
||||
_savedState = saveState ? Gdi32.SaveDC(HDC) : 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Gdi32.HDC"/> from the the given <paramref name="graphics"/>. Applies <paramref name="apply"/>
|
||||
/// properties as specified.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// When a <see cref="Graphics"/> object is created from a <see cref="Gdi32.HDC"/> the clipping region and
|
||||
/// the viewport origin are applied (<see cref="Gdi32.GetViewportExtEx(Gdi32.HDC, out Size)"/>). The clipping
|
||||
/// region isn't reflected in <see cref="Graphics.Clip"/>, which is combined with the HDC HRegion. We provide
|
||||
/// the capacity to do the same to the retrieved HDC with <see cref="ApplyGraphicsProperties.Clipping"/>.
|
||||
/// region isn't reflected in <see cref="Graphics.Clip"/>, which is combined with the HDC HRegion.
|
||||
///
|
||||
/// The Graphics object saves and restores DC state when performing operations that would modify the DC to
|
||||
/// maintain the DC in it's original or returned state after <see cref="Graphics.ReleaseHdc()"/>.
|
||||
///
|
||||
/// Outside of munging the DC with <paramref name="apply"/> we should consider adding an option to skip saving
|
||||
/// the state here when we know we aren't changing the DC state without restoring it (e.g. selecting a pen into
|
||||
/// the HDC without selecting the original pen back.
|
||||
/// maintain the DC in its original or returned state after <see cref="Graphics.ReleaseHdc()"/>.
|
||||
/// </remarks>
|
||||
/// <param name="saveState">
|
||||
/// When true, always saves the state. Otherwise only saves the state if the HDC is modified due
|
||||
/// to <paramref name="apply" />.
|
||||
/// <param name="applyGraphicsState">
|
||||
/// Applies the origin transform and clipping region of the <paramref name="deviceContext"/> if it is an
|
||||
/// object of type <see cref="Graphics"/>. Otherwise this is a no-op.
|
||||
/// </param>
|
||||
public DeviceContextHdcScope(Graphics graphics, ApplyGraphicsProperties apply, bool saveState = true)
|
||||
/// <param name="saveHdcState">
|
||||
/// When true, saves and restores the <see cref="Gdi32.HDC"/> state.
|
||||
/// </param>
|
||||
public DeviceContextHdcScope(
|
||||
IDeviceContext deviceContext,
|
||||
bool applyGraphicsState = true,
|
||||
bool saveHdcState = false)
|
||||
{
|
||||
DeviceContext = graphics;
|
||||
_savedState = 0;
|
||||
DeviceContext = deviceContext ?? throw new ArgumentNullException(nameof(deviceContext));
|
||||
ApplyGraphicsProperties apply = applyGraphicsState ? ApplyGraphicsProperties.All : ApplyGraphicsProperties.None;
|
||||
_savedHdcState = 0;
|
||||
|
||||
if (apply == ApplyGraphicsProperties.None)
|
||||
if (apply == ApplyGraphicsProperties.None || !(DeviceContext is Graphics graphics))
|
||||
{
|
||||
// GetHdc() locks the Graphics object, it cannot be used until ReleaseHdc() is called
|
||||
HDC = (Gdi32.HDC)graphics.GetHdc();
|
||||
_savedState = saveState ? Gdi32.SaveDC(HDC) : 0;
|
||||
HDC = (Gdi32.HDC)DeviceContext.GetHdc();
|
||||
_savedHdcState = saveHdcState ? Gdi32.SaveDC(HDC) : 0;
|
||||
return;
|
||||
}
|
||||
|
||||
bool applyTransform = apply.HasFlag(ApplyGraphicsProperties.TranslateTransform);
|
||||
bool applyClipping = apply.HasFlag(ApplyGraphicsProperties.Clipping);
|
||||
|
||||
// This API is very expensive
|
||||
object[]? data = applyTransform || applyClipping ? (object[])graphics.GetContextInfo() : null;
|
||||
|
||||
using Region? clipRegion = (Region?)data?[0];
|
||||
|
@ -88,9 +81,9 @@ namespace System.Windows.Forms
|
|||
|
||||
HDC = (Gdi32.HDC)graphics.GetHdc();
|
||||
|
||||
if (saveState || applyClipping || applyTransform)
|
||||
if (saveHdcState || applyClipping || applyTransform)
|
||||
{
|
||||
_savedState = Gdi32.SaveDC(HDC);
|
||||
_savedHdcState = Gdi32.SaveDC(HDC);
|
||||
}
|
||||
|
||||
if (applyClipping)
|
||||
|
@ -125,24 +118,18 @@ namespace System.Windows.Forms
|
|||
}
|
||||
}
|
||||
|
||||
public static implicit operator Gdi32.HDC(DeviceContextHdcScope scope) => scope.HDC;
|
||||
public static explicit operator IntPtr(DeviceContextHdcScope scope) => scope.HDC.Handle;
|
||||
public static implicit operator Gdi32.HDC(in DeviceContextHdcScope scope) => scope.HDC;
|
||||
public static explicit operator IntPtr(in DeviceContextHdcScope scope) => scope.HDC.Handle;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_savedState != 0)
|
||||
if (_savedHdcState != 0)
|
||||
{
|
||||
Gdi32.RestoreDC(HDC, _savedState);
|
||||
Gdi32.RestoreDC(HDC, _savedHdcState);
|
||||
}
|
||||
|
||||
if (DeviceContext is Graphics graphics)
|
||||
{
|
||||
graphics.ReleaseHdc((IntPtr)HDC);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeviceContext.ReleaseHdc();
|
||||
}
|
||||
// Note that Graphics keeps track of the HDC it passes back, so we don't need to pass it back in
|
||||
DeviceContext?.ReleaseHdc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
@ -15,70 +16,50 @@ namespace System.Windows.Forms
|
|||
internal static partial class DpiHelper
|
||||
{
|
||||
internal const double LogicalDpi = 96.0;
|
||||
private static bool s_isInitialized = false;
|
||||
private static bool s_isInitializeDpiHelperForWinforms = false;
|
||||
|
||||
/// <summary>
|
||||
/// The primary screen's (device) current DPI
|
||||
/// </summary>
|
||||
private static double s_deviceDpi = LogicalDpi;
|
||||
private static double s_logicalToDeviceUnitsScalingFactor = 0.0;
|
||||
private static InterpolationMode s_interpolationMode = InterpolationMode.Invalid;
|
||||
|
||||
// Backing field, indicating that we will need to send a PerMonitorV2 query in due course.
|
||||
private static bool s_doesNeedQueryForPerMonitorV2Awareness = false;
|
||||
private static readonly bool s_perMonitorAware = GetPerMonitorAware();
|
||||
|
||||
// Backing field, indicating that either DPI is <> 96 or we are in some PerMonitor HighDpi mode.
|
||||
private static bool s_isScalingRequirementMet = false;
|
||||
internal static int DeviceDpi { get; } = GetDeviceDPI();
|
||||
|
||||
private static void Initialize()
|
||||
private static int GetDeviceDPI()
|
||||
{
|
||||
if (s_isInitialized)
|
||||
return;
|
||||
// This never changes for the process. Depending on what the DPI awareness settings are we'll get
|
||||
// either the actual DPI of the primary display at process startup or the default LogicalDpi;
|
||||
|
||||
using var dc = User32.GetDcScope.ScreenDC;
|
||||
s_deviceDpi = Gdi32.GetDeviceCaps(dc, Gdi32.DeviceCapability.LOGPIXELSX);
|
||||
s_isInitialized = true;
|
||||
if (!OsVersion.IsWindows10_1607OrGreater)
|
||||
{
|
||||
using var dc = User32.GetDcScope.ScreenDC;
|
||||
return Gdi32.GetDeviceCaps(dc, Gdi32.DeviceCapability.LOGPIXELSX);
|
||||
}
|
||||
// This avoids needing to create a DC
|
||||
return (int)User32.GetDpiForSystem();
|
||||
}
|
||||
|
||||
internal static void InitializeDpiHelperForWinforms()
|
||||
private static bool GetPerMonitorAware()
|
||||
{
|
||||
if (s_isInitializeDpiHelperForWinforms)
|
||||
if (!OsVersion.IsWindows10_1607OrGreater)
|
||||
{
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize shared fields
|
||||
Initialize();
|
||||
HRESULT result = SHCore.GetProcessDpiAwareness(
|
||||
IntPtr.Zero,
|
||||
out SHCore.PROCESS_DPI_AWARENESS processDpiAwareness);
|
||||
|
||||
if (OsVersion.IsWindows10_1607OrGreater)
|
||||
Debug.Assert(result.Succeeded(), $"Failed to get ProcessDpi HRESULT: {result}");
|
||||
Debug.Assert(Enum.IsDefined(typeof(SHCore.PROCESS_DPI_AWARENESS), processDpiAwareness));
|
||||
|
||||
return result.Succeeded() && processDpiAwareness switch
|
||||
{
|
||||
// We are on Windows 10/1603 or greater, but we could still be DpiUnaware or SystemAware, so let's find that out...
|
||||
IntPtr hProcess = Kernel32.OpenProcess(
|
||||
Kernel32.ProcessAccessOptions.QUERY_INFORMATION,
|
||||
BOOL.FALSE,
|
||||
Kernel32.GetCurrentProcessId());
|
||||
SHCore.GetProcessDpiAwareness(hProcess, out SHCore.PROCESS_DPI_AWARENESS processDpiAwareness);
|
||||
|
||||
// Only if we're not, it makes sense to query for PerMonitorV2 awareness from now on, if needed.
|
||||
if (!(processDpiAwareness == SHCore.PROCESS_DPI_AWARENESS.UNAWARE ||
|
||||
processDpiAwareness == SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE))
|
||||
{
|
||||
s_doesNeedQueryForPerMonitorV2Awareness = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsScalingRequired || s_doesNeedQueryForPerMonitorV2Awareness)
|
||||
{
|
||||
s_isScalingRequirementMet = true;
|
||||
}
|
||||
|
||||
s_isInitializeDpiHelperForWinforms = true;
|
||||
SHCore.PROCESS_DPI_AWARENESS.UNAWARE => false,
|
||||
SHCore.PROCESS_DPI_AWARENESS.SYSTEM_AWARE => false,
|
||||
SHCore.PROCESS_DPI_AWARENESS.PER_MONITOR_AWARE => true,
|
||||
_ => true
|
||||
};
|
||||
}
|
||||
|
||||
internal static bool DoesCurrentContextRequireScaling
|
||||
=> true;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a boolean to specify if we should enable processing of WM_DPICHANGED and related messages
|
||||
/// </summary>
|
||||
|
@ -86,8 +67,7 @@ namespace System.Windows.Forms
|
|||
{
|
||||
get
|
||||
{
|
||||
InitializeDpiHelperForWinforms();
|
||||
if (s_doesNeedQueryForPerMonitorV2Awareness)
|
||||
if (s_perMonitorAware)
|
||||
{
|
||||
// We can't cache this value because different top level windows can have different DPI awareness context
|
||||
// for mixed mode applications.
|
||||
|
@ -104,36 +84,12 @@ namespace System.Windows.Forms
|
|||
/// <summary>
|
||||
/// Indicates, if rescaling becomes necessary, either because we are not 96 DPI or we're PerMonitorV2Aware.
|
||||
/// </summary>
|
||||
internal static bool IsScalingRequirementMet
|
||||
{
|
||||
get
|
||||
{
|
||||
InitializeDpiHelperForWinforms();
|
||||
return s_isScalingRequirementMet;
|
||||
}
|
||||
}
|
||||
internal static bool IsScalingRequirementMet => IsScalingRequired || s_perMonitorAware;
|
||||
|
||||
internal static int DeviceDpi
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return (int)s_deviceDpi;
|
||||
}
|
||||
}
|
||||
|
||||
private static double LogicalToDeviceUnitsScalingFactor
|
||||
{
|
||||
get
|
||||
{
|
||||
if (s_logicalToDeviceUnitsScalingFactor == 0.0)
|
||||
{
|
||||
Initialize();
|
||||
s_logicalToDeviceUnitsScalingFactor = s_deviceDpi / LogicalDpi;
|
||||
}
|
||||
return s_logicalToDeviceUnitsScalingFactor;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Returns the ratio of <see cref="DeviceDpi"/> to <see cref="LogicalDpi"/>.
|
||||
/// </summary>
|
||||
internal static double LogicalToDeviceUnitsScalingFactor => DeviceDpi / LogicalDpi;
|
||||
|
||||
private static InterpolationMode InterpolationMode
|
||||
{
|
||||
|
@ -201,14 +157,7 @@ namespace System.Windows.Forms
|
|||
/// Returns whether scaling is required when converting between logical-device units,
|
||||
/// if the application opted in the automatic scaling in the .config file.
|
||||
/// </summary>
|
||||
public static bool IsScalingRequired
|
||||
{
|
||||
get
|
||||
{
|
||||
Initialize();
|
||||
return s_deviceDpi != LogicalDpi;
|
||||
}
|
||||
}
|
||||
public static bool IsScalingRequired => DeviceDpi != LogicalDpi;
|
||||
|
||||
/// <summary>
|
||||
/// scale logical pixel to the factor
|
||||
|
@ -221,7 +170,7 @@ namespace System.Windows.Forms
|
|||
|
||||
/// <summary>
|
||||
/// Transforms a horizontal or vertical integer coordinate from logical to device units
|
||||
/// by scaling it up for current DPI and rounding to nearest integer value
|
||||
/// by scaling it up for current DPI and rounding to nearest integer value
|
||||
/// </summary>
|
||||
/// <param name="value">value in logical units</param>
|
||||
/// <returns>value in device units</returns>
|
||||
|
@ -229,10 +178,11 @@ namespace System.Windows.Forms
|
|||
{
|
||||
if (devicePixels == 0)
|
||||
{
|
||||
return (int)Math.Round(LogicalToDeviceUnitsScalingFactor * (double)value);
|
||||
return (int)Math.Round(LogicalToDeviceUnitsScalingFactor * value);
|
||||
}
|
||||
|
||||
double scalingFactor = devicePixels / LogicalDpi;
|
||||
return (int)Math.Round(scalingFactor * (double)value);
|
||||
return (int)Math.Round(scalingFactor * value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -243,10 +193,11 @@ namespace System.Windows.Forms
|
|||
/// <returns>Padding in device units</returns>
|
||||
public static Padding LogicalToDeviceUnits(Padding logicalPadding, int deviceDpi = 0)
|
||||
{
|
||||
return new Padding(LogicalToDeviceUnits(logicalPadding.Left, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Top, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Right, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Bottom, deviceDpi));
|
||||
return new Padding(
|
||||
LogicalToDeviceUnits(logicalPadding.Left, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Top, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Right, deviceDpi),
|
||||
LogicalToDeviceUnits(logicalPadding.Bottom, deviceDpi));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace System.Windows.Forms.Tests
|
|||
graphics.Clip = region;
|
||||
graphics.Transform = new Matrix(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f);
|
||||
|
||||
using (var hdcScope = new DeviceContextHdcScope(graphics, ApplyGraphicsProperties.All))
|
||||
using (var hdcScope = new DeviceContextHdcScope(graphics))
|
||||
{
|
||||
using var regionScope = new Gdi32.RegionScope(hdcScope);
|
||||
Assert.False(regionScope.IsNull);
|
||||
|
|
|
@ -1040,8 +1040,6 @@ namespace System.Windows.Forms
|
|||
{
|
||||
ApplicationContext.MainForm.Visible = true;
|
||||
}
|
||||
|
||||
DpiHelper.InitializeDpiHelperForWinforms();
|
||||
}
|
||||
|
||||
Form oldForm = _currentForm;
|
||||
|
|
|
@ -776,12 +776,6 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
#region Draw Content Helpers
|
||||
|
||||
// the DataGridViewButtonCell uses this method
|
||||
internal static void PaintButtonBackground(WindowsGraphics wg, Rectangle bounds, WindowsBrush background)
|
||||
{
|
||||
wg.FillRectangle(background, bounds);
|
||||
}
|
||||
|
||||
internal void PaintButtonBackground(PaintEventArgs e, Rectangle bounds, Brush background)
|
||||
{
|
||||
if (background == null)
|
||||
|
@ -906,16 +900,6 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
colors.windowFrame = foreColor;
|
||||
|
||||
/* debug * /
|
||||
colors.buttonFace = Color.Yellow;
|
||||
colors.buttonShadow = Color.Blue;
|
||||
colors.highlight = Color.Brown;
|
||||
colors.lowButtonFace = Color.Beige;
|
||||
colors.lowHighlight = Color.Cyan;
|
||||
colors.windowFrame = Color.Red;
|
||||
colors.windowText = Color.Green;
|
||||
/ * debug */
|
||||
|
||||
if (colors.buttonFace.GetBrightness() < .5)
|
||||
{
|
||||
colors.constrastButtonShadow = colors.lowHighlight;
|
||||
|
@ -939,7 +923,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
colors.windowText = colors.windowFrame;
|
||||
}
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(graphics, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(graphics, applyGraphicsState: false);
|
||||
|
||||
colors.buttonFace = hdc.GetNearestColor(colors.buttonFace);
|
||||
colors.buttonShadow = hdc.GetNearestColor(colors.buttonShadow);
|
||||
|
@ -1620,12 +1604,13 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
protected virtual Size GetTextSize(Size proposedSize)
|
||||
{
|
||||
//set the Prefix field of TextFormatFlags
|
||||
// Set the Prefix field of TextFormatFlags
|
||||
proposedSize = LayoutUtils.FlipSizeIf(verticalText, proposedSize);
|
||||
Size textSize = Size.Empty;
|
||||
|
||||
if (useCompatibleTextRendering)
|
||||
{ // GDI+ text rendering.
|
||||
{
|
||||
// GDI+ text rendering.
|
||||
using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics())
|
||||
{
|
||||
using (StringFormat gdipStringFormat = StringFormat)
|
||||
|
@ -1635,10 +1620,12 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(text))
|
||||
{ // GDI text rendering (Whidbey feature).
|
||||
{
|
||||
// GDI text rendering (Whidbey feature).
|
||||
textSize = TextRenderer.MeasureText(text, font, proposedSize, TextFormatFlags);
|
||||
}
|
||||
//else skip calling MeasureText, it should return 0,0
|
||||
|
||||
// Else skip calling MeasureText, it should return 0,0
|
||||
|
||||
return LayoutUtils.FlipSizeIf(verticalText, textSize);
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
// Note: PaintEvent.HDC == 0 if GDI+ has used the HDC -- it wouldn't be safe for us
|
||||
// to use it without enough bookkeeping to negate any performance gain of using GDI.
|
||||
if (color.A == 255 && e.HDC != IntPtr.Zero)
|
||||
if (color.A == 255 && !e.HDC.IsNull)
|
||||
{
|
||||
if (DisplayInformation.BitsPerPixel > 8)
|
||||
{
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms.Internal;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms.ButtonInternal
|
||||
|
@ -38,7 +37,13 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
#region Drawing Helpers
|
||||
|
||||
protected void DrawCheckFlat(PaintEventArgs e, LayoutData layout, Color checkColor, Color checkBackground, Color checkBorder, ColorData colors)
|
||||
protected void DrawCheckFlat(
|
||||
PaintEventArgs e,
|
||||
LayoutData layout,
|
||||
Color checkColor,
|
||||
Color checkBackground,
|
||||
Color checkBorder,
|
||||
ColorData colors)
|
||||
{
|
||||
Rectangle bounds = layout.checkBounds;
|
||||
|
||||
|
@ -52,10 +57,10 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
bounds.Height--;
|
||||
}
|
||||
|
||||
using (var hdc = new DeviceContextHdcScope(e.Graphics, ApplyGraphicsProperties.All, saveState: false))
|
||||
using (var scope = new PaintEventHdcScope(e))
|
||||
{
|
||||
using var hpen = new Gdi32.CreatePenScope(checkBorder);
|
||||
hdc.DrawRectangle(bounds, hpen);
|
||||
scope.HDC.DrawRectangle(bounds, hpen);
|
||||
|
||||
// Now subtract, since the rest of the code is like Everett.
|
||||
if (layout.options.everettButtonCompat)
|
||||
|
@ -74,21 +79,26 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
}
|
||||
else
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(e.Graphics, ApplyGraphicsProperties.All, saveState: false);
|
||||
using var scope = new PaintEventHdcScope(e);
|
||||
using var hbrush = new Gdi32.CreateBrushScope(checkBackground);
|
||||
|
||||
// Even though we are using GDI here as opposed to GDI+ in Everett, we still need to add 1.
|
||||
bounds.Width++;
|
||||
bounds.Height++;
|
||||
RECT rect = bounds;
|
||||
User32.FillRect(hdc, ref rect, hbrush);
|
||||
scope.HDC.FillRectangle(bounds, hbrush);
|
||||
}
|
||||
|
||||
DrawCheckOnly(e, layout, colors, checkColor, checkBackground);
|
||||
}
|
||||
|
||||
// used by DataGridViewCheckBoxCell
|
||||
internal static void DrawCheckBackground(bool controlEnabled, CheckState controlCheckState, Graphics g, Rectangle bounds, Color checkColor, Color checkBackground, bool disabledColors, ColorData colors)
|
||||
internal static void DrawCheckBackground(
|
||||
bool controlEnabled,
|
||||
CheckState controlCheckState,
|
||||
Graphics g,
|
||||
Rectangle bounds,
|
||||
Color checkBackground,
|
||||
bool disabledColors)
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
|
||||
|
@ -117,7 +127,13 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
User32.FillRect(hdc, ref rect, hbrush);
|
||||
}
|
||||
|
||||
protected void DrawCheckBackground(PaintEventArgs e, Rectangle bounds, Color checkColor, Color checkBackground, bool disabledColors, ColorData colors)
|
||||
protected void DrawCheckBackground(
|
||||
PaintEventArgs e,
|
||||
Rectangle bounds,
|
||||
Color checkColor,
|
||||
Color checkBackground,
|
||||
bool disabledColors,
|
||||
ColorData colors)
|
||||
{
|
||||
// Area behind check
|
||||
|
||||
|
@ -127,7 +143,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
}
|
||||
else
|
||||
{
|
||||
DrawCheckBackground(Control.Enabled, Control.CheckState, e.Graphics, bounds, checkColor, checkBackground, disabledColors, colors);
|
||||
DrawCheckBackground(Control.Enabled, Control.CheckState, e.Graphics, bounds, checkBackground, disabledColors);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,22 +205,31 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
internal static Rectangle DrawPopupBorder(Graphics g, Rectangle r, ColorData colors)
|
||||
{
|
||||
using (WindowsGraphics wg = WindowsGraphics.FromGraphics(g))
|
||||
{
|
||||
using (WindowsPen high = new WindowsPen(wg.DeviceContext, colors.highlight),
|
||||
shadow = new WindowsPen(wg.DeviceContext, colors.buttonShadow),
|
||||
face = new WindowsPen(wg.DeviceContext, colors.buttonFace))
|
||||
{
|
||||
wg.DrawLine(high, r.Right - 1, r.Top, r.Right - 1, r.Bottom);
|
||||
wg.DrawLine(high, r.Left, r.Bottom - 1, r.Right, r.Bottom - 1);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
return DrawPopupBorder(hdc, r, colors);
|
||||
}
|
||||
|
||||
wg.DrawLine(shadow, r.Left, r.Top, r.Left, r.Bottom);
|
||||
wg.DrawLine(shadow, r.Left, r.Top, r.Right - 1, r.Top);
|
||||
internal static Rectangle DrawPopupBorder(PaintEventArgs e, Rectangle r, ColorData colors)
|
||||
{
|
||||
using var hdc = new PaintEventHdcScope(e);
|
||||
return DrawPopupBorder(hdc, r, colors);
|
||||
}
|
||||
|
||||
internal static Rectangle DrawPopupBorder(Gdi32.HDC hdc, Rectangle r, ColorData colors)
|
||||
{
|
||||
using var high = new Gdi32.CreatePenScope(colors.highlight);
|
||||
using var shadow = new Gdi32.CreatePenScope(colors.buttonShadow);
|
||||
using var face = new Gdi32.CreatePenScope(colors.buttonFace);
|
||||
|
||||
hdc.DrawLine(high, r.Right - 1, r.Top, r.Right - 1, r.Bottom);
|
||||
hdc.DrawLine(high, r.Left, r.Bottom - 1, r.Right, r.Bottom - 1);
|
||||
|
||||
hdc.DrawLine(shadow, r.Left, r.Top, r.Left, r.Bottom);
|
||||
hdc.DrawLine(shadow, r.Left, r.Top, r.Right - 1, r.Top);
|
||||
|
||||
hdc.DrawLine(face, r.Right - 2, r.Top + 1, r.Right - 2, r.Bottom - 1);
|
||||
hdc.DrawLine(face, r.Left + 1, r.Bottom - 2, r.Right - 1, r.Bottom - 2);
|
||||
|
||||
wg.DrawLine(face, r.Right - 2, r.Top + 1, r.Right - 2, r.Bottom - 1);
|
||||
wg.DrawLine(face, r.Left + 1, r.Bottom - 2, r.Right - 1, r.Bottom - 2);
|
||||
}
|
||||
}
|
||||
r.Inflate(-1, -1);
|
||||
return r;
|
||||
}
|
||||
|
@ -237,30 +262,36 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
protected void DrawCheckBox(PaintEventArgs e, LayoutData layout)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
ButtonState style = GetState();
|
||||
|
||||
if (Control.CheckState == CheckState.Indeterminate)
|
||||
{
|
||||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
CheckBoxRenderer.DrawCheckBox(g, new Point(layout.checkBounds.Left, layout.checkBounds.Top), CheckBoxRenderer.ConvertFromButtonState(style, true, Control.MouseIsOver), Control.HandleInternal);
|
||||
CheckBoxRenderer.DrawCheckBox(
|
||||
e.Graphics,
|
||||
new Point(layout.checkBounds.Left, layout.checkBounds.Top),
|
||||
CheckBoxRenderer.ConvertFromButtonState(style, true, Control.MouseIsOver),
|
||||
Control.HandleInternal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlPaint.DrawMixedCheckBox(g, layout.checkBounds, style);
|
||||
ControlPaint.DrawMixedCheckBox(e.Graphics, layout.checkBounds, style);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
CheckBoxRenderer.DrawCheckBox(g, new Point(layout.checkBounds.Left, layout.checkBounds.Top), CheckBoxRenderer.ConvertFromButtonState(style, false, Control.MouseIsOver), Control.HandleInternal);
|
||||
CheckBoxRenderer.DrawCheckBox(
|
||||
e.Graphics,
|
||||
new Point(layout.checkBounds.Left, layout.checkBounds.Top),
|
||||
CheckBoxRenderer.ConvertFromButtonState(style, false, Control.MouseIsOver),
|
||||
Control.HandleInternal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlPaint.DrawCheckBox(g, layout.checkBounds, style);
|
||||
ControlPaint.DrawCheckBox(e.Graphics, layout.checkBounds, style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
protected override LayoutOptions Layout(PaintEventArgs e)
|
||||
{
|
||||
LayoutOptions layout = CommonLayout();
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio(e.Graphics));
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio());
|
||||
layout.shadowedText = false;
|
||||
|
||||
return layout;
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
{
|
||||
Graphics g = e.Graphics;
|
||||
ColorData colors = PaintPopupRender(e.Graphics).Calculate();
|
||||
LayoutData layout = PaintPopupLayout(e, false).Layout();
|
||||
LayoutData layout = PaintPopupLayout(show3D: false).Layout();
|
||||
|
||||
Region original = e.Graphics.Clip;
|
||||
PaintButtonBackground(e, Control.ClientRectangle, null);
|
||||
|
@ -44,7 +44,6 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
internal override void PaintOver(PaintEventArgs e, CheckState state)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
if (Control.Appearance == Appearance.Button)
|
||||
{
|
||||
ButtonPopupAdapter adapter = new ButtonPopupAdapter(Control);
|
||||
|
@ -53,15 +52,22 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
else
|
||||
{
|
||||
ColorData colors = PaintPopupRender(e.Graphics).Calculate();
|
||||
LayoutData layout = PaintPopupLayout(e, true).Layout();
|
||||
LayoutData layout = PaintPopupLayout(show3D: true).Layout();
|
||||
|
||||
Region original = e.Graphics.Clip;
|
||||
PaintButtonBackground(e, Control.ClientRectangle, null);
|
||||
|
||||
PaintImage(e, layout);
|
||||
|
||||
DrawCheckBackground(e, layout.checkBounds, colors.windowText, colors.options.highContrast ? colors.buttonFace : colors.highlight, true, colors);
|
||||
DrawPopupBorder(g, layout.checkBounds, colors);
|
||||
DrawCheckBackground(
|
||||
e,
|
||||
layout.checkBounds,
|
||||
colors.windowText,
|
||||
colors.options.highContrast ? colors.buttonFace : colors.highlight,
|
||||
disabledColors: true,
|
||||
colors);
|
||||
|
||||
DrawPopupBorder(e, layout.checkBounds, colors);
|
||||
DrawCheckOnly(e, layout, colors, colors.windowText, colors.highlight);
|
||||
|
||||
if (!string.IsNullOrEmpty(Control.Text))
|
||||
|
@ -86,7 +92,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
{
|
||||
Graphics g = e.Graphics;
|
||||
ColorData colors = PaintPopupRender(e.Graphics).Calculate();
|
||||
LayoutData layout = PaintPopupLayout(e, true).Layout();
|
||||
LayoutData layout = PaintPopupLayout(show3D: true).Layout();
|
||||
|
||||
Region original = e.Graphics.Clip;
|
||||
PaintButtonBackground(e, Control.ClientRectangle, null);
|
||||
|
@ -94,7 +100,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
PaintImage(e, layout);
|
||||
|
||||
DrawCheckBackground(e, layout.checkBounds, colors.windowText, colors.buttonFace, true, colors);
|
||||
DrawPopupBorder(g, layout.checkBounds, colors);
|
||||
DrawPopupBorder(e, layout.checkBounds, colors);
|
||||
DrawCheckOnly(e, layout, colors, colors.windowText, colors.buttonFace);
|
||||
|
||||
AdjustFocusRectangle(layout);
|
||||
|
@ -111,42 +117,51 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
protected override LayoutOptions Layout(PaintEventArgs e)
|
||||
{
|
||||
LayoutOptions layout = PaintPopupLayout(e, /* up = */ true);
|
||||
LayoutOptions layout = PaintPopupLayout(show3D: true);
|
||||
Debug.Assert(layout.GetPreferredSizeCore(LayoutUtils.MaxSize)
|
||||
== PaintPopupLayout(e, /* up = */ false).GetPreferredSizeCore(LayoutUtils.MaxSize),
|
||||
== PaintPopupLayout(show3D: false).GetPreferredSizeCore(LayoutUtils.MaxSize),
|
||||
"The state of show3D should not effect PreferredSize");
|
||||
return layout;
|
||||
}
|
||||
|
||||
internal static LayoutOptions PaintPopupLayout(Graphics g, bool show3D, int checkSize, Rectangle clientRectangle, Padding padding,
|
||||
bool isDefault, Font font, string text, bool enabled, ContentAlignment textAlign, RightToLeft rtl,
|
||||
Control control = null)
|
||||
internal static LayoutOptions PaintPopupLayout(
|
||||
bool show3D,
|
||||
int checkSize,
|
||||
Rectangle clientRectangle,
|
||||
Padding padding,
|
||||
bool isDefault,
|
||||
Font font,
|
||||
string text,
|
||||
bool enabled,
|
||||
ContentAlignment textAlign,
|
||||
RightToLeft rtl,
|
||||
Control control = null)
|
||||
{
|
||||
LayoutOptions layout = CommonLayout(clientRectangle, padding, isDefault, font, text, enabled, textAlign, rtl);
|
||||
layout.shadowedText = false;
|
||||
if (show3D)
|
||||
{
|
||||
layout.checkSize = (int)(checkSize * GetDpiScaleRatio(g, control) + 1);
|
||||
layout.checkSize = (int)(checkSize * GetDpiScaleRatio(control) + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
layout.checkSize = (int)(checkSize * GetDpiScaleRatio(g, control));
|
||||
layout.checkSize = (int)(checkSize * GetDpiScaleRatio(control));
|
||||
layout.checkPaddingSize = 1;
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
private LayoutOptions PaintPopupLayout(PaintEventArgs e, bool show3D)
|
||||
private LayoutOptions PaintPopupLayout(bool show3D)
|
||||
{
|
||||
LayoutOptions layout = CommonLayout();
|
||||
layout.shadowedText = false;
|
||||
if (show3D)
|
||||
{
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio(e.Graphics) + 1);
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio() + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio(e.Graphics));
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio());
|
||||
layout.checkPaddingSize = 1;
|
||||
}
|
||||
return layout;
|
||||
|
|
|
@ -126,10 +126,13 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics())
|
||||
{
|
||||
layout.checkSize = CheckBoxRenderer.GetGlyphSize(g, CheckBoxRenderer.ConvertFromButtonState(GetState(), true, Control.MouseIsOver), Control.HandleInternal).Width;
|
||||
}
|
||||
layout.checkSize = CheckBoxRenderer.GetGlyphSize(
|
||||
WindowsFormsUtils.GetMeasurementDeviceContext(),
|
||||
CheckBoxRenderer.ConvertFromButtonState(
|
||||
GetState(),
|
||||
true,
|
||||
Control.MouseIsOver),
|
||||
Control.HandleInternal).Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -139,7 +142,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
}
|
||||
else
|
||||
{
|
||||
layout.checkSize = (int)(layout.checkSize * GetDpiScaleRatio(e.Graphics));
|
||||
layout.checkSize = (int)(layout.checkSize * GetDpiScaleRatio());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,12 +81,12 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
return layout;
|
||||
}
|
||||
|
||||
internal double GetDpiScaleRatio(Graphics g)
|
||||
internal double GetDpiScaleRatio()
|
||||
{
|
||||
return GetDpiScaleRatio(g, Control);
|
||||
return GetDpiScaleRatio(Control);
|
||||
}
|
||||
|
||||
internal static double GetDpiScaleRatio(Graphics g, Control control)
|
||||
internal static double GetDpiScaleRatio(Control control)
|
||||
{
|
||||
if (DpiHelper.IsPerMonitorV2Awareness
|
||||
&& control != null && control.IsHandleCreated)
|
||||
|
@ -94,12 +94,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
return control._deviceDpi / DpiHelper.LogicalDpi;
|
||||
}
|
||||
|
||||
if (g == null)
|
||||
{
|
||||
return 1.0F;
|
||||
}
|
||||
|
||||
return g.DpiX / 96;
|
||||
return DpiHelper.LogicalToDeviceUnitsScalingFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms.Internal;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms.ButtonInternal
|
||||
{
|
||||
|
@ -75,7 +76,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
field = SystemColors.Control;
|
||||
}
|
||||
|
||||
double scale = GetDpiScaleRatio(e.Graphics);
|
||||
double scale = GetDpiScaleRatio();
|
||||
|
||||
using (WindowsGraphics wg = WindowsGraphics.FromGraphics(e.Graphics))
|
||||
{
|
||||
|
@ -140,29 +141,36 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
protected void DrawCheckOnly(PaintEventArgs e, LayoutData layout, Color checkColor, Color checkBackground, bool disabledColors)
|
||||
{
|
||||
// check
|
||||
//
|
||||
if (Control.Checked)
|
||||
if (!Control.Checked)
|
||||
{
|
||||
if (!Control.Enabled && disabledColors)
|
||||
{
|
||||
checkColor = SystemColors.ControlDark;
|
||||
}
|
||||
|
||||
double scale = GetDpiScaleRatio(e.Graphics);
|
||||
using (WindowsGraphics wg = WindowsGraphics.FromGraphics(e.Graphics))
|
||||
{
|
||||
using (WindowsBrush brush = new WindowsSolidBrush(wg.DeviceContext, checkColor))
|
||||
{
|
||||
// circle drawing doesn't work at this size
|
||||
int offset = 5;
|
||||
Rectangle vCross = new Rectangle(layout.checkBounds.X + GetScaledNumber(offset, scale), layout.checkBounds.Y + GetScaledNumber(offset - 1, scale), GetScaledNumber(2, scale), GetScaledNumber(4, scale));
|
||||
wg.FillRectangle(brush, vCross);
|
||||
Rectangle hCross = new Rectangle(layout.checkBounds.X + GetScaledNumber(offset - 1, scale), layout.checkBounds.Y + GetScaledNumber(offset, scale), GetScaledNumber(4, scale), GetScaledNumber(2, scale));
|
||||
wg.FillRectangle(brush, hCross);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Control.Enabled && disabledColors)
|
||||
{
|
||||
checkColor = SystemColors.ControlDark;
|
||||
}
|
||||
|
||||
double scale = GetDpiScaleRatio();
|
||||
using var paintScope = new PaintEventHdcScope(e);
|
||||
Gdi32.HDC hdc = paintScope.HDC;
|
||||
using var brush = new Gdi32.CreateBrushScope(checkColor);
|
||||
|
||||
// Circle drawing doesn't work at this size
|
||||
int offset = 5;
|
||||
|
||||
Rectangle vCross = new Rectangle(
|
||||
layout.checkBounds.X + GetScaledNumber(offset, scale),
|
||||
layout.checkBounds.Y + GetScaledNumber(offset - 1, scale),
|
||||
GetScaledNumber(2, scale),
|
||||
GetScaledNumber(4, scale));
|
||||
hdc.FillRectangle(vCross, brush);
|
||||
|
||||
Rectangle hCross = new Rectangle(
|
||||
layout.checkBounds.X + GetScaledNumber(offset - 1, scale),
|
||||
layout.checkBounds.Y + GetScaledNumber(offset, scale),
|
||||
GetScaledNumber(4, scale), GetScaledNumber(2, scale));
|
||||
hdc.FillRectangle(hCross, brush);
|
||||
}
|
||||
|
||||
protected ButtonState GetState()
|
||||
|
@ -193,8 +201,6 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
protected void DrawCheckBox(PaintEventArgs e, LayoutData layout)
|
||||
{
|
||||
Graphics g = e.Graphics;
|
||||
|
||||
Rectangle check = layout.checkBounds;
|
||||
if (!Application.RenderWithVisualStyles)
|
||||
{
|
||||
|
@ -205,11 +211,15 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
|
||||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
RadioButtonRenderer.DrawRadioButton(g, new Point(check.Left, check.Top), RadioButtonRenderer.ConvertFromButtonState(style, Control.MouseIsOver), Control.HandleInternal);
|
||||
RadioButtonRenderer.DrawRadioButton(
|
||||
e.Graphics,
|
||||
new Point(check.Left, check.Top),
|
||||
RadioButtonRenderer.ConvertFromButtonState(style, Control.MouseIsOver),
|
||||
Control.HandleInternal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlPaint.DrawRadioButton(g, check, style);
|
||||
ControlPaint.DrawRadioButton(e.Graphics, check, style);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
protected override LayoutOptions Layout(PaintEventArgs e)
|
||||
{
|
||||
LayoutOptions layout = CommonLayout();
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio(e.Graphics));
|
||||
layout.checkSize = (int)(flatCheckSize * GetDpiScaleRatio());
|
||||
layout.shadowedText = false;
|
||||
|
||||
return layout;
|
||||
|
|
|
@ -68,8 +68,6 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
return new ButtonStandardAdapter(Control);
|
||||
}
|
||||
|
||||
#region Temp
|
||||
|
||||
protected override LayoutOptions Layout(PaintEventArgs e)
|
||||
{
|
||||
LayoutOptions layout = CommonLayout();
|
||||
|
@ -79,19 +77,17 @@ namespace System.Windows.Forms.ButtonInternal
|
|||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
ButtonBase b = Control;
|
||||
using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics())
|
||||
{
|
||||
layout.checkSize = RadioButtonRenderer.GetGlyphSize(g, RadioButtonRenderer.ConvertFromButtonState(GetState(), b.MouseIsOver), b.HandleInternal).Width;
|
||||
}
|
||||
layout.checkSize = RadioButtonRenderer.GetGlyphSize(
|
||||
WindowsFormsUtils.GetMeasurementDeviceContext(),
|
||||
RadioButtonRenderer.ConvertFromButtonState(GetState(), b.MouseIsOver),
|
||||
b.HandleInternal).Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
layout.checkSize = (int)(layout.checkSize * GetDpiScaleRatio(e.Graphics));
|
||||
layout.checkSize = (int)(layout.checkSize * GetDpiScaleRatio());
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,9 @@ namespace System.Windows.Forms
|
|||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
visualStyleRenderer.DrawBackground(g, bounds, handle);
|
||||
contentBounds = visualStyleRenderer.GetBackgroundContentRectangle(g, bounds);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
visualStyleRenderer.DrawBackground(hdc, bounds, handle);
|
||||
contentBounds = visualStyleRenderer.GetBackgroundContentRectangle(hdc, bounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -137,9 +138,14 @@ namespace System.Windows.Forms
|
|||
/// </summary>
|
||||
public static void DrawButton(Graphics g, Rectangle bounds, string buttonText, Font font, bool focused, PushButtonState state)
|
||||
{
|
||||
DrawButton(g, bounds, buttonText, font,
|
||||
TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine,
|
||||
focused, state);
|
||||
DrawButton(
|
||||
g,
|
||||
bounds,
|
||||
buttonText,
|
||||
font,
|
||||
TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine,
|
||||
focused,
|
||||
state);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
|
@ -93,7 +94,8 @@ namespace System.Windows.Forms
|
|||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
visualStyleRenderer.DrawBackground(g, glyphBounds, hWnd);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
visualStyleRenderer.DrawBackground(hdc, glyphBounds, hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -173,7 +175,17 @@ namespace System.Windows.Forms
|
|||
/// <summary>
|
||||
/// Renders a CheckBox control.
|
||||
/// </summary>
|
||||
public static void DrawCheckBox(Graphics g, Point glyphLocation, Rectangle textBounds, string checkBoxText, Font font, TextFormatFlags flags, Image image, Rectangle imageBounds, bool focused, CheckBoxState state)
|
||||
public static void DrawCheckBox(
|
||||
Graphics g,
|
||||
Point glyphLocation,
|
||||
Rectangle textBounds,
|
||||
string checkBoxText,
|
||||
Font font,
|
||||
TextFormatFlags flags,
|
||||
Image image,
|
||||
Rectangle imageBounds,
|
||||
bool focused,
|
||||
CheckBoxState state)
|
||||
{
|
||||
Rectangle glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(g, state));
|
||||
Color textColor;
|
||||
|
@ -214,17 +226,26 @@ namespace System.Windows.Forms
|
|||
/// Returns the size of the CheckBox glyph.
|
||||
/// </summary>
|
||||
public static Size GetGlyphSize(Graphics g, CheckBoxState state)
|
||||
{
|
||||
return GetGlyphSize(g, state, IntPtr.Zero);
|
||||
}
|
||||
=> GetGlyphSize(g, state, default);
|
||||
|
||||
internal static Size GetGlyphSize(Graphics g, CheckBoxState state, IntPtr hWnd)
|
||||
{
|
||||
if (!RenderWithVisualStyles)
|
||||
{
|
||||
return new Size(13, 13);
|
||||
}
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
return GetGlyphSize(hdc, state, IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal static Size GetGlyphSize(Gdi32.HDC hdc, CheckBoxState state, IntPtr hWnd)
|
||||
{
|
||||
if (RenderWithVisualStyles)
|
||||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
return visualStyleRenderer.GetPartSize(g, ThemeSizeType.Draw, hWnd);
|
||||
return visualStyleRenderer.GetPartSize(hdc, ThemeSizeType.Draw, hWnd);
|
||||
}
|
||||
|
||||
return new Size(13, 13);
|
||||
|
|
|
@ -594,12 +594,15 @@ namespace System.Windows.Forms
|
|||
// the Renderer might return a different size in different DPI modes..
|
||||
if (Application.RenderWithVisualStyles)
|
||||
{
|
||||
VisualStyles.CheckBoxState cbState = CheckBoxRenderer.ConvertFromButtonState(state, false, ((e.State & DrawItemState.HotLight) == DrawItemState.HotLight));
|
||||
idealCheckSize = (int)(CheckBoxRenderer.GetGlyphSize(e.Graphics, cbState, HandleInternal)).Width;
|
||||
VisualStyles.CheckBoxState cbState = CheckBoxRenderer.ConvertFromButtonState(
|
||||
state,
|
||||
isMixed: false,
|
||||
(e.State & DrawItemState.HotLight) == DrawItemState.HotLight);
|
||||
|
||||
idealCheckSize = CheckBoxRenderer.GetGlyphSize(e.Graphics, cbState, HandleInternal).Width;
|
||||
}
|
||||
|
||||
// Determine bounds for the checkbox
|
||||
//
|
||||
int centeringFactor = Math.Max((height - idealCheckSize) / 2, 0);
|
||||
|
||||
// Keep the checkbox within the item's upper and lower bounds
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
|
@ -120,17 +121,18 @@ namespace System.Windows.Forms
|
|||
/// </summary>
|
||||
public static void DrawDropDownButton(Graphics g, Rectangle bounds, ComboBoxState state)
|
||||
{
|
||||
DrawDropDownButtonForHandle(g, bounds, state, IntPtr.Zero);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
DrawDropDownButtonForHandle(hdc, bounds, state, IntPtr.Zero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Renders a ComboBox drop-down button in per-monitor scenario.
|
||||
/// </summary>
|
||||
/// <param name="g">graphics object</param>
|
||||
/// <param name="hdc">device context</param>
|
||||
/// <param name="bounds">dropdown button bounds</param>
|
||||
/// <param name="state"> state</param>
|
||||
/// <param name="handle"> handle of the control</param>
|
||||
internal static void DrawDropDownButtonForHandle(Graphics g, Rectangle bounds, ComboBoxState state, IntPtr handle)
|
||||
internal static void DrawDropDownButtonForHandle(Gdi32.HDC hdc, Rectangle bounds, ComboBoxState state, IntPtr handle)
|
||||
{
|
||||
if (visualStyleRenderer == null)
|
||||
{
|
||||
|
@ -141,7 +143,7 @@ namespace System.Windows.Forms
|
|||
visualStyleRenderer.SetParameters(ComboBoxElement.ClassName, ComboBoxElement.Part, (int)state);
|
||||
}
|
||||
|
||||
visualStyleRenderer.DrawBackground(g, bounds, handle);
|
||||
visualStyleRenderer.DrawBackground(hdc, bounds, handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -320,12 +320,12 @@ namespace System.Windows.Forms
|
|||
// Screen Dpi
|
||||
if (DpiHelper.IsPerMonitorV2Awareness)
|
||||
{
|
||||
_currentAutoScaleDimensions = new SizeF((float)_deviceDpi, (float)_deviceDpi);
|
||||
_currentAutoScaleDimensions = new SizeF(_deviceDpi, _deviceDpi);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this DPI value comes from the primary monitor.
|
||||
_currentAutoScaleDimensions = WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Dpi;
|
||||
_currentAutoScaleDimensions = new SizeF(DpiHelper.DeviceDpi, DpiHelper.DeviceDpi);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -355,7 +355,6 @@ namespace System.Windows.Forms
|
|||
#endif
|
||||
Properties = new PropertyStore();
|
||||
|
||||
DpiHelper.InitializeDpiHelperForWinforms();
|
||||
// Initialize DPI to the value on the primary screen, we will have the correct value when the Handle is created.
|
||||
_deviceDpi = DpiHelper.DeviceDpi;
|
||||
|
||||
|
@ -5277,7 +5276,7 @@ namespace System.Windows.Forms
|
|||
|
||||
using Bitmap image = new Bitmap(width, height, bitmap.PixelFormat);
|
||||
using Graphics g = Graphics.FromImage(image);
|
||||
using var hDc = new DeviceContextHdcScope(g, saveState: false);
|
||||
using var hDc = new DeviceContextHdcScope(g, applyGraphicsState: false);
|
||||
|
||||
// Send the WM_PRINT message.
|
||||
User32.SendMessageW(
|
||||
|
@ -5288,7 +5287,7 @@ namespace System.Windows.Forms
|
|||
|
||||
// Now BLT the result to the destination bitmap.
|
||||
using Graphics destGraphics = Graphics.FromImage(bitmap);
|
||||
using var desthDC = new DeviceContextHdcScope(destGraphics, saveState: false);
|
||||
using var desthDC = new DeviceContextHdcScope(destGraphics, applyGraphicsState: false);
|
||||
Gdi32.BitBlt(
|
||||
desthDC,
|
||||
targetBounds.X,
|
||||
|
@ -7497,39 +7496,19 @@ namespace System.Windows.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
Message m;
|
||||
bool releaseDC = false;
|
||||
IntPtr hdc = IntPtr.Zero;
|
||||
|
||||
if (!(e is PrintPaintEventArgs ppev))
|
||||
{
|
||||
IntPtr flags = (IntPtr)(User32.PRF.CHILDREN | User32.PRF.CLIENT | User32.PRF.ERASEBKGND | User32.PRF.NONCLIENT);
|
||||
hdc = e.HDC;
|
||||
|
||||
if (hdc == IntPtr.Zero)
|
||||
{
|
||||
// a manually created paintevent args
|
||||
hdc = e.Graphics.GetHdc();
|
||||
releaseDC = true;
|
||||
}
|
||||
m = Message.Create(Handle, User32.WM.PRINTCLIENT, hdc, flags);
|
||||
using var scope = new PaintEventHdcScope(e);
|
||||
Message m = Message.Create(Handle, User32.WM.PRINTCLIENT, (IntPtr)scope.HDC, flags);
|
||||
DefWndProc(ref m);
|
||||
}
|
||||
else
|
||||
{
|
||||
m = ppev.Message;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Message m = ppev.Message;
|
||||
DefWndProc(ref m);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (releaseDC)
|
||||
{
|
||||
e.Graphics.ReleaseHdcInternal(hdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8488,7 +8467,7 @@ namespace System.Windows.Forms
|
|||
Point scrollLocation = scrollOffset;
|
||||
if (this is ScrollableControl scrollControl && scrollLocation != Point.Empty)
|
||||
{
|
||||
scrollLocation = ((ScrollableControl)this).AutoScrollPosition;
|
||||
scrollLocation = scrollControl.AutoScrollPosition;
|
||||
}
|
||||
|
||||
if (ControlPaint.IsImageTransparent(BackgroundImage))
|
||||
|
@ -8510,38 +8489,23 @@ namespace System.Windows.Forms
|
|||
// use GDI because it is faster for simple things than creating
|
||||
// a graphics object, brush, etc. Also, we may be able to
|
||||
// use a system brush, avoiding the brush create altogether.
|
||||
//
|
||||
|
||||
Color color = backColor;
|
||||
|
||||
// Note: PaintEvent.HDC == 0 if GDI+ has used the HDC -- it wouldn't be safe for us
|
||||
// to use it without enough bookkeeping to negate any performance gain of using GDI.
|
||||
if (color.A == 255)
|
||||
{
|
||||
if (e.HDC != IntPtr.Zero && DisplayInformation.BitsPerPixel > 8)
|
||||
{
|
||||
Gdi32.HDC hdc = (Gdi32.HDC)e.HDC;
|
||||
using var hbrush = new Gdi32.CreateBrushScope(hdc.GetNearestColor(color));
|
||||
hdc.FillRectangle(rectangle, hbrush);
|
||||
}
|
||||
else
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(e.Graphics, ApplyGraphicsProperties.All, saveState: false);
|
||||
using var hbrush = new Gdi32.CreateBrushScope(hdc.GetNearestColor(color));
|
||||
hdc.FillRectangle(rectangle, hbrush);
|
||||
}
|
||||
using var scope = new PaintEventHdcScope(e);
|
||||
Gdi32.HDC hdc = scope.HDC;
|
||||
using var hbrush = new Gdi32.CreateBrushScope(hdc.GetNearestColor(color));
|
||||
hdc.FillRectangle(rectangle, hbrush);
|
||||
}
|
||||
else
|
||||
else if (color.A > 0)
|
||||
{
|
||||
// don't paint anything from 100% transparent background
|
||||
if (color.A > 0)
|
||||
{
|
||||
// Color has some transparency or we have no HDC, so we must
|
||||
// fall back to using GDI+.
|
||||
using (Brush brush = new SolidBrush(color))
|
||||
{
|
||||
e.Graphics.FillRectangle(brush, rectangle);
|
||||
}
|
||||
}
|
||||
// Color has some transparency (but not completely transparent) use GDI+.
|
||||
using Brush brush = new SolidBrush(color);
|
||||
e.Graphics.FillRectangle(brush, rectangle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11689,6 +11653,7 @@ namespace System.Windows.Forms
|
|||
private void WmDisplayChange(ref Message m)
|
||||
{
|
||||
BufferedGraphicsManager.Current.Invalidate();
|
||||
|
||||
DefWndProc(ref m);
|
||||
}
|
||||
|
||||
|
|
|
@ -355,33 +355,6 @@ namespace System.Windows.Forms
|
|||
return Gdi32.CreateBrushIndirect(ref lb);
|
||||
}
|
||||
|
||||
// roughly the same code as in Graphics.cs
|
||||
internal static void CopyPixels(IntPtr sourceHwnd, IDeviceContext targetDC, Point sourceLocation, Point destinationLocation, Size blockRegionSize, CopyPixelOperation copyPixelOperation)
|
||||
{
|
||||
int destWidth = blockRegionSize.Width;
|
||||
int destHeight = blockRegionSize.Height;
|
||||
|
||||
using var dc = new User32.GetDcScope(sourceHwnd);
|
||||
using var targetHDC = new DeviceContextHdcScope(targetDC, saveState: false);
|
||||
|
||||
BOOL result = Gdi32.BitBlt(
|
||||
targetHDC,
|
||||
destinationLocation.X,
|
||||
destinationLocation.Y,
|
||||
destWidth,
|
||||
destHeight,
|
||||
dc,
|
||||
sourceLocation.X,
|
||||
sourceLocation.Y,
|
||||
(Gdi32.ROP)copyPixelOperation);
|
||||
|
||||
// Zero result indicates a win32 exception has been thrown
|
||||
if (!result.IsTrue())
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a border of the specified style and color to the given graphics.
|
||||
/// </summary>
|
||||
|
@ -1092,7 +1065,7 @@ namespace System.Windows.Forms
|
|||
}
|
||||
|
||||
// Get Win32 dc with Graphics properties applied to it.
|
||||
using var hdc = new DeviceContextHdcScope(graphics, ApplyGraphicsProperties.All, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(graphics);
|
||||
User32.DrawEdge(hdc, ref rc, edge, flags);
|
||||
}
|
||||
|
||||
|
@ -1424,7 +1397,7 @@ namespace System.Windows.Forms
|
|||
using (Graphics g2 = Graphics.FromImage(bitmap))
|
||||
{
|
||||
g2.Clear(Color.Transparent);
|
||||
using var dc = new DeviceContextHdcScope(g2, saveState: false);
|
||||
using var dc = new DeviceContextHdcScope(g2, applyGraphicsState: false);
|
||||
User32.DrawFrameControl(dc, ref rcCheck, User32.DFC.MENU, User32.DFCS.MENUCHECK);
|
||||
}
|
||||
|
||||
|
@ -1511,40 +1484,36 @@ namespace System.Windows.Forms
|
|||
}
|
||||
|
||||
RECT rcFrame = new RECT(0, 0, width, height);
|
||||
using (Bitmap bitmap = new Bitmap(width, height))
|
||||
using Bitmap bitmap = new Bitmap(width, height);
|
||||
using Graphics g2 = Graphics.FromImage(bitmap);
|
||||
g2.Clear(Color.Transparent);
|
||||
|
||||
using (var hdc = new DeviceContextHdcScope(g2, applyGraphicsState: false))
|
||||
{
|
||||
using (Graphics g2 = Graphics.FromImage(bitmap))
|
||||
// Get Win32 dc with Graphics properties applied to it.
|
||||
User32.DrawFrameControl(hdc, ref rcFrame, kind, state);
|
||||
}
|
||||
|
||||
if (foreColor == Color.Empty || backColor == Color.Empty)
|
||||
{
|
||||
graphics.DrawImage(bitmap, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace black/white with foreColor/backColor.
|
||||
ImageAttributes attrs = new ImageAttributes();
|
||||
ColorMap cm1 = new ColorMap
|
||||
{
|
||||
g2.Clear(Color.Transparent);
|
||||
|
||||
using (var hdc = new DeviceContextHdcScope(g2, saveState: false))
|
||||
{
|
||||
// Get Win32 dc with Graphics properties applied to it.
|
||||
User32.DrawFrameControl(hdc, ref rcFrame, kind, state);
|
||||
}
|
||||
|
||||
if (foreColor == Color.Empty || backColor == Color.Empty)
|
||||
{
|
||||
graphics.DrawImage(bitmap, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Replace black/white with foreColor/backColor.
|
||||
ImageAttributes attrs = new ImageAttributes();
|
||||
ColorMap cm1 = new ColorMap
|
||||
{
|
||||
OldColor = Color.Black,
|
||||
NewColor = foreColor
|
||||
};
|
||||
ColorMap cm2 = new ColorMap
|
||||
{
|
||||
OldColor = Color.White,
|
||||
NewColor = backColor
|
||||
};
|
||||
attrs.SetRemapTable(new ColorMap[2] { cm1, cm2 }, ColorAdjustType.Bitmap);
|
||||
graphics.DrawImage(bitmap, new Rectangle(x, y, width, height), 0, 0, width, height, GraphicsUnit.Pixel, attrs, null, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
OldColor = Color.Black,
|
||||
NewColor = foreColor
|
||||
};
|
||||
ColorMap cm2 = new ColorMap
|
||||
{
|
||||
OldColor = Color.White,
|
||||
NewColor = backColor
|
||||
};
|
||||
attrs.SetRemapTable(new ColorMap[2] { cm1, cm2 }, ColorAdjustType.Bitmap);
|
||||
graphics.DrawImage(bitmap, new Rectangle(x, y, width, height), 0, 0, width, height, GraphicsUnit.Pixel, attrs, null, IntPtr.Zero);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -780,40 +780,17 @@ namespace System.Windows.Forms
|
|||
DataGridView.Enabled).Calculate();
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
using (WindowsGraphics wg = WindowsGraphics.FromHdc(hdc))
|
||||
{
|
||||
WindowsBrush windowsBrush;
|
||||
if (colors.options.highContrast)
|
||||
{
|
||||
windowsBrush = new WindowsSolidBrush(wg.DeviceContext, colors.buttonShadow);
|
||||
}
|
||||
else
|
||||
{
|
||||
windowsBrush = new WindowsSolidBrush(wg.DeviceContext, colors.lowHighlight);
|
||||
}
|
||||
try
|
||||
{
|
||||
ButtonBaseAdapter.PaintButtonBackground(wg, valBounds, windowsBrush);
|
||||
}
|
||||
finally
|
||||
{
|
||||
windowsBrush.Dispose();
|
||||
}
|
||||
}
|
||||
using var hbrush = new Gdi32.CreateBrushScope(
|
||||
colors.options.highContrast ? colors.buttonShadow : colors.lowHighlight);
|
||||
hdc.FillRectangle(valBounds, hbrush);
|
||||
}
|
||||
else if (DataGridView.MouseEnteredCellAddress.Y == rowIndex &&
|
||||
DataGridView.MouseEnteredCellAddress.X == ColumnIndex &&
|
||||
mouseInContentBounds)
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
using (WindowsGraphics wg = WindowsGraphics.FromHdc(hdc))
|
||||
{
|
||||
Color mouseOverBackColor = SystemColors.ControlDark;
|
||||
using (WindowsBrush windowBrush = new WindowsSolidBrush(wg.DeviceContext, mouseOverBackColor))
|
||||
{
|
||||
ButtonBaseAdapter.PaintButtonBackground(wg, valBounds, windowBrush);
|
||||
}
|
||||
}
|
||||
using var hbrush = new Gdi32.CreateBrushScope(SystemColors.ControlDark);
|
||||
hdc.FillRectangle(valBounds, hbrush);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -718,6 +718,7 @@ namespace System.Windows.Forms
|
|||
checkBoxSize.Height -= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (freeDimension)
|
||||
{
|
||||
case DataGridViewFreeDimension.Width:
|
||||
|
@ -753,6 +754,7 @@ namespace System.Windows.Forms
|
|||
checkBoxSize = SystemInformation.Border3DSize.Width * 2 + 9 + 2 * DATAGRIDVIEWCHECKBOXCELL_margin;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (freeDimension)
|
||||
{
|
||||
case DataGridViewFreeDimension.Width:
|
||||
|
@ -1390,21 +1392,22 @@ namespace System.Windows.Forms
|
|||
if ((ButtonState & (ButtonState.Pushed | ButtonState.Checked)) != 0)
|
||||
{
|
||||
// paint down
|
||||
ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g,
|
||||
true /*show3D*/,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
ButtonBaseAdapter.LayoutOptions options = CheckBoxPopupAdapter.PaintPopupLayout(
|
||||
show3D: true,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
isDefault: false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
|
||||
options.everettButtonCompat = false;
|
||||
ButtonBaseAdapter.LayoutData layout = options.Layout();
|
||||
|
||||
if (paint && DataGridViewCell.PaintContentForeground(paintParts))
|
||||
if (paint && PaintContentForeground(paintParts))
|
||||
{
|
||||
ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g,
|
||||
cellStyle.ForeColor,
|
||||
|
@ -1414,10 +1417,8 @@ namespace System.Windows.Forms
|
|||
checkState,
|
||||
g,
|
||||
layout.checkBounds,
|
||||
colors.windowText,
|
||||
colors.buttonFace,
|
||||
true /*disabledColors*/,
|
||||
colors);
|
||||
disabledColors: true);
|
||||
CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors);
|
||||
CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width,
|
||||
checkState == CheckState.Checked || checkState == CheckState.Indeterminate,
|
||||
|
@ -1437,34 +1438,35 @@ namespace System.Windows.Forms
|
|||
{
|
||||
// paint over
|
||||
|
||||
ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g,
|
||||
true /*show3D*/,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
ButtonBaseAdapter.LayoutOptions options = CheckBoxPopupAdapter.PaintPopupLayout(
|
||||
show3D: true,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
isDefault: false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
|
||||
options.everettButtonCompat = false;
|
||||
ButtonBaseAdapter.LayoutData layout = options.Layout();
|
||||
|
||||
if (paint && DataGridViewCell.PaintContentForeground(paintParts))
|
||||
if (paint && PaintContentForeground(paintParts))
|
||||
{
|
||||
ButtonBaseAdapter.ColorData colors = ButtonBaseAdapter.PaintPopupRender(g,
|
||||
cellStyle.ForeColor,
|
||||
cellStyle.BackColor,
|
||||
DataGridView.Enabled).Calculate();
|
||||
CheckBoxBaseAdapter.DrawCheckBackground(DataGridView.Enabled,
|
||||
checkState,
|
||||
g,
|
||||
layout.checkBounds,
|
||||
colors.windowText,
|
||||
colors.options.highContrast ? colors.buttonFace : colors.highlight,
|
||||
true /*disabledColors*/,
|
||||
colors);
|
||||
CheckBoxBaseAdapter.DrawCheckBackground(
|
||||
DataGridView.Enabled,
|
||||
checkState,
|
||||
g,
|
||||
layout.checkBounds,
|
||||
colors.options.highContrast ? colors.buttonFace : colors.highlight,
|
||||
disabledColors: true);
|
||||
|
||||
CheckBoxBaseAdapter.DrawPopupBorder(g, layout.checkBounds, colors);
|
||||
CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width,
|
||||
checkState == CheckState.Checked || checkState == CheckState.Indeterminate,
|
||||
|
@ -1481,17 +1483,17 @@ namespace System.Windows.Forms
|
|||
else
|
||||
{
|
||||
// paint up
|
||||
ButtonBaseAdapter.LayoutOptions options = ButtonInternal.CheckBoxPopupAdapter.PaintPopupLayout(g,
|
||||
false /*show3D*/,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
ButtonBaseAdapter.LayoutOptions options = CheckBoxPopupAdapter.PaintPopupLayout(
|
||||
show3D: false,
|
||||
checkBoxSize.Width,
|
||||
checkBounds,
|
||||
Padding.Empty,
|
||||
false,
|
||||
cellStyle.Font,
|
||||
string.Empty,
|
||||
DataGridView.Enabled,
|
||||
DataGridViewUtilities.ComputeDrawingContentAlignmentForCellStyleAlignment(cellStyle.Alignment),
|
||||
DataGridView.RightToLeft);
|
||||
|
||||
options.everettButtonCompat = false;
|
||||
ButtonBaseAdapter.LayoutData layout = options.Layout();
|
||||
|
@ -1502,14 +1504,14 @@ namespace System.Windows.Forms
|
|||
cellStyle.ForeColor,
|
||||
cellStyle.BackColor,
|
||||
DataGridView.Enabled).Calculate();
|
||||
CheckBoxBaseAdapter.DrawCheckBackground(DataGridView.Enabled,
|
||||
checkState,
|
||||
g,
|
||||
layout.checkBounds,
|
||||
colors.windowText,
|
||||
colors.options.highContrast ? colors.buttonFace : colors.highlight,
|
||||
true /*disabledColors*/,
|
||||
colors);
|
||||
CheckBoxBaseAdapter.DrawCheckBackground(
|
||||
DataGridView.Enabled,
|
||||
checkState,
|
||||
g,
|
||||
layout.checkBounds,
|
||||
colors.options.highContrast ? colors.buttonFace : colors.highlight,
|
||||
disabledColors: true);
|
||||
|
||||
ButtonBaseAdapter.DrawFlatBorder(g, layout.checkBounds, colors.buttonShadow);
|
||||
CheckBoxBaseAdapter.DrawCheckOnly(checkBoxSize.Width,
|
||||
checkState == CheckState.Checked || checkState == CheckState.Indeterminate,
|
||||
|
|
|
@ -1426,8 +1426,8 @@ namespace System.Windows.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(e.Graphics, saveState: false);
|
||||
color = hdc.GetNearestColor(Enabled ? ForeColor : DisabledColor);
|
||||
using var scope = new PaintEventHdcScope(e);
|
||||
color = scope.HDC.GetNearestColor(Enabled ? ForeColor : DisabledColor);
|
||||
}
|
||||
|
||||
// Do actual drawing
|
||||
|
|
|
@ -1309,9 +1309,11 @@ namespace System.Windows.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(e.Graphics, saveState: false);
|
||||
foreColor = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(hdc, ColorTranslator.ToWin32(DisabledColor)));
|
||||
using (var scope = new PaintEventHdcScope(e))
|
||||
{
|
||||
foreColor = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(scope.HDC, ColorTranslator.ToWin32(DisabledColor)));
|
||||
}
|
||||
|
||||
Rectangle clientRectWidthPadding = ClientRectWithPadding;
|
||||
|
||||
|
@ -1501,9 +1503,11 @@ namespace System.Windows.Forms
|
|||
brushColor = linkBrush.Color;
|
||||
}
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(g, saveState: false);
|
||||
brushColor = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(hdc, ColorTranslator.ToWin32(brushColor)));
|
||||
using (var hdc = new DeviceContextHdcScope(g))
|
||||
{
|
||||
brushColor = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(hdc, ColorTranslator.ToWin32(brushColor)));
|
||||
}
|
||||
|
||||
Rectangle clientRectWithPadding = ClientRectWithPadding;
|
||||
TextRenderer.DrawText(
|
||||
|
@ -1562,9 +1566,12 @@ namespace System.Windows.Forms
|
|||
}
|
||||
else
|
||||
{
|
||||
using var hdc = new DeviceContextHdcScope(g, saveState: false);
|
||||
Color color = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(hdc, ColorTranslator.ToWin32(foreBrush.Color)));
|
||||
Color color;
|
||||
using (var hdc = new DeviceContextHdcScope(g, applyGraphicsState: false))
|
||||
{
|
||||
color = ColorTranslator.FromWin32(
|
||||
Gdi32.GetNearestColor(hdc, ColorTranslator.ToWin32(foreBrush.Color)));
|
||||
}
|
||||
|
||||
Rectangle clientRectWithPadding = ClientRectWithPadding;
|
||||
TextRenderer.DrawText(
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
|
@ -70,7 +68,9 @@ namespace System.Windows.Forms
|
|||
/// HDC, or the GDI+ Graphics object has been created (meaning GDI+ now owns the
|
||||
/// HDC), 0 is returned.
|
||||
/// </summary>
|
||||
internal IntPtr HDC => _graphics == null ? (IntPtr)_dc : IntPtr.Zero;
|
||||
internal Gdi32.HDC HDC => _graphics == null ? _dc : default;
|
||||
|
||||
internal bool IsGraphicsCreated => _graphics != null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref='Drawing.Graphics'/> object used to paint.
|
||||
|
|
|
@ -340,16 +340,16 @@ namespace System.Windows.Forms
|
|||
{
|
||||
using (Graphics g = WindowsFormsUtils.CreateMeasurementGraphics())
|
||||
{
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonPressedHighlight] = GetAlphaBlendedColor(g, SystemColors.Window, GetAlphaBlendedColor(g, SystemColors.Highlight, SystemColors.Window, 160), 50);
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonCheckedHighlight] = GetAlphaBlendedColor(g, SystemColors.Window, GetAlphaBlendedColor(g, SystemColors.Highlight, SystemColors.Window, 80), 20);
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonSelectedHighlight] = rgbTable[ProfessionalColorTable.KnownColors.ButtonCheckedHighlight];
|
||||
rgbTable[KnownColors.ButtonPressedHighlight] = GetAlphaBlendedColor(g, SystemColors.Window, GetAlphaBlendedColor(g, SystemColors.Highlight, SystemColors.Window, 160), 50);
|
||||
rgbTable[KnownColors.ButtonCheckedHighlight] = GetAlphaBlendedColor(g, SystemColors.Window, GetAlphaBlendedColor(g, SystemColors.Highlight, SystemColors.Window, 80), 20);
|
||||
rgbTable[KnownColors.ButtonSelectedHighlight] = rgbTable[KnownColors.ButtonCheckedHighlight];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonPressedHighlight] = SystemColors.Highlight;
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonCheckedHighlight] = SystemColors.ControlLight;
|
||||
rgbTable[ProfessionalColorTable.KnownColors.ButtonSelectedHighlight] = SystemColors.ControlLight;
|
||||
rgbTable[KnownColors.ButtonPressedHighlight] = SystemColors.Highlight;
|
||||
rgbTable[KnownColors.ButtonCheckedHighlight] = SystemColors.ControlLight;
|
||||
rgbTable[KnownColors.ButtonSelectedHighlight] = SystemColors.ControlLight;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,13 +103,14 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
{
|
||||
pevent.Graphics.FillRectangle(SystemBrushes.Window, dropDownButtonRect);
|
||||
}
|
||||
if (!DpiHelper.IsScalingRequirementMet)
|
||||
|
||||
using (var scope = new PaintEventHdcScope(pevent))
|
||||
{
|
||||
ComboBoxRenderer.DrawDropDownButton(pevent.Graphics, dropDownButtonRect, cbState);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComboBoxRenderer.DrawDropDownButtonForHandle(pevent.Graphics, dropDownButtonRect, cbState, HandleInternal);
|
||||
ComboBoxRenderer.DrawDropDownButtonForHandle(
|
||||
scope.HDC,
|
||||
dropDownButtonRect,
|
||||
cbState,
|
||||
DpiHelper.IsScalingRequirementMet ? HandleInternal : IntPtr.Zero);
|
||||
}
|
||||
|
||||
// Redraw focus cues
|
||||
|
|
|
@ -2205,15 +2205,9 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
return;
|
||||
}
|
||||
|
||||
VisualStyleElement element = null;
|
||||
if (fExpanded)
|
||||
{
|
||||
element = VisualStyleElement.ExplorerTreeView.Glyph.Opened;
|
||||
}
|
||||
else
|
||||
{
|
||||
element = VisualStyleElement.ExplorerTreeView.Glyph.Closed;
|
||||
}
|
||||
VisualStyleElement element = fExpanded
|
||||
? VisualStyleElement.ExplorerTreeView.Glyph.Opened
|
||||
: VisualStyleElement.ExplorerTreeView.Glyph.Closed;
|
||||
|
||||
// Invert color if it is not overriden by developer.
|
||||
if (colorInversionNeededInHC)
|
||||
|
@ -2228,7 +2222,9 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
}
|
||||
|
||||
VisualStyleRenderer explorerTreeRenderer = new VisualStyleRenderer(element);
|
||||
explorerTreeRenderer.DrawBackground(g, outline, handle);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
explorerTreeRenderer.DrawBackground(hdc, outline, handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2390,8 +2386,7 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
int textWidth = GetValueTextWidth(strValue, g, f);
|
||||
bool doToolTip = false;
|
||||
|
||||
// To check if text contains multiple lines
|
||||
//
|
||||
// Check if text contains multiple lines
|
||||
if (textWidth >= rect.Width || GetMultipleLines(strValue))
|
||||
{
|
||||
doToolTip = true;
|
||||
|
@ -2404,8 +2399,6 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
|
||||
// Do actual drawing
|
||||
|
||||
//strValue = ReplaceCRLF(strValue);
|
||||
|
||||
// bump the text down 2 pixels and over 1 pixel.
|
||||
if ((paintFlags & PaintValueFlags.PaintInPlace) != PaintValueFlags.None)
|
||||
{
|
||||
|
@ -2419,7 +2412,7 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
|
||||
Matrix m = g.Transform;
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(g, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
RECT lpRect = new Rectangle(rect.X + (int)m.OffsetX + 2, rect.Y + (int)m.OffsetY - 1, rect.Width - 4, rect.Height);
|
||||
Gdi32.HGDIOBJ hfont = (Gdi32.HGDIOBJ)GetHfont(valueModified);
|
||||
|
||||
|
@ -2432,7 +2425,7 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
{
|
||||
oldTextColor = Gdi32.SetTextColor(hdc, COLORREF.RgbToCOLORREF(textColor.ToArgb()));
|
||||
oldBkColor = Gdi32.SetBkColor(hdc, COLORREF.RgbToCOLORREF(bkColor.ToArgb()));
|
||||
hfont = Gdi32.SelectObject(hdc, hfont);
|
||||
using var fontSelection = new Gdi32.SelectObjectScope(hdc, hfont);
|
||||
User32.DT format = User32.DT.EDITCONTROL | User32.DT.EXPANDTABS | User32.DT.NOCLIP | User32.DT.SINGLELINE | User32.DT.NOPREFIX;
|
||||
if (gridHost.DrawValuesRightToLeft)
|
||||
{
|
||||
|
@ -2457,7 +2450,6 @@ namespace System.Windows.Forms.PropertyGridInternal
|
|||
{
|
||||
Gdi32.SetTextColor(hdc, oldTextColor);
|
||||
Gdi32.SetBkColor(hdc, oldBkColor);
|
||||
Gdi32.SelectObject(hdc, hfont);
|
||||
}
|
||||
|
||||
if (doToolTip)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms.VisualStyles;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
|
@ -15,34 +16,24 @@ namespace System.Windows.Forms
|
|||
/// </summary>
|
||||
public static class RadioButtonRenderer
|
||||
{
|
||||
//Make this per-thread, so that different threads can safely use these methods.
|
||||
// Make this per-thread, so that different threads can safely use these methods.
|
||||
[ThreadStatic]
|
||||
private static VisualStyleRenderer visualStyleRenderer = null;
|
||||
private static readonly VisualStyleElement RadioElement = VisualStyleElement.Button.RadioButton.UncheckedNormal;
|
||||
private static bool renderMatchingApplicationState = true;
|
||||
private static VisualStyleRenderer t_visualStyleRenderer = null;
|
||||
|
||||
private static readonly VisualStyleElement s_radioElement = VisualStyleElement.Button.RadioButton.UncheckedNormal;
|
||||
|
||||
/// <summary>
|
||||
/// If this property is true, then the renderer will use the setting from Application.RenderWithVisualStyles to
|
||||
/// determine how to render.
|
||||
/// If this property is false, the renderer will always render with visualstyles.
|
||||
/// </summary>
|
||||
public static bool RenderMatchingApplicationState
|
||||
{
|
||||
get
|
||||
{
|
||||
return renderMatchingApplicationState;
|
||||
}
|
||||
set
|
||||
{
|
||||
renderMatchingApplicationState = value;
|
||||
}
|
||||
}
|
||||
public static bool RenderMatchingApplicationState { get; set; } = true;
|
||||
|
||||
private static bool RenderWithVisualStyles
|
||||
{
|
||||
get
|
||||
{
|
||||
return (!renderMatchingApplicationState || Application.RenderWithVisualStyles);
|
||||
return (!RenderMatchingApplicationState || Application.RenderWithVisualStyles);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,7 +46,7 @@ namespace System.Windows.Forms
|
|||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
return visualStyleRenderer.IsBackgroundPartiallyTransparent();
|
||||
return t_visualStyleRenderer.IsBackgroundPartiallyTransparent();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -73,7 +64,7 @@ namespace System.Windows.Forms
|
|||
{
|
||||
InitializeRenderer(0);
|
||||
|
||||
visualStyleRenderer.DrawParentBackground(g, bounds, childControl);
|
||||
t_visualStyleRenderer.DrawParentBackground(g, bounds, childControl);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,16 +78,20 @@ namespace System.Windows.Forms
|
|||
|
||||
internal static void DrawRadioButton(Graphics g, Point glyphLocation, RadioButtonState state, IntPtr hWnd)
|
||||
{
|
||||
Rectangle glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(g, state, hWnd));
|
||||
|
||||
Rectangle glyphBounds;
|
||||
if (RenderWithVisualStyles)
|
||||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
visualStyleRenderer.DrawBackground(g, glyphBounds, hWnd);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(hdc, state, hWnd));
|
||||
t_visualStyleRenderer.DrawBackground(hdc, glyphBounds, hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var hdc = new DeviceContextHdcScope(g))
|
||||
{
|
||||
glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(hdc, state, hWnd));
|
||||
}
|
||||
ControlPaint.DrawRadioButton(g, glyphBounds, ConvertToButtonState(state));
|
||||
}
|
||||
}
|
||||
|
@ -121,15 +116,19 @@ namespace System.Windows.Forms
|
|||
|
||||
internal static void DrawRadioButton(Graphics g, Point glyphLocation, Rectangle textBounds, string radioButtonText, Font font, TextFormatFlags flags, bool focused, RadioButtonState state, IntPtr hWnd)
|
||||
{
|
||||
Rectangle glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(g, state, hWnd));
|
||||
Rectangle glyphBounds;
|
||||
using (var hdc = new DeviceContextHdcScope(g))
|
||||
{
|
||||
glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(hdc, state, hWnd));
|
||||
}
|
||||
Color textColor;
|
||||
|
||||
if (RenderWithVisualStyles)
|
||||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
visualStyleRenderer.DrawBackground(g, glyphBounds);
|
||||
textColor = visualStyleRenderer.GetColor(ColorProperty.TextColor);
|
||||
t_visualStyleRenderer.DrawBackground(g, glyphBounds);
|
||||
textColor = t_visualStyleRenderer.GetColor(ColorProperty.TextColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -165,17 +164,21 @@ namespace System.Windows.Forms
|
|||
|
||||
internal static void DrawRadioButton(Graphics g, Point glyphLocation, Rectangle textBounds, string radioButtonText, Font font, TextFormatFlags flags, Image image, Rectangle imageBounds, bool focused, RadioButtonState state, IntPtr hWnd)
|
||||
{
|
||||
Rectangle glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(g, state, hWnd));
|
||||
Rectangle glyphBounds;
|
||||
using (var hdc = new DeviceContextHdcScope(g))
|
||||
{
|
||||
glyphBounds = new Rectangle(glyphLocation, GetGlyphSize(hdc, state, hWnd));
|
||||
}
|
||||
Color textColor;
|
||||
|
||||
if (RenderWithVisualStyles)
|
||||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
//Keep this drawing order! It matches default drawing order.
|
||||
visualStyleRenderer.DrawImage(g, imageBounds, image);
|
||||
visualStyleRenderer.DrawBackground(g, glyphBounds);
|
||||
textColor = visualStyleRenderer.GetColor(ColorProperty.TextColor);
|
||||
// Keep this drawing order! It matches default drawing order.
|
||||
t_visualStyleRenderer.DrawImage(g, imageBounds, image);
|
||||
t_visualStyleRenderer.DrawBackground(g, glyphBounds);
|
||||
textColor = t_visualStyleRenderer.GetColor(ColorProperty.TextColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -197,16 +200,17 @@ namespace System.Windows.Forms
|
|||
/// </summary>
|
||||
public static Size GetGlyphSize(Graphics g, RadioButtonState state)
|
||||
{
|
||||
return GetGlyphSize(g, state, IntPtr.Zero);
|
||||
using var hdc = new DeviceContextHdcScope(g);
|
||||
return GetGlyphSize(hdc, state, IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal static Size GetGlyphSize(Graphics g, RadioButtonState state, IntPtr hWnd)
|
||||
internal static Size GetGlyphSize(Gdi32.HDC hdc, RadioButtonState state, IntPtr hWnd)
|
||||
{
|
||||
if (RenderWithVisualStyles)
|
||||
{
|
||||
InitializeRenderer((int)state);
|
||||
|
||||
return visualStyleRenderer.GetPartSize(g, ThemeSizeType.Draw, hWnd);
|
||||
return t_visualStyleRenderer.GetPartSize(hdc, ThemeSizeType.Draw, hWnd);
|
||||
}
|
||||
|
||||
return new Size(13, 13);
|
||||
|
@ -275,21 +279,21 @@ namespace System.Windows.Forms
|
|||
private static void InitializeRenderer(int state)
|
||||
{
|
||||
RadioButtonState radioButtonState = (RadioButtonState)state;
|
||||
int part = RadioElement.Part;
|
||||
int part = s_radioElement.Part;
|
||||
if (SystemInformation.HighContrast
|
||||
&& (radioButtonState == RadioButtonState.CheckedDisabled || radioButtonState == RadioButtonState.UncheckedDisabled)
|
||||
&& VisualStyleRenderer.IsCombinationDefined(RadioElement.ClassName, VisualStyleElement.Button.RadioButton.HighContrastDisabledPart))
|
||||
&& VisualStyleRenderer.IsCombinationDefined(s_radioElement.ClassName, VisualStyleElement.Button.RadioButton.HighContrastDisabledPart))
|
||||
{
|
||||
part = VisualStyleElement.Button.RadioButton.HighContrastDisabledPart;
|
||||
}
|
||||
|
||||
if (visualStyleRenderer == null)
|
||||
if (t_visualStyleRenderer == null)
|
||||
{
|
||||
visualStyleRenderer = new VisualStyleRenderer(RadioElement.ClassName, part, state);
|
||||
t_visualStyleRenderer = new VisualStyleRenderer(s_radioElement.ClassName, part, state);
|
||||
}
|
||||
else
|
||||
{
|
||||
visualStyleRenderer.SetParameters(RadioElement.ClassName, part, state);
|
||||
t_visualStyleRenderer.SetParameters(s_radioElement.ClassName, part, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
wg.DrawText(text, wf, pt, foreColor);
|
||||
|
@ -37,7 +37,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
wg.DrawText(text, wf, pt, foreColor, backColor);
|
||||
|
@ -80,7 +80,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
wg.DrawText(text, wf, bounds, foreColor);
|
||||
|
@ -95,7 +95,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
wg.DrawText(text, wf, bounds, foreColor, backColor);
|
||||
|
@ -188,7 +188,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
return wg.MeasureText(text, wf);
|
||||
|
@ -207,7 +207,7 @@ namespace System.Windows.Forms
|
|||
|
||||
Gdi32.QUALITY fontQuality = WindowsFont.WindowsFontQualityFromTextRenderingHint(dc as Graphics);
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc, saveState: false);
|
||||
using var hdc = new DeviceContextHdcScope(dc, applyGraphicsState: false);
|
||||
using WindowsGraphics wg = WindowsGraphics.FromHdc(hdc);
|
||||
using WindowsFont? wf = WindowsGraphicsCacheManager.GetWindowsFont(font, fontQuality);
|
||||
return wg.MeasureText(text, wf, proposedSize);
|
||||
|
|
|
@ -2632,11 +2632,6 @@ namespace System.Windows.Forms
|
|||
}
|
||||
#endregion
|
||||
|
||||
internal static Graphics GetMeasurementGraphics()
|
||||
{
|
||||
return WindowsFormsUtils.CreateMeasurementGraphics();
|
||||
}
|
||||
|
||||
internal ToolStripItem GetSelectedItem()
|
||||
{
|
||||
ToolStripItem selectedItem = null;
|
||||
|
@ -2909,7 +2904,7 @@ namespace System.Windows.Forms
|
|||
{
|
||||
using Bitmap image = new Bitmap(bounds.Width, bounds.Height);
|
||||
using Graphics g = Graphics.FromImage(image);
|
||||
using var imageHdc = new DeviceContextHdcScope(g, saveState: false);
|
||||
using var imageHdc = new DeviceContextHdcScope(g, applyGraphicsState: false);
|
||||
|
||||
// Send the actual wm_print message
|
||||
User32.SendMessageW(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
|
@ -276,7 +276,11 @@ namespace System.Windows.Forms
|
|||
vsr.SetParameters(VisualStyleElement.Spin.Up.Pressed);
|
||||
}
|
||||
|
||||
vsr.DrawBackground(e.Graphics, new Rectangle(0, 0, _parent._defaultButtonsWidth, half_height), HandleInternal);
|
||||
using var paintScope = new PaintEventHdcScope(e);
|
||||
vsr.DrawBackground(
|
||||
paintScope,
|
||||
new Rectangle(0, 0, _parent._defaultButtonsWidth, half_height),
|
||||
HandleInternal);
|
||||
|
||||
if (!Enabled)
|
||||
{
|
||||
|
@ -291,19 +295,24 @@ namespace System.Windows.Forms
|
|||
vsr.SetParameters(_mouseOver == ButtonID.Down ? VisualStyleElement.Spin.Down.Hot : VisualStyleElement.Spin.Down.Normal);
|
||||
}
|
||||
|
||||
vsr.DrawBackground(e.Graphics, new Rectangle(0, half_height, _parent._defaultButtonsWidth, half_height), HandleInternal);
|
||||
vsr.DrawBackground(
|
||||
paintScope,
|
||||
new Rectangle(0, half_height, _parent._defaultButtonsWidth, half_height),
|
||||
HandleInternal);
|
||||
}
|
||||
else
|
||||
{
|
||||
ControlPaint.DrawScrollButton(e.Graphics,
|
||||
new Rectangle(0, 0, _parent._defaultButtonsWidth, half_height),
|
||||
ScrollButton.Up,
|
||||
_pushed == ButtonID.Up ? ButtonState.Pushed : (Enabled ? ButtonState.Normal : ButtonState.Inactive));
|
||||
ControlPaint.DrawScrollButton(
|
||||
e.Graphics,
|
||||
new Rectangle(0, 0, _parent._defaultButtonsWidth, half_height),
|
||||
ScrollButton.Up,
|
||||
_pushed == ButtonID.Up ? ButtonState.Pushed : (Enabled ? ButtonState.Normal : ButtonState.Inactive));
|
||||
|
||||
ControlPaint.DrawScrollButton(e.Graphics,
|
||||
new Rectangle(0, half_height, _parent._defaultButtonsWidth, half_height),
|
||||
ScrollButton.Down,
|
||||
_pushed == ButtonID.Down ? ButtonState.Pushed : (Enabled ? ButtonState.Normal : ButtonState.Inactive));
|
||||
ControlPaint.DrawScrollButton(
|
||||
e.Graphics,
|
||||
new Rectangle(0, half_height, _parent._defaultButtonsWidth, half_height),
|
||||
ScrollButton.Down,
|
||||
_pushed == ButtonID.Down ? ButtonState.Pushed : (Enabled ? ButtonState.Normal : ButtonState.Inactive));
|
||||
}
|
||||
|
||||
if (half_height != (ClientSize.Height + 1) / 2)
|
||||
|
|
|
@ -545,10 +545,15 @@ namespace System.Windows.Forms
|
|||
clipTop.Intersect(clipBounds);
|
||||
clipRight.Intersect(clipBounds);
|
||||
clipBottom.Intersect(clipBounds);
|
||||
vsr.DrawBackground(e.Graphics, bounds, clipLeft, HandleInternal);
|
||||
vsr.DrawBackground(e.Graphics, bounds, clipTop, HandleInternal);
|
||||
vsr.DrawBackground(e.Graphics, bounds, clipRight, HandleInternal);
|
||||
vsr.DrawBackground(e.Graphics, bounds, clipBottom, HandleInternal);
|
||||
|
||||
using (var scope = new PaintEventHdcScope(e))
|
||||
{
|
||||
vsr.DrawBackground(scope, bounds, clipLeft, HandleInternal);
|
||||
vsr.DrawBackground(scope, bounds, clipTop, HandleInternal);
|
||||
vsr.DrawBackground(scope, bounds, clipRight, HandleInternal);
|
||||
vsr.DrawBackground(scope, bounds, clipBottom, HandleInternal);
|
||||
}
|
||||
|
||||
// Draw rectangle around edit control with background color
|
||||
using (Pen pen = new Pen(BackColor))
|
||||
{
|
||||
|
|
|
@ -16,21 +16,16 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public sealed class VisualStyleRenderer : IHandle
|
||||
{
|
||||
private const TextFormatFlags AllGraphicsProperties = TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.PreserveGraphicsTranslateTransform;
|
||||
|
||||
private string _class;
|
||||
private int part;
|
||||
private int state;
|
||||
private HRESULT lastHResult = 0;
|
||||
private static readonly int numberOfPossibleClasses = VisualStyleElement.Count; //used as size for themeHandles
|
||||
private HRESULT _lastHResult = 0;
|
||||
private static readonly int s_numberOfPossibleClasses = VisualStyleElement.Count; //used as size for themeHandles
|
||||
|
||||
[ThreadStatic]
|
||||
private static Hashtable? themeHandles; // per-thread cache of ThemeHandle objects.
|
||||
private static Hashtable? t_themeHandles; // per-thread cache of ThemeHandle objects.
|
||||
|
||||
[ThreadStatic]
|
||||
private static long threadCacheVersion = 0;
|
||||
private static long t_threadCacheVersion = 0;
|
||||
|
||||
private static long globalCacheVersion = 0;
|
||||
private static long s_globalCacheVersion = 0;
|
||||
|
||||
static VisualStyleRenderer()
|
||||
{
|
||||
|
@ -66,7 +61,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
// In some cases, this check isn't enough, since the theme handle creation
|
||||
// could fail for some other reason. Try creating a theme handle here - if successful, return true,
|
||||
// else return false.
|
||||
IntPtr hTheme = GetHandle("BUTTON", false); //Button is an arbitrary choice.
|
||||
IntPtr hTheme = GetHandle("BUTTON", false); // Button is an arbitrary choice.
|
||||
supported = (hTheme != IntPtr.Zero);
|
||||
}
|
||||
|
||||
|
@ -85,9 +80,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public static bool IsElementDefined(VisualStyleElement element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(element));
|
||||
}
|
||||
|
||||
return IsCombinationDefined(element.ClassName, element.Part);
|
||||
}
|
||||
|
@ -98,14 +91,9 @@ namespace System.Windows.Forms.VisualStyles
|
|||
|
||||
if (!IsSupported)
|
||||
{
|
||||
if (!VisualStyleInformation.IsEnabledByUser)
|
||||
{
|
||||
throw new InvalidOperationException(SR.VisualStyleNotActive);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(SR.VisualStylesDisabledInClientArea);
|
||||
}
|
||||
throw new InvalidOperationException(VisualStyleInformation.IsEnabledByUser
|
||||
? SR.VisualStylesDisabledInClientArea
|
||||
: SR.VisualStyleNotActive);
|
||||
}
|
||||
|
||||
IntPtr hTheme = GetHandle(className, false);
|
||||
|
@ -124,7 +112,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
}
|
||||
}
|
||||
|
||||
//if the combo isn't defined, check the validity of our theme handle cache
|
||||
// If the combo isn't defined, check the validity of our theme handle cache
|
||||
if (!returnVal)
|
||||
{
|
||||
using (ThemeHandle? tHandle = ThemeHandle.Create(className, false))
|
||||
|
@ -134,7 +122,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
returnVal = IsThemePartDefined(tHandle, part, 0).IsTrue();
|
||||
}
|
||||
|
||||
//if we did, in fact get a new correct theme handle, our cache is out of date -- update it now.
|
||||
// If we did, in fact get a new correct theme handle, our cache is out of date -- update it now.
|
||||
if (returnVal)
|
||||
{
|
||||
RefreshCache();
|
||||
|
@ -159,51 +147,30 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public VisualStyleRenderer(string className, int part, int state)
|
||||
{
|
||||
if (className == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(className));
|
||||
}
|
||||
if (!IsCombinationDefined(className, part))
|
||||
{
|
||||
throw new ArgumentException(SR.VisualStylesInvalidCombination);
|
||||
}
|
||||
|
||||
_class = className;
|
||||
this.part = part;
|
||||
this.state = state;
|
||||
if (!IsCombinationDefined(className, part))
|
||||
throw new ArgumentException(SR.VisualStylesInvalidCombination);
|
||||
|
||||
Class = className;
|
||||
Part = part;
|
||||
State = state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current _class. Use SetParameters to set.
|
||||
/// </summary>
|
||||
public string Class
|
||||
{
|
||||
get
|
||||
{
|
||||
return _class;
|
||||
}
|
||||
}
|
||||
public string Class { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current part. Use SetParameters to set.
|
||||
/// </summary>
|
||||
public int Part
|
||||
{
|
||||
get
|
||||
{
|
||||
return part;
|
||||
}
|
||||
}
|
||||
public int Part { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current state. Use SetParameters to set.
|
||||
/// </summary>
|
||||
public int State
|
||||
{
|
||||
get
|
||||
{
|
||||
return state;
|
||||
}
|
||||
}
|
||||
public int State { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying HTheme handle.
|
||||
|
@ -218,17 +185,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
{
|
||||
if (!IsSupported)
|
||||
{
|
||||
if (!VisualStyleInformation.IsEnabledByUser)
|
||||
{
|
||||
throw new InvalidOperationException(SR.VisualStyleNotActive);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(SR.VisualStylesDisabledInClientArea);
|
||||
}
|
||||
throw new InvalidOperationException(VisualStyleInformation.IsEnabledByUser
|
||||
? SR.VisualStylesDisabledInClientArea
|
||||
: SR.VisualStyleNotActive);
|
||||
}
|
||||
|
||||
return GetHandle(_class);
|
||||
return GetHandle(Class);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,10 +199,8 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public void SetParameters(VisualStyleElement element)
|
||||
{
|
||||
if (element == null)
|
||||
{
|
||||
if (element is null)
|
||||
throw new ArgumentNullException(nameof(element));
|
||||
}
|
||||
|
||||
SetParameters(element.ClassName, element.Part, element.State);
|
||||
}
|
||||
|
@ -253,13 +213,11 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public void SetParameters(string className, int part, int state)
|
||||
{
|
||||
if (!IsCombinationDefined(className, part))
|
||||
{
|
||||
throw new ArgumentException(SR.VisualStylesInvalidCombination);
|
||||
}
|
||||
|
||||
_class = className;
|
||||
this.part = part;
|
||||
this.state = state;
|
||||
Class = className;
|
||||
Part = part;
|
||||
State = state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -267,35 +225,28 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public void DrawBackground(IDeviceContext dc, Rectangle bounds)
|
||||
{
|
||||
DrawBackground(dc, bounds, IntPtr.Zero);
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
DrawBackground(hdc, bounds, IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal unsafe void DrawBackground(IDeviceContext dc, Rectangle bounds, IntPtr hWnd)
|
||||
internal unsafe void DrawBackground(Gdi32.HDC dc, Rectangle bounds, IntPtr hWnd)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
if (IntPtr.Zero != hWnd)
|
||||
{
|
||||
if (IntPtr.Zero != hWnd)
|
||||
{
|
||||
using (ThemeHandle hTheme = ThemeHandle.Create(_class, true, hWnd)!)
|
||||
{
|
||||
RECT rect = bounds;
|
||||
lastHResult = DrawThemeBackground(hTheme, wgr, part, state, ref rect, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rect = bounds;
|
||||
lastHResult = DrawThemeBackground(this, wgr, part, state, ref rect, null);
|
||||
}
|
||||
using ThemeHandle hTheme = ThemeHandle.Create(Class, true, hWnd)!;
|
||||
RECT rect = bounds;
|
||||
_lastHResult = DrawThemeBackground(hTheme, dc, Part, State, ref rect, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rect = bounds;
|
||||
_lastHResult = DrawThemeBackground(this, dc, Part, State, ref rect, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,41 +255,30 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public void DrawBackground(IDeviceContext dc, Rectangle bounds, Rectangle clipRectangle)
|
||||
{
|
||||
DrawBackground(dc, bounds, clipRectangle, IntPtr.Zero);
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
DrawBackground(hdc, bounds, clipRectangle, IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal unsafe void DrawBackground(IDeviceContext dc, Rectangle bounds, Rectangle clipRectangle, IntPtr hWnd)
|
||||
internal unsafe void DrawBackground(Gdi32.HDC dc, Rectangle bounds, Rectangle clipRectangle, IntPtr hWnd)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
if (bounds.Width < 0 || bounds.Height < 0 || clipRectangle.Width < 0 || clipRectangle.Height < 0)
|
||||
return;
|
||||
}
|
||||
if (clipRectangle.Width < 0 || clipRectangle.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
if (IntPtr.Zero != hWnd)
|
||||
{
|
||||
if (IntPtr.Zero != hWnd)
|
||||
{
|
||||
using (ThemeHandle hTheme = ThemeHandle.Create(_class, true, hWnd)!)
|
||||
{
|
||||
RECT rect = bounds;
|
||||
RECT clipRect = clipRectangle;
|
||||
lastHResult = DrawThemeBackground(hTheme, wgr, part, state, ref rect, &clipRect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rect = bounds;
|
||||
RECT clipRect = clipRectangle;
|
||||
lastHResult = DrawThemeBackground(this, wgr, part, state, ref rect, &clipRect);
|
||||
}
|
||||
using ThemeHandle hTheme = ThemeHandle.Create(Class, true, hWnd)!;
|
||||
RECT rect = bounds;
|
||||
RECT clipRect = clipRectangle;
|
||||
_lastHResult = DrawThemeBackground(hTheme, dc, Part, State, ref rect, &clipRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
RECT rect = bounds;
|
||||
RECT clipRect = clipRectangle;
|
||||
_lastHResult = DrawThemeBackground(this, dc, Part, State, ref rect, &clipRect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -347,30 +287,36 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Rectangle DrawEdge(IDeviceContext dc, Rectangle bounds, Edges edges, EdgeStyle style, EdgeEffects effects)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
return DrawEdge(hdc, bounds, edges, style, effects);
|
||||
}
|
||||
|
||||
internal Rectangle DrawEdge(Gdi32.HDC dc, Rectangle bounds, Edges edges, EdgeStyle style, EdgeEffects effects)
|
||||
{
|
||||
if (!ClientUtils.IsEnumValid_Masked(edges, (int)edges, (uint)(Edges.Left | Edges.Top | Edges.Right | Edges.Bottom | Edges.Diagonal)))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(edges), (int)edges, typeof(Edges));
|
||||
}
|
||||
|
||||
if (!ClientUtils.IsEnumValid_NotSequential(style, (int)style, (int)EdgeStyle.Raised, (int)EdgeStyle.Sunken, (int)EdgeStyle.Etched, (int)EdgeStyle.Bump))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(style), (int)style, typeof(EdgeStyle));
|
||||
}
|
||||
|
||||
if (!ClientUtils.IsEnumValid_Masked(effects, (int)effects, (uint)(EdgeEffects.FillInterior | EdgeEffects.Flat | EdgeEffects.Soft | EdgeEffects.Mono)))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(effects), (int)effects, typeof(EdgeEffects));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
RECT destRect = bounds;
|
||||
var contentRect = new RECT();
|
||||
lastHResult = DrawThemeEdge(this, wgr, part, state, ref destRect, (User32.EDGE)style, (User32.BF)edges | (User32.BF)effects | User32.BF.ADJUST, ref contentRect);
|
||||
_lastHResult = DrawThemeEdge(
|
||||
this,
|
||||
dc,
|
||||
Part,
|
||||
State,
|
||||
ref destRect,
|
||||
(User32.EDGE)style,
|
||||
(User32.BF)edges | (User32.BF)effects | User32.BF.ADJUST,
|
||||
ref contentRect);
|
||||
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
|
@ -381,19 +327,13 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public void DrawImage(Graphics g, Rectangle bounds, Image image)
|
||||
{
|
||||
if (g == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(g));
|
||||
}
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(image));
|
||||
}
|
||||
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g.DrawImage(image, bounds);
|
||||
}
|
||||
|
@ -405,24 +345,16 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public void DrawImage(Graphics g, Rectangle bounds, ImageList imageList, int imageIndex)
|
||||
{
|
||||
if (g == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(g));
|
||||
}
|
||||
|
||||
if (imageList == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(imageList));
|
||||
}
|
||||
|
||||
if (imageIndex < 0 || imageIndex >= imageList.Images.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(imageIndex), imageIndex, string.Format(SR.InvalidArgument, nameof(imageIndex), imageIndex));
|
||||
}
|
||||
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// DrawThemeIcon currently seems to do nothing, but still return S_OK. As a workaround,
|
||||
// we call DrawImage on the graphics object itself for now.
|
||||
|
@ -436,25 +368,20 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public void DrawParentBackground(IDeviceContext dc, Rectangle bounds, Control childControl)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
if (childControl == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(childControl));
|
||||
}
|
||||
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (childControl.IsHandleCreated)
|
||||
{
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT rc = bounds;
|
||||
lastHResult = DrawThemeParentBackground(childControl, wgr, ref rc);
|
||||
_lastHResult = DrawThemeParentBackground(childControl, hdc, ref rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,22 +406,23 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public void DrawText(IDeviceContext dc, Rectangle bounds, string? textToDraw, bool drawDisabled, TextFormatFlags flags)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
DrawText(hdc, bounds, textToDraw, drawDisabled, flags);
|
||||
}
|
||||
|
||||
internal void DrawText(Gdi32.HDC dc, Rectangle bounds, string? textToDraw, bool drawDisabled, TextFormatFlags flags)
|
||||
{
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(textToDraw))
|
||||
{
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
uint disableFlag = drawDisabled ? 0x1u : 0u;
|
||||
RECT rect = bounds;
|
||||
lastHResult = DrawThemeText(this, wgr, part, state, textToDraw, textToDraw.Length, (User32.DT)flags, disableFlag, ref rect);
|
||||
_lastHResult = DrawThemeText(this, dc, Part, State, textToDraw, textToDraw.Length, (User32.DT)flags, disableFlag, ref rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,18 +431,20 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Rectangle GetBackgroundContentRectangle(IDeviceContext dc, Rectangle bounds)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
return GetBackgroundContentRectangle(hdc, bounds);
|
||||
}
|
||||
|
||||
internal Rectangle GetBackgroundContentRectangle(Gdi32.HDC dc, Rectangle bounds)
|
||||
{
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
return Rectangle.Empty;
|
||||
|
||||
RECT boundsRect = bounds;
|
||||
lastHResult = GetThemeBackgroundContentRect(this, wgr, part, state, ref boundsRect, out RECT rect);
|
||||
_lastHResult = GetThemeBackgroundContentRect(this, dc, Part, State, ref boundsRect, out RECT rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
@ -523,18 +453,15 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Rectangle GetBackgroundExtent(IDeviceContext dc, Rectangle contentBounds)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
if (contentBounds.Width < 0 || contentBounds.Height < 0)
|
||||
{
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
if (contentBounds.Width < 0 || contentBounds.Height < 0)
|
||||
return Rectangle.Empty;
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT contentBoundsRect = contentBounds;
|
||||
lastHResult = GetThemeBackgroundExtent(this, wgr, part, state, ref contentBoundsRect, out RECT extentRect);
|
||||
_lastHResult = GetThemeBackgroundExtent(this, hdc, Part, State, ref contentBoundsRect, out RECT extentRect);
|
||||
return extentRect;
|
||||
}
|
||||
|
||||
|
@ -545,30 +472,27 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Region? GetBackgroundRegion(IDeviceContext dc, Rectangle bounds)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
if (bounds.Width < 0 || bounds.Height < 0)
|
||||
return null;
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT boundsRect = bounds;
|
||||
lastHResult = GetThemeBackgroundRegion(this, wgr, part, state, ref boundsRect, out IntPtr hRegion);
|
||||
_lastHResult = GetThemeBackgroundRegion(this, hdc, Part, State, ref boundsRect, out Gdi32.HRGN hRegion);
|
||||
|
||||
// GetThemeBackgroundRegion returns a null hRegion if it fails to create one, it could be because the bounding
|
||||
// box is too big. For more info see code in %xpsrc%\shell\themes\uxtheme\imagefile.cpp if you have an enlistment to it.
|
||||
|
||||
if (hRegion == IntPtr.Zero)
|
||||
if (hRegion.IsNull)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// From the GDI+ sources it doesn't appear as if they take ownership of the hRegion, so this is safe to do.
|
||||
// We need to DeleteObject in order to not leak.
|
||||
Region region = Region.FromHrgn(hRegion);
|
||||
Region region = Region.FromHrgn(hRegion.Handle);
|
||||
Gdi32.DeleteObject(hRegion);
|
||||
return region;
|
||||
}
|
||||
|
@ -579,12 +503,10 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public bool GetBoolean(BooleanProperty prop)
|
||||
{
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)BooleanProperty.Transparent, (int)BooleanProperty.SourceShrink))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(BooleanProperty));
|
||||
}
|
||||
|
||||
BOOL val = BOOL.FALSE;
|
||||
lastHResult = GetThemeBool(this, part, state, (int)prop, ref val);
|
||||
_lastHResult = GetThemeBool(this, Part, State, (int)prop, ref val);
|
||||
return val.IsTrue();
|
||||
}
|
||||
|
||||
|
@ -593,14 +515,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Color GetColor(ColorProperty prop)
|
||||
{
|
||||
//valid values are 0xed9 to 0xeef
|
||||
// Valid values are 0xed9 to 0xeef
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)ColorProperty.BorderColor, (int)ColorProperty.AccentColorHint))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(ColorProperty));
|
||||
}
|
||||
|
||||
int color = 0;
|
||||
lastHResult = GetThemeColor(this, part, state, (int)prop, ref color);
|
||||
_lastHResult = GetThemeColor(this, Part, State, (int)prop, ref color);
|
||||
return ColorTranslator.FromWin32(color);
|
||||
}
|
||||
|
||||
|
@ -609,14 +529,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public int GetEnumValue(EnumProperty prop)
|
||||
{
|
||||
//valid values are 0xfa1 to 0xfaf
|
||||
// Valid values are 0xfa1 to 0xfaf
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)EnumProperty.BackgroundType, (int)EnumProperty.TrueSizeScalingType))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(EnumProperty));
|
||||
}
|
||||
|
||||
int val = 0;
|
||||
lastHResult = GetThemeEnumValue(this, part, state, (int)prop, ref val);
|
||||
_lastHResult = GetThemeEnumValue(this, Part, State, (int)prop, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -625,16 +543,14 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe string GetFilename(FilenameProperty prop)
|
||||
{
|
||||
//valid values are 0xbb9 to 0xbc0
|
||||
// Valid values are 0xbb9 to 0xbc0
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)FilenameProperty.ImageFile, (int)FilenameProperty.GlyphImageFile))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(FilenameProperty));
|
||||
}
|
||||
|
||||
Span<char> filename = stackalloc char[512];
|
||||
fixed (char* pFilename = filename)
|
||||
{
|
||||
lastHResult = GetThemeFilename(this, part, state, (int)prop, pFilename, filename.Length);
|
||||
_lastHResult = GetThemeFilename(this, Part, State, (int)prop, pFilename, filename.Length);
|
||||
}
|
||||
return filename.SliceAtFirstNull().ToString();
|
||||
}
|
||||
|
@ -645,21 +561,17 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Font? GetFont(IDeviceContext dc, FontProperty prop)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
if (!ClientUtils.IsEnumValid_NotSequential(prop, (int)prop, (int)FontProperty.TextFont, (int)FontProperty.GlyphFont))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(FontProperty));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
lastHResult = GetThemeFont(this, wgr, part, state, (int)prop, out User32.LOGFONTW logfont);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
_lastHResult = GetThemeFont(this, hdc, Part, State, (int)prop, out User32.LOGFONTW logfont);
|
||||
|
||||
// Check for a failed HR.
|
||||
if (!lastHResult.Succeeded())
|
||||
if (!_lastHResult.Succeeded())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -685,14 +597,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public int GetInteger(IntegerProperty prop)
|
||||
{
|
||||
//valid values are 0x961 to 0x978
|
||||
// Valid values are 0x961 to 0x978
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)IntegerProperty.ImageCount, (int)IntegerProperty.MinDpi5))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(IntegerProperty));
|
||||
}
|
||||
|
||||
int val = 0;
|
||||
lastHResult = GetThemeInt(this, part, state, (int)prop, ref val);
|
||||
_lastHResult = GetThemeInt(this, Part, State, (int)prop, ref val);
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -701,33 +611,27 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public Size GetPartSize(IDeviceContext dc, ThemeSizeType type)
|
||||
{
|
||||
return GetPartSize(dc, type, IntPtr.Zero);
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
return GetPartSize(hdc, type, IntPtr.Zero);
|
||||
}
|
||||
|
||||
internal unsafe Size GetPartSize(IDeviceContext dc, ThemeSizeType type, IntPtr hWnd)
|
||||
internal unsafe Size GetPartSize(Gdi32.HDC dc, ThemeSizeType type, IntPtr hWnd = default)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
// valid values are 0x0 to 0x2
|
||||
// Valid values are 0x0 to 0x2
|
||||
if (!ClientUtils.IsEnumValid(type, (int)type, (int)ThemeSizeType.Minimum, (int)ThemeSizeType.Draw))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(ThemeSizeType));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
if (DpiHelper.IsPerMonitorV2Awareness && hWnd != IntPtr.Zero)
|
||||
{
|
||||
using (ThemeHandle hTheme = ThemeHandle.Create(_class, true, hWnd)!)
|
||||
{
|
||||
lastHResult = GetThemePartSize(hTheme, wgr, part, state, null, type, out Size dpiSize);
|
||||
return dpiSize;
|
||||
}
|
||||
using ThemeHandle hTheme = ThemeHandle.Create(Class, true, hWnd)!;
|
||||
_lastHResult = GetThemePartSize(hTheme, dc, Part, State, null, type, out Size dpiSize);
|
||||
return dpiSize;
|
||||
}
|
||||
|
||||
lastHResult = GetThemePartSize(this, wgr, part, state, null, type, out Size size);
|
||||
_lastHResult = GetThemePartSize(this, dc, Part, State, null, type, out Size size);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -736,20 +640,16 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe Size GetPartSize(IDeviceContext dc, Rectangle bounds, ThemeSizeType type)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
//valid values are 0x0 to 0x2
|
||||
// Valid values are 0x0 to 0x2
|
||||
if (!ClientUtils.IsEnumValid(type, (int)type, (int)ThemeSizeType.Minimum, (int)ThemeSizeType.Draw))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(ThemeSizeType));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT boundsRect = bounds;
|
||||
lastHResult = GetThemePartSize(this, wgr, part, state, &boundsRect, type, out Size size);
|
||||
_lastHResult = GetThemePartSize(this, hdc, Part, State, &boundsRect, type, out Size size);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -760,11 +660,9 @@ namespace System.Windows.Forms.VisualStyles
|
|||
{
|
||||
//valid values are 0xd49 to 0xd50
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)PointProperty.Offset, (int)PointProperty.MinSize5))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(PointProperty));
|
||||
}
|
||||
|
||||
lastHResult = GetThemePosition(this, part, state, (int)prop, out Point point);
|
||||
_lastHResult = GetThemePosition(this, Part, State, (int)prop, out Point point);
|
||||
return point;
|
||||
}
|
||||
|
||||
|
@ -773,19 +671,15 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe Padding GetMargins(IDeviceContext dc, MarginProperty prop)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
//valid values are 0xe11 to 0xe13
|
||||
// Valid values are 0xe11 to 0xe13
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)MarginProperty.SizingMargins, (int)MarginProperty.CaptionMargins))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(MarginProperty));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
lastHResult = GetThemeMargins(this, wgr, part, state, (int)prop, null, out MARGINS margins);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
_lastHResult = GetThemeMargins(this, hdc, Part, State, (int)prop, null, out MARGINS margins);
|
||||
|
||||
return new Padding(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight);
|
||||
}
|
||||
|
@ -795,16 +689,14 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe string GetString(StringProperty prop)
|
||||
{
|
||||
//valid values are 0xc81 to 0xc81
|
||||
// Valid values are 0xc81 to 0xc81
|
||||
if (!ClientUtils.IsEnumValid(prop, (int)prop, (int)StringProperty.Text, (int)StringProperty.Text))
|
||||
{
|
||||
throw new InvalidEnumArgumentException(nameof(prop), (int)prop, typeof(StringProperty));
|
||||
}
|
||||
|
||||
Span<char> aString = stackalloc char[512];
|
||||
fixed (char* pString = aString)
|
||||
{
|
||||
lastHResult = GetThemeString(this, part, state, (int)prop, pString, aString.Length);
|
||||
_lastHResult = GetThemeString(this, Part, State, (int)prop, pString, aString.Length);
|
||||
}
|
||||
return aString.SliceAtFirstNull().ToString();
|
||||
}
|
||||
|
@ -814,18 +706,14 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe Rectangle GetTextExtent(IDeviceContext dc, string textToDraw, TextFormatFlags flags)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(textToDraw))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textToDraw));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
lastHResult = GetThemeTextExtent(this, wgr, part, state, textToDraw, textToDraw.Length, (uint)flags, null, out RECT rect);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
_lastHResult = GetThemeTextExtent(this, hdc, Part, State, textToDraw, textToDraw.Length, (uint)flags, null, out RECT rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
@ -834,19 +722,15 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public unsafe Rectangle GetTextExtent(IDeviceContext dc, Rectangle bounds, string textToDraw, TextFormatFlags flags)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(textToDraw))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(textToDraw));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT boundsRect = bounds;
|
||||
lastHResult = GetThemeTextExtent(this, wgr, part, state, textToDraw, textToDraw.Length, (uint)flags, &boundsRect, out RECT rect);
|
||||
_lastHResult = GetThemeTextExtent(this, hdc, Part, State, textToDraw, textToDraw.Length, (uint)flags, &boundsRect, out RECT rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
|
@ -855,13 +739,11 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public TextMetrics GetTextMetrics(IDeviceContext dc)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
lastHResult = GetThemeTextMetrics(this, wgr, part, state, out TextMetrics tm);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
_lastHResult = GetThemeTextMetrics(this, hdc, Part, State, out TextMetrics tm);
|
||||
return tm;
|
||||
}
|
||||
|
||||
|
@ -870,14 +752,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public HitTestCode HitTestBackground(IDeviceContext dc, Rectangle backgroundRectangle, Point pt, HitTestOptions options)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT backgroundRect = backgroundRectangle;
|
||||
lastHResult = HitTestThemeBackground(this, wgr, part, state, (uint)options, ref backgroundRect, IntPtr.Zero, pt, out ushort htCode);
|
||||
_lastHResult = HitTestThemeBackground(this, hdc, Part, State, (uint)options, ref backgroundRect, IntPtr.Zero, pt, out ushort htCode);
|
||||
return (HitTestCode)htCode;
|
||||
}
|
||||
|
||||
|
@ -887,13 +767,10 @@ namespace System.Windows.Forms.VisualStyles
|
|||
public HitTestCode HitTestBackground(Graphics g, Rectangle backgroundRectangle, Region region, Point pt, HitTestOptions options)
|
||||
{
|
||||
if (g == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(g));
|
||||
}
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(region));
|
||||
}
|
||||
|
||||
IntPtr hRgn = region.GetHrgn(g);
|
||||
return HitTestBackground(g, backgroundRectangle, hRgn, pt, options);
|
||||
|
@ -904,14 +781,12 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public HitTestCode HitTestBackground(IDeviceContext dc, Rectangle backgroundRectangle, IntPtr hRgn, Point pt, HitTestOptions options)
|
||||
{
|
||||
if (dc == null)
|
||||
{
|
||||
if (dc is null)
|
||||
throw new ArgumentNullException(nameof(dc));
|
||||
}
|
||||
|
||||
using var wgr = new WindowsGraphicsWrapper(dc, AllGraphicsProperties);
|
||||
using var hdc = new DeviceContextHdcScope(dc);
|
||||
RECT backgroundRect = backgroundRectangle;
|
||||
lastHResult = HitTestThemeBackground(this, wgr, part, state, (uint)options, ref backgroundRect, hRgn, pt, out ushort htCode);
|
||||
_lastHResult = HitTestThemeBackground(this, hdc, Part, State, (uint)options, ref backgroundRect, hRgn, pt, out ushort htCode);
|
||||
return (HitTestCode)htCode;
|
||||
}
|
||||
|
||||
|
@ -920,27 +795,21 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
public bool IsBackgroundPartiallyTransparent()
|
||||
{
|
||||
return IsThemeBackgroundPartiallyTransparent(this, part, state).IsTrue();
|
||||
return IsThemeBackgroundPartiallyTransparent(this, Part, State).IsTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is similar to GetLastError in Win32. It returns the last HRESULT returned from a native call
|
||||
/// into theme apis. We eat the errors and let the user handle any errors that occurred.
|
||||
/// </summary>
|
||||
public int LastHResult
|
||||
{
|
||||
get
|
||||
{
|
||||
return (int)lastHResult;
|
||||
}
|
||||
}
|
||||
public int LastHResult => (int)_lastHResult;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates the ThemeHandle cache hashtable.
|
||||
/// </summary>
|
||||
private static void CreateThemeHandleHashtable()
|
||||
{
|
||||
themeHandles = new Hashtable(numberOfPossibleClasses);
|
||||
t_themeHandles = new Hashtable(s_numberOfPossibleClasses);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -957,7 +826,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
// its handle, this whole version check won't work, but it is unlikely to happen.
|
||||
|
||||
// this is not ideal.
|
||||
globalCacheVersion++;
|
||||
s_globalCacheVersion++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -968,14 +837,14 @@ namespace System.Windows.Forms.VisualStyles
|
|||
{
|
||||
ThemeHandle? tHandle = null;
|
||||
|
||||
if (themeHandles != null)
|
||||
if (t_themeHandles != null)
|
||||
{
|
||||
string[] classNames = new string[themeHandles.Keys.Count];
|
||||
themeHandles.Keys.CopyTo(classNames, 0);
|
||||
string[] classNames = new string[t_themeHandles.Keys.Count];
|
||||
t_themeHandles.Keys.CopyTo(classNames, 0);
|
||||
|
||||
foreach (string className in classNames)
|
||||
{
|
||||
tHandle = (ThemeHandle?)themeHandles[className];
|
||||
tHandle = (ThemeHandle?)t_themeHandles[className];
|
||||
if (tHandle != null)
|
||||
{
|
||||
tHandle.Dispose();
|
||||
|
@ -988,7 +857,7 @@ namespace System.Windows.Forms.VisualStyles
|
|||
tHandle = ThemeHandle.Create(className, false);
|
||||
if (tHandle != null)
|
||||
{
|
||||
themeHandles[className] = tHandle;
|
||||
t_themeHandles[className] = tHandle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1006,18 +875,18 @@ namespace System.Windows.Forms.VisualStyles
|
|||
/// </summary>
|
||||
private static IntPtr GetHandle(string className, bool throwExceptionOnFail)
|
||||
{
|
||||
if (themeHandles == null)
|
||||
if (t_themeHandles == null)
|
||||
{
|
||||
CreateThemeHandleHashtable();
|
||||
}
|
||||
|
||||
if (threadCacheVersion != globalCacheVersion)
|
||||
if (t_threadCacheVersion != s_globalCacheVersion)
|
||||
{
|
||||
RefreshCache();
|
||||
threadCacheVersion = globalCacheVersion;
|
||||
t_threadCacheVersion = s_globalCacheVersion;
|
||||
}
|
||||
|
||||
if (!themeHandles!.Contains(className))
|
||||
if (!t_themeHandles!.Contains(className))
|
||||
{
|
||||
// See if it is already in cache
|
||||
ThemeHandle? tHandle = ThemeHandle.Create(className, throwExceptionOnFail);
|
||||
|
@ -1026,11 +895,11 @@ namespace System.Windows.Forms.VisualStyles
|
|||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
themeHandles.Add(className, tHandle);
|
||||
t_themeHandles.Add(className, tHandle);
|
||||
return tHandle.Handle;
|
||||
}
|
||||
|
||||
return ((ThemeHandle)themeHandles[className]!).Handle;
|
||||
return ((ThemeHandle)t_themeHandles[className]!).Handle;
|
||||
}
|
||||
|
||||
// This wrapper class is needed for safely cleaning up TLS cache of handles.
|
||||
|
|
|
@ -42,7 +42,10 @@ namespace System.Windows.Forms
|
|||
/// This <see cref="Graphics"/> requires disposal.
|
||||
/// </remarks>
|
||||
public static Graphics CreateMeasurementGraphics()
|
||||
=> WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Hdc.CreateGraphics();
|
||||
=> GetMeasurementDeviceContext().CreateGraphics();
|
||||
|
||||
public static Gdi32.HDC GetMeasurementDeviceContext()
|
||||
=> WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.Hdc;
|
||||
|
||||
/// <summary>
|
||||
/// If you want to know if a piece of text contains one and only one &
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using static Interop;
|
||||
|
||||
namespace System.Windows.Forms
|
||||
{
|
||||
/// <summary>
|
||||
/// Scope for <see cref="PaintEventArgs"/> that prefers to avoid creating <see cref="System.Drawing.Graphics"/> if
|
||||
/// possible to get HDC.
|
||||
/// </summary>
|
||||
internal readonly ref struct PaintEventHdcScope
|
||||
{
|
||||
internal Gdi32.HDC HDC { get; }
|
||||
private readonly DeviceContextHdcScope _scope;
|
||||
|
||||
public PaintEventHdcScope(PaintEventArgs args)
|
||||
{
|
||||
if (!args.IsGraphicsCreated)
|
||||
{
|
||||
HDC = args.HDC;
|
||||
_scope = default;
|
||||
}
|
||||
else
|
||||
{
|
||||
_scope = new DeviceContextHdcScope(args.Graphics);
|
||||
HDC = _scope.HDC;
|
||||
}
|
||||
}
|
||||
|
||||
public static implicit operator Gdi32.HDC(in PaintEventHdcScope scope) => scope.HDC;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_scope.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -196,9 +196,12 @@ namespace System.Windows.Forms.Internal
|
|||
/// <summary>
|
||||
/// Creates a DeviceContext object wrapping a memory DC compatible with the specified device.
|
||||
/// </summary>
|
||||
/// <param name="hdc">
|
||||
/// If <see cref="Gdi32.HDC"/> is default a memory DC compatible with the application's current screen is
|
||||
/// created. In this case the returned DC is only valid for the lifetime of the creating thread.
|
||||
/// </param>
|
||||
public static DeviceContext FromCompatibleDC(Gdi32.HDC hdc)
|
||||
{
|
||||
// If hdc is null, the function creates a memory DC compatible with the application's current screen.
|
||||
// In this case the thread that calls CreateCompatibleDC owns the HDC that is created. When this thread is destroyed,
|
||||
// the HDC is no longer valid.
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ namespace System.Windows.Forms.Internal
|
|||
// Get the font height from the specified size. size is in point units and height in logical
|
||||
// units (pixels when using MM_TEXT) so we need to make the conversion using the number of
|
||||
// pixels per logical inch along the screen height. (1 point = 1/72 inch.)
|
||||
int pixelsY = (int)Math.Ceiling(WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.DpiY * font.SizeInPoints / 72);
|
||||
int pixelsY = (int)Math.Ceiling(DpiHelper.DeviceDpi * font.SizeInPoints / 72);
|
||||
|
||||
// The lfHeight represents the font cell height (line spacing) which includes the internal
|
||||
// leading; we specify a negative size value (in pixels) for the height so the font mapper
|
||||
|
|
|
@ -12893,7 +12893,7 @@ namespace System.Windows.Forms.Tests
|
|||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void Control_WndProc_InvokePrintClientWithoutHandleWithoutWParamUserPaint_ThrowsNullReferenceException()
|
||||
public void Control_WndProc_InvokePrintClientWithoutHandleWithoutWParamUserPaint_DoesNotThrow()
|
||||
{
|
||||
using (new NoAssertContext())
|
||||
{
|
||||
|
@ -12908,10 +12908,10 @@ namespace System.Windows.Forms.Tests
|
|||
Msg = (int)User32.WM.PRINTCLIENT,
|
||||
Result = (IntPtr)250
|
||||
};
|
||||
Assert.Throws<NullReferenceException>(() => control.WndProc(ref m));
|
||||
control.WndProc(ref m);
|
||||
Assert.Equal((IntPtr)250, m.Result);
|
||||
Assert.False(control.IsHandleCreated);
|
||||
Assert.Equal(0, paintCallCount);
|
||||
Assert.Equal(1, paintCallCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12997,7 +12997,7 @@ namespace System.Windows.Forms.Tests
|
|||
}
|
||||
|
||||
[WinFormsFact]
|
||||
public void Control_WndProc_InvokePrintClientWithHandleWithoutWParamUserPaint_ThrowsNullReferenceException()
|
||||
public void Control_WndProc_InvokePrintClientWithHandleWithoutWParamUserPaint_DoesNotThrow()
|
||||
{
|
||||
using var control = new SubControl();
|
||||
control.SetStyle(ControlStyles.UserPaint, true);
|
||||
|
@ -13017,13 +13017,14 @@ namespace System.Windows.Forms.Tests
|
|||
Msg = (int)User32.WM.PRINTCLIENT,
|
||||
Result = (IntPtr)250
|
||||
};
|
||||
Assert.Throws<NullReferenceException>(() => control.WndProc(ref m));
|
||||
|
||||
control.WndProc(ref m);
|
||||
Assert.Equal((IntPtr)250, m.Result);
|
||||
Assert.True(control.IsHandleCreated);
|
||||
Assert.Equal(1, invalidatedCallCount);
|
||||
Assert.Equal(0, invalidatedCallCount);
|
||||
Assert.Equal(0, styleChangedCallCount);
|
||||
Assert.Equal(0, createdCallCount);
|
||||
Assert.Equal(0, paintCallCount);
|
||||
Assert.Equal(1, paintCallCount);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> WndProc_PrintClientWithHandleWithWParam_TestData()
|
||||
|
|
Загрузка…
Ссылка в новой задаче