So Sánh Xử Lý Thông Điệp Hệ Thống và Quản Lý Cửa Sổ Giữa WinForms và Avalonia UI

Phân Tích Khác Biệt Triển Khai Giao Diện Không Viền

Khi phát triển ứng dụng tìm kiếm tập tin trên nền .NET, việc lựa chọn giữa WinForms và Avalonia UI đặt ra nhiều thách thức kỹ thuật. Bài viết tập trung vào ba khía cạnh then chốt: xử lý thông điệp hệ thống, di chuyển cửa sổ không tiêu đề, và thay đổi kích thước giao diện không viền.

Xử Lý Thông Điệp Hệ Thống

Đăng ký phím tắt hệ thống thông qua API RegisterHotKey yêu cầu cơ chế bắt thông điệp khác biệt giữa hai framework:

[DllImport("user32.dll")]
static extern bool RegisterHotKey(IntPtr hWnd, int id, uint mod, uint vk);

// Đăng ký phím tắt Ctrl+Shift+S
RegisterHotKey(Handle, 1001, 0x0002 | 0x0004, (uint)Keys.S);

WinForms: Ghi đè WndProc

Triển khai xử lý thông điệp thông qua phương thức WndProc với cấu trúc tối ưu hiệu suất:

protected override void WndProc(ref Message msg)
{
    if (msg.Msg == 0x0312 && msg.WParam.ToInt32() == 1001)
    {
        ToggleVisibility();
        return;
    }
    base.WndProc(ref msg);
}

Avalonia: Hook API Hệ Thống

Sử dụng cơ chế hook của Win32 thông qua Win32Platform để tránh mất thông điệp:

private void SetupSystemHooks()
{
    var platform = (Win32Platform)Application.Current.Platform!;
    platform.AddWndProcHook(WndProcHook);
}

private IntPtr WndProcHook(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == 0x0312 && wParam.ToInt32() == 1001)
    {
        ToggleVisibility();
        handled = true;
    }
    return IntPtr.Zero;
}

Di Chuyển Cửa Sổ Không Viền

Thao tác kéo thả yêu cầu xử lý sự kiện chuột khác nhau ở mỗi framework:

WinForms: Đánh Lừa Hệ Thống

Sử dụng hằng số hệ thống để giả lập thao tác trên thanh tiêu đề:

private const int WM_SYSCOMMAND = 0x0112;
private const int SC_DRAGMOVE = 0xF012;

[DllImport("user32.dll")]
private static extern int ReleaseCapture();

[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

private void HeaderBar_PointerPressed(object sender, PointerPressedEventArgs e)
{
    ReleaseCapture();
    SendMessage(Handle, WM_SYSCOMMAND, SC_DRAGMOVE, 0);
}

Avalonia: API Tích Hợp Sẵn

Triển khai trực tiếp thông qua phương thức BeginMoveDrag:

private void HeaderBar_PointerPressed(object sender, PointerPressedEventArgs e)
{
    if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed)
    {
        BeginMoveDrag(e);
    }
}

Thay Đổi Kích Thước Cửa Sổ

Quản lý vùng thao tác thay đổi kích thước khi không có viền cửa sổ:

WinForms: Xử Lý WM_NCHITTEST

Ghi đè WndProc để xác định vùng thao tác chuột:

protected override void WndProc(ref Message m)
{
    if (m.Msg == 0x0084) // WM_NCHITTEST
    {
        var point = PointToClient(new Point(m.LParam));
        var hitTest = CalculateResizeHitTest(point);
        if (hitTest != 0) m.Result = (IntPtr)hitTest;
        else base.WndProc(ref m);
        return;
    }
    base.WndProc(ref m);
}

private int CalculateResizeHitTest(Point point)
{
    const int borderThickness = 8;
    var size = ClientSize;
    
    if (point.X < borderThickness)
    {
        if (point.Y < borderThickness) return 13; // Góc trái trên
        if (point.Y > size.Height - borderThickness) return 16; // Góc trái dưới
        return 10; // Cạnh trái
    }
    // Tương tự cho các cạnh còn lại...
    return 0;
}

Avalonia: Cấu Hình XAML

Thiết lập thuộc tính mở rộng vùng client trong file giao diện:

<Window 
    xmlns:platform="clr-namespace:Avalonia.Win32;assembly=Avalonia.Win32"
    platform:WindowIconHelper.ExtendClientAreaToDecorations="True"
    platform:WindowIconHelper.ExtendClientAreaChrome="NoSystemChrome"
    platform:WindowIconHelper.TitleBarHeight="-1">
    <!-- Nội dung giao diện -->
</Window>

Thẻ: WinForms AvaloniaUI .NET window-management system-messages

Đăng vào ngày 9 tháng 7 lúc 19:52