首先把要请教的问题写在最顶部:
1。事件最好的包装方法是怎样的?怎样才能扩展它?可不可以给一个可运行的Minimal例程?
2。如何向WNDCLASS 的回调传递另一个类的成员方法,当然签名是相同的。直接传递是不行的,因delegate 和function不可隐式转换。
诚意请教,请赐教,谢谢!
dmd2031+windows xp sp3 +bud
compile:
bud -O -release -gui -cleanup winwrapapp.d
想着自己也能写一个GUI框架那多好啊,最起码也能学多一点东西,今天小试了一下用类封装Win32 编程,很明显事件部分是一大难点;另外D2的string 在与Win32 API 交互时的转换也很费事。做做笔记先。以下代码编译通过,可正常运行,但事件部分实在谈不上类封装。
注:1.为了支持中文,用了Win32 的Unicode API.
2.Event类和Form类引用的Windows API 头文件来自D2 自带的std.c.windows.windows模块,如果改用win32包(
http://www.dsource.org/projects/bindings/wiki/WindowsApi)的话则方便许多,因更全面,所以不用那么多的extern(Windows)...
主程序:
module winwrapApp;
import samsTools.form;
int main(string[] args)
{
auto app=new Form("我的第一个WIN32 CLASS WRAPPER 窗口");
return app.show;
}
Event类:
module samsTools.event;
//import win32.windows;
import std.c.windows.windows;
extern(Windows) int MessageBoxW(HWND,in wchar*,in wchar*,int);
class Event
{
public:
this()
{
//to-do
}
//just a beginning test...
//Oops!!!if wndProc is a non-static method,can not pass it to
//Form.WNDCLASS.lpfnWndProc directly!!!
extern(Windows)
static int wndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch(msg)
{
case WM_CREATE:
//ti = new TrayIcon (hwnd,
//TI_MYTRAYICON,LoadIconA(null, IDI_APPLICATION),"TrayIcon!");
//ti.show();
break;
case WM_LBUTTONDOWN:
MessageBoxW(null,"左键被按下\nLeft button clicked!", "事件发生了",
MB_ICONINFORMATION);
break;
/*
case WM_RESIZE:
showMessage("Windows 被更改了大小","事件通知");
break;
*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
private:
enum EventType
{
Unknown=-1
//to-do
}
}
Form类:
module samsTools.form;
import samsTools.event;
//import win32.windows;
import std.c.windows.windows;
extern(Windows) HWND GetModuleHandleW(HWND);
extern(Windows) int MessageBoxW(HWND,in wchar*,in wchar*,int);
extern(Windows) HWND CreateWindowExW(
int,const(wchar*),const (wchar*),int,int,int,int,int,HWND,HWND,HWND,void*);
extern(Windows) bool GetMessageW(LPMSG,HWND,int,int);
class Form
{
public:
this(const wstring title="Windows Template")
{
this._title=title;
appInstance=GetModuleHandleW(null);
//event=new Event;
}
int show()
{
if(! initApiClass)
return 1;
if(! initWidget)
return 2;
return loop;
}
HINSTANCE handle()
{
return appInstance;
}
const wstring title()
{
return _title;
}
private:
HINSTANCE appInstance;
HWND appWnd;
WNDCLASS wc;
MSG msg;
const wstring _title;
//Event event;
bool initApiClass()
{
wc.lpszClassName = "winapi class";
wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &Event.wndProc;
wc.hInstance = appInstance;
wc.hIcon = LoadIconA(null, IDI_APPLICATION);
wc.hCursor = LoadCursorA(null, IDC_ARROW);
wc.hbrBackground = cast(HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = null;
wc.cbClsExtra = wc.cbWndExtra = 0;
if(!RegisterClassA(&wc))
{
MessageBoxW(null, "Window registration failure.", null, MB_ICONERROR);
return false;
}
return true;
}
bool initWidget()
{
appWnd = CreateWindowExW(0, "winapi class",
_title.ptr, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 300, 300, null, null, appInstance, null);
if(appWnd is null)
{
MessageBoxW(null, "Window creation failure.", null, MB_ICONERROR);
return false;
}
return true;
}
int loop()
{
while(GetMessageW(&msg, null, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
return cast(int)msg.wParam;
}
}