Add more HGDIOBJ handles and scopes (#3528)

This cuts a number of uneccesary allocations and sets up to remove much more. The goal is to remove WindowsGraphics and DeviceContext (and other related classes) which are extremely slow and allocate a lot. Getting rid of these classes will also improve code clarity.

- Introduce more scopes and handle extensions to move away from DeviceContext, WindowsGraphics, etc.
- Introduce HDC, HFONT, HBRUSH, HPEN and other HGDIOBJ objects
- Add IHandle to DeviceContext, WindowsGraphics for the HDC
- Add IHandle to WindowsBrush for the HBRUSH
- Add a referemce to this to the end of message processing to root Control
- Remove MarshalByRefObject from internal classes
- Improve perf of background drawing
- Move ApplyGraphicProperties to Primitives
- Cut dead code
- Note: Did not change COM interface defintions
This commit is contained in:
Jeremy Kuhne 2020-06-30 17:07:20 -07:00 коммит произвёл GitHub
Родитель 4c1c9d66bb
Коммит dfd8105aa6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
181 изменённых файлов: 2203 добавлений и 1812 удалений

Просмотреть файл

@ -12,7 +12,6 @@ using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
@ -1937,6 +1936,7 @@ namespace System.ComponentModel.Design
IntegralHeight = false,
Font = ActionPanel.Font
};
listBox.KeyDown += new KeyEventHandler(OnListBoxKeyDown);
TypeConverter.StandardValuesCollection standardValues = GetStandardValues();
if (standardValues != null)
@ -1955,20 +1955,22 @@ namespace System.ComponentModel.Design
// All measurement code borrowed from WinForms PropertyGridView.cs
int maxWidth = 0;
// The listbox draws with GDI, not GDI+. So, we use a normal DC here.
IntPtr hdc = User32.GetDC(new HandleRef(listBox, listBox.Handle));
IntPtr hFont = listBox.Font.ToHfont();
var tm = new Gdi32.TEXTMETRICW();
try
using (var hdc = new User32.GetDcScope(listBox.Handle))
{
hFont = Gdi32.SelectObject(hdc, hFont);
using var hFont = new Gdi32.ObjectScope(listBox.Font.ToHFONT());
using var fontSelection = new Gdi32.SelectObjectScope(hdc, hFont);
var tm = new Gdi32.TEXTMETRICW();
if (listBox.Items.Count > 0)
{
foreach (string s in listBox.Items)
{
var textSize = new Size();
Gdi32.GetTextExtentPoint32W(new HandleRef(listBox, hdc), s, s.Length, ref textSize);
maxWidth = Math.Max((int)textSize.Width, maxWidth);
Gdi32.GetTextExtentPoint32W(hdc, s, s.Length, ref textSize);
maxWidth = Math.Max(textSize.Width, maxWidth);
}
}
@ -1976,17 +1978,12 @@ namespace System.ComponentModel.Design
// border + padding + scrollbar
maxWidth += 2 + tm.tmMaxCharWidth + SystemInformation.VerticalScrollBarWidth;
hFont = Gdi32.SelectObject(hdc, hFont);
}
finally
{
Gdi32.DeleteObject(hFont);
User32.ReleaseDC(new HandleRef(listBox, listBox.Handle), hdc);
listBox.Height = Math.Max(tm.tmHeight + 2, Math.Min(ListBoxMaximumHeight, listBox.PreferredHeight));
listBox.Width = Math.Max(maxWidth, EditRegionSize.Width);
_ignoreDropDownValue = false;
}
listBox.Height = Math.Max(tm.tmHeight + 2, Math.Min(ListBoxMaximumHeight, listBox.PreferredHeight));
listBox.Width = Math.Max(maxWidth, EditRegionSize.Width);
_ignoreDropDownValue = false;
try
{
ShowDropDown(listBox, SystemColors.ControlDark);

Просмотреть файл

@ -227,7 +227,7 @@ namespace System.ComponentModel.Design
get
{
using var hdc = User32.GetDcScope.ScreenDC;
using var font = new Gdi32.ObjectScope(Font.ToHfont());
using var font = new Gdi32.ObjectScope(Font.ToHFONT());
using var fontSelection = new Gdi32.SelectObjectScope(hdc, font);
RECT rect = new RECT();

Просмотреть файл

@ -11,7 +11,6 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Windows.Forms.Design.Behavior;
using static Interop;
@ -28,10 +27,10 @@ namespace System.Windows.Forms.Design
//brush used to draw the resizeable selection borders around controls/components
private static HatchBrush s_selectionBorderBrush = new HatchBrush(HatchStyle.Percent50, SystemColors.ControlDarkDark, Color.Transparent);
//Pens and Brushes used via GDI to render our grabhandles
private static IntPtr s_grabHandleFillBrushPrimary = Gdi32.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window));
private static IntPtr s_grabHandleFillBrush = Gdi32.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText));
private static IntPtr s_grabHandlePenPrimary = Gdi32.CreatePen(Gdi32.PS.SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText));
private static IntPtr s_grabHandlePen = Gdi32.CreatePen(Gdi32.PS.SOLID, 1, ColorTranslator.ToWin32(SystemColors.Window));
private static Gdi32.HBRUSH s_grabHandleFillBrushPrimary = Gdi32.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.Window));
private static Gdi32.HBRUSH s_grabHandleFillBrush = Gdi32.CreateSolidBrush(ColorTranslator.ToWin32(SystemColors.ControlText));
private static Gdi32.HPEN s_grabHandlePenPrimary = Gdi32.CreatePen(Gdi32.PS.SOLID, 1, ColorTranslator.ToWin32(SystemColors.ControlText));
private static Gdi32.HPEN s_grabHandlePen = Gdi32.CreatePen(Gdi32.PS.SOLID, 1, ColorTranslator.ToWin32(SystemColors.Window));
//The box-like image used as the user is dragging comps from the toolbox
private static Bitmap s_boxImage = null;
@ -282,24 +281,14 @@ namespace System.Windows.Forms.Design
/// </summary>
public static void DrawGrabHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
{
IntPtr hDC = graphics.GetHdc();
try
{
//set our pen and brush based on primary selection
IntPtr oldBrush = Gdi32.SelectObject(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
IntPtr oldPen = Gdi32.SelectObject(hDC, isPrimary ? s_grabHandlePenPrimary : s_grabHandlePen);
using var hDC = new DeviceContextHdcScope(graphics);
//draw our rounded rect grabhandle
Gdi32.RoundRect(hDC, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom, 2, 2);
// Set our pen and brush based on primary selection
using var brushSelection = new Gdi32.SelectObjectScope(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
using var penSelection = new Gdi32.SelectObjectScope(hDC, isPrimary ? s_grabHandlePenPrimary : s_grabHandlePen);
//restore old pen and brush
Gdi32.SelectObject(hDC, oldBrush);
Gdi32.SelectObject(hDC, oldPen);
}
finally
{
graphics.ReleaseHdcInternal(hDC);
}
// Draw our rounded rect grabhandle
Gdi32.RoundRect(hDC, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom, 2, 2);
}
/// <summary>
@ -307,23 +296,14 @@ namespace System.Windows.Forms.Design
/// </summary>
public static void DrawNoResizeHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
{
IntPtr hDC = graphics.GetHdc();
try
{
//set our pen and brush based on primary selection
IntPtr oldBrush = Gdi32.SelectObject(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
IntPtr oldPen = Gdi32.SelectObject(hDC, s_grabHandlePenPrimary);
using var hDC = new DeviceContextHdcScope(graphics);
//draw our rect no-resize handle
Gdi32.Rectangle(hDC, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
//restore old pen and brush
Gdi32.SelectObject(hDC, oldBrush);
Gdi32.SelectObject(hDC, oldPen);
}
finally
{
graphics.ReleaseHdcInternal(hDC);
}
// Set our pen and brush based on primary selection
using var brushSelection = new Gdi32.SelectObjectScope(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
using var penSelection = new Gdi32.SelectObjectScope(hDC, s_grabHandlePenPrimary);
// Draw our rect no-resize handle
Gdi32.Rectangle(hDC, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom);
}
/// <summary>
@ -331,26 +311,17 @@ namespace System.Windows.Forms.Design
/// </summary>
public static void DrawLockedHandle(Graphics graphics, Rectangle bounds, bool isPrimary, Glyph glyph)
{
IntPtr hDC = graphics.GetHdc();
try
{
IntPtr oldPen = Gdi32.SelectObject(hDC, s_grabHandlePenPrimary);
// Upper rect - upper rect is always filled with the primary brush
IntPtr oldBrush = Gdi32.SelectObject(hDC, s_grabHandleFillBrushPrimary);
Gdi32.RoundRect(hDC, bounds.Left + LOCKHANDLEUPPER_OFFSET, bounds.Top, bounds.Left + LOCKHANDLEUPPER_OFFSET + LOCKHANDLESIZE_UPPER, bounds.Top + LOCKHANDLESIZE_UPPER, 2, 2);
using var hDC = new DeviceContextHdcScope(graphics);
// Lower rect - its fillbrush depends on the primary selection
Gdi32.SelectObject(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
Gdi32.Rectangle(hDC, bounds.Left, bounds.Top + LOCKHANDLELOWER_OFFSET, bounds.Right, bounds.Bottom);
using var penSelection = new Gdi32.SelectObjectScope(hDC, s_grabHandlePenPrimary);
//restore old pen and brush
Gdi32.SelectObject(hDC, oldBrush);
Gdi32.SelectObject(hDC, oldPen);
}
finally
{
graphics.ReleaseHdcInternal(hDC);
}
// Upper rect - upper rect is always filled with the primary brush
using var brushSelection = new Gdi32.SelectObjectScope(hDC, s_grabHandleFillBrushPrimary);
Gdi32.RoundRect(hDC, bounds.Left + LOCKHANDLEUPPER_OFFSET, bounds.Top, bounds.Left + LOCKHANDLEUPPER_OFFSET + LOCKHANDLESIZE_UPPER, bounds.Top + LOCKHANDLESIZE_UPPER, 2, 2);
// Lower rect - its fillbrush depends on the primary selection
Gdi32.SelectObject(hDC, isPrimary ? s_grabHandleFillBrushPrimary : s_grabHandleFillBrush);
Gdi32.Rectangle(hDC, bounds.Left, bounds.Top + LOCKHANDLELOWER_OFFSET, bounds.Right, bounds.Bottom);
}
/// <summary>
@ -455,39 +426,33 @@ namespace System.Windows.Forms.Design
/// </summary>
public static void GenerateSnapShotWithBitBlt(Control control, ref Image image)
{
//get the DC's and create our image
HandleRef hWnd = new HandleRef(control, control.Handle);
IntPtr controlDC = User32.GetDC(hWnd);
image = new Bitmap(Math.Max(control.Width, MINCONTROLBITMAPSIZE), Math.Max(control.Height, MINCONTROLBITMAPSIZE), PixelFormat.Format32bppPArgb);
// Get the DC's and create our image
using var controlDC = new User32.GetDcScope(control.Handle);
image = new Bitmap(
Math.Max(control.Width, MINCONTROLBITMAPSIZE),
Math.Max(control.Height, MINCONTROLBITMAPSIZE),
PixelFormat.Format32bppPArgb);
using (Graphics gDest = Graphics.FromImage(image))
using Graphics gDest = Graphics.FromImage(image);
if (control.BackColor == Color.Transparent)
{
if (control.BackColor == Color.Transparent)
{
gDest.Clear(SystemColors.Control);
}
IntPtr destDC = gDest.GetHdc();
try
{
// Perform our bitblit operation to push the image into the dest bitmap
Gdi32.BitBlt(
destDC,
0,
0,
image.Width,
image.Height,
controlDC,
0,
0,
Gdi32.ROP.SRCCOPY);
}
finally
{
// Clean up all our handles and what not
gDest.ReleaseHdc(destDC);
}
gDest.Clear(SystemColors.Control);
}
using var destDC = new DeviceContextHdcScope(gDest);
// Perform our bitblit operation to push the image into the dest bitmap
Gdi32.BitBlt(
destDC,
0,
0,
image.Width,
image.Height,
controlDC,
0,
0,
Gdi32.ROP.SRCCOPY);
}
/// <summary>
@ -613,29 +578,20 @@ namespace System.Windows.Forms.Design
//get the font metrics via gdi
int fontAscent = 0;
int fontHeight = 0;
using (Graphics g = ctrl.CreateGraphics())
{
IntPtr dc = g.GetHdc();
IntPtr hFont = ctrl.Font.ToHfont();
IntPtr hFontOld;
try
{
hFontOld = Gdi32.SelectObject(dc, hFont);
var metrics = new Gdi32.TEXTMETRICW();
Gdi32.GetTextMetricsW(new HandleRef(ctrl, dc), ref metrics);
//add the font ascent to the baseline
fontAscent = metrics.tmAscent + 1;
fontHeight = metrics.tmHeight;
Gdi32.SelectObject(dc, hFontOld);
}
finally
{
Gdi32.DeleteObject(hFont);
g.ReleaseHdc(dc);
}
}
//now add it all up
using Graphics g = ctrl.CreateGraphics();
using var dc = new DeviceContextHdcScope(g);
using var hFont = new Gdi32.ObjectScope(ctrl.Font.ToHFONT());
using var hFontOld = new Gdi32.SelectObjectScope(dc, hFont);
var metrics = new Gdi32.TEXTMETRICW();
Gdi32.GetTextMetricsW(dc, ref metrics);
// Add the font ascent to the baseline
fontAscent = metrics.tmAscent + 1;
fontHeight = metrics.tmHeight;
// Now add it all up
if ((alignment & anyTopAlignment) != 0)
{
return face.Top + fontAscent;

Просмотреть файл

@ -10,8 +10,8 @@ internal partial class Interop
{
public struct IMAGEINFO
{
public IntPtr hbmImage;
public IntPtr hbmMask;
public Gdi32.HBITMAP hbmImage;
public Gdi32.HBITMAP hbmMask;
public int Unused1;
public int Unused2;
public RECT rcImage;

Просмотреть файл

@ -13,9 +13,9 @@ internal partial class Interop
public static partial class ImageList
{
[DllImport(Libraries.Comctl32, ExactSpelling = true, EntryPoint = "ImageList_Add")]
public static extern int Add(IntPtr himl, IntPtr hbmImage, IntPtr hbmMask);
public static extern int Add(IntPtr himl, Gdi32.HBITMAP hbmImage, Gdi32.HBITMAP hbmMask);
public static int Add(IHandle himl, IntPtr hbmImage, IntPtr hbmMask)
public static int Add(IHandle himl, Gdi32.HBITMAP hbmImage, Gdi32.HBITMAP hbmMask)
{
int result = Add(himl.Handle, hbmImage, hbmMask);
GC.KeepAlive(himl);

Просмотреть файл

@ -4,7 +4,6 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal partial class Interop
{
@ -13,9 +12,9 @@ internal partial class Interop
public static partial class ImageList
{
[DllImport(Libraries.Comctl32, ExactSpelling = true, EntryPoint = "ImageList_Draw")]
public static extern BOOL Draw(IntPtr himl, int i, IntPtr hdcDst, int x, int y, ILD fStyle);
public static extern BOOL Draw(IntPtr himl, int i, Gdi32.HDC hdcDst, int x, int y, ILD fStyle);
public static BOOL Draw(IHandle himl, int i, IntPtr hdcDst, int x, int y, ILD fStyle)
public static BOOL Draw(IHandle himl, int i, Gdi32.HDC hdcDst, int x, int y, ILD fStyle)
{
BOOL result = Draw(himl.Handle, i, hdcDst, x, y, fStyle);
GC.KeepAlive(himl);

Просмотреть файл

@ -12,7 +12,7 @@ internal static partial class Interop
{
public User32.NMHDR nmcd;
public CDDS dwDrawStage;
public IntPtr hdc;
public Gdi32.HDC hdc;
public RECT rc;
public IntPtr dwItemSpec;
public CDIS uItemState;

Просмотреть файл

@ -11,40 +11,65 @@ internal static partial class Interop
{
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern BOOL BitBlt(
IntPtr hdc,
HDC hdc,
int x,
int y,
int cx,
int cy,
IntPtr hdcSrc,
HDC hdcSrc,
int x1,
int y1,
ROP rop);
public static BOOL BitBlt(
HandleRef hdc,
IHandle hdc,
int x,
int y,
int cx,
int cy,
HandleRef hdcSrc,
HDC hdcSrc,
int x1,
int y1,
ROP rop)
{
BOOL result = BitBlt(
hdc.Handle,
(HDC)hdc.Handle,
x,
y,
cx,
cy,
hdcSrc.Handle,
hdcSrc,
x1,
y1,
rop
);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(hdcSrc.Wrapper);
GC.KeepAlive(hdc);
return result;
}
public static BOOL BitBlt(
HDC hdc,
int x,
int y,
int cx,
int cy,
IHandle hdcSrc,
int x1,
int y1,
ROP rop)
{
BOOL result = BitBlt(
hdc,
x,
y,
cx,
cy,
(HDC)hdcSrc.Handle,
x1,
y1,
rop
);
GC.KeepAlive(hdcSrc);
return result;
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static unsafe extern IntPtr CreateBitmap(int nWidth, int nHeight, uint nPlanes, uint nBitCount, void* lpvBits);
public static unsafe extern HBITMAP CreateBitmap(int nWidth, int nHeight, uint nPlanes, uint nBitCount, void* lpvBits);
}
}

Просмотреть файл

@ -0,0 +1,54 @@
// 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 lifetime of a <see cref="HBITMAP"/> created via <see cref="CreateBitmap"/>
/// Deletes the <see cref="HBITMAP"/> (if any) 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 risking a double delete.
/// </remarks>
public ref struct CreateBitmapScope
{
public HBITMAP HBitmap { get; }
/// <summary>
/// Creates a bitmap using <see cref="CreateBitmap"/>
/// </summary>
public unsafe CreateBitmapScope(int nWidth, int nHeight, uint nPlanes, uint nBitCount, void* lpvBits)
{
HBitmap = CreateBitmap(nWidth, nHeight, nPlanes, nBitCount, lpvBits);
}
/// <summary>
/// Creates a bitmap compatible with the given <see cref="HDC"/> via <see cref="CreateCompatibleBitmap"/>
/// </summary>
public CreateBitmapScope(HDC hdc, int cx, int cy)
{
HBitmap = CreateCompatibleBitmap(hdc, cx, cy);
}
public static implicit operator HBITMAP(CreateBitmapScope scope) => scope.HBitmap;
public static implicit operator HGDIOBJ(CreateBitmapScope scope) => scope.HBitmap;
public static explicit operator IntPtr(CreateBitmapScope scope) => scope.HBitmap.Handle;
public bool IsNull => HBitmap.IsNull;
public void Dispose()
{
if (!HBitmap.IsNull)
{
DeleteObject(HBitmap);
}
}
}
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateBrushIndirect(ref LOGBRUSH lb);
public static extern HBRUSH CreateBrushIndirect(ref LOGBRUSH lb);
}
}

Просмотреть файл

@ -0,0 +1,45 @@
// 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.Drawing;
internal static partial class Interop
{
internal static partial class Gdi32
{
/// <summary>
/// Helper to scope the lifetime of a <see cref="HBRUSH"/>.
/// </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 risking a double delete.
/// </remarks>
public ref struct CreateBrushScope
{
public HBRUSH HBrush { get; }
/// <summary>
/// Creates a solid brush based on the <paramref name="color"/> using <see cref="CreateSolidBrush(int)"/>.
/// </summary>
public CreateBrushScope(Color color)
{
HBrush = CreateSolidBrush(ColorTranslator.ToWin32(color));
}
public static implicit operator HBRUSH(CreateBrushScope scope) => scope.HBrush;
public static implicit operator HGDIOBJ(CreateBrushScope scope) => scope.HBrush;
public bool IsNull => HBrush.IsNull;
public void Dispose()
{
if (!HBrush.IsNull)
{
DeleteObject(HBrush);
}
}
}
}
}

Просмотреть файл

@ -10,13 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int cx, int cy);
public static IntPtr CreateCompatibleBitmap(HandleRef hdc, int cx, int cy)
{
IntPtr result = CreateCompatibleBitmap(hdc.Handle, cx, cy);
GC.KeepAlive(hdc.Wrapper);
return result;
}
public static extern HBITMAP CreateCompatibleBitmap(HDC hdc, int cx, int cy);
}
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
public static extern HDC CreateCompatibleDC(HDC hDC);
public static IntPtr CreateCompatibleDC(HandleRef hDC)
public static HDC CreateCompatibleDC(HandleRef hDC)
{
IntPtr result = CreateCompatibleDC(hDC.Handle);
HDC result = CreateCompatibleDC((HDC)hDC.Handle);
GC.KeepAlive(hDC.Wrapper);
return result;
}

Просмотреть файл

@ -10,10 +10,10 @@ internal static partial class Interop
internal static partial class Gdi32
{
/// <remarks>
/// Use <see cref="DeleteDC(IntPtr)"/> when finished with the returned DC.
/// Use <see cref="DeleteDC(HDC)"/> when finished with the returned DC.
/// Calling with ("DISPLAY", null, null, IntPtr.Zero) will retrieve a DC for the entire desktop.
/// </remarks>
[DllImport(Libraries.Gdi32, SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr CreateDC(string lpszDriver, string? lpszDeviceName, string? lpszOutput, IntPtr devMode);
public static extern HDC CreateDC(string lpszDriver, string? lpszDeviceName, string? lpszOutput, IntPtr devMode);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr CreateDIBSection(IntPtr hdc, IntPtr pbmi, DIB usage, byte[] ppvBits, IntPtr hSection, uint offset);
public static extern HBITMAP CreateDIBSection(HDC hdc, IntPtr pbmi, DIB usage, byte[] ppvBits, IntPtr hSection, uint offset);
}
}

Просмотреть файл

@ -18,19 +18,40 @@ internal static partial class Interop
/// </remarks>
public ref struct CreateDcScope
{
public IntPtr HDC { get; }
public HDC HDC { get; }
/// <param name="hdc">Creates a compatible DC based off this.</param>
public CreateDcScope(IntPtr hdc)
/// <summary>
/// Creates a compatible HDC for <paramref name="hdc"/> using <see cref="CreateCompatibleDC(HDC)"/>.
/// </summary>
/// <remarks>
/// Passing a null HDC will use the current screen.
/// </remarks>
public CreateDcScope(HDC hdc)
{
HDC = CreateCompatibleDC(hdc);
}
public static implicit operator IntPtr(CreateDcScope dcScope) => dcScope.HDC;
public CreateDcScope(
string lpszDriverName,
string? lpszDeviceName = null,
string? lpszOutput = null,
IntPtr lpInitData = default,
bool informationOnly = true)
{
HDC = informationOnly
? CreateICW(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData)
: CreateDC(lpszDriverName, lpszDeviceName, lpszOutput, lpInitData);
}
public static implicit operator HDC(CreateDcScope dcScope) => dcScope.HDC;
public static implicit operator HGDIOBJ(CreateDcScope dcScope) => dcScope.HDC;
public static explicit operator IntPtr(CreateDcScope dcScope) => dcScope.HDC.Handle;
public bool IsNull => HDC.IsNull;
public void Dispose()
{
if (HDC != IntPtr.Zero)
if (!HDC.IsNull)
{
DeleteDC(HDC);
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CreateFontIndirectW(ref User32.LOGFONTW lplf);
public static extern HFONT CreateFontIndirectW(ref User32.LOGFONTW lplf);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr CreateHalftonePalette(IntPtr hdc);
public static extern HPALETTE CreateHalftonePalette(HDC hdc);
}
}

Просмотреть файл

@ -10,9 +10,9 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)]
private static extern unsafe IntPtr CreateICW(char* lpszDriverName, char* lpszDeviceName, char* lpszOutput, IntPtr /*DEVMODE*/ lpInitData);
private static extern unsafe HDC CreateICW(char* lpszDriverName, char* lpszDeviceName, char* lpszOutput, IntPtr /*DEVMODE*/ lpInitData);
public static unsafe IntPtr CreateICW(string lpszDriverName, string lpszDeviceName, string lpszOutput, IntPtr /*DEVMODE*/ lpInitData)
public static unsafe HDC CreateICW(string lpszDriverName, string? lpszDeviceName, string? lpszOutput, IntPtr /*DEVMODE*/ lpInitData)
{
fixed (char* driverName = lpszDriverName)
fixed (char* deviceName = lpszDeviceName)

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreatePatternBrush(IntPtr hbm);
public static extern HBRUSH CreatePatternBrush(HBITMAP hbm);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr CreatePen(PS nStyle, int nWidth, int crColor);
public static extern HPEN CreatePen(PS nStyle, int nWidth, int crColor);
}
}

Просмотреть файл

@ -0,0 +1,48 @@
// 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.Drawing;
internal static partial class Interop
{
internal static partial class Gdi32
{
/// <summary>
/// Helper to scope the lifetime of a <see cref="HPEN"/>.
/// </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 risking a double delete.
/// </remarks>
public ref struct CreatePenScope
{
public HPEN HPen { get; }
/// <summary>
/// Creates a solid pen based on the <paramref name="color"/> and <paramref name="width"/>.
/// </summary>
public CreatePenScope(Color color, int width = 1)
{
// From MSDN: if width > 1, the style must be PS_NULL, PS_SOLID, or PS_INSIDEFRAME.
HPen = CreatePen(
width > 1 ? PS.GEOMETRIC | PS.SOLID : default,
width,
ColorTranslator.ToWin32(color));
}
public static implicit operator HPEN(CreatePenScope scope) => scope.HPen;
public bool IsNull => HPen.IsNull;
public void Dispose()
{
if (!HPen.IsNull)
{
DeleteObject(HPen);
}
}
}
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr CreateSolidBrush(int crColor);
public static extern HBRUSH CreateSolidBrush(int crColor);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true)]
public static extern BOOL DeleteDC(IntPtr hDC);
public static extern BOOL DeleteDC(Gdi32.HDC hDC);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern IntPtr ExtCreatePen(PS fnStyle, int dwWidth, ref LOGBRUSH lplb, uint dwStyleCount, uint* lpStyle);
public unsafe static extern HPEN ExtCreatePen(PS fnStyle, int dwWidth, ref LOGBRUSH lplb, uint dwStyleCount, uint* lpStyle);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = false, CharSet = CharSet.Unicode)]
public unsafe static extern BOOL ExtTextOutW(IntPtr hdc, int x, int y, ETO options, ref RECT lprect, string lpString, int c, int* lpDx);
public unsafe static extern BOOL ExtTextOutW(HDC hdc, int x, int y, ETO options, ref RECT lprect, string lpString, int c, int* lpDx);
}
}

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int GetBkColor(IntPtr hdc);
public static extern int GetBkColor(HDC hdc);
public static int GetBkColor(IHandle hdc)
{
int result = GetBkColor(hdc.Handle);
int result = GetBkColor((HDC)hdc.Handle);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int GetClipRgn(IntPtr hdc, HRGN hrgn);
public static extern int GetClipRgn(HDC hdc, HRGN hrgn);
}
}

Просмотреть файл

@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr GetCurrentObject(IntPtr hdc, ObjectType type);
public static extern HGDIOBJ GetCurrentObject(HDC hdc, ObjectType type);
public static IntPtr GetCurrentObject(HandleRef hdc, ObjectType type)
public static HGDIOBJ GetCurrentObject(IHandle hdc, ObjectType type)
{
IntPtr result = GetCurrentObject(hdc.Handle, type);
GC.KeepAlive(hdc.Wrapper);
HGDIOBJ result = GetCurrentObject((HDC)hdc.Handle, type);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -10,6 +10,13 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32)]
public static extern int GetDIBits(IntPtr hdc, IntPtr hbm, uint start, uint cLines, byte[] lpvBits, ref BITMAPINFO lpbmi, DIB usage);
public static extern int GetDIBits(
HDC hdc,
HBITMAP hbm,
uint start,
uint cLines,
byte[] lpvBits,
ref BITMAPINFO lpbmi,
DIB usage);
}
}

Просмотреть файл

@ -18,12 +18,12 @@ internal static partial class Interop
}
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, DeviceCapability nIndex);
public static extern int GetDeviceCaps(HDC hDC, DeviceCapability nIndex);
public static int GetDeviceCaps(HandleRef hDC, DeviceCapability nIndex)
public static int GetDeviceCaps(IHandle hDC, DeviceCapability nIndex)
{
int caps = GetDeviceCaps(hDC.Handle, nIndex);
GC.KeepAlive(hDC.Wrapper);
int caps = GetDeviceCaps((HDC)hDC.Handle, nIndex);
GC.KeepAlive(hDC);
return caps;
}
}

