Move GetWindowText and MapWindowPoints to Core.

Also add cast operators for HandleRef to faciliate converting between the generic and non-generic version to help WPF which publically exposes the generic version.
This commit is contained in:
Jeremy Kuhne 2024-10-29 16:24:12 -07:00 коммит произвёл GitHub
Родитель 40b639631f
Коммит 6505997339
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
28 изменённых файлов: 81 добавлений и 46 удалений

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

@ -74,6 +74,8 @@ FDEX_PROP_FLAGS
FILETIME
GetCurrentThreadId
GetSysColorBrush
GetWindowText
GetWindowTextLength
GdipBitmapLockBits
GdipBitmapUnlockBits
GdipCreateFromHWND
@ -156,6 +158,7 @@ LoadIcon
LoadRegTypeLib
LPARAM
LRESULT
MapWindowPoints
MAX_PATH
MonitorFromPoint
MonitorFromRect

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

@ -1,11 +1,24 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Windows.Win32.Foundation;
/// <summary>
/// Adapter to use when owning classes cannot directly implement <see cref="IHandle{T}"/>.
/// </summary>
/// <remarks>
/// <para>
/// Whenever you need to keep the owning object from being finalized during interop calls, use
/// <see cref="GC.KeepAlive(object?)"/> on the <see cref="Wrapper"/> <see langword="object"/>.
/// </para>
/// <para>
/// This is the typed equivalent of <see cref="HandleRef"/>. Marshalling doesn't know this, and while one
/// could write a custom marshaler, we want our imports to do no marshalling for performance and trimming reasons.
/// </para>
/// </remarks>
internal readonly struct HandleRef<THandle> : IHandle<THandle>, IEquatable<HandleRef<THandle>>
where THandle : unmanaged, IEquatable<THandle>
{
@ -36,5 +49,27 @@ internal readonly struct HandleRef<THandle> : IHandle<THandle>, IEquatable<Handl
public static bool operator ==(HandleRef<THandle> left, HandleRef<THandle> right) => left.Equals(right);
public static bool operator !=(HandleRef<THandle> left, HandleRef<THandle> right) => !(left == right);
public static unsafe explicit operator HandleRef(HandleRef<THandle> handle)
{
if (sizeof(nint) != sizeof(THandle))
{
throw new InvalidCastException();
}
THandle local = handle.Handle;
return new(handle.Wrapper, Unsafe.As<THandle, nint>(ref local));
}
public static unsafe explicit operator HandleRef<THandle>(HandleRef handle)
{
if (sizeof(nint) != sizeof(THandle))
{
throw new InvalidCastException();
}
nint local = handle.Handle;
return new(handle.Wrapper, Unsafe.As<nint, THandle>(ref local));
}
public bool IsNull => Handle.Equals(default);
}

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

