附文
附文
委托代码生成器
刘强
2004年4月2日
为了解决在定制委托时的不灵活性,我特意编写了这个小工具,它能够方便地将委托声明转化为如上面所述的代码。下面是其基本用法。
在你的某个头文件中,如test.h,以__delegate
关键字声明一个委托:
__delegate void WinHandler ( HWND
hwnd ,UINT message ,WPARAM wParam,LPARAM lParam);
然后转到命令行模式,进入test.h的目录,键如如下命令:
delegate.exe test.h /out test.hxx
它将生成test.hxx文件。你可以向你的源程序中包含这个文件,以使用你所定义的委托。如,可以是这样:#include
“test.hxx”
你可以在一个文件里定义多个委托,也可以在多个文件里定义多个委托.但是你只能指定一个的输出文件.如果你没有用/out
选项指定输出文件,则默认输出为delegate.h。如:
delegate.exe test.h test1.h
test2.h /out test.hxx
使用/help选项得到帮助信息,使用/version选项得到版本信息.
在由委托生成的代码当中,Add/RemoveFunction接受的参数类型默认为'void*',这样不利于编译器为我们做函数匹配检查.
/ptm选项强制参数类型为我们定义的委托类型.
使用delegate.exe/help可以查到详细信息:
Delegate generator version 1.1.0
Copyright
Cambest(Tcliuqiang,Liuqiang,Lewis Liu).
2004--3--31, All rights reserved.
/out </o>[output file] Specify the
output file.
/ptm Force the Add/RemoveFunction
parameter type match. Default is 'void *'.
/keyword Specify the keyword.
Default is '__delegate'.
/include Remove delegate
declaration from source file,and include the generated file to your source file.
/help </h /?> Print this
messages.
/version </v> Print version of
delegate.exe
Please feedback bugs to
下面是具体的示例:
[示例1]
//test.h:
#include <string>
#include <list>
using namespace std;
enum STATUS
{
FINDING,
FOUND,
PROCESS
};
__delegate void HandleWnd(HWND
hwnd,DWORD lParam,WROD wParam,UINT type);
enum TYPE
{
NORMAL,
SEPARATOR
};
__delegate void WINAPI CALLBACK
WinProc(HWND hwnd,DWORD lParam);
bool IsSeparator(char ch);
void Process(string t);
void Parse(istream in,ostream out);
//test1.h:
#define WINAPI 0
/*下面是委托定义*/
__delegate void WinHandler ( HWND hwnd ,UINT
message ,WPARAM wParam,LPARAM lParam);
/*不要在定义之中注释*/
下面是由delegate.exetest.htest1.h/outtest.hxx生成的代码:
//test.hxx
#include <list>
using namespace std;
/*
Generated by delegate.exe.
Please don't modify this file.
If you encountered any
problems,please feedback to cambest@sohu.com.
*/
typedef unsigned int __NativePtr;
typedef void (* __Handle_WinHandler)(HWND
hwnd,UINT message,WPARAM wParam,LPARAM lParam);
class WinHandler
{
private:
list<__NativePtr> ftns;
public:
void AddFunction(void *)
{
__NativePtr np=(__NativePtr)ftn;
ftns.push_back(np);
}
void RemoveFunction(void *ftn)
{
__NativePtr np=(__NativePtr)ftn;
ftns.remove(np);
}
void operator += (void *ftn)
{
this->AddFunction(ftn);
}
void operator -= (void *ftn)
{
this->RemoveFunction(ftn);
}
int Invoke(HWND hwnd,UINT
message,WPARAM wParam,LPARAM lParam)
{
__Handle_WinHandler
handle;
list<__NativePtr>::iterator
itr=ftns.begin();
try
{
for(;itr!=ftns.end();itr++)
{
handle=(__Handle_WinHandler)*itr;
handle(hwnd,message,wParam,lParam);
}
}
catch(int *_e)
{
return 0;
}
return 1;
}
int operator() (HWND hwnd,UINT
message,WPARAM wParam,LPARAM lParam)
{
return
Invoke(hwnd,message,wParam,lParam);
}
};
/*
Generated by delegate.exe.
Please don't modify this file.
If you encountered any
problems,please feedback to cambest@sohu.com.
*/
typedef void (* __Handle_HandleWnd)(HWND
hwnd,DWORD lParam,WROD wParam,UINT type);
class HandleWnd
{
private:
list<__NativePtr> ftns;
public:
void AddFunction(void *)
{
__NativePtr np=(__NativePtr)ftn;
ftns.push_back(np);
}
void RemoveFunction(void *ftn)
{
__NativePtr np=(__NativePtr)ftn;
ftns.remove(np);
}
void operator += (void *ftn)
{
this->AddFunction(ftn);
}
void operator -= (void *ftn)
{
this->RemoveFunction(ftn);
}
int Invoke(HWND hwnd,DWORD
lParam,WROD wParam,UINT type)
{
__Handle_HandleWnd handle;
list<__NativePtr>::iterator
itr=ftns.begin();
try
{
for(;itr!=ftns.end();itr++)
{
handle=(__Handle_HandleWnd)*itr;
handle(hwnd,lParam,wParam,type);
}
}
catch(int *_e)
{
return 0;
}
return 1;
}
int operator() (HWND hwnd,DWORD
lParam,WROD wParam,UINT type)
{
return
Invoke(hwnd,lParam,wParam,type);
}
};
/*
Generated by delegate.exe.
Please don't modify this file.
If you encountered any
problems,please feedback to cambest@sohu.com.
*/
typedef void WINAPI CALLBACK (* __Handle_WinProc)(HWND
hwnd,DWORD lParam);
class WinProc
{
private:
list<__NativePtr> ftns;
public:
void AddFunction(void *)
{
__NativePtr np=(__NativePtr)ftn;
ftns.push_back(np);
}
void RemoveFunction(void *ftn)
{
__NativePtr np=(__NativePtr)ftn;
ftns.remove(np);
}
void operator += (void *ftn)
{
this->AddFunction(ftn);
}
void operator -= (void *ftn)
{
this->RemoveFunction(ftn);
}
int Invoke(HWND hwnd,DWORD lParam)
{
__Handle_WinProc handle;
list<__NativePtr>::iterator
itr=ftns.begin();
try
{
for(;itr!=ftns.end();itr++)
{
handle=(__Handle_WinProc)*itr;
handle(hwnd,lParam);
}
}
catch(int *_e)
{
return 0;
}
return 1;
}
int operator() (HWND hwnd,DWORD
lParam)
{
return Invoke(hwnd,lParam);
}
};
注意:最新的Visual
C++ .Net 版本已经支持同名关键字
__delegate,这是微软公司为了将Visual
C++向.net移植而添加的新关键字,只有Visual
C++ .Net 支持,其他如Visual
C++ 6.0、Borland
C++ Builder 、GNU
C++ 等都不支持。但两个完全没有联系.幸运的是,delegate小工具支持/keyword
选项,它可以指定你自己定义的关键字,如__delegate__。这样,delegate工具可以在你的源代码中查找以__delegate__开头的委托定义,而不是默认的__delegate。
另外一点就是/include选项可以将你的源代码中的委托声明删除,并相应的在其中添加包含输出文件的语句。如,test1.h有这样的声明:
__delegate__ void
WinProcHandler(HWND hwnd, LPARAM lParam,WPARA wParam);
执行命令
delegate test1.h /ptm /include /out ptxx.h
则test1.h中的这条语句被置换成:
#include “ptxx.h”
这样做有可以使你做最少的维护.
[示例2]
//hello.cpp
#include <iostream>
using namespace std;
__delegate void SHO(char * s);
void Print(char *str)
{
cout<<"It is in Print :"<<str<<endl;
}
void Good(char *str)
{
cout<<"It is in Good ,say good to
you ::"<<str<<endl;
}
void main()
{
SHO s;
s+=Print;
s+=Good;
s("I am the best!");
}
//生成委托代码:delegate.exe
Hello.cpp /fpm /include /out SHO.h
#include <iostream>
using namespace std;
#include "SHO.h"
void Print(char *str)
{
cout<<"It is in Print :"<<str<<endl;
}
void Good(char *str)
{
cout<<"It is in Good ,say good to
you ::"<<str<<endl;
}
void main()
{
SHO s;
s+=Print;
s+=Good;
s("I am the best!");
s-=Print;
s(“jjj kkk lll ttt”);
}
编译:(这里使用Microsoft
C++编译器)
cl Hello.cpp /EHsc
由于delegate生成的代码包含异常处理,所以在编译hello.cpp时你需要指定/EHsc选项,否则会给出警告信息,但不妨碍编译成功.
输出:
It is in Print :I am the best!
It is in
Good ,say good to you ::I am the best!
It is in
Good ,say good to you ::jjj kkk lll ttt
你可以打开SHO.H文件看看里面是怎样定义的.
由于只是测试版本,这个小工具的功能还不是很强。比如,你不能在委托声明语句中间有注释,而只能在声明前或声明之后添加注释。另外由于时间关系,我在处理委托返回值没有做到很好的处理。我希望这个问题很快会解决。有什么意见和建议,请将之反馈到我的邮箱:cambest@sohu.com.