WinUi로 WndProc이용하여 윈도우 메시지 처리하기

WinUi로는 WndProc을 쓸 수 없다. 윈도우 메시지를 처리하려면 SetWindowLong을 이용해 메시지를 가로채 처리해야 한다.

Changes an attribute of the specified window.
SetWindowLongA function (winuser.h)

SetWindowLongA는 앤시 버전이고 SetWindowLongW는 유니코드 버전이다. SetWindowLong은 두 버전 가운데 하나를 자동으로 선택하는 alias다. 따라서 SetWindowLong는 검색해 봐야 나오지 않는다.

DllImport의 EntryPoint에는 SetWindowLong를 설정해도 작동하지만 LoadLibrary는 그렇지 않다. A/W를 특정해야 한다.

The method name or EntryPoint should be the exact spelling of the entry point name.
Source generation for platform invokes

LoadLibrary를 쓸 때에는 SetWindowLongA/W와 SetWindowLongPtrA/W도 구별하여 전자는 x86에 후자는 x64에 써야 한다.

public sealed partial class MainWindow : Window
{
    delegate nint WndProcDelegate(nint hWnd, uint msg, nint wParam, nint lParam);

    nint Handle;
    WndProcDelegate WndProc_;
    nint OriginalPointer;
    int GWLP_WNDPROC = -4;

    public MainWindow()
    {
        InitializeComponent();

        Handle = WindowNative.GetWindowHandle(this);

        WndProc_ = WndProc;

        nint pointer = Marshal.GetFunctionPointerForDelegate(WndProc_);

        OriginalPointer = SetWindowLong(Handle, GWLP_WNDPROC, pointer);
    }

    // x86

    [LibraryImport("user32.dll", EntryPoint = "SetWindowLongA")] private static partial nint SetWindowLong(nint hWnd, int nIndex, nint dwNewLong);
    [LibraryImport("user32.dll", EntryPoint = "GetWindowLongA")] private static partial nint GetWindowLong(nint hWnd, int nIndex);
    [LibraryImport("user32.dll", EntryPoint = "CallWindowProcA")] private static partial nint CallWindowProc(nint lpPrevWndFunc, nint hWnd, uint msg, nint wParam, nint lParam);

    nint WndProc(nint hWnd, uint msg, nint wParam, nint lParam)
    {
        // do something        

        return CallWindowProc(OriginalPointer, hWnd, msg, wParam, lParam);
    }
}

x86 전용인 ls증권 api를 이용하느라 위와 같이 했다.