On Friday, 28 February 2020 at 09:12:38 UTC, Simen Kjærås wrote:
On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев wrote:
Searching solution for idea !

For whatever reason, it seems my attempts at answering this earlier has disappeared into the void. Here:

import core.sys.windows.windows;
import std.stdio;

class Base {
    LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message) {
            case WM_KEYDOWN:
                return tryCall!"OnWM_KEYDOWN"(wParam, lParam);
            default:
        }
        return 0;
    }

    auto tryCall(string name, Args...)(Args args) {
        import std.meta;

        alias This = typeof(this);
        alias module_ = __traits(parent, This);

        enum isSubclass(T...) = is(T[0] : This);
alias getModuleMember(string name) = __traits(getMember, module_, name);
        enum hasMethod(T) = __traits(hasMember, T, name);

        // Get every member in this module
        enum memberNames = __traits(allMembers, module_);
alias members = staticMap!(getModuleMember, memberNames);

        // Filter away anything that isn't derived from Base
        alias subclasses = Filter!(isSubclass, members);

// Get rid of anything that doesn't have a method with the correct name alias subclassesWithMethod = Filter!(hasMethod, subclasses);

        // Sort them so you get the most derived types first
        alias Types = DerivedToFront!subclassesWithMethod;

// Check for each type if the `this` is an instance of that specific one
        static foreach (T; Types) {
            if (cast(T)this !is null) {
                // And look up that method and call it.
return __traits(getMember, cast(T)this, name)(args);
            }
        }

// If `this` is not one of the types with that method, return some default value
        return 0;
    }
}

class Button : Base {
    LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) {
        writeln("WM_KEYDOWN");
        return 0;
    }
}

unittest {
    Base b1 = new Base();
    Base b2 = new Button();

    writeln("Base:");
    b1.On(WM_KEYDOWN, 0, 0);
    writeln("Button:");
    b2.On(WM_KEYDOWN, 0, 0);
}

Now, this only works for subclasses defined in the same module. A possibly better solution would be interfaces:

import core.sys.windows.windows;
import std.stdio;

class Base {
    LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
        switch (message) {
            case WM_KEYDOWN:
                if (cast(IKeyDown)this) {
return (cast(IKeyDown)this).OnWM_KEYDOWN(wParam, lParam);
                }
            default:
        }
        return 0;
    }
}

interface IKeyDown {
    LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam);
}

class Button : Base, IKeyDown {
    LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) {
        writeln("WM_KEYDOWN");
        return 0;
    }
}

unittest {
    Base b1 = new Base();
    Base b2 = new Button();

    writeln("Base:");
    b1.On(WM_KEYDOWN, 0, 0);
    writeln("Button:");
    b2.On(WM_KEYDOWN, 0, 0);
}

--
  Simen

Yes. Thank !
I read it.
Problem is - OS has many messages + user messages... It mean what interfaces like IKeyDown must me declared. All. Dream on write less code...

Some like code generation. In message dispatcher. Like this:

    import core.sys.windows.windows;
    import std.stdio;
    import std.traits;


    template canOn( T, M )
    {
enum string callbackName = "On" ~ __traits( identifier, M );

        static if ( __traits( hasMember, T, callbackName ) )
enum canOn = isCallable!( __traits( getMember, T, callbackName ) );
        else
            enum canOn = false;
    }

    void maybeOn( T, alias M )( T o, M message )
    {
enum string callbackName = "On" ~ __traits( identifier, M );

        static if ( canOn!(T, M) )
            __traits( getMember, T, callbackName )();
    }


    void On( T, alias M )( T o, M message )
    {
        o.maybeOn( message );
    }


    class Base
    {
        void Send( T, alias M )( T o, M message )
        {
            // generate code in dispatcher
            // if ( canOn!( T, M ) )
            //   writeCode(
            //     q{
            //        if ( message == WM_KEYUP )
            //           o.OnWM_KEYUP();
            //      }
            //   );
            o.On( message );
        }
    }

    class A : Base
    {
        void OnWM_KEYUP()
        {
            writeln( "A.OnKey()" );
        }
    }


    void main()
    {
        auto a = new A();
        a.Send( a, WM_KEYUP );
    }


Here I have compile error... at
    void On( T, alias M )( T o, M message )

Now I reading Template doc for up skill...

Thank!
  • Call method if declare... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Simen Kjærås via Digitalmars-d-learn
      • Re: Call meth... Виталий Фадеев via Digitalmars-d-learn
        • Re: Call ... drug via Digitalmars-d-learn
        • Re: Call ... Simen Kjærås via Digitalmars-d-learn
          • Re: C... Виталий Фадеев via Digitalmars-d-learn
            • ... Виталий Фадеев via Digitalmars-d-learn
              • ... Виталий Фадеев via Digitalmars-d-learn
                • ... Simen Kjærås via Digitalmars-d-learn
                • ... Виталий Фадеев via Digitalmars-d-learn
    • Re: Call method i... Alexandru Ermicioi via Digitalmars-d-learn

Reply via email to