【问题标题】:Cannot convert from 'LRESULT (__clrcall....) to 'WNDPROC'无法从 'LRESULT (__clrcall....) 转换为 'WNDPROC'
【发布时间】:2012-12-12 17:28:30
【问题描述】:

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

};
}

【问题讨论】:

  • 试试w.lpfnWndProc = (WNDPROC) WindowProc;
  • @BartekBanachewicz 这可能行不通。它将消除编译器错误,但您可能会遇到运行时错误。
  • 试试w.lpfnWndProc = &Win32Demo::WindowProc;
  • OMG:2020 年有人对此投了赞成票 :-),顺便说一句。

标签: visual-c++ c++-cli


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    显然,托管类的方法不支持 __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

    【讨论】:

      猜你喜欢
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 2019-07-13
      相关资源
      最近更新 更多