@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
namespace Windows.Win32;
internal static partial class PInvoke
internal static partial class PInvokeCore
{
[SkipLocalsInit]
public static unsafe string GetWindowText<T>(T hWnd) where T : IHandle<HWND>

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

@ -3,7 +3,7 @@
namespace Windows.Win32;
internal static partial class PInvoke
internal static partial class PInvokeCore
{
/// <inheritdoc cref="GetWindowTextLength(HWND)"/>
public static int GetWindowTextLength<T>(T hWnd) where T : IHandle<HWND>

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

@ -5,7 +5,7 @@ using System.Drawing;
namespace Windows.Win32;
internal static partial class PInvoke
internal static partial class PInvokeCore
{
/// <inheritdoc cref="MapWindowPoints(HWND, HWND, Point*, uint)"/>
public static unsafe int MapWindowPoints<TFrom, TTo>(TFrom hWndFrom, TTo hWndTo, ref RECT lpRect)

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

@ -334,7 +334,7 @@ public sealed partial class MultilineStringEditor
return string.Empty;
}
string windowText = PInvoke.GetWindowText(this);
string windowText = PInvokeCore.GetWindowText(this);
if (!_ctrlEnterPressed)
{
return windowText;

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

@ -270,7 +270,7 @@ public sealed partial class BehaviorService : IDisposable
}
Point pt = new(c.Left, c.Top);
PInvoke.MapWindowPoints(c.Parent, _adornerWindow, ref pt);
PInvokeCore.MapWindowPoints(c.Parent, _adornerWindow, ref pt);
if (c.Parent.IsMirrored)
{
pt.X -= c.Width;
@ -284,7 +284,7 @@ public sealed partial class BehaviorService : IDisposable
/// </summary>
public Point MapAdornerWindowPoint(IntPtr handle, Point pt)
{
PInvoke.MapWindowPoints((HWND)handle, _adornerWindow, ref pt);
PInvokeCore.MapWindowPoints((HWND)handle, _adornerWindow, ref pt);
return pt;
}

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

@ -287,7 +287,7 @@ public partial class ControlDesigner : ComponentDesigner
Point nativeOffset = default;
if (Control.Parent is { } parent)
{
PInvoke.MapWindowPoints(Control, parent, ref nativeOffset);
PInvokeCore.MapWindowPoints(Control, parent, ref nativeOffset);
}
Point offset = Control.Location;
@ -1778,7 +1778,7 @@ public partial class ControlDesigner : ComponentDesigner
if (m.MsgInternal >= PInvokeCore.WM_MOUSEFIRST && m.MsgInternal <= PInvokeCore.WM_MOUSELAST)
{
location = PARAM.ToPoint(m.LParamInternal);
PInvoke.MapWindowPoints(m, (HWND)default, ref location);
PInvokeCore.MapWindowPoints(m, (HWND)default, ref location);
}
else if (m.MsgInternal >= PInvokeCore.WM_NCMOUSEMOVE && m.MsgInternal <= PInvokeCore.WM_NCMBUTTONDBLCLK)
{
@ -2068,9 +2068,9 @@ public partial class ControlDesigner : ComponentDesigner
{
// Re-map the clip rect we pass to the paint event args to our child coordinates.
Point point = default;
PInvoke.MapWindowPoints(m.HWND, Control, ref point);
PInvokeCore.MapWindowPoints(m.HWND, Control, ref point);
graphics.TranslateTransform(-point.X, -point.Y);
PInvoke.MapWindowPoints(m.HWND, Control, ref clip);
PInvokeCore.MapWindowPoints(m.HWND, Control, ref clip);
}
Rectangle paintRect = clip;

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

@ -83,7 +83,7 @@ internal class ListViewDesigner : ControlDesigner
HWND headerHwnd = (HWND)PInvokeCore.SendMessage(listView, PInvoke.LVM_GETHEADER);
if (hwndHit == headerHwnd)
{
PInvoke.MapWindowPoints(HWND.Null, headerHwnd, ref point);
PInvokeCore.MapWindowPoints(HWND.Null, headerHwnd, ref point);
_hdrhit.pt = point;
PInvokeCore.SendMessage(headerHwnd, PInvoke.HDM_HITTEST, 0, ref _hdrhit);
if (_hdrhit.flags == HEADER_HITTEST_INFO_FLAGS.HHT_ONDIVIDER)

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

@ -108,7 +108,7 @@ internal sealed class ToolStripAdornerWindowService : IDisposable
}
Point pt = new(c.Left, c.Top);
PInvoke.MapWindowPoints(c.Parent, _toolStripAdornerWindow, ref pt);
PInvokeCore.MapWindowPoints(c.Parent, _toolStripAdornerWindow, ref pt);
return pt;
}

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

@ -239,8 +239,6 @@ GetViewportExtEx
GetWindow
GetWindowDpiAwarenessContext
GetWindowPlacement
GetWindowText
GetWindowTextLength
GetWindowThreadProcessId
GetWorldTransform
GMR_*
@ -456,7 +454,6 @@ LVTILEVIEWINFO_FLAGS
LVTILEVIEWINFO_MASK
MA_*
MapVirtualKey
MapWindowPoints
MAX_TAB_STOPS
MCGRIDINFO
MCGRIDINFO_FLAGS

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

@ -34,7 +34,7 @@ public class GetWindowTextTests
windowClass.BeforeGetTextLengthCallback = () => shortText;
}
string result = PInvoke.GetWindowText(windowHandle);
string result = PInvokeCore.GetWindowText(windowHandle);
PInvoke.DestroyWindow(windowHandle);
Assert.Equal(longText, result);

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

@ -66,7 +66,7 @@ internal unsafe class LabelEditAccessibleObject : AccessibleObject
};
public override string? Name => _labelEdit.TryGetTarget(out var target)
? PInvoke.GetWindowText(target)
? PInvokeCore.GetWindowText(target)
: null;
private protected override bool IsInternal => true;

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

@ -61,7 +61,7 @@ internal sealed unsafe class LabelEditUiaTextProvider : UiaTextProvider
public override SupportedTextSelection SupportedTextSelection => SupportedTextSelection.SupportedTextSelection_Single;
public override string Text => PInvoke.GetWindowText(_owningChildEdit);
public override string Text => PInvokeCore.GetWindowText(_owningChildEdit);
public override int TextLength => (int)PInvokeCore.SendMessage(_owningChildEdit, PInvokeCore.WM_GETTEXTLENGTH);
@ -225,7 +225,7 @@ internal sealed unsafe class LabelEditUiaTextProvider : UiaTextProvider
public override Point PointToScreen(Point pt)
{
PInvoke.MapWindowPoints(_owningChildEdit.Handle, HWND.Null, ref pt);
PInvokeCore.MapWindowPoints(_owningChildEdit.Handle, HWND.Null, ref pt);
return pt;
}
@ -269,7 +269,7 @@ internal sealed unsafe class LabelEditUiaTextProvider : UiaTextProvider
// Convert screen to client coordinates.
// (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.)
if (PInvoke.MapWindowPoints(HWND.Null, _owningChildEdit.Handle, ref clientLocation) == 0)
if (PInvokeCore.MapWindowPoints(HWND.Null, _owningChildEdit.Handle, ref clientLocation) == 0)
{
*pRetVal = ComHelpers.GetComPointer<ITextRangeProvider>(
new UiaTextRange(
@ -305,7 +305,7 @@ internal sealed unsafe class LabelEditUiaTextProvider : UiaTextProvider
public override Rectangle RectangleToScreen(Rectangle rect)
{
RECT r = rect;
PInvoke.MapWindowPoints(_owningChildEdit.Handle, HWND.Null, ref r);
PInvokeCore.MapWindowPoints(_owningChildEdit.Handle, HWND.Null, ref r);
return r;
}

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

@ -360,7 +360,7 @@ public partial class Control
HWND hwndMap = hwnd.IsNull ? hwndParent : hwnd;
Point pt = new(PARAM.LOWORD(lpmsg->lParam), PARAM.HIWORD(lpmsg->lParam));
PInvoke.MapWindowPoints(hwndMap, _control, ref pt);
PInvokeCore.MapWindowPoints(hwndMap, _control, ref pt);
// Check to see if this message should really go to a child control, and if so, map the
// point into that child's window coordinates.
@ -1812,7 +1812,7 @@ public partial class Control
RECT rcIntersect = intersect;
HWND hWndParent = PInvoke.GetParent(_control);
PInvoke.MapWindowPoints(hWndParent, _control, ref rcIntersect);
PInvokeCore.MapWindowPoints(hWndParent, _control, ref rcIntersect);
_lastClipRect = rcIntersect;
setRegion = true;

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

@ -3581,7 +3581,7 @@ public unsafe partial class Control :
}
using var scope = MultithreadSafeCallScope.Create();
return PInvoke.GetWindowText(this);
return PInvokeCore.GetWindowText(this);
}
set
{
@ -8462,7 +8462,7 @@ public unsafe partial class Control :
/// </summary>
public Point PointToClient(Point p)
{
PInvoke.MapWindowPoints((HWND)default, this, ref p);
PInvokeCore.MapWindowPoints((HWND)default, this, ref p);
return p;
}
@ -8471,7 +8471,7 @@ public unsafe partial class Control :
/// </summary>
public Point PointToScreen(Point p)
{
PInvoke.MapWindowPoints(this, (HWND)default, ref p);
PInvokeCore.MapWindowPoints(this, (HWND)default, ref p);
return p;
}
@ -9250,7 +9250,7 @@ public unsafe partial class Control :
public Rectangle RectangleToClient(Rectangle r)
{
RECT rect = r;
PInvoke.MapWindowPoints(HWND.Null, this, ref rect);
PInvokeCore.MapWindowPoints(HWND.Null, this, ref rect);
return rect;
}
@ -9260,7 +9260,7 @@ public unsafe partial class Control :
public Rectangle RectangleToScreen(Rectangle r)
{
RECT rect = r;
PInvoke.MapWindowPoints(this, HWND.Null, ref rect);
PInvokeCore.MapWindowPoints(this, HWND.Null, ref rect);
return rect;
}
@ -10721,7 +10721,7 @@ public unsafe partial class Control :
PInvokeCore.GetWindowRect(this, out rect);
if (!GetTopLevel())
{
PInvoke.MapWindowPoints(HWND.Null, PInvoke.GetParent(this), ref rect);
PInvokeCore.MapWindowPoints(HWND.Null, PInvoke.GetParent(this), ref rect);
}
}

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

@ -51,7 +51,7 @@ public partial class ComboBox
// Translate the item rect to screen coordinates
RECT translated = itemRect;
PInvoke.MapWindowPoints(listHandle, HWND.Null, ref translated);
PInvokeCore.MapWindowPoints(listHandle, HWND.Null, ref translated);
return translated;
}
}

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

