Thread overview
How to register class member function as lpfnWndProc? Cannot convert delegate to function
Sep 28, 2012
deed
Sep 28, 2012
Jesse Phillips
Sep 28, 2012
Maxim Fomin
Sep 28, 2012
Andrej Mitrovic
Sep 30, 2012
deed
September 28, 2012
Hi

I am trying to register a class member function as wc.lpfnWndProc, but get the error message "cannot implicitly convert expression (&this.WndProc) of type extern (Windows) int delegate(...) to extern (Windows) int function(...).

I have:

extern (Windows)
class App
{
    HRESULT initialize(HINSTANCE hInstance, int iCmdShow)
    {
        WNDCLASS wc;
        ...
        wc.lpfnWndProc = &wndProc;
        ...
    }

    HRESULT wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)
        {
            ...
        }
    }
    ...
}


(Defining wndProc as a global function works, but is not what I want to do...)
What is the issue here and how do I make it work?
September 28, 2012
On Friday, 28 September 2012 at 17:53:59 UTC, deed wrote:

> (Defining wndProc as a global function works, but is not what I want to do...)
> What is the issue here and how do I make it work?

You are interfacing with C, which does not support functions with state (delegate). You must pass it a function, and while you can get at the function pointer of a delegate this is unsafe.

You make it work by providing a function and not a delegate. I do not know how to wrap a delegate to make that work.
September 28, 2012
On Friday, 28 September 2012 at 17:53:59 UTC, deed wrote:
> Hi
>
> I am trying to register a class member function as wc.lpfnWndProc, but get the error message "cannot implicitly convert expression (&this.WndProc) of type extern (Windows) int delegate(...) to extern (Windows) int function(...).
>
> I have:
>
> extern (Windows)
> class App
> {
>     HRESULT initialize(HINSTANCE hInstance, int iCmdShow)
>     {
>         WNDCLASS wc;
>         ...
>         wc.lpfnWndProc = &wndProc;
>         ...
>     }
>
>     HRESULT wndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
>     {
>         switch (message)
>         {
>             ...
>         }
>     }
>     ...
> }
>
>
> (Defining wndProc as a global function works, but is not what I want to do...)
> What is the issue here and how do I make it work?

Because wndProc in your case cannot be converted to a delegate. You can make it a module-level function (there is no globals in D) or try to make it static function - I currently cannot check whether it works. In any way, what gives you making wndProc a class member function?
September 28, 2012
On 9/28/12, Maxim Fomin <maxim@maxim-fomin.ru> wrote:
> try to make it static function

If only one app is ever supposed to be instantiated you can use a static function and a static reference to the class instance: http://dpaste.dzfl.pl/b1497fa1

Otherwise you could use a hashmap to redirect wndProc's to class instances by using a HWND as the key and App as the value, something like:

App[HWND] apps;

extern (Windows)
LRESULT winDispatch(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    auto app = hwnd in apps;

    if (app !is null)
    {
        return app.wndProc(hwnd, message, wParam, lParam);
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

apps would be written to any time a new App instance is created.
Anyway there are multiple ways of doing this, it depends on what you need.
September 30, 2012
Thanks to all of you for your informative replies. I was testing different code structures and wondered whether this was possible.