【发布时间】:2021-06-18 01:01:51
【问题描述】:
所以我正在尝试使用 PInvoke 制作一个 winapi 应用程序。到目前为止,我已经能够打开一个窗口,但是从那里,我似乎无法使 WndProc 工作。现在,应用程序启动了,但它既不会响应调整大小,也不会响应移动或任何东西,除了悬停在控制按钮上方。
WindowLL.cs:
public delegate long WndProc(IntPtr hWnd, uint message, byte wParam, long lParam);
public static unsafe class WindowLL
{
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern ushort RegisterClassExA(ref WNDCLASSEX _class);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern IntPtr CreateWindowExA(
uint extraStyle,
ushort className,
//[MarshalAs(UnmanagedType.LPWStr)]
//string className,
[MarshalAs(UnmanagedType.LPStr)]
string title,
uint style,
int x,
int y,
int width,
int height,
IntPtr parent,
IntPtr menu,
IntPtr instance,
IntPtr parameter
);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern bool DestroyWindow(IntPtr hWnd);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
public static extern bool ShowWindow(IntPtr hWnd, int cmdShow);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetMessage(
out MSG lpMsg,
IntPtr hWnd,
uint wMsgFilterMin,
uint wMsgFilterMax
);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint DispatchMessage(ref MSG lpMsg);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern uint TranslateMessage(ref MSG lpMsg);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
public static extern long DefWindowProcA(
IntPtr hWnd,
uint Msg,
byte wParam,
long lParam
);
}
结构(分成不同的文件):
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr hwnd;
public uint message;
public byte wParam;
public long lParam;
public short time;
public POINT pt;
public short lPrivate;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public long X;
public long Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct WNDCLASSEX
{
public uint cbSize;
public uint style;
public WndProc lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszMenuName;
[MarshalAs(UnmanagedType.LPStr)]
public string lpszClassName;
public IntPtr hIconSm;
}
程序.cs:
class Program
{
static long WndProc(IntPtr hWnd, uint message, byte wParam, long lParam)
{
return WindowLL.DefWindowProcA(hWnd, message, wParam, lParam);
}
static void Main(string[] args)
{
var winCalss = new WNDCLASSEX() {
lpszClassName = "test",
lpfnWndProc = WndProc,
cbSize = (uint)Marshal.SizeOf(typeof(WNDCLASSEX)),
};
var classId = WindowLL.RegisterClassExA(ref winCalss);
var overlapped =
WindowStyle.Overlapped |
WindowStyle.Caption |
WindowStyle.SysMenu |
WindowStyle.ThickFrame |
WindowStyle.MinimizeBox |
WindowStyle.MaximizeBox;
IntPtr hWnd = WindowLL.CreateWindowExA(0,
classId, "test",
(uint)overlapped,
0, 0,
1280, 720,
IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero
);
WindowLL.ShowWindow(hWnd, (int)NCmdShow.Show);
while (WindowLL.GetMessage(out var msg, hWnd, 0, 0)) {
WindowLL.TranslateMessage(ref msg);
WindowLL.DispatchMessage(ref msg);
}
}
}
【问题讨论】:
-
"尝试使用 PInvoke 制作一个 winapi 应用程序" 很好奇,为什么? Win32 API 是裸机,但曲折且充满怪癖。 C# 更简单、更安全,但是是沙盒的。将两者结合起来就像挑选两全其美的樱桃。
-
@dxiv 我只想制作一个包装器,比如 WinForms,因为我觉得它一团糟。我也完全清楚我自愿忍受的:)。如果我在 C++ 中做,然后在 C# 中使用 C++ 库,可能会是一个好主意,但我对 C 或 C++ 感到不舒服
-
C++/CLI 让您可以从本机实现无缝导出托管接口。