Class methods in D?
Mehrdad
wfunction at hotmail.com
Fri May 4 07:31:19 PDT 2012
Oooooh okay, I see. Let me try it. :)
@Everyone: Haha thanks for pointing me to the existing libraries.
:) I'm doing this more for learning than anything else, so I'm
trying to solve these problems myself instead of just using
another library.
And it seems to be going well:
class Window
{
private static shared tstring classNames[TypeInfo];
shared static this() { EnableVisualStyles();
RegisterClass(typeid(typeof(this))); }
public static Window fromHandle(HWND hWnd) { assert(0,
"fromHandle() not implemented"); }
private static extern(Windows) LRESULT StaticWndProc(HWND hWnd,
UINT uMsg, WPARAM wParam, LPARAM lParam)
{
enum tstring WINDOW_INSTANCE_PROP = "WINDOW_INSTANCE";
if (uMsg == WM_NCCREATE || uMsg == WM_CREATE)
{
auto this_ =
cast(typeof(this))(cast(LPCREATESTRUCT)lParam).lpCreateParams;
this_._hWnd = hWnd;
BOOL success = SetProp(hWnd, WINDOW_INSTANCE_PROP,
cast(void*)this_);
assert(success, "Could not set window instance information.");
}
return (cast(typeof(this))cast(void*)GetProp(hWnd,
WINDOW_INSTANCE_PROP)).WndProc(uMsg, wParam, lParam);
}
protected static void RegisterClass(
TypeInfo_Class type, tstring className = null, bool
existingWin32Class = false, UINT style = 0, HICON hIcon = null,
HCURSOR hCursor = LoadCursor(null, IDC_ARROW), HBRUSH
hBrBackground = GetSysColorBrush(COLOR_3DFACE),
HICON hIconSm = null, tstring menuName = null, int cbClsExtra =
0, int cbWndExtra = 0, HINSTANCE hInstance = null)
in { assert(type !in classNames); }
body
{
if (className == null) { className = "WINDOW_CLASS_" ~
to!tstring(type.name); }
if (!existingWin32Class)
{
WNDCLASSEX wndClassEx;
wndClassEx = typeof(wndClassEx)(wndClassEx.sizeof, style,
&StaticWndProc, cbClsExtra, cbWndExtra, hInstance, hIcon,
hCursor, hBrBackground, menuName.toSZ(), className.toSZ(),
hIconSm);
ATOM atom = RegisterClassEx(&wndClassEx);
assert(atom != 0, "Unable to RegisterClass window class.");
}
synchronized(typeid(typeof(this))) { classNames[type] =
className.idup; }
}
public static void EnableVisualStyles()
{
tchar[MAX_PATH] dir;
dir[GetSystemDirectory(dir.ptr, dir.length)] = '\0';
enum ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID = 0x00000004,
ACTCTX_FLAG_RESOURCE_NAME_VALID = 0x00000008,
ACTCTX_FLAG_SET_PROCESS_DEFAULT = 0x00000010;
auto actCtx = ACTCTX(
ACTCTX.sizeof, ACTCTX_FLAG_RESOURCE_NAME_VALID |
ACTCTX_FLAG_SET_PROCESS_DEFAULT |
ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID,
"shell32.dll", PROCESSOR_ARCHITECTURE_INTEL, 0, dir.ptr,
MAKEINTRESOURCE(124), null, null);
auto hActCtx = CreateActCtx(actCtx);
assert(hActCtx != INVALID_HANDLE_VALUE);
ULONG_PTR ulpActivationCookie;
BOOL success = ActivateActCtx(hActCtx, ulpActivationCookie);
assert(success);
}
private HWND _hWnd;
public @property auto hWnd() const { assert(this.isWindow,
"Invalid window handle."); return cast(HWND)this._hWnd; }
public @property auto hWnd(typeof(this._hWnd) value) {
assert(this._hWnd == null, "Cannot overwrite valid window
handle."); this._hWnd = value; }
public @property auto isWindow() const { return
.IsWindow(cast(HWND)this._hWnd); }
public this() { }
public void CreateWindow(scope tstring windowName = null, Window
parent = null, DWORD style = WS_OVERLAPPEDWINDOW,
DWORD exStyle = 0, int x = CW_USEDEFAULT, int y =
CW_USEDEFAULT, int width = CW_USEDEFAULT,
int height = CW_USEDEFAULT, HMENU hMenu = null, HINSTANCE
hInstance = null)
{
this.hWnd = .CreateWindowEx(exStyle, this.className.toSZ(),
windowName.toSZ(), style, x, y, width, height, parent is null ?
null : parent.hWnd, hMenu, hInstance, cast(void*)this);
assert(this.hWnd != null);
}
private final @property tstring className() {
synchronized(typeid(typeof(this))) { return
classNames[typeid(this)]; } }
protected LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM
lParam)
{
return .DefWindowProc(this.hWnd, uMsg, wParam, lParam);
}
public ~this() { }
public auto GetFont(HFONT hFont)
{ return this.SendMessage(WM_GETFONT); }
public auto SetFont(HFONT hFont, bool redraw = true)
{ return this.SendMessage(WM_SETFONT, cast(WPARAM)hFont, redraw
? 1 : 0); }
template opDispatch(string name)
{
public auto opDispatch(T...)(scope T args)
{ return mixin(q{.} ~ name ~ q{(this.hWnd, args)}); }
}
}
mixin template Win32WindowT(string wrapperClassName, string
win32ClassName)
{
mixin(Format!(
q{
class %s : Window
{
shared static this() { RegisterClass(typeid(typeof(this)),
"%s", true); }
}
}, wrapperClassName, win32ClassName));
}
mixin Win32WindowT!(q{Button}, "Button");
On Friday, 4 May 2012 at 12:27:41 UTC, Steven Schveighoffer wrote:
> On Fri, 04 May 2012 01:13:07 -0400, Mehrdad
> <wfunction at hotmail.com> wrote:
>
>> Hmm... how exactly do you use RTInfo? (Is it usable yet? All I
>> see is a void* and a dummy template.)
>
> You have to fill in object.di's RTInfo(T) to be whatever you
> want. As I said, it's very beta, intended as a hook to use for
> more precise garbage collection, or any other runtime info
> goodies you want to put in there. See my example for a hint.
>
> Essentially, the compiler's going to do this:
>
> class C {...}
>
> // compiler: hmmm... have to generate TypeInfo_Class for C.
> Let me set up all the normal hooks
>
> TypeInfo_Class CTypeInfo;
> CTypeInfo.name = "C";
> ...
>
> // compiler: ok, now let me generate the RTInfo part
> CTypeInfo.m_rtInfo = RTInfo!C;
>
> Now, you can call typeid(instanceOfC).rtInfo and it will give
> you the data that comes from RTInfo!C. And you don't have to
> know the type of instanceOfC, it could be Object. It's
> essentially a way to convert compile-time data into runtime
> data.
>
> -Steve
More information about the Digitalmars-d
mailing list