3

我尝试在 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;
}

};
}
4

2 回答 2

2

这会出错,因为您的 WndProc() 函数正在编译为 IL,而不是机器代码。发生这种情况是因为您使用 /clr 编译它。这不仅仅是一个编译时错误,它也不能在运行时工作。Windows 不知道如何调用托管方法,除非您从 Marshal::GetFunctionPointerForDelegate() 获得帮助。

最好不要去那里。将此代码移动到一个单独的 .cpp 文件中,您可以在不使用 /clr 选项的情况下编译该文件。或#pragma managed(push, off)在此代码之前使用,以便将其编译为机器代码而不是 IL。

并考虑为您提供相同功能的托管类包装器。就像 System.Windows.Forms 命名空间中的类一样。或者,如果您想保留此代码,则从 NativeWindow 类派生您自己的类以附加窗口句柄,从而允许您使用托管代码覆盖 WndProc()。

于 2012-12-27T15:22:42.437 回答
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

于 2012-12-27T14:15:31.743 回答