Call method if declared only

Simen Kjærås simen.kjaras at gmail.com
Fri Feb 28 12:21:41 UTC 2020


On Friday, 28 February 2020 at 10:33:11 UTC, Виталий Фадеев wrote:
> Thanks all !
> I happy !
> Check this one:
>     void On( T, M )( T o, M message )
>     {
[snip]
>     void main()
>     {
>         auto a = new A();
>         a.Send( a, WM_KEYUP );
>         a.Send( a, WM_KEYDOWN );
>     }

That does mostly work, but fails for this code:

void main()
{
     Base a = new A();
     a.send( a, WM_KEYUP );
}

Basically, whenever you assign a derived to a base, this solution 
doesn't work, because T will be Base, not A.

I enjoyed with the previous code, so I wrote the code necessary 
to handle any WM_ message:

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

template startsWith(string prefix) {
     enum startsWith(string s) = s.length >= prefix.length && 
s[0..prefix.length] == prefix;
}

enum getMessageValue(string s) = __traits(getMember, 
core.sys.windows.winuser, s);

// Get the all the WM_ messages
alias messageNames = Filter!(startsWith!"WM_", 
__traits(allMembers, core.sys.windows.winuser));
alias messageValues = NoDuplicates!(staticMap!(getMessageValue, 
messageNames));

class Base {
     LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
         switch (message) {
             foreach (msg; messageValues) {
                 case msg:
                     if (auto that = 
cast(IMessageHandler!msg)this) {
                         return that.handle(wParam, lParam);
                     }
                     break;
             }
             default:
         }
         return 0;
     }
}

interface IMessageHandler(alias msg) {
     mixin("LRESULT On"~__traits(identifier, msg)~"(WPARAM wParam, 
LPARAM lParam);");
     alias handle = mixin("On"~__traits(identifier, msg));
}

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

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

     writeln("Base:");
     // None of these will print anything, as Base doesn't handle 
them
     b1.On(WM_KEYDOWN, 0, 0);
     b1.On(WM_SETTINGCHANGE, 0, 0);
     b1.On(WM_DRAWITEM, 0, 0);
     writeln("Button:");
     b2.On(WM_KEYDOWN, 0, 0);
     b2.On(WM_SETTINGCHANGE, 0, 0);
     // This will print nothing, as Button doesn't handle that 
message.
     b2.On(WM_DRAWITEM, 0, 0);
}

--
   Simen


More information about the Digitalmars-d-learn mailing list