I get an exception message like "cannot find window class" with the following code snippet.
bool bRet; WNDCLASS wc; lpszCmdLine = null; hInstance = System.Diagnostics.Process.GetCurrentProcess().Handle; WNDCLASSEX wndClass = new WNDCLASSEX(); wndClass.cbSize = Marshal.SizeOf(typeof(WNDCLASSEX)); string szName = "HelloWin"; wndClass.style = (int) (ClassStyles.HorizontalRedraw | ClassStyles.VerticalRedraw); wndClass.lpfnWndProc = Marshal.GetFunctionPointerForDelegate((WndProc)((hWnd, message, wParam, lParam) => { IntPtr hdc; PAINTSTRUCT ps; RECT rect; switch ((WM)message) { case WM.PAINT: hdc = WinAPI.BeginPaint(hWnd, out ps); WinAPI.GetClientRect(hWnd, out rect); WinAPI.DrawText(hdc, "Hello, Windows 98!", -1, ref rect, Win32_DT_Constant.DT_SINGLELINE | Win32_DT_Constant.DT_CENTER | Win32_DT_Constant.DT_VCENTER); WinAPI.EndPaint(hWnd, ref ps); return IntPtr.Zero; break; case WM.DESTROY: WinAPI.PostQuitMessage(0); return IntPtr.Zero; break; } return WinAPI.DefWindowProc(hWnd, (WM)message, wParam, lParam); } )); wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = hInstance; wndClass.hIcon = WinAPI.LoadIcon( IntPtr.Zero, new IntPtr((int)SystemIcons.IDI_APPLICATION)); //wndClass.hCursor = WinAPI.LoadCursor(IntPtr.Zero, (int)IdcStandardCursor.IDC_ARROW); wndClass.hCursor = WinAPI.LoadCursor(IntPtr.Zero, (int)Win32_IDC_Constants.IDC_ARROW); wndClass.hbrBackground = WinAPI.GetStockObject(StockObjects.WHITE_BRUSH); wndClass.lpszMenuName = null; wndClass.lpszClassName = szName; //WindowStyleEx.WS_EX_OVERLAPPEDWINDOW ushort regResult = (ushort)WinAPI.RegisterClassEx(ref wndClass); // change the varie RegisterClassEx2 if (regResult == 0) { int lastError = Marshal.GetLastWin32Error(); string errorMessage = new Win32Exception(lastError).Message; WinAPI.MessageBox(IntPtr.Zero, "This program requires windows NT!", szName, (int) MessageBoxOptions.IconError); } // this varie of CreateWindowEx do no work IntPtr hwnd = WinAPI.CreateWindowEx( 0, szName, "The Hello Program", WindowStyles.WS_OVERLAPPEDWINDOW, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, IntPtr.Zero, IntPtr.Zero, hInstance, IntPtr.Zero); if (hwnd == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); string errorMessage = new Win32Exception(lastError).Message; } WinAPI.ShowWindow(hwnd, ShowWindowCommands.Normal); WinAPI.UpdateWindow(hwnd); WinAPI.UpdateWindow(hwnd); MSG msg; while (WinAPI.GetMessage(out msg, IntPtr.Zero, 0, 0) != 0) { WinAPI.TranslateMessage(ref msg); WinAPI.DispatchMessage(ref msg); }
The error happens at this block of code.
if (hwnd == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); string errorMessage = new Win32Exception(lastError).Message; }
Why this is failing, we are creating a WNDCLASSEX, and initialize the ClassName to "HelloWin", and then we try to create a windows by that name "HelloWin", but it told us that "Cannot find the window class"? why ?
Check on the refernces, and MSDN on the CreateWindowEx function.
Type: LPCTSTR
A null-terminated string or a class atom created by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in the low-order word of lpClassName; the high-order word must be zero. If lpClassName is a string, it specifies the window class name. The class name can be any name registered with RegisterClass or RegisterClassEx, provided that the module that registers the class is also the module that creates the window. The class name can also be any of the predefined system class names.
it seems there is a known issue regarding the null terminated string represented clas name to the CreateWindowEx function, so we SHOULD use the ATOM variant of the CreateWindowEx function. So we will revise the RegisterClassEx and the CreatWindowEx call as such.
UInt16 regRest = WinAPI.RegisterClassEx2(ref wndClass);
and
IntPtr hwnd = WinAPI.CreateWindowEx2( 0, regRest, "The hello proram", WindowStyles.WS_OVERLAPPEDWINDOW, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, Win32_CW_Constant.CW_USEDEFAULT, IntPtr.Zero, IntPtr.Zero, hInstance, IntPtr.Zero);
So, as you can see the result of the RegisterClassEx call - the ATOM value is passed to the CreateWindowEx2 function..
In order to support this kind of call, we have to declare variant of the RegisterClassEx or CreateWindowEx as such.
// To use CreateWindow, just pass 0 as the first argument. [DllImport("user32.dll", SetLastError = true, EntryPoint="CreateWindowEx")] public static extern IntPtr CreateWindowEx( WindowStylesEx dwExStyle, string lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); // Create a window, but accept a atom value. [DllImport("user32.dll", SetLastError = true, EntryPoint="CreateWindowEx")] public static extern IntPtr CreateWindowEx2( WindowStylesEx dwExStyle, UInt16 lpClassName, string lpWindowName, WindowStyles dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
so we have import the CreateWindowEx method which accepts a String class name just as the CreateWndowEx, and the method which takes ATOM value as the class name and rename it to CreateWindowEx2..
and because return type denote a ATOM value, you may have the following RegisterClassEx calls .
[DllImport("user32.dll")] //public static extern short RegisterClassEx([In] ref WNDCLASS lpwcx); public static extern short RegisterClassEx([In] ref WNDCLASSEX lpwcx); [DllImport("user32.dll", SetLastError = true, EntryPoint = "RegisterClassEx")] public static extern UInt16 RegisterClassEx2([In] ref WNDCLASSEX lpwcx);
An ATOM value is a UInt16 idenfier. The RegisterClassEx2 function has given a different name RegisterClassEx2.
References:
Problems with p/Invoke CreateWindowEx() and RegisterEx()
相关推荐
本教程将深入探讨如何利用C#的PInvoke特性来显示系统自带动画资源。 首先,理解PInvoke的概念至关重要。PInvoke是.NET Framework提供的一种机制,允许C#代码调用非托管(即C/C++编写的)动态链接库(DLL)中的函数...
2. **PInvoke 技术**:由于 FFmpeg 主要是用 C/C++ 编写的,为了在 C# 中使用,开发者可能利用 PInvoke(Platform Invoke)技术,通过DllImport特性导入 FFmpeg 的动态链接库(DLL),使得 C# 能够调用 C/C++ 的函数...
c 使用 ...Vanara.PInvoke.Kernel32: https://github.com/dahall/Vanara SharpGIS.NmeaParser: https://github.com/dotMorten/NmeaParser NAudio: https://github.com/naudio/NAudio GuerrillaNtp
标题中的“使用Signature Tool自动生成PInvoke调用Windows API的C#函数声明”是指一种高效的方法,用于在C#中调用Windows API函数。PInvoke(Platform Invoke)是.NET框架提供的一种机制,允许托管代码(如C#)直接...
"Interop Without PInvoke - Consuming Native Libraries in C#.-StaticLib" 主题探讨了一种替代方法,即如何在不使用P/Invoke的情况下,在C#中消费静态链接库(StaticLib)。 首先,理解C#中的互操作性(Interop)...
"Interop Without PInvoke - Consuming Native Libraries in C#.-DynamicLib"探讨了一种替代方法,即使用C#的动态编程功能来消费本地库,以实现更简洁且灵活的交互。 C#中的`System.Runtime.InteropServices....
标题 "PInvoke Interop Assistant.rar" 暗示了这是一个关于C#与C++之间互操作(Interop)的工具包,特别关注P/Invoke技术。P/Invoke是.NET框架提供的一种机制,允许托管代码(C#)调用非托管代码(通常为C或C++编写...
目前知道的情况被调用的C/C++函数只能是...PInvoke assistant工具可以辅助生成C#和VB的引入声明,还可以查看常见的常量枚举 能否调用重载的c++函数导出还没有试验,目前找到的信息看还是不行 字符串只支持C里的char* w_
标题中的“PInvoke.net官方提供的VS API插件”是指一个专为Visual Studio(VS)设计的插件,它由PInvoke.net网站开发并提供。PInvoke.net是一个知名的资源库,致力于收集、整理和分享有关在.NET Framework中进行平台...
PInvoke插件 RedGate.PInvokeExtension VS平台调用插件 PInvoke 平台调用 调用C++ 调用系统 C#调C++, Search Module: Directory Constants Delegates Enums Interfaces Structures Desktop ...
这个压缩包文件“自动生成PInvoke调用Windows API的C#函数声明.rar”提供了一个工具,帮助开发者自动创建必要的PInvoke声明,使得C#能够与Windows API进行交互。PInvoke(Platform Invoke)是.NET框架提供的一种机制...
Audio Compression Manager pInvoke for C#.NET Function: acmStreamOpen..... Structure: WAVEFORMATEX....
RedGate官方提供的PInvoke Visual Studio Add-in免费插件,只支持vs2003和vs2005,实际上组件也是支持vs2008的,所以我修改了AddIn文件,增加了一个注册表导入文件,方便大家使用。安装源程序,用附件中的...
该包装器使用“ PInvoke”(例如peek / poke)来“托管”从托管代码到非托管代码的调用。 听起来很复杂,确实如此。 它也是完全不必要的。 为什么不将DLL作为托管代码? 为什么不简单地在项目中引用该库并仅调用其...
.NET PInvoke逆向调用是.NET Framework提供的一种技术,它允许托管代码(如C#编写的程序)调用非托管代码,通常是操作系统提供的系统API函数。这种技术在处理与硬件交互、利用底层操作系统功能或者使用旧版库时非常...
- Pinvoke.net: 一个关于P/Invoke签名的在线数据库,可以快速查找和学习API函数的C#实现。 - CodeProject: 包含许多C#与Windows API交互的实例项目和技术文章。 总结,C#查找窗口句柄是通过调用Windows API实现的,...
Microsoft 推出的 P/Invoke Interop Assistant#C/C++ API 转 C# 工具 找资源不易,限定5个积分
edit and add PInvoke* signatures, user-defined types, and any other information related to calling Win32 and other unmanaged APIs from managed code (written in languages such as C# or VB.NET). ...