Просмотреть файл

@ -4,18 +4,17 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern MM GetMapMode(IntPtr hdc);
public static extern MM GetMapMode(HDC hdc);
public static MM GetMapMode(IHandle hdc)
{
MM result = GetMapMode(hdc.Handle);
MM result = GetMapMode((HDC)hdc.Handle);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int GetNearestColor(IntPtr hdc, int color);
public static extern int GetNearestColor(HDC hdc, int color);
}
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern ObjectType GetObjectType(IntPtr h);
public static extern ObjectType GetObjectType(HGDIOBJ h);
public static ObjectType GetObjectType(HandleRef h)
{
ObjectType result = GetObjectType(h.Handle);
ObjectType result = GetObjectType((HGDIOBJ)h.Handle);
GC.KeepAlive(h.Wrapper);
return result;
}

Просмотреть файл

@ -10,10 +10,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
private unsafe static extern int GetObjectW(IntPtr h, int c, void* pv);
private unsafe static extern int GetObjectW(HGDIOBJ h, int c, void* pv);
public unsafe static bool GetObjectW<T>(IntPtr h, out T @object) where T : unmanaged
public unsafe static bool GetObjectW<T>(HGDIOBJ h, out T @object) where T : unmanaged
{
// HGDIOBJ isn't technically correct, but close enough to filter out bigger mistakes (HWND, etc.).
@object = default;
fixed (void* pv = &@object)
{
@ -23,7 +25,7 @@ internal static partial class Interop
public static bool GetObjectW<T>(HandleRef h, out T @object) where T : unmanaged
{
bool result = GetObjectW(h.Handle, out @object);
bool result = GetObjectW((HGDIOBJ)h.Handle, out @object);
GC.KeepAlive(h.Wrapper);
return result;
}

Просмотреть файл

@ -10,9 +10,9 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true)]
private unsafe static extern uint GetPaletteEntries(IntPtr hpal, uint iStart, uint nEntries, PALETTEENTRY* lppe);
private unsafe static extern uint GetPaletteEntries(HPALETTE hpal, uint iStart, uint nEntries, PALETTEENTRY* lppe);
public unsafe static uint GetPaletteEntries(IntPtr hpal, Span<PALETTEENTRY> entries)
public unsafe static uint GetPaletteEntries(HPALETTE hpal, Span<PALETTEENTRY> entries)
{
fixed (PALETTEENTRY* entry = &MemoryMarshal.GetReference(entries))
{

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern R2 GetROP2(IntPtr hdc);
public static extern R2 GetROP2(HDC hdc);
public static R2 GetROP2(IHandle hdc)
{
R2 result = GetROP2(hdc.Handle);
R2 result = GetROP2((HDC)hdc.Handle);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -15,6 +15,6 @@ internal static partial class Interop
}
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern IntPtr GetStockObject(StockObject nIndex);
public static extern HGDIOBJ GetStockObject(StockObject nIndex);
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern uint GetSystemPaletteEntries(IntPtr hdc, uint iStart, uint cEntries, byte[] pPalEntries);
public static extern uint GetSystemPaletteEntries(HDC hdc, uint iStart, uint cEntries, byte[] pPalEntries);
}
}

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int GetTextColor(IntPtr hdc);
public static extern int GetTextColor(HDC hdc);
public static int GetTextColor(IHandle hdc)
{
int result = GetTextColor(hdc.Handle);
int result = GetTextColor((HDC)hdc.Handle);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern BOOL GetTextExtentPoint32W(IntPtr hdc, string lpString, int c, ref Size psizl);
public static extern BOOL GetTextExtentPoint32W(HDC hdc, string lpString, int c, ref Size psizl);
public static BOOL GetTextExtentPoint32W(HandleRef hdc, string lpString, int c, ref Size psizl)
{
BOOL result = GetTextExtentPoint32W(hdc.Handle, lpString, c, ref psizl);
BOOL result = GetTextExtentPoint32W((HDC)hdc.Handle, lpString, c, ref psizl);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern BOOL GetTextMetricsW(IntPtr hdc, ref TEXTMETRICW lptm);
public static extern BOOL GetTextMetricsW(HDC hdc, ref TEXTMETRICW lptm);
public static BOOL GetTextMetricsW(HandleRef hdc, ref TEXTMETRICW lptm)
public static BOOL GetTextMetricsW(IHandle hdc, ref TEXTMETRICW lptm)
{
BOOL result = GetTextMetricsW(hdc.Handle, ref lptm);
GC.KeepAlive(hdc.Wrapper);
BOOL result = GetTextMetricsW((HDC)hdc.Handle, ref lptm);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -12,11 +12,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL GetViewportExtEx(IntPtr hdc, out Size lpsize);
public static extern BOOL GetViewportExtEx(HDC hdc, out Size lpsize);
public static BOOL GetViewportExtEx(IHandle hdc, out Size lpsize)
{
BOOL result = GetViewportExtEx(hdc.Handle, out lpsize);
BOOL result = GetViewportExtEx((HDC)hdc.Handle, out lpsize);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -12,11 +12,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL GetViewportOrgEx(IntPtr hdc, out Point lppoint);
public unsafe static extern BOOL GetViewportOrgEx(HDC hdc, out Point lppoint);
public unsafe static BOOL GetViewportOrgEx(IHandle hdc, out Point lppoint)
{
BOOL result = GetViewportOrgEx(hdc.Handle, out lppoint);
BOOL result = GetViewportOrgEx((HDC)hdc.Handle, out lppoint);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -0,0 +1,25 @@
// 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
{
public readonly struct HBITMAP
{
public IntPtr Handle { get; }
public HBITMAP(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static implicit operator HGDIOBJ(HBITMAP hbitmap) => new HGDIOBJ(hbitmap.Handle);
public static explicit operator HBITMAP(HGDIOBJ hbitmap) => new HBITMAP(hbitmap.Handle);
public static explicit operator HBITMAP(IntPtr hbitmap) => new HBITMAP(hbitmap);
public static explicit operator IntPtr(HBITMAP hbitmap) => hbitmap.Handle;
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// 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
{
public readonly struct HBRUSH
{
public IntPtr Handle { get; }
public HBRUSH(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static explicit operator IntPtr(HBRUSH hbrush) => hbrush.Handle;
public static explicit operator HBRUSH(IntPtr hbrush) => new HBRUSH(hbrush);
public static implicit operator HGDIOBJ(HBRUSH hbrush) => new HGDIOBJ(hbrush.Handle);
public static explicit operator HBRUSH(HGDIOBJ hbrush) => new HBRUSH(hbrush.Handle);
}
}
}

Просмотреть файл

@ -0,0 +1,30 @@
// 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.Drawing;
internal static partial class Interop
{
internal static partial class Gdi32
{
public readonly struct HDC
{
public IntPtr Handle { get; }
public HDC(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static explicit operator IntPtr(HDC hdc) => hdc.Handle;
public static explicit operator HDC(IntPtr hdc) => new HDC(hdc);
public static implicit operator HGDIOBJ(HDC hdc) => new HGDIOBJ(hdc.Handle);
public static bool operator ==(HDC value1, HDC value2) => value1.Handle == value2.Handle;
public static bool operator !=(HDC value1, HDC value2) => value1.Handle != value2.Handle;
public override bool Equals(object? obj) => obj is HDC hdc && hdc.Handle == Handle;
public override int GetHashCode() => Handle.GetHashCode();
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
// 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
{
public readonly struct HFONT
{
public IntPtr Handle { get; }
public HFONT(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static implicit operator HGDIOBJ(HFONT hfont) => new HGDIOBJ(hfont.Handle);
public static explicit operator HFONT(HGDIOBJ hfont) => new HFONT(hfont.Handle);
public static explicit operator HFONT(IntPtr hfont) => new HFONT(hfont);
public static explicit operator IntPtr(HFONT hfont) => hfont.Handle;
}
}
}

Просмотреть файл

@ -8,11 +8,21 @@ internal static partial class Interop
{
internal static partial class Gdi32
{
public ref struct HGDIOBJ
public struct HGDIOBJ
{
public IntPtr Handle { get; }
public HGDIOBJ(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static explicit operator IntPtr(HGDIOBJ hgdiobj) => hgdiobj.Handle;
public static explicit operator HGDIOBJ(IntPtr hgdiobj) => new HGDIOBJ(hgdiobj);
public static bool operator ==(HGDIOBJ value1, HGDIOBJ value2) => value1.Handle == value2.Handle;
public static bool operator !=(HGDIOBJ value1, HGDIOBJ value2) => value1.Handle != value2.Handle;
public override bool Equals(object? obj) => obj is HGDIOBJ hgdiobj && hgdiobj.Handle == Handle;
public override int GetHashCode() => Handle.GetHashCode();
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
// 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
{
public readonly struct HPALETTE
{
public IntPtr Handle { get; }
public HPALETTE(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static explicit operator IntPtr(HPALETTE hpalette) => hpalette.Handle;
public static explicit operator HPALETTE(IntPtr hpalette) => new HPALETTE(hpalette);
public static implicit operator HGDIOBJ(HPALETTE hpalette) => new HGDIOBJ(hpalette.Handle);
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
// 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
{
public readonly struct HPEN
{
public IntPtr Handle { get; }
public HPEN(IntPtr handle) => Handle = handle;
public bool IsNull => Handle == IntPtr.Zero;
public static explicit operator IntPtr(HPEN hpen) => hpen.Handle;
public static explicit operator HPEN(IntPtr hpen) => new HPEN(hpen);
public static implicit operator HGDIOBJ(HPEN hpen) => new HGDIOBJ(hpen.Handle);
}
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL LPtoDP(IntPtr hdc, ref RECT lppt, int c);
public static extern BOOL LPtoDP(HDC hdc, ref RECT lppt, int c);
}
}

Просмотреть файл

@ -12,10 +12,10 @@ internal static partial class Interop
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL LineTo(IntPtr hdc, int x, int y);
public static BOOL LineTo(HandleRef hdc, int x, int y)
public static BOOL LineTo(IHandle hdc, int x, int y)
{
BOOL result = LineTo(hdc.Handle, x, y);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -13,10 +13,10 @@ internal static partial class Interop
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL MoveToEx(IntPtr hdc, int x, int y, Point* lppt);
public unsafe static BOOL MoveToEx(HandleRef 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);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -20,12 +20,12 @@ internal static partial class Interop
public HGDIOBJ Object { get; }
/// <param name="object">The object to be deleted when the scope closes.</param>
public ObjectScope(IntPtr @object)
public ObjectScope(HGDIOBJ @object)
{
Object = new HGDIOBJ(@object);
Object = @object;
}
public static implicit operator IntPtr(ObjectScope objectScope) => objectScope.Object.Handle;
public static implicit operator HGDIOBJ(ObjectScope objectScope) => objectScope.Object;
public void Dispose()
{

Просмотреть файл

@ -11,12 +11,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL OffsetViewportOrgEx(IntPtr hdc, int x, int y, ref Point lppt);
public static extern BOOL OffsetViewportOrgEx(HDC hdc, int x, int y, ref Point lppt);
public static BOOL OffsetViewportOrgEx(HandleRef hdc, int x, int y, ref Point lppt)
public static BOOL OffsetViewportOrgEx(IHandle hdc, int x, int y, ref Point lppt)
{
BOOL result = OffsetViewportOrgEx(hdc.Handle, x, y, ref lppt);
GC.KeepAlive(hdc.Wrapper);
BOOL result = OffsetViewportOrgEx((HDC)hdc.Handle, x, y, ref lppt);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL PatBlt(IntPtr hdc, int x, int y, int w, int h, ROP rop);
public static extern BOOL PatBlt(HDC hdc, int x, int y, int w, int h, ROP rop);
public static BOOL PatBlt(HandleRef hdc, int x, int y, int w, int h, ROP rop)
{
BOOL result = PatBlt(hdc.Handle, x, y, w, h, rop);
BOOL result = PatBlt((HDC)hdc.Handle, x, y, w, h, rop);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL Rectangle(IntPtr hdc, int left, int top, int right, int bottom);
public static extern BOOL Rectangle(HDC hdc, int left, int top, int right, int bottom);
public static BOOL Rectangle(HandleRef hdc, int left, int top, int right, int bottom)
{
BOOL result = Rectangle(hdc.Handle, left, top, right, bottom);
BOOL result = Rectangle((HDC)hdc.Handle, left, top, right, bottom);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -38,10 +38,10 @@ internal static partial class Interop
}
/// <summary>
/// Creates a clipping region copy via <see cref="GetClipRgn(IntPtr, HRGN)"/> for the given device context.
/// Creates a clipping region copy via <see cref="GetClipRgn(HDC, HRGN)"/> for the given device context.
/// </summary>
/// <param name="hdc">Handle to a device context to copy the clipping region from.</param>
public RegionScope(IntPtr hdc)
public RegionScope(HDC hdc)
{
HRGN region = CreateRectRgn(0, 0, 0, 0);
int result = GetClipRgn(hdc, region);

Просмотреть файл

@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL RestoreDC(IntPtr hdc, int nSavedDC);
public static extern BOOL RestoreDC(HDC hdc, int nSavedDC);
public static BOOL RestoreDC(HandleRef hdc, int nSavedDC)
public static BOOL RestoreDC(IHandle hdc, int nSavedDC)
{
BOOL result = RestoreDC(hdc.Handle, nSavedDC);
GC.KeepAlive(hdc.Wrapper);
BOOL result = RestoreDC((HDC)hdc.Handle, nSavedDC);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BOOL RoundRect(IntPtr hdc, int left, int top, int right, int bottom, int width, int height);
public static extern BOOL RoundRect(HDC hdc, int left, int top, int right, int bottom, int width, int height);
}
}

Просмотреть файл

@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int SaveDC(IntPtr hdc);
public static extern int SaveDC(HDC hdc);
public static int SaveDC(HandleRef hdc)
public static int SaveDC(IHandle hdc)
{
int result = SaveDC(hdc.Handle);
GC.KeepAlive(hdc.Wrapper);
int result = SaveDC((HDC)hdc.Handle);
GC.KeepAlive(hdc);
return result;
}
}

Просмотреть файл

@ -12,15 +12,25 @@ internal static partial class Interop
/// Helper to scope lifetime of a saved device context state.
/// </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 risking a double restore.
/// 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 restore.
///
/// The state that is saved includes ICM (color management), palette, path drawing state, and other objects
/// that are selected into the DC (bitmap, brush, pen, clipping region, font).
///
/// Ideally saving the entire DC state can be avoided for simple drawing operations and relying on restoring
/// individual state pieces can be done instead (putting back the original pen, etc.).
/// </remarks>
public ref struct SaveDcScope
{
public IntPtr HDC { get; }
public HDC HDC { get; }
private readonly int _savedState;
public SaveDcScope(IntPtr hdc)
/// <summary>
/// Saves the device context state using <see cref="SaveDC(HDC)"/>.
/// </summary>
/// <param name="hdc"></param>
public SaveDcScope(HDC hdc)
{
_savedState = SaveDC(hdc);
HDC = hdc;

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true)]
public static extern RegionType SelectClipRgn(IntPtr hdc, HRGN hrgn);
public static extern RegionType SelectClipRgn(HDC hdc, HRGN hrgn);
}
}

Просмотреть файл

@ -10,20 +10,19 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, SetLastError = true, ExactSpelling = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr h);
public static extern HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h);
public static IntPtr SelectObject(HandleRef hdc, IntPtr h)
public static HGDIOBJ SelectObject(IHandle hdc, HGDIOBJ h)
{
IntPtr lastObject = SelectObject(hdc.Handle, h);
GC.KeepAlive(hdc.Wrapper);
HGDIOBJ lastObject = SelectObject((HDC)hdc.Handle, h);
GC.KeepAlive(hdc);
return lastObject;
}
public static IntPtr SelectObject(HandleRef hdc, HandleRef h)
public static HGDIOBJ SelectObject(HandleRef hdc, HGDIOBJ h)
{
IntPtr lastObject = SelectObject(hdc.Handle, h.Handle);
HGDIOBJ lastObject = SelectObject((HDC)hdc.Handle, h);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(h.Wrapper);
return lastObject;
}
}

Просмотреть файл

@ -10,14 +10,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true, SetLastError = true)]
public static extern IntPtr SelectPalette(IntPtr hdc, IntPtr hPal, BOOL bForceBkgd);
public static IntPtr SelectPalette(HandleRef hdc, HandleRef hPal, BOOL bForceBkgd)
{
IntPtr result = SelectPalette(hdc.Handle, hPal.Handle, bForceBkgd);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(hPal.Wrapper);
return result;
}
public static extern HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd);
}
}

Просмотреть файл

@ -0,0 +1,48 @@
// 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.Drawing;
internal static partial class Interop
{
internal static partial class Gdi32
{
/// <summary>
/// Helper to scope palette selection.
/// </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 risking a double pallete reset.
/// </remarks>
public ref struct SelectPaletteScope
{
public HDC HDC { get; }
public HPALETTE HPalette { get; }
public SelectPaletteScope(HDC hdc, HPALETTE hpalette, bool forceBackground, bool realizePalette)
{
HDC = hdc;
HPalette = SelectPalette(hdc, hpalette, forceBackground.ToBOOL());
if (!HPalette.IsNull && realizePalette)
{
RealizePalette((IntPtr)hdc);
}
}
public static SelectPaletteScope HalftonePalette(HDC hdc, bool forceBackground, bool realizePalette)
=> new SelectPaletteScope(hdc, (HPALETTE)Graphics.GetHalftonePalette(), forceBackground, realizePalette);
public static implicit operator HPALETTE(SelectPaletteScope paletteScope) => paletteScope.HPalette;
public void Dispose()
{
if (!HPalette.IsNull)
{
SelectPalette(HDC, HPalette, bForceBkgd: BOOL.FALSE);
}
}
}
}
}

Просмотреть файл

@ -18,13 +18,13 @@ internal static partial class Interop
/// </remarks>
internal ref struct SelectObjectScope
{
private readonly IntPtr _hdc;
public IntPtr PreviousObject;
private readonly HDC _hdc;
public HGDIOBJ PreviousObject;
/// <summary>
/// Selects <paramref name="object"/> into the given <paramref name="hdc"/>.
/// </summary>
public SelectObjectScope(IntPtr hdc, IntPtr @object)
public SelectObjectScope(HDC hdc, HGDIOBJ @object)
{
_hdc = hdc;
PreviousObject = SelectObject(hdc, @object);

Просмотреть файл

@ -4,25 +4,24 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int SetBkColor(IntPtr hdc, int color);
public static extern int SetBkColor(HDC hdc, int color);
public static int SetBkColor(IHandle hdc, int color)
{
int result = SetBkColor(hdc.Handle, color);
int result = SetBkColor((HDC)hdc.Handle, color);
GC.KeepAlive(hdc);
return result;
}
public static int SetBkColor(HandleRef hdc, int color)
{
int result = SetBkColor(hdc.Handle, color);
int result = SetBkColor((HDC)hdc.Handle, color);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -4,25 +4,24 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern BKMODE SetBkMode(IntPtr hdc, BKMODE mode);
public static extern BKMODE SetBkMode(HDC hdc, BKMODE mode);
public static BKMODE SetBkMode(IHandle hdc, BKMODE mode)
{
BKMODE result = SetBkMode(hdc.Handle, mode);
BKMODE result = SetBkMode((HDC)hdc.Handle, mode);
GC.KeepAlive(hdc);
return result;
}
public static BKMODE SetBkMode(HandleRef hdc, BKMODE mode)
{
BKMODE result = SetBkMode(hdc.Handle, mode);
BKMODE result = SetBkMode((HDC)hdc.Handle, mode);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern MM SetMapMode(IntPtr hdc, MM mode);
public static extern MM SetMapMode(HDC hdc, MM mode);
public static MM SetMapMode(IHandle hdc, MM mode)
{
MM result = SetMapMode(hdc.Handle, mode);
MM result = SetMapMode((HDC)hdc.Handle, mode);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -4,18 +4,17 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern Gdi32.R2 SetROP2(IntPtr hdc, R2 rop2);
public static extern R2 SetROP2(HDC hdc, R2 rop2);
public static Gdi32.R2 SetROP2(IHandle hdc, R2 rop2)
public static R2 SetROP2(IHandle hdc, R2 rop2)
{
Gdi32.R2 result = SetROP2(hdc.Handle, rop2);
R2 result = SetROP2((HDC)hdc.Handle, rop2);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -16,15 +16,15 @@ internal static partial class Interop
/// 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 Rop2Scope
internal ref struct SetRop2Scope
{
private readonly R2 _previousRop;
private readonly IntPtr _hdc;
private readonly HDC _hdc;
/// <summary>
/// Selects <paramref name="rop2"/> into the given <paramref name="hdc"/>.
/// </summary>
public Rop2Scope(IntPtr hdc, R2 rop2)
public SetRop2Scope(HDC hdc, R2 rop2)
{
_hdc = hdc;
_previousRop = SetROP2(hdc, rop2);

Просмотреть файл

@ -4,25 +4,24 @@
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int SetTextColor(IntPtr hdc, int color);
public static extern int SetTextColor(HDC hdc, int color);
public static int SetTextColor(IHandle hdc, int color)
{
int result = SetTextColor(hdc.Handle, color);
int result = SetTextColor((HDC)hdc.Handle, color);
GC.KeepAlive(hdc);
return result;
}
public static int SetTextColor(HandleRef hdc, int color)
{
int result = SetTextColor(hdc.Handle, color);
int result = SetTextColor((HDC)hdc.Handle, color);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -5,18 +5,17 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL SetViewportExtEx(IntPtr hdc, int x, int y, Size *lpsz);
public unsafe static extern BOOL SetViewportExtEx(HDC hdc, int x, int y, Size *lpsz);
public unsafe static BOOL SetViewportExtEx(IHandle hdc, int x, int y, Size *lpsz)
{
BOOL result = SetViewportExtEx(hdc.Handle, x, y, lpsz);
BOOL result = SetViewportExtEx((HDC)hdc.Handle, x, y, lpsz);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -5,18 +5,17 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
internal static partial class Interop
{
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL SetViewportOrgEx(IntPtr hdc, int x, int y, Point *lppt);
public unsafe static extern BOOL SetViewportOrgEx(HDC hdc, int x, int y, Point *lppt);
public unsafe static BOOL SetViewportOrgEx(IHandle hdc, int x, int y, Point *lppt)
{
BOOL result = SetViewportOrgEx(hdc.Handle, x, y, lppt);
BOOL result = SetViewportOrgEx((HDC)hdc.Handle, x, y, lppt);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -11,6 +11,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL SetWindowExtEx(IntPtr hdc, int x, int y, Size *lpsz);
public unsafe static extern BOOL SetWindowExtEx(HDC hdc, int x, int y, Size *lpsz);
}
}

Просмотреть файл

@ -11,6 +11,6 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public unsafe static extern BOOL SetWindowOrgEx(IntPtr hdc, int x, int y, Point *lppt);
public unsafe static extern BOOL SetWindowOrgEx(HDC hdc, int x, int y, Point *lppt);
}
}

Просмотреть файл

@ -10,6 +10,19 @@ internal static partial class Interop
internal static partial class Gdi32
{
[DllImport(Libraries.Gdi32, ExactSpelling = true)]
public static extern int StretchDIBits(IntPtr hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, byte[] lpBits, ref BITMAPINFO lpbmi, DIB usage, ROP rop);
public static extern int StretchDIBits(
HDC hdc,
int xDest,
int yDest,
int DestWidth,
int DestHeight,
int xSrc,
int ySrc,
int SrcWidth,
int SrcHeight,
byte[] lpBits,
ref BITMAPINFO lpbmi,
DIB usage,
ROP rop);
}
}

Просмотреть файл

@ -17,22 +17,25 @@ internal static partial class Interop
/// </remarks>
public ref struct BeginPaintScope
{
public IntPtr HDC { get; }
public PAINTSTRUCT _paintStruct;
public Gdi32.HDC HDC { get; }
public IntPtr HWND { get; }
private PAINTSTRUCT _paintStruct;
public PAINTSTRUCT PaintStruct => _paintStruct;
public BeginPaintScope(IntPtr hwnd)
{
_paintStruct = default;
HDC = BeginPaint(hwnd, ref _paintStruct);
HDC = (Gdi32.HDC)BeginPaint(hwnd, ref _paintStruct);
HWND = hwnd;
}
public static implicit operator IntPtr(BeginPaintScope paintScope) => paintScope.HDC;
public static implicit operator Gdi32.HDC(BeginPaintScope paintScope) => paintScope.HDC;
public void Dispose()
{
if (HDC != IntPtr.Zero)
if (!HDC.IsNull)
{
EndPaint(HWND, ref _paintStruct);
}

Просмотреть файл

@ -11,18 +11,19 @@ internal static partial class Interop
[Flags]
public enum DCX : uint
{
WINDOW = 0x00000001,
CACHE = 0x00000002,
NORESETATTRS = 0x00000004,
CLIPCHILDREN = 0x00000008,
CLIPSIBLINGS = 0x00000010,
PARENTCLIP = 0x00000020,
EXCLUDERGN = 0x00000040,
INTERSECTRGN = 0x00000080,
EXCLUDEUPDATE = 0x00000100,
INTERSECTUPDATE = 0x00000200,
LOCKWINDOWUPDATE = 0x00000400,
VALIDATE = 0x00200000,
WINDOW = 0x00000001,
CACHE = 0x00000002,
NORESETATTRS = 0x00000004,
CLIPCHILDREN = 0x00000008,
CLIPSIBLINGS = 0x00000010,
PARENTCLIP = 0x00000020,
EXCLUDERGN = 0x00000040,
INTERSECTRGN = 0x00000080,
EXCLUDEUPDATE = 0x00000100,
INTERSECTUPDATE = 0x00000200,
LOCKWINDOWUPDATE = 0x00000400,
USESTYLE = 0x00010000,
VALIDATE = 0x00200000,
}
}
}

Просмотреть файл

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.InteropServices;
internal static partial class Interop
{
@ -17,7 +16,7 @@ internal static partial class Interop
public ODA itemAction;
public ODS itemState;
public IntPtr hwndItem;
public IntPtr hDC;
public Gdi32.HDC hDC;
public RECT rcItem;
public IntPtr itemData;
}

Просмотреть файл

@ -10,8 +10,8 @@ internal static partial class Interop
internal static partial class User32
{
/// <summary>
/// Text format flags for <see cref="DrawTextExW(IntPtr, string, int, ref RECT, DT, ref DRAWTEXTPARAMS)"/> and
/// <see cref="DrawTextW(IntPtr, string, int, ref RECT, DT)"/>
/// Text format flags for <see cref="DrawTextExW(Gdi32.HDC, string, int, ref RECT, DT, ref DRAWTEXTPARAMS)"/> and
/// <see cref="DrawTextW(Gdi32.HDC, string, int, ref RECT, DT)"/>
/// </summary>
[Flags]
public enum DT : uint

Просмотреть файл

@ -10,13 +10,6 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
private static extern BOOL DrawEdge(IntPtr hdc, ref RECT qrc, EDGE edge, BF grfFlags);
public static BOOL DrawEdge(HandleRef hdc, ref RECT qrc, EDGE edge, BF grfFlags)
{
BOOL result = DrawEdge(hdc.Handle, ref qrc, edge, grfFlags);
GC.KeepAlive(hdc.Wrapper);
return result;
}
public static extern BOOL DrawEdge(Gdi32.HDC hdc, ref RECT qrc, EDGE edge, BF grfFlags);
}
}

Просмотреть файл

@ -10,11 +10,18 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern BOOL DrawFrameControl(IntPtr hdc, ref RECT rect, DFC type, DFCS state);
public static extern BOOL DrawFrameControl(Gdi32.HDC hdc, ref RECT rect, DFC type, DFCS state);
public static BOOL DrawFrameControl(IHandle hdc, ref RECT rect, DFC type, DFCS state)
{
BOOL result = DrawFrameControl((Gdi32.HDC)hdc.Handle, ref rect, type, state);
GC.KeepAlive(hdc);
return result;
}
public static BOOL DrawFrameControl(HandleRef hdc, ref RECT rect, DFC type, DFCS state)
{
BOOL result = DrawFrameControl(hdc.Handle, ref rect, type, state);
BOOL result = DrawFrameControl((Gdi32.HDC)hdc.Handle, ref rect, type, state);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true, CharSet = CharSet.Unicode)]
public static extern int DrawTextW(IntPtr hdc, string lpchText, int nCount, ref RECT lprc, DT format);
public static extern int DrawTextW(Gdi32.HDC hdc, string lpchText, int nCount, ref RECT lprc, DT format);
public static int DrawTextW(HandleRef hdc, string lpchText, int cchText, ref RECT lprc, DT format)
{
int result = DrawTextW(hdc.Handle, lpchText, cchText, ref lprc, format);
int result = DrawTextW((Gdi32.HDC)hdc.Handle, lpchText, cchText, ref lprc, format);
GC.KeepAlive(hdc.Wrapper);
return result;
}

Просмотреть файл

@ -11,9 +11,9 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, EntryPoint = "DrawTextExW", ExactSpelling = true, CharSet = CharSet.Unicode)]
private static extern int DrawTextExWInternal(IntPtr hdc, string lpchText, int cchText, ref RECT lprc, DT format, ref DRAWTEXTPARAMS lpdtp);
private static extern int DrawTextExWInternal(Gdi32.HDC hdc, string lpchText, int cchText, ref RECT lprc, DT format, ref DRAWTEXTPARAMS lpdtp);
public static unsafe int DrawTextExW(IntPtr hdc, string lpchText, int cchText, ref RECT lprc, DT format, ref DRAWTEXTPARAMS lpdtp)
public static unsafe int DrawTextExW(Gdi32.HDC hdc, string lpchText, int cchText, ref RECT lprc, DT format, ref DRAWTEXTPARAMS lpdtp)
{
lpdtp.cbSize = (uint)sizeof(DRAWTEXTPARAMS);
return DrawTextExWInternal(hdc, lpchText, cchText, ref lprc, format, ref lpdtp);
@ -21,7 +21,7 @@ internal static partial class Interop
public static int DrawTextExW(IHandle hdc, string lpchText, int cchText, ref RECT lprc, DT format, ref DRAWTEXTPARAMS lpdtp)
{
int result = DrawTextExW(hdc.Handle, lpchText, cchText, ref lprc, format, ref lpdtp);
int result = DrawTextExW((Gdi32.HDC)hdc.Handle, lpchText, cchText, ref lprc, format, ref lpdtp);
GC.KeepAlive(hdc);
return result;
}

Просмотреть файл

@ -10,13 +10,12 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern int FillRect(IntPtr hDC, ref RECT lprc, IntPtr hbr);
public static extern int FillRect(Gdi32.HDC hDC, ref RECT lprc, Gdi32.HBRUSH hbr);
public static int FillRect(HandleRef hDC, ref RECT lprc, HandleRef hbr)
public static int FillRect(IHandle hDC, ref RECT lprc, Gdi32.HBRUSH hbr)
{
int result = FillRect(hDC.Handle, ref lprc, hbr.Handle);
GC.KeepAlive(hDC.Wrapper);
GC.KeepAlive(hbr.Wrapper);
int result = FillRect((Gdi32.HDC)hDC.Handle, ref lprc, hbr);
GC.KeepAlive(hDC);
return result;
}
}

Просмотреть файл

@ -10,11 +10,11 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern IntPtr GetDC(IntPtr hWnd);
public static extern Gdi32.HDC GetDC(IntPtr hWnd);
public static IntPtr GetDC(HandleRef hWnd)
public static Gdi32.HDC GetDC(HandleRef hWnd)
{
IntPtr dc = GetDC(hWnd.Handle);
Gdi32.HDC dc = GetDC(hWnd.Handle);
GC.KeepAlive(hWnd.Wrapper);
return dc;
}

Просмотреть файл

@ -11,11 +11,11 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern IntPtr GetDCEx(IntPtr hWnd, IntPtr hrgnClip, DCX flags);
public static extern Gdi32.HDC GetDCEx(IntPtr hWnd, IntPtr hrgnClip, DCX flags);
public static IntPtr GetDCEx(IHandle hWnd, IntPtr hrgnClip, DCX flags)
public static Gdi32.HDC GetDCEx(IHandle hWnd, IntPtr hrgnClip, DCX flags)
{
IntPtr result = GetDCEx(hWnd.Handle, hrgnClip, flags);
Gdi32.HDC result = GetDCEx(hWnd.Handle, hrgnClip, flags);
GC.KeepAlive(hWnd);
return result;
}

Просмотреть файл

@ -3,21 +3,23 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
internal static partial class Interop
{
internal static partial class User32
{
/// <summary>
/// Helper to scope lifetime of an HDC retrieved via GetDC/Ex. Releases the HDC (if any) when disposed.
/// Helper to scope lifetime of an <see cref="Gdi32.HDC"/> retrieved via <see cref="GetDC(IntPtr)"/> and
/// <see cref="GetDCEx(IntPtr, IntPtr, DCX)"/>. Releases the <see cref="Gdi32.HDC"/> (if any) 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 risking a double release.
/// 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>
public ref struct GetDcScope
{
public IntPtr HDC { get; }
public Gdi32.HDC HDC { get; }
public IntPtr HWND { get; }
public GetDcScope(IntPtr hwnd)
@ -26,6 +28,15 @@ internal static partial class Interop
HDC = GetDC(hwnd);
}
/// <summary>
/// Creates a <see cref="Gdi32.HDC"/> using <see cref="GetDCEx(IntPtr, IntPtr, DCX)"/>.
/// </summary>
/// <remarks>
/// GetWindowDC calls GetDCEx(hwnd, null, DCX_WINDOW | DCX_USESTYLE).
///
/// GetDC calls GetDCEx(hwnd, null, DCX_USESTYLE) when given a handle. (When given null it has additional
/// logic, and can't be replaced directly by GetDCEx.
/// </remarks>
public GetDcScope(IntPtr hwnd, IntPtr hrgnClip, DCX flags)
{
HWND = hwnd;
@ -36,17 +47,19 @@ internal static partial class Interop
/// Creates a DC scope for the primary monitor (not the entire desktop).
/// </summary>
/// <remarks>
/// <see cref="Gdi32.CreateDC(string, string, string, IntPtr)" /> is
/// the API to get the DC for the entire desktop.
/// <see cref="Gdi32.CreateDC(string, string, string, IntPtr)" /> is the API to get the DC for the
/// entire desktop.
/// </remarks>
public static GetDcScope ScreenDC
=> new GetDcScope(IntPtr.Zero);
public static GetDcScope ScreenDC => new GetDcScope(IntPtr.Zero);
public static implicit operator IntPtr(GetDcScope dcScope) => dcScope.HDC;
public bool IsNull => HDC.IsNull;
public static implicit operator IntPtr(GetDcScope dcScope) => dcScope.HDC.Handle;
public static implicit operator Gdi32.HDC(GetDcScope dcScope) => dcScope.HDC;
public void Dispose()
{
if (HDC != IntPtr.Zero)
if (!HDC.IsNull)
{
ReleaseDC(HWND, HDC);
}

Просмотреть файл

@ -32,21 +32,21 @@ internal static partial class Interop
public BOOL fIcon;
public uint xHotspot;
public uint yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
public Gdi32.HBITMAP hbmMask;
public Gdi32.HBITMAP hbmColor;
public void Dispose()
{
if (hbmMask != IntPtr.Zero)
if (!hbmMask.IsNull)
{
Gdi32.DeleteObject(hbmMask);
hbmMask = IntPtr.Zero;
hbmMask = default;
}
if (hbmColor != IntPtr.Zero)
if (!hbmColor.IsNull)
{
Gdi32.DeleteObject(hbmColor);
hbmColor = IntPtr.Zero;
hbmColor = default;
}
}
}

Просмотреть файл

@ -10,6 +10,6 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern IntPtr GetSysColorBrush(int nIndex);
public static extern Gdi32.HBRUSH GetSysColorBrush(int nIndex);
}
}

Просмотреть файл

@ -1,22 +0,0 @@
// 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
{
[DllImport(Libraries.User32, ExactSpelling = true)]
private static extern IntPtr GetWindowDC(IntPtr hWnd);
public static IntPtr GetWindowDC(HandleRef hWnd)
{
IntPtr result = GetWindowDC(hWnd.Handle);
GC.KeepAlive(hWnd.Wrapper);
return result;
}
}
}

Просмотреть файл

@ -8,6 +8,6 @@ internal static partial class Interop
{
internal static partial class User32
{
public delegate BOOL MONITORENUMPROC(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);
public delegate BOOL MONITORENUMPROC(IntPtr monitor, Gdi32.HDC hdc, IntPtr lprcMonitor, IntPtr lParam);
}
}

Просмотреть файл

@ -10,21 +10,13 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
public static extern int ReleaseDC(IntPtr hWnd, Gdi32.HDC hDC);
public static int ReleaseDC(HandleRef hWnd, IntPtr hDC)
public static int ReleaseDC(HandleRef hWnd, Gdi32.HDC hDC)
{
int result = ReleaseDC(hWnd.Handle, hDC);
GC.KeepAlive(hWnd.Wrapper);
return result;
}
public static int ReleaseDC(HandleRef hWnd, HandleRef hDC)
{
int result = ReleaseDC(hWnd.Handle, hDC.Handle);
GC.KeepAlive(hWnd.Wrapper);
GC.KeepAlive(hDC.Wrapper);
return result;
}
}
}

Просмотреть файл

@ -19,7 +19,7 @@ internal static partial class Interop
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public Gdi32.HBRUSH hbrBackground;
public char* lpszMenuName;
public char* lpszClassName;
}

Просмотреть файл

@ -10,12 +10,12 @@ internal static partial class Interop
internal static partial class User32
{
[DllImport(Libraries.User32, ExactSpelling = true)]
public static extern IntPtr WindowFromDC(IntPtr hDC);
public static extern IntPtr WindowFromDC(Gdi32.HDC hDC);
public static IntPtr WindowFromDC(HandleRef hDC)
public static IntPtr WindowFromDC(IHandle hDC)
{
IntPtr result = WindowFromDC(hDC.Handle);
GC.KeepAlive(hDC.Wrapper);
IntPtr result = WindowFromDC((Gdi32.HDC)hDC.Handle);
GC.KeepAlive(hDC);
return result;
}
}

Просмотреть файл

@ -10,13 +10,13 @@ internal static partial class Interop
public static partial class UxTheme
{
[DllImport(Libraries.UxTheme, ExactSpelling = true)]
public static extern unsafe HRESULT DrawThemeBackground(IntPtr hTheme, IntPtr 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, HandleRef 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)
{
HRESULT hr = DrawThemeBackground(hTheme.Handle, hdc.Handle, iPartId, iStateId, ref pRect, pClipRect);
HRESULT hr = DrawThemeBackground(hTheme.Handle, (Gdi32.HDC)hdc.Handle, iPartId, iStateId, ref pRect, pClipRect);
GC.KeepAlive(hTheme);
GC.KeepAlive(hdc.Wrapper);
GC.KeepAlive(hdc);
return hr;
}
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше