我尝试在VS 2010中创建托管C ++程序集以与WinAPI连接,并在我的其他C#程序集中使用它。我已阅读所有帖子,甚至在GitHub中的代码中搜索,但没有成功。 也许是关于错误信息中的__clrcall,不应该是__stdcall吗?有什么想法吗?
确切的错误消息是:
错误C2440:'=':无法将'LRESULT(__ clrcall xxx :: Win32Demo :: *)(HWND,UINT,WPARAM,LPARAM)'转换为'WNDPROC'
源代码:
#pragma once
using namespace System;
using namespace System::Drawing;
#include "stdafx.h"
#include "windows.h"
namespace xxx
{
ref class Win32Demo
{
private: HWND__ * handle;
private: static Char * windowClass;
public:
Win32Demo(void)
{
}
static Win32Demo()
{
tagWNDCLASSEXW w;
windowClass = (wchar_t*) L"Hello";
w.cbSize = sizeof(tagWNDCLASSEXW);
w.style = 0x803;
w.lpfnWndProc = WindowProc; // Error
w.cbClsExtra = 0;
w.cbWndExtra = 0;
w.hInstance = 0;
w.hIcon = 0;
w.hCursor = 0;
w.hbrBackground = CreateSolidBrush(0);
w.lpszMenuName = NULL;
w.lpszClassName = windowClass;
w.hIconSm = 0;
}
public :
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
return 0;
}
};
}
答案 0 :(得分:1)
这是错误的,因为您的WndProc()函数正在编译为IL,而不是机器代码。发生这种情况是因为你使用/ clr编译它有效。它不仅仅是编译时错误,它也无法在运行时运行。 Windows不知道如何调用托管方法,而不是没有从Marshal :: GetFunctionPointerForDelegate()获得的帮助。
最好不去那里。将此代码移动到您在没有/ clr选项的情况下编译的单独.cpp文件中。或者在此代码之前使用#pragma managed(push, off)
,以便将其编译为机器代码而不是IL。
并考虑托管类包装器,它们为您提供相同类型的功能。与System.Windows.Forms命名空间中的类一样。或者,如果你想保留这段代码,那么从NativeWindow类派生你自己的类来附加窗口句柄,允许你用托管代码覆盖WndProc()。
答案 1 :(得分:0)
显然,托管类的方法不支持__stdcall调用约定。因此,您需要将WindowProc放在非托管类中:
class WindowProcCallback
{
public:
static LRESULT __stdcall WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
...
}
};
ref class Win32Demo
{
...
};
一个建议:打开警告,以便收到有关此类内容的警告。有了警告,您就会收到以下警告:
warning C4441: calling convention of '__stdcall ' ignored; '__clrcall ' used instead