WTL是什么? 这是从网上摘录的一段WTL作者的话:
//===================================
WTL是一个基于模板的、专为开发用户界面的程序库。它扩展了ATL,并提供了一些类用来实现应用程序的用户界面、组件和控件。它提供了各种类来支持各种各样的用户界面元素:顶级窗口、MDI、标准控件和通用控件、通用的对话框、属性表以及属性页、GDI对象、UI更新、可卷动的窗口、分割窗口、命令条等等……
WTL的实现使用了和ATL一样的模板架构,所以对于ATL开发者显得很自然。同时它并没有改变或者是隐藏那些Windows相关结构,那些Windows程序员在使用WTL时也不会感到很吃惊。WTL的一个主要设计原则就是避免在没有引用到其他WTL类时,出现不必要的内部依赖。这意味着我们的程序将只包含有我们实际上所使用的代码,除此之外再无其他的东西。加上了模板的使用后,这样做得到的结果就是一些非常小的,不依赖于运行库的程序。
WTL专注于用面向对象的方法来编写Windows的用户界面程序,同时保持代码的尺寸很小。同时,它也为开发者提供了一个很好的基础,可以写新的类来扩展WTL。
最后,我在编写WTL时就希望开发者能够喜欢在开发中使用它。我同样也希望您能够使用它并喜欢上它。
//===================================
最重要的一点,它是开源的.
原先WTL是专为VC写的,其它的C++编译器是无福享用的(因为它基于ATL,而ATL是有版权的,这点M$做得比较绝),好在Borland已经帮我们获得了ATL的使用权,网上又有高手对WTL做了For BCB的修改,使我们在用VCL的同时,又多了一个选择。
好,进入正题,
装备:
- rc资源编辑器 ResEdit http://www.resedit.net VeryGooooooood的一般人我不告诉他的rc资源编辑器。
- WTL for BCB bccSDK http://sourceforge.net/projects/bccsdk/ 这个就是传说中高手修改的Win SDK for BCB,有MSN,WMP,MS Speech SDK等, 其中就有我们要用到的ATL和WTL。
- BCB5.0 | BCB6.0 | BDS2006 | CB2007 如果不认识这个请跳过此文章,谢谢
准备工作:
设置BCB的Include路径为bccsdk/include/atl和bccsdk/include/wtl, 链接路径为bccsdk/lib。 很简单吧:)
对您的要求:
如果您能理解下面这段代码就没什么问题了,
代码1,模板类
int Fun( void * Data){
T * tData = static_cast < T *> (Data);
return tData -> Fun();
}
};
代码2,Win SDK & 消息 (下面的代码显示一个蓝色的窗体,上有一大问号)
LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
... {
switch(uMsg)
...{
case WM_PAINT:
...{
PAINTSTRUCT ps;
HDC dc=BeginPaint(hwnd,&ps);
RECT R;
GetClientRect(hwnd,&R);
HBRUSH bsBlue=CreateSolidBrush(RGB(0,0,255));
FillRect(dc,&R,bsBlue);
DeleteObject(bsBlue);
InflateRect(&R,-50,-50);
DrawFrameControl(dc,&R,DFC_CAPTION,DFCS_CAPTIONHELP);
EndPaint(hwnd,&ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd,uMsg,wParam,lParam);
}
}
BOOL InitApplication(HINSTANCE hinstance)
... {
WNDCLASSEX wcx;
// Fill in the window class structure with parameters
// that describe the main window.
wcx.cbSize = sizeof(wcx); // size of structure
wcx.style = CS_HREDRAW | CS_VREDRAW; // redraw if size changes
wcx.lpfnWndProc = MainWndProc; // points to window procedure
wcx.cbClsExtra = 0; // no extra class memory
wcx.cbWndExtra = 0; // no extra window memory
wcx.hInstance = hinstance; // handle of instance
wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION); // predefined app. icon
wcx.hCursor = LoadCursor(NULL, IDC_ARROW); // predefined arrow
wcx.hbrBackground = GetStockObject(WHITE_BRUSH); // white background brush
wcx.lpszMenuName = "MainMenu"; // name of menu resource
wcx.lpszClassName = "MainWClass"; // name of window class
wcx.hIconSm = NULL;
// Register the window class.
return RegisterClassEx(&wcx);
}
BOOL InitInstance(HINSTANCE hinstance, int nCmdShow)
... {
HWND hwnd = CreateWindow(
"MainWClass", // name of window class
"Sample", // title-bar string
WS_OVERLAPPEDWINDOW, // top-level window
CW_USEDEFAULT, // default horizontal position
CW_USEDEFAULT, // default vertical position
CW_USEDEFAULT, // default width
CW_USEDEFAULT, // default height
(HWND) NULL, // no owner window
(HMENU) NULL, // use class menu
hinstance, // handle of application instance
(LPVOID) NULL); // no window-creation data
if (!hwnd) return FALSE;
// Show the window and send a WM_PAINT message to the window
// procedure.
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
return TRUE;
}
WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
... {
MSG msg;
if (!InitApplication(hinstance)) return FALSE;
if (!InitInstance(hinstance, nCmdShow)) return FALSE;
while (GetMessage(&msg, (HWND) NULL, 0, 0))
...{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
看明白了吗?好,一切就绪,我们开始第一个WTL程序吧:
上面的SDK代码,主要的功能代码是WM_PAINT的消息处理,不过却用了更多的让人头昏脑涨的代码在窗体注册/显示之上,下面我们用WTL实现上面的功能:
在BCB里新建一工程,选Console Wizard, 选项如下:
//---------------------
Source Type: C++
Use VCL: No
Use CLX: No
Multi Threaded: No
Console Application: No
//---------------------
在Unit1.cpp里输入下面代码:
#include < atlapp.h >
CAppModule _Module;
#include < atlwin.h >
#include < atlframe.h >
#include < atlcrack.h >
#include < atlmisc.h >
class CMyWin : public CFrameWindowImpl < CMyWin > ... {
public:
DECLARE_FRAME_WND_CLASS_EX("MainWClass",0,CS_HREDRAW|CS_VREDRAW,COLOR_WINDOW);
BEGIN_MSG_MAP_EX(CMyWin)
MSG_WM_PAINT(OnPaint)
CHAIN_MSG_MAP(CFrameWindowImpl<CMyWin>)
END_MSG_MAP()
void OnPaint(HDC)...{
CPaintDC dc(*this);
CRect R;
GetClientRect(&R);
CBrush bsBlue=CreateSolidBrush(RGB(0,0,255));
dc.FillRect(R,bsBlue);
R.InflateRect(-50,-50);
dc.DrawFrameControl(R,DFC_CAPTION,DFCS_CAPTIONHELP);
}
} ;
WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
... {
int nRet;
_Module.Init(NULL,hinstance);
...{
CMyWin mywin;
mywin.CreateEx();
mywin.ShowWindow(nCmdShow);
CMessageLoop MsgLoop;
nRet=MsgLoop.Run();
}
_Module.Term();
return nRet;
}
如果你的Include路径和Lib路径没有设置错误的话,应该可以编译通过了.
对比一下SDK代码,简洁了不少吧。不过和VCL比还有点差距(而且不能RAD),但它有一个比VCL拽的优点:生成的文件非常小,几乎和SDK编写的一样。 so我们的口号是: "SDK的效率,VCL的简洁"
代码看不明白? 没关系,鄙人下回自会分解:)
下回:WTL里的"TApplication","TForm","TStatusBar", "TToolBar" 和 "TCoolBar" 还有一个"alClient属性的TPanel"