3
votes

I try to create a managed C++ assembly in VS 2010 to interface with WinAPI and use it in my other C# assemblies. I've read all posts, even searched in code in GitHub, with no success. Maybe its about the __clrcall in the error message, should not it be __stdcall? Any ideas?

The exact error message is:

error C2440: '=' : cannot convert from 'LRESULT (__clrcall xxx::Win32Demo::* )(HWND,UINT,WPARAM,LPARAM)' to 'WNDPROC'

The source code:

#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;
}

};
}
2
Try w.lpfnWndProc = (WNDPROC) WindowProc; - Bartek Banachewicz
@BartekBanachewicz That probably won't work. It will remove the compiler error but you may get a runtime error. - user1610015
Try w.lpfnWndProc = &Win32Demo::WindowProc; - acraig5075
OMG: Someone in 2020 upvoted this :-), thx btw. - g.pickardou

2 Answers

2
votes

This goes wrong because your WndProc() function is being compiled to IL, not machine code. Which happened because you compile it with /clr in effect. It is not just a compile time error, it also cannot work at runtime. Windows doesn't know how to call a managed method, not without the kind of help you get from Marshal::GetFunctionPointerForDelegate().

It is better to just not go there. Either move this code in a separate .cpp file that you compile without the /clr option. Or use #pragma managed(push, off) before this code so that it gets compiled to machine code instead of IL.

And consider the managed class wrappers that give you the same kind of functionality. Like the classes in the System.Windows.Forms namespace. Or if you want to keep this code then derive your own class from the NativeWindow class to attach the window handle, allowing you to override WndProc() with managed code.

0
votes

Apparently the __stdcall calling convention is not supported for methods of managed classes. So you'll need to put WindowProc inside an unmanaged class:

class WindowProcCallback
{
public:
    static LRESULT __stdcall WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        ...
    }
};

ref class Win32Demo
{
    ...
};

One suggestion: turn on warnings so that you get warnings about stuff like this. With warnings you would have gotten the following warning:

warning C4441: calling convention of '__stdcall ' ignored; '__clrcall ' used instead