gpt4 book ai didi

c# - 从 C# 注册自定义 win32 窗口类

转载 作者:可可西里 更新时间:2023-11-01 12:33:20 27 4
gpt4 key购买 nike

我有一个用 WPF 编写的新应用程序,它需要支持旧的 API,以允许它接收已发布到隐藏窗口的消息。通常,另一个应用程序使用 FindWindow 通过其自定义窗口类的名称来识别隐藏窗口。

1) 我假设要实现一个自定义窗口类,我需要使用旧式 win32 调用吗?

我的旧 c++ 应用程序使用 RegisterClass 和 CreateWindow 来制作最简单的隐形窗口。

我相信我应该能够在 C# 中做同样的事情。我不希望我的项目必须编译任何非托管代码。

我已尝试从 System.Windows.Interop.HwndHost 继承并使用 System.Runtime.InteropServices.DllImport 引入上述 API 方法。

这样做我可以成功地托管一个标准的 win32 窗口,例如WPF 中的“列表框”。但是,当我为我的自定义窗口调用 CreateWindowEx 时,它总是返回 null。

我对 RegisterClass 的调用成功了,但我不确定我应该设置什么WNDCLASS.lpfnWndProc 成员。

2) 有谁知道如何成功做到这一点?

最佳答案

郑重声明,我终于让它发挥作用了。原来我遇到的困难归结为字符串编码问题。我必须更精确地导入 win32 函数。

下面是将在 C# 中创建自定义窗口类的代码 - 对于支持您可能拥有的依赖于自定义窗口类的旧 API 很有用。

只要消息泵在线程上运行,它就应该在 WPF 或 Winforms 中工作。

编辑:已更新以修复由于提前收集包装回调的委托(delegate)而报告的崩溃。委托(delegate)现在作为成员持有,并且委托(delegate)显式编码(marshal)为函数指针。这解决了这个问题,并且更容易理解该行为。

class CustomWindow : IDisposable
{
delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

[System.Runtime.InteropServices.StructLayout(
System.Runtime.InteropServices.LayoutKind.Sequential,
CharSet = System.Runtime.InteropServices.CharSet.Unicode
)]
struct WNDCLASS
{
public uint style;
public IntPtr lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public string lpszMenuName;
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
public string lpszClassName;
}

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern System.UInt16 RegisterClassW(
[System.Runtime.InteropServices.In] ref WNDCLASS lpWndClass
);

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern IntPtr CreateWindowExW(
UInt32 dwExStyle,
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
string lpClassName,
[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
string lpWindowName,
UInt32 dwStyle,
Int32 x,
Int32 y,
Int32 nWidth,
Int32 nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam
);

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern System.IntPtr DefWindowProcW(
IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam
);

[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
static extern bool DestroyWindow(
IntPtr hWnd
);

private const int ERROR_CLASS_ALREADY_EXISTS = 1410;

private bool m_disposed;
private IntPtr m_hwnd;

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
if (!m_disposed) {
if (disposing) {
// Dispose managed resources
}

// Dispose unmanaged resources
if (m_hwnd != IntPtr.Zero) {
DestroyWindow(m_hwnd);
m_hwnd = IntPtr.Zero;
}

}
}

public CustomWindow(string class_name){

if (class_name == null) throw new System.Exception("class_name is null");
if (class_name == String.Empty) throw new System.Exception("class_name is empty");

m_wnd_proc_delegate = CustomWndProc;

// Create WNDCLASS
WNDCLASS wind_class = new WNDCLASS();
wind_class.lpszClassName = class_name;
wind_class.lpfnWndProc = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(m_wnd_proc_delegate);

UInt16 class_atom = RegisterClassW(ref wind_class);

int last_error = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

if (class_atom == 0 && last_error != ERROR_CLASS_ALREADY_EXISTS) {
throw new System.Exception("Could not register window class");
}

// Create window
m_hwnd = CreateWindowExW(
0,
class_name,
String.Empty,
0,
0,
0,
0,
0,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero
);
}

private static IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
return DefWindowProcW(hWnd, msg, wParam, lParam);
}

private WndProc m_wnd_proc_delegate;
}

关于c# - 从 C# 注册自定义 win32 窗口类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/128561/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com