Compare commits

..
2 Commits
5 changed files with 60 additions and 45 deletions
+14 -2
View File
@@ -26,22 +26,34 @@ namespace IPClab1;
public sealed partial class MainWindow : Window public sealed partial class MainWindow : Window
{ {
private readonly DispatcherTimer timer = new() { Interval = TimeSpan.FromMilliseconds(100) }; private readonly DispatcherTimer timer = new() { Interval = TimeSpan.FromMilliseconds(100) };
private bool IsClosed;
public MainWindowViewModel ViewModel; public MainWindowViewModel ViewModel;
public MainWindow(MainWindowViewModel viewModel) public MainWindow(MainWindowViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
IsClosed = false;
Closed += MainWindow_Closed;
ViewModel = viewModel; ViewModel = viewModel;
ExtendsContentIntoTitleBar = true; ExtendsContentIntoTitleBar = true;
SetTitleBar(AppTitleBar); SetTitleBar(AppTitleBar);
timer.Tick += Timer_Tick; timer.Tick += Timer_Tick;
timer.Start(); timer.Start();
} }
private void MainWindow_Closed(object sender, WindowEventArgs args) => IsClosed = true;
private void Timer_Tick(object? sender, object e) private void Timer_Tick(object? sender, object e)
{ {
AppTitleBar.Title = Title; if (!IsClosed)
ViewModel.RefreshInfo(); {
AppTitleBar.Title = Title;
ViewModel.RefreshInfo();
}
} }
private void GridView_SizeChanged(object sender, SizeChangedEventArgs e) private void GridView_SizeChanged(object sender, SizeChangedEventArgs e)
+1
View File
@@ -0,0 +1 @@
[assembly: System.Runtime.CompilerServices.DisableRuntimeMarshalling]
+17 -17
View File
@@ -8,7 +8,7 @@ using IPClab1.Enums;
namespace IPClab1.Services; namespace IPClab1.Services;
public class WindowInteractionService public partial class WindowInteractionService
{ {
private const uint WM_MOUSEMOVE = 0x0200; private const uint WM_MOUSEMOVE = 0x0200;
private const uint WM_LBUTTONDOWN = 0x0201; private const uint WM_LBUTTONDOWN = 0x0201;
@@ -21,22 +21,22 @@ public class WindowInteractionService
private const int SC_MAXIMIZE = 0xF030; private const int SC_MAXIMIZE = 0xF030;
private const int SC_RESTORE = 0xF120; private const int SC_RESTORE = 0xF120;
[DllImport("user32.dll", CharSet = CharSet.Auto)] [LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); private static partial IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto)] [LibraryImport("user32.dll", EntryPoint = "PostMessageW")]
private static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [return: MarshalAs(UnmanagedType.Bool)]
// 1. Get Class Name private static partial bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
// 2. Get Geometry [LibraryImport("user32.dll", EntryPoint = "GetClassNameW", SetLastError = true)]
[DllImport("user32.dll", SetLastError = true)] private static partial int GetClassName(IntPtr hWnd, [Out] char[] lpClassName, int nMaxCount);
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
// 3. Get Parent [LibraryImport("user32.dll", SetLastError = true)]
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)] [return: MarshalAs(UnmanagedType.Bool)]
private static extern IntPtr GetParent(IntPtr hWnd); private static partial bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[LibraryImport("user32.dll")]
private static partial IntPtr GetParent(IntPtr hWnd);
public void SimulateClick(IntPtr hwnd, int x, int y) public void SimulateClick(IntPtr hwnd, int x, int y)
{ {
@@ -81,9 +81,9 @@ public class WindowInteractionService
public string GetWindowDetails(IntPtr hwnd) public string GetWindowDetails(IntPtr hwnd)
{ {
StringBuilder classNameBuffer = new StringBuilder(256); char[] classNameBuffer = new char[256];
GetClassName(hwnd, classNameBuffer, classNameBuffer.Capacity); int length = GetClassName(hwnd, classNameBuffer, classNameBuffer.Length);
string className = classNameBuffer.ToString(); string className = length > 0 ? new string(classNameBuffer, 0, length) : string.Empty;
GetWindowRect(hwnd, out RECT rect); GetWindowRect(hwnd, out RECT rect);
+26 -25
View File
@@ -13,7 +13,7 @@ using Windows.Graphics.Imaging;
namespace IPClab1.Services; namespace IPClab1.Services;
public class WindowListService public partial class WindowListService
{ {
#region Win32 P/Invoke Declarations #region Win32 P/Invoke Declarations
@@ -27,34 +27,34 @@ public class WindowListService
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll")] [LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); private static partial bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")] [LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)] [return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd); private static partial bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [LibraryImport("user32.dll", EntryPoint = "GetWindowTextW", SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); private static partial int GetWindowText(IntPtr hWnd, [Out] char[] lpString, int nMaxCount);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] [LibraryImport("user32.dll", EntryPoint = "GetWindowTextLengthW", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd); private static partial int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Auto)] [LibraryImport("user32.dll", EntryPoint = "SendMessageW")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); private static partial IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr", CharSet = CharSet.Auto)] [LibraryImport("user32.dll", EntryPoint = "GetClassLongPtrW")]
private static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex); private static partial IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetClassLong", CharSet = CharSet.Auto)] [LibraryImport("user32.dll", EntryPoint = "GetClassLongW")]
private static extern uint GetClassLong32(IntPtr hWnd, int nIndex); private static partial uint GetClassLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true)] [LibraryImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); private static partial uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("shell32.dll", CharSet = CharSet.Auto)] [LibraryImport("shell32.dll", EntryPoint = "ExtractIconW", StringMarshalling = StringMarshalling.Utf16)]
private static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex); private static partial IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);
private IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex) private IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
{ {
@@ -85,13 +85,14 @@ public class WindowListService
foreach (var hWnd in handles) foreach (var hWnd in handles)
{ {
// Fetch window text title cleanly // Fetch window text title cleanly
int length = GetWindowTextLength(hWnd); var length = GetWindowTextLength(hWnd);
var builder = new StringBuilder(length + 1); var titleBuffer = new char[length + 1];
GetWindowText(hWnd, builder, builder.Capacity);
string title = builder.ToString(); var actualLength = GetWindowText(hWnd, titleBuffer, titleBuffer.Length);
var title = actualLength > 0 ? new string(titleBuffer, 0, actualLength) : string.Empty;
// Fetch numeric process identifier // Fetch numeric process identifier
GetWindowThreadProcessId(hWnd, out uint processId); GetWindowThreadProcessId(hWnd, out var processId);
// Fetch and map the icon image synchronously/asynchronously into WinUI structures // Fetch and map the icon image synchronously/asynchronously into WinUI structures
SoftwareBitmapSource iconSource = await GetWinUi3IconAsync(hWnd); SoftwareBitmapSource iconSource = await GetWinUi3IconAsync(hWnd);
@@ -110,7 +111,7 @@ public class WindowListService
private Icon GetIconFromHwnd(IntPtr hWnd) private Icon GetIconFromHwnd(IntPtr hWnd)
{ {
IntPtr hIcon = SendMessage(hWnd, WM_GETICON, ICON_BIG, IntPtr.Zero); var hIcon = SendMessage(hWnd, WM_GETICON, ICON_BIG, IntPtr.Zero);
if (hIcon == IntPtr.Zero) if (hIcon == IntPtr.Zero)
hIcon = SendMessage(hWnd, WM_GETICON, ICON_SMALL2, IntPtr.Zero); hIcon = SendMessage(hWnd, WM_GETICON, ICON_SMALL2, IntPtr.Zero);
+2 -1
View File
@@ -48,7 +48,8 @@ public partial class MainWindowViewModel(WindowListService windowListService, Wi
partial void OnSelectedWindowChanged(WindowInfo value) partial void OnSelectedWindowChanged(WindowInfo value)
{ {
(Width, Height) = _windowInteractionService.GetWindowSize(value.Hwnd); if (value != null)
(Width, Height) = _windowInteractionService.GetWindowSize(value.Hwnd);
} }
[ObservableProperty] [ObservableProperty]