@ -97,7 +97,7 @@ public partial class ComboBox
public override string Text
=> _owningComboBox.IsHandleCreated
? PInvoke.GetWindowText(_owningChildEdit)
? PInvokeCore.GetWindowText(_owningChildEdit)
: string.Empty;
public override int TextLength
@ -292,7 +292,7 @@ public partial class ComboBox
public override Point PointToScreen(Point pt)
{
PInvoke.MapWindowPoints(_owningChildEdit, (HWND)default, ref pt);
PInvokeCore.MapWindowPoints(_owningChildEdit, (HWND)default, ref pt);
return pt;
}
@ -342,7 +342,7 @@ public partial class ComboBox
// Convert screen to client coordinates.
// (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.)
if (PInvoke.MapWindowPoints((HWND)default, _owningChildEdit, ref clientLocation) == 0)
if (PInvokeCore.MapWindowPoints((HWND)default, _owningChildEdit, ref clientLocation) == 0)
{
*pRetVal = ComHelpers.GetComPointer<ITextRangeProvider>(
new UiaTextRange(

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

@ -391,7 +391,7 @@ public partial class RichTextBox : TextBoxBase
get => base.Font;
set
{
if (!IsHandleCreated || PInvoke.GetWindowTextLength(this) <= 0)
if (!IsHandleCreated || PInvokeCore.GetWindowTextLength(this) <= 0)
{
base.Font = value;
return;
@ -1965,7 +1965,7 @@ public partial class RichTextBox : TextBoxBase
return -1;
}
textLength = PInvoke.GetWindowTextLength(this);
textLength = PInvokeCore.GetWindowTextLength(this);
if (start == end)
{
start = 0;
@ -3392,7 +3392,7 @@ public partial class RichTextBox : TextBoxBase
LRESULT compMode = PInvokeCore.SendMessage(this, PInvokeCore.EM_GETIMECOMPMODE);
if (compMode != PInvoke.ICM_NOTOPEN)
{
int textLength = PInvoke.GetWindowTextLength(this);
int textLength = PInvokeCore.GetWindowTextLength(this);
if (selStart == selEnd && textLength == MaxLength)
{
PInvokeCore.SendMessage(this, PInvokeCore.WM_KILLFOCUS);

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

@ -107,7 +107,7 @@ public abstract partial class TextBoxBase
// Convert screen to client coordinates.
// (Essentially ScreenToClient but MapWindowPoints accounts for window mirroring using WS_EX_LAYOUTRTL.)
if (PInvoke.MapWindowPoints((HWND)default, Owner, ref clientLocation) == 0)
if (PInvokeCore.MapWindowPoints((HWND)default, Owner, ref clientLocation) == 0)
{
*pRetVal = ComHelpers.GetComPointer<ITextRangeProvider>(
new UiaTextRange(

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

@ -1089,7 +1089,7 @@ public abstract partial class TextBoxBase : Control
// Note: Currently WinForms does not fully support surrogates. If
// the text contains surrogate characters this property may return incorrect values.
=> IsHandleCreated ? PInvoke.GetWindowTextLength(this) : Text.Length;
=> IsHandleCreated ? PInvokeCore.GetWindowTextLength(this) : Text.Length;
internal override string WindowText
{

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

@ -586,7 +586,7 @@ public partial class StatusStrip : ToolStrip
gripLocation = new Point(SizeGripBounds.Right, SizeGripBounds.Bottom);
}
PInvoke.MapWindowPoints(this, rootHwnd, ref gripLocation);
PInvokeCore.MapWindowPoints(this, rootHwnd, ref gripLocation);
int deltaBottomEdge = Math.Abs(rootHwndClientArea.bottom - gripLocation.Y);
int deltaRightEdge = Math.Abs(rootHwndClientArea.right - gripLocation.X);

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

@ -333,7 +333,7 @@ public static partial class ToolStripManager
if (activeToolStrip is not null)
{
Point translatedLocation = location;
PInvoke.MapWindowPoints(hwndMouseMessageIsFrom, activeToolStrip, ref translatedLocation);
PInvokeCore.MapWindowPoints(hwndMouseMessageIsFrom, activeToolStrip, ref translatedLocation);
if (!activeToolStrip.ClientRectangle.Contains(translatedLocation))
{
if (activeToolStrip is ToolStripDropDown activeToolStripDropDown)

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

@ -151,7 +151,7 @@ public abstract partial class FileDialog : CommonDialog
set => SetOption(OFN_NODEREFERENCELINKS, !value);
}
private protected string DialogCaption => PInvoke.GetWindowText(_dialogHWnd);
private protected string DialogCaption => PInvokeCore.GetWindowText(_dialogHWnd);
/// <summary>
/// Gets or sets a string containing the file name selected in the file dialog box.

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

@ -158,7 +158,7 @@ internal sealed partial class WindowsFormsUtils
}
#if DEBUG
string windowText = PInvoke.GetWindowText(hwnd);
string windowText = PInvokeCore.GetWindowText(hwnd);
string typeOfControl = "Unknown";
string nameOfControl = "";
Control? c = Control.FromHandle(hwnd);
@ -283,7 +283,7 @@ internal sealed partial class WindowsFormsUtils
/// </remarks>
public static Point TranslatePoint(Point point, Control fromControl, Control toControl)
{
PInvoke.MapWindowPoints(fromControl, toControl, ref point);
PInvokeCore.MapWindowPoints(fromControl, toControl, ref point);
return point;
}

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

@ -2052,7 +2052,7 @@ public partial class ToolTip : Component, IExtenderProvider, IHandle<HWND>
// Use GetWindowText instead of GetCaptionForTool to retrieve the actual caption.
// GetCaptionForTool doesn't work correctly when the text for a tool is retrieved
// by TTN_NEEDTEXT notification (e.g. TabPages of TabControl).
AnnounceText(toolControl, PInvoke.GetWindowText(this));
AnnounceText(toolControl, PInvokeCore.GetWindowText(this));
}
// We need to re-get the rectangle of the tooltip here because

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

@ -442,7 +442,7 @@ public static class TestHelpers
HWND foregroundWindow = PInvokeCore.GetForegroundWindow();
string windowTitle = PInvoke.GetWindowText(foregroundWindow);
string windowTitle = PInvokeCore.GetWindowText(foregroundWindow);
if (PInvoke.GetWindowThreadProcessId(foregroundWindow, out uint processId) == 0 ||
processId != process.Id)

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

@ -85,7 +85,7 @@ public class SendInput
// Move the window into the foreground as it may not have been achieved by the 'SetWindowPos' call
if (!PInvoke.SetForegroundWindow(window))
{
string windowTitle = PInvoke.GetWindowText(window);
string windowTitle = PInvokeCore.GetWindowText(window);
if (PInvoke.GetWindowThreadProcessId(window, out uint processId) == 0 || processId != Environment.ProcessId)
{
string message = $"ForegroundWindow doesn't belong the test process! The current window HWND: {window}, title:{windowTitle}.";