Skip to content

Commit

Permalink
Add a screen device context method
Browse files Browse the repository at this point in the history
Add a few device context bits and sort NativeMethods.txt.
  • Loading branch information
JeremyKuhne committed Jan 22, 2024
1 parent 3d137c0 commit d355c29
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 14 deletions.
16 changes: 15 additions & 1 deletion src/thirtytwo/DeviceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ namespace Windows;
/// <summary>
/// DeviceContext handle (HDC)
/// </summary>
/// <devdoc>
/// <see href="https://devblogs.microsoft.com/oldnewthing/20060601-06/?p=31003">What does the CS_OWNDC class style do?</see>
/// <see href="https://devblogs.microsoft.com/oldnewthing/20060602-00/?p=30993">What does the CS_CLASSDC class style do?</see>
/// </devdoc>
public readonly struct DeviceContext : IDisposable, IHandle<HDC>
{
public HDC Handle { get; private init; }
Expand All @@ -16,6 +20,16 @@ namespace Windows;
private readonly HWND HWND { get; init; }
private readonly CollectionType Type { get; init; }

/// <summary>
/// Creates a screen device context.
/// </summary>
public static DeviceContext Create() => new()
{
HWND = default,
Type = CollectionType.Release,
Handle = Interop.GetDC(HWND.Null)
};

public static DeviceContext Create(
HDC hdc,
bool ownsHandle = false)
Expand Down Expand Up @@ -47,7 +61,7 @@ public static DeviceContext Create<THdc, THwnd>(
}

public static DeviceContext Create<THwnd>(
ref PAINTSTRUCT paintStruct,
ref readonly PAINTSTRUCT paintStruct,
THwnd hwnd)
where THwnd : IHandle<HWND>
{
Expand Down
21 changes: 21 additions & 0 deletions src/thirtytwo/DeviceContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ public static GRAPHICS_MODE SetGraphicsMode<T>(this T deviceContext, GRAPHICS_MO
return mode;
}

/// <inheritdoc cref="Interop.GetWorldTransform(HDC, XFORM*)"/>
public static unsafe bool GetWorldTransform<T>(this T deviceContext, ref Matrix3x2 transform)
where T : IHandle<HDC>
{
fixed (Matrix3x2* t = &transform)
{
bool result = Interop.GetWorldTransform(deviceContext.Handle, (XFORM*)t);
GC.KeepAlive(deviceContext.Wrapper);
return result;
}
}

/// <inheritdoc cref="Interop.SetWorldTransform(HDC, XFORM*)"/>
public static unsafe bool SetWorldTransform<T>(this T deviceContext, ref Matrix3x2 transform)
where T : IHandle<HDC>
Expand All @@ -39,6 +51,15 @@ public static unsafe bool SetWorldTransform<T>(this T deviceContext, ref Matrix3
}
}

/// <inheritdoc cref="Interop.GetDeviceCaps(HDC, GET_DEVICE_CAPS_INDEX)"/>
public static int GetDeviceCaps<T>(this T deviceContext, GET_DEVICE_CAPS_INDEX index)
where T : IHandle<HDC>
{
int result = Interop.GetDeviceCaps(deviceContext.Handle, index);
GC.KeepAlive(deviceContext.Wrapper);
return result;
}

/// <summary>
/// Converts the requested point size to height based on the DPI of the given device context.
/// </summary>
Expand Down
27 changes: 15 additions & 12 deletions src/thirtytwo/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ DefWindowProc
DeleteDC
DestroyIcon
DestroyWindow
DISP_E_*
DISPATCH_CONSTRUCT
DispatchMessage
DISP_E_*
DISPID_ACC_*
DISPID_Delete
DISPID_Name
Expand Down Expand Up @@ -123,6 +123,7 @@ GetWindowRect
GetWindowRgn
GetWindowText
GetWindowTextLength
GetWorldTransform
GlobalAlloc
GlobalFree
GlobalLock
Expand Down Expand Up @@ -161,20 +162,20 @@ InvalidateRect
IOleClientSite
IOleContainer
IOleControlSite
IOleInPlaceFrame
IOleInPlaceObject
IOleInPlaceSite
IOleInPlaceFrame
IOleObject
IOleWindow
IPropertyNotifySink
IProvideClassInfo
IProvideMultipleClassInfo
IRawElementProviderSimple
IRecordInfo
IsClipboardFormatAvailable
IServiceProvider
ISimpleFrameSite
ISupportErrorInfo
IsClipboardFormatAvailable
IsWindowEnabled
IsWindowVisible
IUIAutomationElement
Expand All @@ -189,6 +190,7 @@ LoadLibrary
LoadRegTypeLib
LocalFree
LOGFONTW
LPtoDP
LsaNtStatusToWinError
MapWindowPoints
MEMBERID_NIL
Expand All @@ -201,25 +203,23 @@ MulDiv
NAVDIR_*
NtQuerySystemInformation
NTSTATUS
OBJ_TYPE
OBJECT_IDENTIFIER
OLECONTF
OLEIVERB*
OLEIVERB_*
OBJ_TYPE
OBJECT_IDENTIFIER
OpenClipboard
PARAMDATA
WIN32_ERROR
WM_*
PeekMessage
POINTS
PostMessage
PostQuitMessage
PROPVARIANT
PropVariantClear
RegisterClassEx
RegisterClipboardFormat
RegCloseKey
RegEnumValue
RegisterClassEx
RegisterClipboardFormat
RegOpenKeyEx
RegQueryInfoKey
RegQueryValueEx
Expand All @@ -233,9 +233,9 @@ SafeArrayGetVartype
SafeArrayLock
SafeArrayUnlock
ScreenToClient
SendMessage
SELFLAG_*
SelectObject
SELFLAG_*
SendMessage
SetActiveWindow
SetClipboardData
SetFocus
Expand All @@ -250,8 +250,8 @@ SetWorldTransform
SHCreateShellItem
SHDefExtractIcon
SHGetStockIconInfo
SHParseDisplayName
ShowWindow
SHParseDisplayName
STATE_SYSTEM_*
STATIC_STYLES
STATUS_BUFFER_OVERFLOW
Expand Down Expand Up @@ -279,7 +279,10 @@ UiaReturnRawElementProvider
UnregisterClass
UpdateLayeredWindow
UpdateWindow
USER_DEFAULT_SCREEN_DPI
VARIANT_*
VIRTUAL_KEY
WIN32_ERROR
WINDOWPOS
WM_*
XFORMCOORDS
2 changes: 1 addition & 1 deletion src/thirtytwo/WindowExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ public static unsafe DeviceContext BeginPaint<T>(this T window, out Rectangle pa
{
PAINTSTRUCT paintStruct = default;
Interop.BeginPaint(window.Handle, &paintStruct);
DeviceContext context = DeviceContext.Create(ref paintStruct, window);
DeviceContext context = DeviceContext.Create(in paintStruct, window);
paintBounds = paintStruct.rcPaint;
GC.KeepAlive(window.Wrapper);
return context;
Expand Down
22 changes: 22 additions & 0 deletions src/thirtytwo_tests/DeviceContextTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using Windows.Win32;
using Windows.Win32.Graphics.Gdi;

namespace Windows;

public unsafe class DeviceContextTests
{
[Fact]
public void DeviceContext_ScreenDeviceContextBehavior()
{
using DeviceContext context = DeviceContext.Create();
int logicalDpi = context.GetDeviceCaps(GET_DEVICE_CAPS_INDEX.LOGPIXELSX);

Point point = new(0, 8192);
Interop.LPtoDP(context, &point, 1);
point.Should().Be(new Point(0, (int)(8192 * (logicalDpi / (float)Interop.USER_DEFAULT_SCREEN_DPI))));
}
}

0 comments on commit d355c29

Please sign in to comment.