posts - 14, comments - 4, trackbacks - 0, articles - 0

2006年7月7日


1 不会英语:CS源于美国,重量级的文档都是英文的。不会英语,那么你只能忍受拙
劣的翻译和大延迟的文档(翻译出来的文档几乎都是很久以前出版的东西)。

2 急于求成:什么都没学习就开始编程是最大的忌讳。写C++程序语法都能错,数据
结构连线性表都不知道,数据库不知道关系模型,TCP编程不知道socket,还是先坐下来学习几年再说(如果说工作急需,我只能说:早干嘛去了)

3 过于好问:勤学好问是一种很好的品质,但是如果把勤学丢了,只留下好问,就是一个恶劣的素质了。事无巨细都去请教别人,一则会让人厌烦,二则由于没有系统学习过程,也是不可能学习好的。

4 只会艳羡别人和说别人不该拿那么多钱,而自己却收入微薄:老实说,绝大多数情况下,收入的高低和你的水平是有正相关关系的。不是否认有关系的存在,但是绝对不会10个人中9个人有关系而独独你没有。少抱怨一些多学习一些,提升自己才是最重要的。

5 过于不求甚解和过于求甚解。了解为什么是很重要的,但是要学习的东西很多,如果什么都弄明白,那么估计头发白了还没有找到所有答案。当然如果什么都不想细致了解,那么只能去做蓝领了。

6 过分崇拜他人:我想信很多人都是很厉害的,值得大家崇拜,但是如果过于崇拜,把他们的话当成圣经就没有必要了。你需要突破他们,而不是崇拜他们。

7 不想吃苦:IT业高收入和高竞争是联系在一起的。没有付出永远别想进步。

posted @ 2006-07-07 23:24 will 阅读(280) | 评论 (0)编辑 收藏

        思考1 : 大局上面仍然有另一个大局
  思考2 : 公平永远有不同角度的公平
  思考3 : 这个游戏只有站在切换器旁边的人可以决定结果

  有一群小朋友在外面玩 而那个地方有两条铁轨,
  一条还在使用, 一条已经停用
  只有一个小朋友选择在停用的铁轨上玩
  其它的小朋友全都在仍在使用的铁轨上玩

  很不巧,火车来了(而且理所当然的往上面有很多小孩的,仍在使用的铁轨上行驶)

  而你正站在铁轨的切换器旁,因此你能让火车转往停用的铁轨
  这样的话你就可以救了大多数的小朋友; 但是那名在停用铁轨上的小朋友将被牺牲
  你会怎么办?

  据说大多数人会选择救多一些的人,换句话说,牺牲那名在停用铁轨上玩的小孩...

  但是这又引出另一个问题
  那一名选择停用铁轨的小孩显然是做出正确决定
  脱离了他的朋友而选择了安全的地方
  而他的朋友们则是无知或任性的选择在不该玩耍的地方玩
  为什么做出正确抉择的人要为了大多数人的无知而牺牲呢?

  [响应与挑战]

  这篇文章蛮发人深省的,看完了感触很深!
  我们常被教育要顾全大局,但公平吗?

  似乎当大家都做的理所当然的时候,
  我们就必须随波逐流,否则就会被放逐而不容于世,
  如渔父中那位老翁劝屈原所说的:
  世人皆浊,何不淈其泥而扬其波?
  众人皆醉,何不餔其糟而歠其醨?
  何故深思高举,自令放为?

  当一个人太坚持自己是"对"的,
  最后的下场可能就是被牺牲的可怜鬼!
  又有谁会为他掬一把同情之泪? 只会嘲笑他的愚蠢!

  我们已经进了社会,学习的就是圆滑的做人,
  当你是主管, 就像文章中那位切换轨道的人,
  内心的正义与现实冲突时, 你会如何抉择呢?

  不过- 换另一个角度,如不选择切换轨道
  因为,那群小朋友一定知道那是活的轨道
  所以,当他们听到火车的声音时,就会知道要跑!

  但若,将轨道切换后那个乖小孩必定惨死,
  因为,他从来没想过火车还会开到废轨道上
  所以,你认为呢?

  或许这样的想法与理念,
  到了人老时才会发现
  自己成为一个不断被牺牲的可怜鬼,
  但这个社会又为什么要把是与非颠倒来又颠倒去呢?

  另外,再想想,一条铁道会被停止使用,自由它的道理。
  是否代表着这个铁道本身有问题,未经验证就使用它会遇到潜藏的危机呢?

  如果切过去之后,被牺牲的就不只是一个或一群小孩了,
  而是整车的乘客呢?

posted @ 2006-07-07 20:13 will 阅读(274) | 评论 (0)编辑 收藏

2006年7月6日

在VC++下实现高彩色工具条

  引言

  一些Windows系统自带程序如资源管理器、Internet Explorer等程序的工具条看上去和其他一些程序的工具条不太一样,在颜色上要漂亮许多。其实这些程序的工具条上的图标均为256色,而普通应用程序 在工具栏上所显示图标的颜色通常只有16色,这就决定了后者在视觉上远没有前者美观。由于Windows随系统而带的程序也是由开发人员编写的应用程序, 这就说明通过程序编码可以实现256色甚至更多色彩的图标在工具栏上的显示。为此笔者经过摸索,通过MFC编程在应用程序中实现了高彩色工具条。现将实现 的主要方法介绍如下,以飨广大读者。

  基本设计思路

  在实现高彩色工具条之前,先研究一下普通16色的工具条的实现过程,并从中总结出改进方法。在VC的资源视图中工具条是一个资源名为 IDR_MAINFRAME的Toolbar型资源,并可通过在编辑按钮上的图标来完成工具条上图标的绘制。虽然在资源视图中工具条上各按钮的图标是相互 独立的,但在存储时并非像图标一样保存为ico格式文件而是以bmp位图格式保存在磁盘上的。该位图是一个由工具条上的按钮图标组成的长条型位图图像,中 间没有任何缝隙,在程序运行和在资源视图对工具条进行编辑时该图像首先装载到一个图像列表中,然后工具栏根据索引依次从图像列表中将图像显示到工具条的各 个按钮上。由于VC限制工具栏上的图标不能超出16色,因此不论是在资源视图直接编辑位图还是用复制粘贴等手段均无法获取超出256色的工具条(注:用复 制粘贴的方法虽然在编辑视图中可以暂时显示出256色的图标,但在程序运行时仍会退化成16色)。

  由于不能在资源视图中通过编辑Toolbar资源实现16色以上的图标,加之工具条在显示时有并不直接从Toolbar获取图标而是从图像列表中读 取,因此可以通过其他一些图像处理软件做好类似于工具条的bmp图像(仅颜色比普通工具条bmp图像丰富,其余完全一样),并以位图的形式加入到程序资 源。在使用时,先将其读取到图像列表,这样图像列表中用于显示到工具条上的图标的颜色就可以是256、24位、甚至32位色的了。由于工具条缺省时将直接 加载资源名为IDR_MAINFRAME的Toolbar型资源作为图标的来源,因此还必须通过SetImageList()函数将含有高彩色工具条位图 的图像列表指定为工具条的图标来源。

  真彩工具条的实现

  由于工具条的创建是在主框架类的OnCreate()函数中完成的,因此高彩色图像的装载和图像列表的替换工作必须也在此进行。在进行程序设计之前, 需要做好各种准备工作,比如高彩色工具条位图的绘制、高彩色位图加入到资源等。绘制工具条位图时,必须控制好图像的尺寸,如需要有N个边长为 M的图标,那么需要绘制的位图尺寸为长=N*M;宽=M。真彩位图在加入到工程之后就不能再在VC的资源视图中进行编辑了。由于这个彩色位图仅起到美化界 面的作用,因此具体对的事件响应等工作还要通过设置原有的Toolbar资源来完成。

  准备工作就绪后,先要把工具条位图装载到图像列表,这样才能被工具条做获取。在作这一步时,必须用::LoadImage()函数去加载工具条位图,并通过宏MAKEINTRESOURCE()来指定具体要加载哪一个资源位图:

HBITMAP hbm = (HBITMAP)::LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_TOOLBAR), //加载IDB_TOOLBAR
IMAGE_BITMAP, //按位图格式
0,0, // cx,cy
LR_CREATEDIBSECTION | LR_LOADMAP3DCOLORS );

LoadImage返回一个位图句柄HBITMAP,但在MFC下使用CBitmaps会更加方便,可创建一个
CBitmap对象并用Attach()成员函数将它与位图句柄联系起来:

CBitmap bm;
bm.Attach(hbm);

  MFC加载工具栏位图时使用了一个内部函数AfxLoadSysColorBitmap()将缺省颜色设定为16色,因此为了显示16色以上的图像,必须在调用图像列表类CImageList的Create()函数创建图像列表时对图像清单做进一步的处理:

m_ilToolBar.Create(32,32,ILC_COLOR8, 4, 4);
m_ilToolBar.Add(&bm,(CBitmap*)NULL);

  这里用ILC_COLOR8标明了创建的图像列表是256色的,在VC的commctrl.h中对其有定义,并且还提供有其他几种颜色位深度的预定义:

#define ILC_COLOR4 0x0004 //16色
#define ILC_COLOR8 0x0008 //256色
#define ILC_COLOR16 0x0010 //16位色
#define ILC_COLOR24 0x0018 //24位色
#define ILC_COLOR32 0x0020 //32位色

  如果使用的工具条位图只有256色(对于多数程序这样已经足够),则显然没有必要再使用更高级别的位深度定义。最后一步,也是最关键的一步,必须通过 SetImageList()函数指定工具条m_wndToolBar的图标来源不再是原来缺省的图像列表而是含有高彩色位图的图像列表 m_ilToolBar:

m_wndToolBar.GetToolBarCtrl().SetImageList(&m_ilToolBar);

  到此为止就可以通过MFC在自己编写的程序中实现类似于IE等软件的漂亮的工具条了。下图就是笔者用上述方法得到的程序界面:



  小结

  本文通过对作为工具条图标来源的图像列表的替换,实现了在普通MFC应用程序中具备了以往只有Windows系统自带程序才具备的高彩色工具条。较好 地美化了程序的界面。本文程序在Windows 98下,由Microsoft Visual C++ 6.0编译通过。


用VC制作非常酷的工具条

  自微软推出Windows 95后,一大批全新的控件使我们的应用程序更加美观,使用也更加方便。其中一个显著的变化就是工具条不再是一个突出的3D小方框,而是变成了平面的状态,但 是只要把鼠标移动到上面,它就会自动地浮出来,大大方便了用户。

  笔者经过一段时间摸索,终于找到了制作这种工具条的方法。原来Windows 95封装了许多常用的控件,大都被放在Comctrl32.dll中,其中Toolbar控件是用于制作工具条的。下面 简要介绍一下如何在VC5.0中添加一个Toolbar。

  众所周知,所有的控件都是某一类型的窗口,所以制作Toolbar也要从制作窗口开始。由于MFC的Toolbar类并不支持新的功能,所以我们只好用SDK方法,通过API调用来完成整个过程 ,该过程与制作一个传统的工具条类似。

  Toolbar是属于comctrl32.dll的扩展功能,所以要先调用InitCommonControlsEx()的函 数。该函数有一个重要的参数决定了对Toolbar的支持,它的主要作用是注册Toolbar窗口,以 便在以后的程序中制作这种窗口,而普通的工具条则要调用InitCommandControls()。需要注意的是这两个函数的写法。

INITCOMMONCONTROLSEX icex;
DWORD dwStyle;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);

//注意下面这两个参数决定了是否注册Toolbar

icex.dwICC=ICC_COOL_CLASSES|ICC_BAR_ CLASSES;
InitCommonControlsEx(&icex);



  然后就可以调用CreateWindowEx这个函数来建立Toolbar窗口:

HWND hwndTB = CreateWindowEx(
WS_EX_TOOLWINDOW, //扩展工具条风格
TOOLBARCLASSNAME, //Toolbar类名
NULL,
WS_CHILD|WS_VISIBLE|TBSTYLE_FLAT, //窗口风格
0,0,0,0, //大小
AfxGetApp()->GetMainWnd(), //父窗口名
NULL,
AfxGetInstanceHandle(), //实例
NULL);



  判断一下窗口句柄,如果不为空,就表示窗口建立成功。此时的Toolbar不过是一个空空的窗口,我们可以根据需要向里面添加按钮。向Toolbar 中添加按钮是通过向它发送消息来 实现的,以下过程与制作传统的工具条基本一致。首先,建立一个ImageList控件,然后通过定义按钮的数据结构来确定每个按钮的类型。
// 建立一个Imagelist 控件,

HWND himl;
//MYICON_CX,MYICON_CY是每个按钮的大小
himl= ImageList_Create(MYICON_CX,MYICON_CY,ILC_COLOR4,0,4);

//加入事先作好的工具条位图IDB_BITMAP2
ImageList_Add( himl,
LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP2)),NULL);

//通过消息把位图加入到Toolbar中
SendMessage(hwndTB, TB_SETIMAGELIST, 0, (LPARAM)himl);

  下面加入5个普通的按钮:

TBBUTTON tbArray[5]; //按钮的数据结构
for(i=0;i<5;i++)
{
tbArray[i].iBitmap = i; //第i个位图
tbArray[i].idCommand = IDM_BUTTONSTART+i;
//命令ID
tbArray[i].fsState = TBSTATE_ENABLED;
tbArray[i].fsStyle = TBSTYLE_BUTTON;
//按钮风格
tbArray[i].dwData = 0;
tbArray[i].iString = i; //显示的字符串
}

//设置按钮结构的大小

::SendMessage(hwndTB,TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
//添加按钮到Toolbar中
::SendMessage(hwndTB,TB_ADDBUTTONS,(UINT)5, (LPARAM)tbArray);



  至此,一个很酷的工具条基本上制作完成,最后再调用函数ShowWindow()即可: ShowWindow(hwndTB, SW_SHOWMAXIMIZED);

  当点击按钮时,Toolbar就把消息传送到父窗口中,由父窗口响应消息。Toolbar中按钮的ID包含在消息函数的wParam参数中,可以设置 它来调度不同的模块。这时可以重载父窗口的O nCommand()函数,根据wParam参数判断点击了哪个按钮。假定父窗口是主窗口框架,代码如下:

BOOL CMainFrame::OnCommand(WPARAM wParam,LPARAM lParam)
{
switch(wParam)
{
case IDM_BUTTONSTART+0:
AfxMessageBox(“你点中了第一个按钮!!", MB_ICONINFORMATION);
break;
case IDM_BUTTONSTART+1:
AfxMessageBox(“你点中了第二个按钮!!",MB_ICONINFORMATION);
break;
case IDM_BUTTONSTART+2:
AfxMessageBox(“你点中了第三个按钮!!", MB_ICONINFORMATION);
break;
}
return CMainFrame::OnCommand(wParam,lParam);
}

Visual C++ 版本6中工具条的新特色

Dave Schmi


  微软在www.microsoft.com/visualc已经推出Visual C++6.0预览版几个月了。正式版预计到今年年底发布。同时,预览版显示出版本6将包含大量的改进和提高,包括支持Internet控件,例如扁平工具 条等。虽然改进的控件包与Internet无关,但它首先出现在Internet Explorer中,因此它就被取做这个名字了。事实上,官方发布的预览版的标题是“针对Internet Explorer 4.0的Visual C++ 5.0技术预览”。

  在以前关于MFC工具条类的讨论专题中,我曾答应提供一个在版本6中工具条的外观演示。有一个很好的消息,那就是你现在用CToolBar所作的所有 工作在新的版本中都是有效的,包括那些在以前的栏目中所描述的一些扩展功能。因此,你将很容易修改现存的程序以获得象Internet Explorer和Visual Studio中那样“酷”的界面。此外,并没有什么坏消息。

工具条的新特色

  早在版本4中,CToolBar就已被MFC库完全实现了。一旦公用控件动态链接库(命名为comctl32.dll)变得无所不在了, CToolBar就成了如今已包含在操作系统中的工具条控件的代名词了。然而,CToolBar并没有揭示公用工具条控件的所有能力。如今,通过 CreateEx()函数,它成功了。

  公用控件动态链接库现在包含了至少三类风格:最初的、在Internet Explorer3.0中加入的以及在Internet Explorer 4.0中加入的。虽然这些版本理论上是向下兼容的,但某些专业人员曾写出一些不能在后来版本中正常运行的应用程序,这可能是这些程序采用了一些没有公开的 功能,而这些功能并没有被包含在所有的版本中。

  Visual C++程序员没有这样的经历,因为在Visual C++4.0或5.0中comctl32.dll并不是一个可以再分发的组件,它在安装Internet Explorer时被更新,因此MFC程序员无法依靠最新版本的某些功能来用于他们的程序。这就是CToolBar仅仅具有最初的DLL的有限功能的原 因。CToolBar能够实现最新的特色意味着微软将在Visual C++6.0中包含最新的DLL并将其作为一个可以再分发的组件。

  绝大多数新特色将由在调用CreateEx()和其它CToolBar成员函数时指定的新的风格标志来确定。下面是commctrl.h的一部分,它定义了TBSTYLE类标识符:


#define TBSTYLE_BUTTON 0x0000
#define TBSTYLE_SEP 0x0001
#define TBSTYLE_CHECK 0x0002
#define TBSTYLE_GROUP 0x0004
#define TBSTYLE_CHECKGROU TBSTYLE_GROUP | TBSTYLE_CHECK)
#if (_WIN32_IE $#@62;= 0x0300)
  #define TBSTYLE_DROPDOWN 0x0008
#endif
#if (_WIN32_IE $#@62;= 0x0400)
  #define TBSTYLE_AUTOSIZE 0x0010
  #define TBSTYLE_NOPREFIX 0x0020
#endif

#define TBSTYLE_TOOLTIPS 0x0100
#define TBSTYLE_WRAPABLE 0x0200
#define TBSTYLE_ALTDRAG 0x0400
#if (_WIN32_IE $#@62;= 0x0300)
  #define TBSTYLE_FLAT 0x0800
  #define TBSTYLE_LIST 0x1000
  #define TBSTYLE_CUSTOMERASE 0x2000
#endif
#if (_WIN32_IE $#@62;= 0x0400)
  #define TBSTYLE_REGISTERDROP 0x4000
  #define TBSTYLE_TRANSPARENT 0x8000
  #define TBSTYLE_EX_DRAWDDARROWS 0x00000001
#endif



  你会注意到其中的一些采用了条件编译,依赖于_WIN32_IE的值,它缺省指的是Internet Explorer 4.0(即取值为0x0400)。对于Internet Explorer 3.0(即取值为0x0300)以前的版本,大多数的TBSTYLE标识符指的是按钮或是一组按钮。Internet Explorer3.0引入了扁平钮、文本标签、下拉列表和自定义绘制。Internet Explorer 4.0增强了下拉列表和自定义绘制功能,并且增加了支持OLE拖动目标到一个工具条。

扁平钮和把手

  在过去的18个月中我常常被问及该如何获得象Internet Explorer和Visual Studio中的工具条一样不使用浮雕按钮而是用扁平钮并且带有便于移动和定位的把手那样酷的界面。这些特色并不被MFC所支持,因此最简单获取的方法就 是购买一个扩展库。而对于Visual C++ 6.0来说却无须多此一举,因为它使得CToolBar类实现了对扁平钮、把手和其它新的视觉效果的支持。

  在预览版中,AppWizard并不会自动包括这些新特色,但它们却很容易被加入。表1显示了AppWizard创建的主框架窗口的OnCreate ()函数,表2显示了需要做哪些修改以获得具有扁平钮和把手的工具条。图1显示了表1创建出的工具条,而图2显示出了表2实现的工具条。


表 1: CMainFrame::OnCreate as generated by AppWizard
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

if(!m_wndToolBar.Create(this)||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  {
   TRACE0("Failed to create toolbar\n");
   return -1; // fail to create
  }

if(!m_wndStatusBar.Create(this) ||
  !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)))
  图1
表2: Adding flat buttons and the gripper
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if(CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
  return -1;

if(!m_wndToolBar.CreateEx(this)||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
  {
   TRACE0("Failed to create toolbar\n");
   return -1; // fail to create
  }

if(!m_wndStatusBar.Create(this)||!m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar\n");
return -1; // fail to create
}

// TODO: Remove this if you dont want tool tips or a resizeable toolbar
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_GRIPPER | CBRS_BORDER_3D | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

// TODO: Delete these three lines if you dont want the toolbar to
// be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar);

return 0;
}
图2

  为了作出扁平按钮我必须使用CreateEx()来代替Create()。这个新的函数在afxext.h中声明:

BOOL CreateEx
(
CWnd* pParentWnd, // parent window
DWORD dwCtrlStyle = TBSTYLE_FLAT, // extended style
DWORD dwStyle = // style
WS_CHILD | WS_VISIBLE | CBRS_ALIGN_TOP,
CRect rcBorders = CRect(0,0,0,0), // border rectangle
UINT nID = AFX_IDW_TOOLBAR // identifier
);


  因为扩展风格缺省指的就是TBSTYLE_FLAT,因此我要得到扁平按钮就只需要简单地将AppWizard形成的代码中的Create()改为 CreateEx()即可。我将在后面实现其它的扩展风格。为了获得把手,我必须在调用SetBarStyle()函数时包含CBRS_GRIPPER标 志,参看表2。这是CControlBar类的一个新风格,而CToolBar类是从它继承而来的。请注意到我也加入了CBRS_BORDER_3D标 志,这是为了修正一个未知的绘制问题,该问题将会在工具条的边缘绘制一些多余的点。这也许意味着预览版确实有这个问题,因为一旦我将3D标志加入就立即解 决了并且也似乎没有影响到别的什么。

  上面所作的两个简单的改变是使得一个已存程序获得酷界面的最省力的方法。在一个程序具有了扁平钮和把手的同时,它也不会发生不应有的其它改变。

posted @ 2006-07-06 19:03 will 阅读(2297) | 评论 (0)编辑 收藏

C/C+语言struct深层探索

出处:PConline

1. struct的巨大作用
  面对一个人的大型C/C++程序时,只看其对struct的使用情况我们就可以对其编写者的编程经验进行评估。因为一个大型的C/C++程序,势必要涉及一些(甚至大量)进行数据组合的结构体,这些结构体可以将原本意义属于一个整体的数据组合在一起。从某种程度上来说,会不会用struct,怎样用struct是区别一个开发人员是否具备丰富开发经历的标志。

  在网络协议、通信控制、嵌入式系统的C/C++编程中,我们经常要传送的不是简单的字节流(char型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。

  经验不足的开发人员往往将所有需要传送的内容依顺序保存在char型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议有所变化,程序就要进行非常细致的修改。

  一个有经验的开发者则灵活运用结构体,举一个例子,假设网络或控制协议中需要传送三种报文,其格式分别为packetA、packetB、packetC:

struct structA
{
int a;
char b;
};

struct structB
{
char a;
short b;
};

struct structC
{
int a;
char b;
float c;
}
  优秀的程序设计者这样设计传送的报文:

struct CommuPacket
{
int iPacketType;  //报文类型标志
union      //每次传送的是三种报文中的一种,使用union
{
  struct structA packetA;
  struct structB packetB;
  struct structC packetC;
}
};
  在进行报文传送时,直接传送struct CommuPacket一个整体。

  假设发送函数的原形如下:

// pSendData:发送字节流的首地址,iLen:要发送的长度
Send(char * pSendData, unsigned int  iLen);
发送方可以直接进行如下调用发送struct CommuPacket的一个实例sendCommuPacket:
Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
假设接收函数的原形如下:
// pRecvData:发送字节流的首地址,iLen:要接收的长度
//返回值:实际接收到的字节数
unsigned int Recv(char * pRecvData, unsigned int  iLen);
  接收方可以直接进行如下调用将接收到的数据保存在struct CommuPacket的一个实例recvCommuPacket中:

Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  接着判断报文类型进行相应处理:

switch(recvCommuPacket. iPacketType)
{
    case PACKET_A:
    …    //A类报文处理
    break;
    case PACKET_B:
    …   //B类报文处理
    break;
    case PACKET_C:
    …   //C类报文处理
    break;
}
  以上程序中最值得注意的是

Send( (char *)&sendCommuPacket , sizeof(CommuPacket) );
Recv( (char *)&recvCommuPacket , sizeof(CommuPacket) );
  中的强制类型转换:(char *)&sendCommuPacket、(char *)&recvCommuPacket,先取地址,再转化为char型指针,这样就可以直接利用处理字节流的函数。

  利用这种强制类型转化,我们还可以方便程序的编写,例如要对sendCommuPacket所处内存初始化为0,可以这样调用标准库函数memset():

memset((char *)&sendCommuPacket,0, sizeof(CommuPacket));

2. struct的成员对齐
  Intel、微软等公司曾经出过一道类似的面试题:
1. #include <iostream.h>
2. #pragma pack(8)
3. struct example1
4. {
5. short a;
6. long b;
7. };
8. struct example2
9. {
10. char c;
11. example1 struct1;
12. short e;   
13. };
14. #pragma pack()
15. int main(int argc, char* argv[])
16. {
17. example2 struct2;
18. cout << sizeof(example1) << endl;
19. cout << sizeof(example2) << endl;
20. cout << (unsigned int)(&struct2.struct1) - (unsigned int)(&struct2) << endl;
21. return 0;
22. }
  问程序的输入结果是什么?
  答案是:
8
16
4
  不明白?还是不明白?下面一一道来:
2.1 自然对界
  struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。
  自然对界(natural alignment)即默认对齐方式,是指按结构体的成员中size最大的成员对齐。
  例如:
struct naturalalign
{
char a;
short b;
char c;
};
  在上述结构体中,size最大的是short,其长度为2字节,因而结构体中的char成员a、c都以2为单位对齐,sizeof(naturalalign)的结果等于6;
  如果改为:
struct naturalalign
{
char a;
int b;
char c;
};
  其结果显然为12。

2.2指定对界
  一般地,可以通过下面的方法来改变缺省的对界条件:
  · 使用伪指令#pragma pack (n),编译器将按照n个字节对齐;
  · 使用伪指令#pragma pack (),取消自定义字节对齐方式。
  注意:如果#pragma pack (n)中指定的n大于结构体中最大成员的size,则其不起作用,结构体仍然按照size最大的成员进行对界。
  例如:
#pragma pack (n)
struct naturalalign
{
char a;
int b;
char c;
};
#pragma pack ()
  当n为4、8、16时,其对齐方式均一样,sizeof(naturalalign)的结果都等于12。而当n为2时,其发挥了作用,使得sizeof(naturalalign)的结果为8。
  在VC++ 6.0编译器中,我们可以指定其对界方式,其操作方式为依次选择projetct > setting > C/C++菜单,在struct member alignment中指定你要的对界方式。
  另外,通过__attribute((aligned (n)))也可以让所作用的结构体成员对齐在n字节边界上,但是它较少被使用,因而不作详细讲解。

2.3 面试题的解答
  至此,我们可以对Intel、微软的面试题进行全面的解答。
  程序中第2行#pragma pack (8)虽然指定了对界为8,但是由于struct example1中的成员最大size为4(long变量size为4),故struct example1仍然按4字节对界,struct example1的size为8,即第18行的输出结果;
  struct example2中包含了struct example1,其本身包含的简单数据成员的最大size为2(short变量e),但是因为其包含了struct example1,而struct example1中的最大成员size为4,struct example2也应以4对界,#pragma pack (8)中指定的对界对struct example2也不起作用,故19行的输出结果为16;
  由于struct example2中的成员以4为单位对界,故其char变量c后应补充3个空,其后才是成员struct1的内存空间,20行的输出结果为4。

posted @ 2006-07-06 18:42 will 阅读(430) | 评论 (0)编辑 收藏

Class Diagrams
Class diagrams are the backbone of almost every object oriented method, including UML. They describe the static structure of a system.

Object Diagrams
Object diagrams describe the static structure of a system at a particular time. They can be used to test class diagrams for accuracy.


Use Case Diagrams
Use case diagrams model the functionality of system using actors and use cases.



Activity Diagrams
Activity diagrams illustrate the dynamic nature of a system by modeling the flow of control from activity to activity. An activity represents an operation on some class in the system that results in a change in the state of the system. Typically, activity diagrams are used to model workflow or business processes and internal operation.

 


Sequence Diagrams
Sequence diagrams describe interactions among classes in terms of an exchange of messages over time.



Collaboration Diagrams
Collaboration diagrams represent interactions between objects as a series of sequenced messages. Collaboration diagrams describe both the static structure and the dynamic behavior of a system.

 


Statechart Diagrams
Statechart diagrams describe the dynamic behavior of a system in response to external stimuli. Statechart diagrams are especially useful in modeling reactive objects whose states are triggered by specific events.

 


Component Diagrams
Component diagrams describe the organization of physical software components, including source code, run-time (binary) code, and executables.

 


Deployment Diagrams
Deployment diagrams depict the physical resources in a system, including nodes, components, and connections.

 


Package Diagrams
Package diagrams are a subset of class diagrams, but developers sometimes treat them as a separate technique. Package diagrams organize elements of a system into related groups to minimize dependencies between packages

posted @ 2006-07-06 18:21 will 阅读(1160) | 评论 (0)编辑 收藏

二进制大对象BLOB(Binary Large Object)
其存取的方式与普通数据有所区别。本文将介绍利用ADO在数据库中存取BLOB数据的具体实现过程,并给出实现图像存取显示的完整示例工程。

二、前期准备

首先我们建立一张名为userinfo的表,包含三个字段:id,username,old,photo,其中photo是一个可以存储二进制数据的字段。

2.1 在SQL SERVER中我们可以在Query Analyzer中直接输入如下语句创建:

CREATE TABLE [dbo].[userphoto] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (50) NULL ,
[old] [int] NULL ,
[photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
其中photo我们定义为image类型的字段。

2.2 在ACCESS中创建的方法如下:

建立一张新表包括id,username,old,photo四个字段,然后打开表,选视图菜单中设计视图,将id设置为自动编号的递增长整型,username为文本,old为数字,photo为OLE对象。
在我们的示例工程中已经包含了一个建立好的ACCESS2000的库,你可以直接拿来使用。

三、具体步骤

3.1 BLOB数据的保存

BLOB类型的数据无法用普通的方式进行存储,我们需要使用AppendChunk函数,AppendChunk包含在Field对象中,原型如下:
HRESULT AppendChunk (const _variant_t & Data );
从函数原型中可以看到关键的问题是我们需把二进制数据赋值给VARIANT类型的变量,下面我们给出具体的代码并作简单的分析:

///假设m_pBMPBuffer指针指向一块长度为m_nFileLen的二进制数据,并且已经成功打开了记录集对象m_pRecordset///

char *pBuf = m_pBMPBuffer ;
VARIANT varBLOB;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];

m_pRecordset->AddNew(); ///添加新记录
m_pRecordset->PutCollect("username",_variant_t("小李")); ///为新记录填充username字段
m_pRecordset->PutCollect("old",_variant_t((long)28); ///填充old字段

if(pBuf){
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = m_nFileLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); ///创建SAFEARRAY对象

for (long i = 0; i < (long)m_nFileLen; i++)
SafeArrayPutElement (psa, &i, pBuf++); ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中

varBLOB.vt = VT_ARRAY | VT_UI1;///将varBLOB的类型设置为BYTE类型的数组

varBLOB.parray = psa; ///为varBLOB变量赋值

m_pRecordset->GetFields()->GetItem("photo")->AppendChunk(varBLOB); ///加入BLOB类型的数据
}

m_pRecordset->Update(); ///保存我们的数据到库中

至此我们的数据已经成功地保存到了数据库中,接下来我们所要做的工作便是将该数据提取出来,让我们继续吧!

3.2 BLOB数据的读取

对应于保存数据时我们所使用的AppendChunk函数,读取数据应该使用GetChunk函数,GetChunk的原型如下:
_variant_t GetChunk (long Length );
给出数据的长度后GetChunk将返回包含数据的VARIANT类型变量,然后我们可以利用SafeArrayAccessData函数得到VARIANT变量中指向数据的char *类型的指针,以方便我们的处理,具体代码如下:

long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;
///得到数据的长度

if(lDataSize > 0)
{
_variant_t varBLOB;

varBLOB = m_pRecordset->GetFields()->GetItem("photo")->GetChunk(lDataSize);

if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判断数据类型是否正确
{
   char *pBuf = NULL;
   SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
   ///得到指向数据的指针 /*****在这里我们可以对pBuf中的数据进行处理*****/
   SafeArrayUnaccessData (varBLOB.parray);
   }

}

以上我们成功实现了BLOB数据在数据库中的存取,为了让大家有现成的例子可以参考,本文提供了示例工程,在示例工程中我们在数据库中保存图像数据,并可以对这些图像进行浏览、修改,该例子还涉及到如何用char *指向的BMP文件数据创建BITMAP对象然后显示出来。

posted @ 2006-07-06 11:56 will 阅读(776) | 评论 (1)编辑 收藏

2006年7月5日

l         创建

                            long i = 0;

                            VARIANT va = {0};

                            va . vt = VT_BSTR ;

                           

                            SAFEARRAYBOUND bounds [1] = {0};

                            bounds [0]. cElements = 5;

                            SAFEARRAY * psa = SafeArrayCreate ( VT_VARIANT , 1, bounds );

 

l         存入元素

                            for ( i = 0; i < 5; i ++)

                            {

                                     va . bstrVal = SysAllocString (L "test" );

                                     SafeArrayPutElement ( psa , & i , & va );

                            }

 

l         获取元素

                            for ( i = 0; i < 5; i ++)

                            {

                                     va . bstrVal = SysAllocString (L "test" );

                                     SafeArrayGetElement ( psa , & i , & va );

                                     SysFreeString ( va . bstrVal );

                            }

 

l         销毁

                            SafeArrayDestroy ( psa );

 

l         生成 VARIANT 变量

                            VARIANT vsa = {0};

                            vsa . vt = VT_ARRAY | VT_BSTR ;

                            vsa . parray = psa ;

posted @ 2006-07-05 20:09 will 阅读(1158) | 评论 (0)编辑 收藏

         野指针,也就是指向不可用内存区域的指针。通常对这种指针进行操作的话,将会使程序发生不可预知的错误。但是,我在文中要说的,就是野指针的“安全”使用方法以及其内部的原因.

首先请诸位看以下一段“危险”的C++代码:

void function( void )
{
    char* str = new char[100];
    delete[] str;
    // Do something
    strcpy( str, "Dangerous!!" );
}

之所以说其危险,是因为这是一段完全合乎语法的代码,编译的时候完美得一点错误也不会有,然而当运行到strcpy一句的时候,问题就会出现,因为在这之前,str的空间已经被delete掉了,所以strcpy当然不会成功。对于这种类似的情况,在林锐博士的书中有过介绍,称其为“野指针”。

那么,诸位有没有见过安全的“野指针”呢?下面请看我的一段C++程序,灵感来自CSDN上的一次讨论。在此,我只需要C++的“类”,C++的其余一概不需要,因此我没有使用任何的C++标准库,连输出都是用printf完成的。

#include <stdio.h>

class CTestClass
{
public:
    CTestClass( void );
    int m_nInteger;
    void Function( void );
};

CTestClass::CTestClass( void )
{
    m_nInteger = 0;
}

void CTestClass::Function( void )
{
    printf( "This is a test function.\n" );
}

void main( void )
{
    CTestClass* p = new CTestClass;
    delete p;
    p->Function();
}

OK,程序到此为止,诸位可以编译运行一下看看结果如何。你也许会惊异地发现:没有任何的出错信息,屏幕上竟然乖乖地出现了这么一行字符串:

This is a test function.

奇怪吗?不要急,还有更奇怪的呢,你可以把主函数中加上一句更不可理喻的:

((CTestClass*)NULL)->Function();

这仍然没有问题!!

我这还有呢,哈哈。现在你在主函数中这么写,倘说上一句不可理喻,那么以下可以叫做无法无天了:

int i = 888;
CTestClass* p2 = (CTestClass*)&i;
p2->Function();

你看到了什么?是的,“This is a test function.”如约而至,没有任何的错误。

你也许要问为什么,但是在我解答你之前,请你在主函数中加入如下代码:

printf( "%d, %d", sizeof( CTestClass ), sizeofint ) );

这时你就会看到真相了:输出结果是——得到的两个十进制数相等。对,由sizeof得到的CTestClass的大小其实就是它的成员m_nInteger的大小。亦即是说,对于CTestClass的一个实例化的对象(设为a)而言,只有a.m_nInteger是属于a这个对象的,而a.Function()却是属于CTestClass这个类的。所以以上看似危险的操作其实都是可行且无误的。

现在你明白为什么我的“野指针”是安全的了,那么以下我所列出的,就是在什么情况下,我的“野指针”不安全:

  1. 在成员函数Function中对成员变量m_nInteger进行操作;
  2. 将成员函数Function声明为虚函数(virtual)。

以上的两种情况,目的就是强迫野指针使用属于自己的东西导致不安全,比如第一种情况中操作本身的m_nInteger,第二种情况中变为虚函数的Function成为了属于对象的函数(这一点可以从sizeof看出来)。

其实,安全的野指针在实际的程序设计中是几乎毫无用处的。我写这一篇文章,意图并不是像孔乙己一样去琢磨回字有几种写法,而是想通过这个小例子向诸位写明白C++的对象实例化本质,希望大家不但要明白what和how,更要明白why。李马二零零三年二月二十日作于自宅。


关于成员函数CTestClass::Function的补充说明

这个函数是一个普通的成员函数,它在编译器的处理下,会成为类似如下的代码:

void Function( const CTestClass * this ) // ①
{
    printf("This is a test function.\n");
}

那么p->Function();一句将被编译器解释为:

Function( p );

这就是说,普通的成员函数必须经由一个对象来调用(经由this指针激活②)。那么由上例的delete之后,p指针将会指向一个无效的地址,然而p本身是一个有效的变量,因此编译能够通过。并且在编译通过之后,由于CTestClass::Function的函数体内并未对这个传入的this指针进行任何的操作,所以在这里,“野指针”便成了一个看似安全的东西。

然而若这样改写CTestClass::Function:

void CTestClass::Function( void )
{
    m_nInteger = 0;
}

那么它将会被编译器解释为:

void Function( const CTestClass * this )
{
    this->m_nInteger = 0;
}

你看到了,在p->Function();的时候,系统将会尝试在传入的这个无效地址中寻找m_nInteger成员并将其赋值为0,剩下的我不用说了——非法操作出现了。

至于virtual虚函数,如果在类定义之中将CTestClass声明为虚函数:

class CTestClass
{
public:
    // ...
    virtual void Function( void );
};

那么C++在构建CTestClass类的对象模型时,将会为之分配一个虚函数表vptr(可以从sizeof看出来)。vptr是一个指针,它指向一个函数指针的数组,数组中的成员即是在CTestClass中声明的所有虚函数。在调用虚函数的时候,必须经由这个vptr,这也就是为什么虚函数较之普通成员函数要消耗一些成本的缘故。以本例而言,p->Function();一句将被编译器解释为:

(*p->vptr[1])( p ); // 调用vptr表中索引号为1的函数(即Function)③

上面的代码已经说明了,如果p指向一个无效的地址,那么必然会有非法操作。

备注:

①关于函数的命名,我采用了原名而没有变化。事实上编译器为了避免函数重载造成的重名情况,会对函数的名字进行处理,使之成为独一无二的名称。
②将成员函数声明为static,可以使成员函数不经由this指针便可调用。
③vptr表中,索引号0为类的type_info。



posted @ 2006-07-05 00:32 will 阅读(1231) | 评论 (0)编辑 收藏

         在进行软件开发过程中间,有很多小功能的实现,虽然这些东西你可以不用,但是如果应用仂将会是你的程序更具有专业性。 
一、设置程序自动运行。  
       很多监控软件要求软件能够在系统重新启动后不用用户去点击图标启动项目,而是直接能够启动运行,方法是写注册表Software\\Microsoft\\Windows\\CurrentVersion\\Run。参考程序可以见下:(查找程序目录的执行文件,存在则进行添加注册表操作) 
         HKEY RegKey; 
         CString sPath; 
         GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH); 
         sPath.ReleaseBuffer(); 
         int nPos; 
    nPos=sPath.ReverseFind(’\\’); 
    sPath=sPath.Left(nPos); 
    CString lpszFile=sPath+"\\****.exe";//这里加上你要查找的执行文件名称 
    CFileFind fFind; 
    BOOL bSuccess; 
    bSuccess=fFind.FindFile(lpszFile); 
    fFind.Close(); 
    if(bSuccess) 
    { 
        CString fullName; 
        fullName=lpszFile; 
        RegKey=NULL; 
        RegOpenKey(HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&RegKey); 
        RegSetValueEx(RegKey,"*****",0,REG_SZ,(const unsigned char*)(LPCTSTR)fullName,fullName.GetLength());//这里加上你需要在注册表中注册的内容 
        this->UpdateData(FALSE); 
    } 
    else 
    { 
        theApp.SetMainSkin(); 
        ::AfxMessageBox("没找到执行程序,自动运行失败"); 
        exit(0); 
    } 

二、自动配置数据源 
    很多的程序都要用到数据库结合的操作,这里举例ACCESS,因为ACCESS在中小型VC系统开发中是最常用到的,如果程序的移植,如果对于很初级的用户来说,你还需要他到配置面板中进行数据源配置的话,那就有点说不过去了。 
         #include <odbcinst.h> 
         //配置数据源,数据库在应用程序目录下,这里比如数据库文件名为***.mdb,程序运行时候可以将数据库文件拷贝到程序目录下面。 
    CString sPath; 
    GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH); 
    sPath.ReleaseBuffer(); 
    int nPos; 
    nPos=sPath.ReverseFind(’\\’); 
    sPath=sPath.Left(nPos); 
    CString lpszFileName = sPath + "\\***.mdb";//这里修改成你的数据库文件名称 
    CFileFind  fFind; 
    if(!fFind.FindFile(lpszFileName)) 
    { 
        ::AfxMessageBox("没有找到数据库"); 
        exit(0); 
    }  
    CString szDesc; 
    szDesc.Format( "DSN=****;Description=****;DESCRIPTION=The DataBase For ***;FIL=MicrosoftAccess;DEFAULTDIR=%s;DBQ=%s;" ,sPath,lpszFileName);//这里***号可以添加成你的描述 

    //添加数据源 
    if(!::SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft Access Driver (*.mdb)",(LPCSTR)szDesc)) 
    { 
        ::AfxMessageBox("32位ODBC数据源配置错误!"); 
        exit(0); 
    } 

三、设置显示模式: 
    很多的程序的移植的运行环境是改变的。有可能你的原来开发环境是1024X768,但是到了那些显示器大于17的时候(分辨率超过你的开发时的分辨率时),程序的显示可能就不好看了。 
         DEVMODE lpDevMode; 
    lpDevMode.dmPelsHeight=768;//Y方向象素点 
    lpDevMode.dmPelsWidth=1024;//X方向象素点 
    lpDevMode.dmDisplayFrequency=85;//屏幕刷新率 
    lpDevMode.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY; 
    ChangeDisplaySettings(&lpDevMode,0); 

四、在你的程序中间加载其他应用程序: 
    你的程序除了调用到各个模块进行协同工作外(DLL),还有可能调用不是同一个开发环境下的应用程序,比如VC环境下调用DELPHI,VB开发的执行程序,你就可以用到下面的方法(将调用的应用程序拷贝程序目录中): 
         CString sPath; 
    GetModuleFileName(NULL,sPath.GetBufferSetLength (MAX_PATH+1),MAX_PATH); 
    sPath.ReleaseBuffer(); 
    int nPos; 
    nPos=sPath.ReverseFind(’\\’); 
    sPath=sPath.Left(nPos); 
    CString lpszFileName = sPath + "\\***.exe";//这里修改成你的调用应用程序的文件名称 
    CFileFind  fFind; 
    if(!fFind.FindFile(lpszFileName)) 
    { 
        ::AfxMessageBox("没有找到调用的应用程序!");  
        return FALSE; 
    } 
    else 
        ShellExecute(NULL,NULL,_T("***.exe"),NULL,sPath,NULL);  

五、结束进程: 
    在你的程序中结束别的程序进程,采用的方法是进行进程列举,然后采用查找的方法进行: 
         #include "TLHELP32.H" 
         DWORD ProcessID[50]; 
    CString kkk[50]; 
    HANDLE SnapShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);  
    PROCESSENTRY32* info=new PROCESSENTRY32; 
    PROCESSENTRY32 ProcessInfo;//声明进程信息变量 
    ProcessInfo.dwSize=sizeof(ProcessInfo);//设置ProcessInfo的大小 
    //返回系统中第一个进程的信息 
    BOOL Status=Process32First(SnapShot,&ProcessInfo); 
    int m_nProcess=0;  
    while(Status) 
    { 
        CString s,str1,str2; 
        s.Format("%d",ProcessInfo.cntThreads); 
        str1.Format("%s",ProcessInfo.szExeFile); 
        str1=ProcessInfo.szExeFile; 
        kkk[m_nProcess]=ProcessInfo.szExeFile;  
        ProcessID[m_nProcess]=ProcessInfo.th32ProcessID;  
        if(str1=="***.exe")//***.exe就是你要结束的进程的名称 
        { 
            HANDLE ProcessHandle; 
            ProcessHandle=OpenProcess (PROCESS_ALL_ACCESS,FALSE,ProcessID[m_nProcess]); 
            TerminateProcess(ProcessHandle,0);     
        } 
        Status=Process32Next(SnapShot,&ProcessInfo); 
        m_nProcess++; 
    } 

posted @ 2006-07-05 00:26 will 阅读(448) | 评论 (0)编辑 收藏

   作为现代C++最重要的特色技术,template正在各个传统领域攻城略地。从基本算法与数据结构,到正则表达式与XML解析,从高性能数学计算,到资源的分配与管理,从网络分布式计算环境,到组件模型创建,从静态多态性的维度扩展,到设计模式的自动生成,神奇的template显示出其令人叹为观止的强劲实力,如果不是有一个隐隐的痛处,template爱好者简直可以去狂欢了。

这个隐隐的痛处,就是在GUI编程领域。

   现有的大部分成熟GUI框架和工具库,其定型时间都在90年代早期,不管是因为什么原因,总之我们根本看不到template技术在这些环境中的任何重要运用。无论是专有MFC和OWL,还是开源的wxWindow和Mozilla, 以至于是专有还是开源都说不清楚的Qt,它们在其他方面有着诸多不同,偏偏倒是在对待模板技术上空前一致:严格限制在底层的数据结构领域内,抵制模板技术流入GUI主体结构。最过分的wxWindow和Mozilla,在代码编写规范里严厉禁止使用1990年之后发展出来的任何C++特性,模板、异常、多继承、STL等等,均在黑名单上。诸位有兴趣,不妨去看看,那与其说是一份C++代码编写规范,倒不如说是对C++现代特性在GUI领域应用的一份不公正的判决书。

难道模板技术真的在GUI领域无用武之地吗?

WTL给出了一个响亮的回答。

   WTL是微软ATL开发组成员Nenad Stefanovic先生在ATL Windowing机制上发展起来的一整套GUI框架,运用template技术组织和创建GUI对象,构筑了精致的面向对象框架(没错,在这里object oriented与template达成了精致的融合)。虽然没有获得微软的官方支持,虽然其使用者人数很少,但是确实是“用过的都说好”,有位微软MVP人士甚至说,这是微软有史以来推出的最优秀的一个framework。真是一个有趣的讽刺,最好的东西居然不被官方支持。有关于WTL的流言不少,比如这东西原本是微软内部专用,只是因为不小心才被泄漏出来等等,这更加剧它的神秘色彩。相信大家对它一定有不少问题。我们特别邀请到了WTL之父Nenad Stefanovic先生,进行了一次网上的访谈,希望能帮助大家了解WTL的真面目。

【C++ View】:I think most of our readers are not very familiar with you, so would you please tell us your story here? We are very fond of that. What do you think about China and Chinese people?

【C++ View】:我想,可能我们的读者中有很多人对您还不是很熟悉,您能不能在此给我们简单介绍一下您自己呢?我们将非常乐意听到您的自述。还有,您能不能也对我们讲述一下您对于中国以及中国人民的基本看法呢?

【Nenad】: I am a software developer at Microsoft. Your readers will probably know me as a creator of Windows Template Library, WTL. I am from former Yugoslavia, where I finished school and started working on software development. I've been living in US for 10 years now.

I am intrigued and impressed by the Chinese culture and tradition. I think that China is now in a great position of progress as a country and a nation. I discovered that, being from former Yugoslavia, I already know many things about China, and getting to know people from China gave me a bit of the "everyday" life perspective as well. I'd like to learn more, so I hope to visit China one day.

【Nenad】:好的。我现在在Microsoft工作,是它里面的一个软件开发人员。你们杂志的读者中可能有人知道,我就是Windows Template Library (WTL)的创作者。我来自于前南斯拉夫,在那我完成了我的学业并开始了我作为软件开发人员的工作生涯。现在,我在美国居住的时间已经超过了10年了。

   中国的文化以及传统给我留下了极为深刻的印象,我对此十分感兴趣。我想,作为一个国家以及民族,中国已经处于一个伟大并且不断在成长中的位置上。作为一个从前南斯拉夫来的人,我早就了解到关于中国的很多事情。在与来自中国的人民的接触过程中,我还了解到了你们日常生活的一些状况。我还想了解更多(有关中国的事情),希望有一天我可以到中国来游览。

【C++ View】:When and why did you first think about WTL? What's its original purpose? How do you see its future?

【C++ View】:您是什么时候开始想起要开发WTL呢?为什么?您在开发它时的最初目的是什么?您又是如何地看待它未来的发展呢?

【Nenad】:WTL was born while I was working on ATL (Active Template Library). We were extending ATL to support ActiveX controls, and I was working on the windowing support. I started thinking that the same techniques can be applied to much broader windowing support, for the much richer UI for controls, components, and also applications. So, WTL was created as a part of ATL that would extend ATL to support any kind of UI related component or application. It did not ship with ATL in Visual Studio, however, so I decided to ship it as a standalone library that extends ATL.

I think that WTL will continue to be a great option for developers writing Windows applications and components. I don't see big changes or additions to WTL, because one of the design principles for WTL was to follow the Win32 UI API and design. It will continue to do so.

【Nenad】:WTL是我在从事ATL (Active Template Library)开发工作时的产物。那时我们正在扩展ATL,使之得以支持ActiveX control,而我负责的就是其中对于窗口机制部分的支持。这时,我就开始想,是不是可以把同样的技术应用到更为广泛的窗口机制中,以获得更丰富的UI控制、组件、以至于应用程序呢?于是,作为ATL的一部分,WTL被开发出来了。它将ATL进行了扩展,以使得它可以支持各种类型的与UI相关的组件或者应用程序。然而,它并没有随着ATL一同集成在Visual Studio中被发布,于是我就决定将它作为一个单独的ATL扩展库发布出去。

我认为WTL将一直是那些在Windows下开发应用程序以及组件的开发者的一个很好的选择。我并不认为在以后,我们会对WTL有一个大的改动(或者增添),因为WTL的一个设计宗旨就是“遵循Win32 UI的API及其设计”。现在如此,将来还是会如此下去。

【C++ View】:I first heard about WTL in July, 2000. At that time, I thought: "No official support, no documentation, no commercial hype, it will die in 6 months." Now, fifteen months passed, it spreads wider and be more vigorous. Lots of C++ programmers, esp. the ones we regard them as "gurus and masters" involved in WTL. I know it's surely because WTL is a wonderful library, but it must be more than a wonderful library to gain such attentions without official force.What do you think WTL's relative success? What's the reason?

【C++ View】:我第一次接触WTL是在2000年7月。在那时,我就想:“没有官方的支持,没有文档,也没有商业吹捧,它最多只能够存活6个月。”但现在15个月过去了,它反而流传得更为广泛,更加的生机勃勃。许多C++程序员,尤其是一些我们所认知的“专家”以及“大师”,都在使用WTL。我当然知道这主要是因为WTL的出色,但我想,能够在没有官方的力量牵涉的情况下吸引如此多的注意,WTL一定还有更出色的东西,请问您是如何看待WTL的成功呢?它成功的原因又是什么?

【Nenad】: I think that the main reason of WTL's success is that it did fit the need of developers at the right time. More and more developers started using ATL, and it was natural for them to start using WTL when they needed more UI support. It seems that WTL was perceived as a more open project than others, judging by the support provided by other parties in the development community. Many people did a wonderful job of creating samples, documentation and support for WTL. The support from the programming community is very important part of the acceptance and success of WTL.

【Nenad】:我认为WTL成功的最主要原因就是,它确实而且及时地满足了开发者的需求。越来越多的开发人员开始使用ATL,当他们需要更多的UI支持时,他们很自然的就会开始使用WTL。 从其他的开发团队所提供支持来看,WTL看起来似乎要比其他的项目更加开放。许许多多人为WTL做了大量工作,如:创建示例代码,撰写文档等。WTL之所以能够被广为接受并获得如此大的成功,来自于这些开发团队的支持绝对是一个重要的因素。

【C++ View】:What do you think about MFC? Do you like it? If you don't, why? And the most confusing thing is Managed C++, is it C++? Do the leaders of MC++ really think some C++ users will go to learn it? Do you believe?

【C++ View】:请问您对于MFC是怎么看的?您喜欢它吗?如果不,为什么呢?还有,最让人迷惑不解的就是Managed C++了,它是不是C++呢?MC++的提倡者是不是真的认为会有一些C++的用户转而去学习它呢?您的看法又是如何呢?

【Nenad】: I think that MFC is a great framework library. Don't forget that MFC was designed at the time that C++ compiler was rather limited, and the main platform was 16-bit Windows. Unfortunately, because MFC was designed as a framework, it was really hard to evolve it to use better C++ support in newer compilers, and to add support for new features added to Windows in the meantime. What I don't like about MFC is the DLL approach, which causes many compatibility problems, and framework design, which dictates too many things about app design.

Managed C++ is an extension to C++ which allows C++ programs to use managed code. It is very important to understand that you can compile your existing C++ code using MC++ without any changes. MC++ allows developers to use both familiar non-managed C++ and managed code in the same module. That provides an excellent way to extend existing code to interact with managed code, as well to create new projects that can use both managed and traditional C++.

【Nenad】:我认为MFC是一个了不起的框架库。请不要忘了,在MFC被设计出来初期,那时的C++编译器还具有很多的限制,并且那时主要的平台还只是16位的Windows。不幸的是,由于MFC被设计成为一个框架,使得我们很难利用新编译器中那些更好的C++特性来改进它,也很难将Windows中的很多新特性添加到MFC中。我不喜欢MFC的地方是它高度依赖DLL的特性——因为它将导致许多兼容性方面的问题;还有就是MFC的整个框架设计——它在应用程序的设计中限定了太多东西。

Managed C++是C++的一个扩展,它允许C++程序得以使用受管(managed)代码。我们需要了解的一个很重要的特性就是,我们可以使用MC++来编译已有的C++代码而无需对它们进行任何改动。MC++允许开发者同时使用他们所熟悉的非受管代码以及受管代码来开发同一个模块。这就提供了一个非常好的途径,使已有的代码与新的受管代码相互作用,并也可使得我们创建一个项目,同时使用受管的和传统的C++代码。

【C++ View】:In the past 15 years or more, C and C++ is the base of almost all Microsoft's technologies(OS, COM, etc.). We C++ user paid a lot of hard work to catch them, because we felt what we paid was worthy(?). Now, it seems the climate changed. .NET is coming, the world is going to be full of CLRs and/or JVMs. There has been a decampment from C++. So what do you think about the future of C++ (not MC++) in Mircosoft technologies? Will it go away? Will it become a marginal language?

【C++ View】:在过去的15年中(甚至更长的一段时间内),C以及C++构成了几乎所有Microsoft技术的基础(如:OS,COM等)。我们这些C++用户花费了大量的时间来熟悉并掌握它们(C以及C++),因为我们相信我们所付出的一定会有回报(?)。但现在的风向好像有了很大的改变。.NET出现了,世界似乎就要充斥CLR (Common Language Runtime,公共语言运行库)以及/或JVM (Java Virtual Machine,Java虚拟机)。现在C++已经出现了退潮的迹象。那么,请问您对于C++(不是MC++)在Microsoft技术中的前景如何看待?它是否会由此消亡?还是就此沦落为一门边缘语言?

【Nenad】:Well, the world is changing too. The new type of development for Web services and connected applications is on the horizon. I think that new languages, like Java, C#, and VB.NET, were developed to address two main issues - to simplify software development and to provide better support for Internet development. Simplifying software development allows more developers to write good applications and cuts down on time needed to finish a project. Supporting Internet development is obviously very important in this time when Internet is used more and more in every part of everyday life.

I think that C++ will continue to be an important language, especially for ISV's and for system development. On the other hand, I believe that .NET will be very important platform soon. .NET has the potential to be the main programming platform for the future, but it is reasonable to expect that the transition will take some time.

【Nenad】:是的,世界也已经发生了变化。对于网络服务以及连接这样的新型应用程序的开发已经浮上了水面。我认为那些新的编程语言(如Java,C#,以及VB.NET)都是针对以下两个主要的问题而开发出来的——简化软件的开发过程以及对于Internet应用程序开发提供更好的的支持。简化软件的开发过程使得更多的开发者可以写出更多更好的应用程序并减少完成开发项目所需要的时间。而支持Internet的开发,对于这个Internet越来越深入到我们的日常生活中的时代来说,毫无疑问是一件非常重要的事情。

我认为C++会继续作为一门重要的编程语言发挥作用,尤其是对那些独立软件开发商和那些系统级开发来说更是如此。从另一方面来说,我相信.NET将会在不久以后成为另外一个非常重要的开发平台。对于未来来说,.NET拥有成为主流编程平台的潜力,但我们必须认识到,这样的过渡阶段肯定要持续一段时间。

【C++ View】:There a lots of beginners in our readers, after they learn (standard) C++, they want to seek a path to master enought Microsoft technologies to be practical and proficient programmers. Could you recommend such a path? Should they learn Win32 API programming? Is it worthy of studying MFC? Is WTL/ATL/STL a reliable solution? Or goto C# directly? Many many people will thank you if you give them frank advice.

【C++ View】:我们的读者中有很多是初学者,在他们学习完(标准)C++后,他们希望能够找到一条道路,掌握到足够多的Microsoft的技术使自己成为经验丰富的、熟练的程序员。您能不能给我们指出这样的一条道路来呢?我们是不是应该学习Win32 API编程?学习MFC是否是值得的?WTL/ATL/STL算得上是一个可靠的解决方案吗?又或是我们应该直接学习C#?如果您能够给我们一些建议,相信会有很多的人为此而感激您的。

【Nenad】:I think that depends on their plans and ambitions. The more of those things you do, the better you are off in the long run. But, you also have to balance that with the practical issues. So, I think that people who see their future in the Internet development can go directly to C# or VB.NET, and study .NET platform. Those who would like to have more knowledge of the Windows platform and services it provides should certainly learn more about Win32 API and libraries that support Windows programming.

【Nenad】:我认为这主要取决于他们的计划以及雄心。你所做的越多,在长时间竞争中你就越占据优势。不过你也要注意保持与实际问题的平衡。我建议那些决心以后只做Internet相关开发的人可以直接去学习C#或者VB.NET,同时学习.NET平台。而那些更多地了解Windows平台以及它所提供的服务方面知识的人,当然就必须需要更多地了解有关Win32 API以及那些支持Windows编程的库相关的知识。

【C++ View】:Soon after I began to learn WTL, a warm-hearted man posted me a email. He wrote: "You won't be a good WTL programmer if not a good ATL programmer, you won't be a good ATL programmer if not a COM programmer. And once you decide to learn COM, you are beginning your travel to hell." Is COM so difficult to learn? How to study WTL? We must learn API, COM, ATL and WTL in sequence, do we? And what about COM, will it remain to be the core technology of Microsoft, or just be substituted by .NET and dismiss?

【C++ View】:在我刚开始学习WTL后不久,有一位热心人给我发了份邮件。他写道:“如果你不是一个好的ATL程序员的话,你就不可能成为一个好的WTL程序员;如果你不会COM编程的话,你就不可能成为一个好的ATL程序员;但一旦你决定开始学习COM,你就迈出了踏向地狱的第一步。”COM是不是真的那么难学?我们应该如何地来学习WTL呢?我们是不是应该按照这样的顺序学下来呢,API->COM->ATL->WTL?还有,COM将会变得如何?他是不是还能够保持Microsoft的核心技术这一头衔,抑或是被.NET给替换掉然后就此消失?

【Nenad】:I don't think it is necessary to master COM to use and understand WTL. Win32 UI knowledge is more important than COM to understand WTL. But it is true that knowledge of ATL is required, and ATL mainly supports COM. So, COM knowledge is desirable, but not required.

I don't think that COM is hell, but it sure does require a lot to learn to be an expert. Keep in mind that many people don't have to be COM experts to use COM, or to use WTL. Just understanding basic principles of COM is enough to use it, and then people can learn more when needed.

【Nenad】:我不认为使用和理解WTL就一定要掌握COM。相比于COM来说,Win32 UI的知识对于理解WTL显得更为重要。但毫无疑问的是,ATL的相关知识是必不可少的。由于ATL主要任务就是支持COM,所以,有COM的知识只是会更好一些而已,但它们并不是必需的。

我也不认为COM是一个噩梦,但毫无疑问的是,想要成为一个COM专家,要学的东西实在是太多了。但请记住一件事情,很多使用COM或者WTL的人并不都是COM方面的专家。要想使用它们,人们所需了解的只是一些COM的基本原理就够了,其他的相关的知识则可以在需要时再去学习。

【C++ View】:What do you think about Generic Programming? Is it a whole different paradigm from OOP, or just OOP's supplemental facility? Can we combine GP and OOP? In the hard work of design and implement WTL, you must had got an insight about the relationship between OOP and GP, what's it?

【C++ View】:请问您对于泛型程序设计是如何看待的?它到底是OOP的一个补充呢,还是完全不同于OOP的另外一个程序设计范型呢?我们是否可以将GP以及OOP一同联合使用?我想,在设计和实作出WTL的艰苦过程中,对于OOP以及GP之间的关系,您一定有了自己的看法,您能不能给我们说一下呢?

【Nenad】:Generic Programming and OOP are very different, mostly because Generic Programming doesn't explicitly express relationships between design elements. They can, however, be used together very efficiently.

WTL uses a combination of Generic Programming and OOP design. Templates are mostly used to implement traditional OOP classes. I'd like to point out that WTL doesn't use any "pure" design, and it doesn't strictly follow any design guidelines or styles. I do think, though, that WTL does use one of the main strengths of the C++ language - it uses appropriate paradigm that is the most suitable for a particular problem.

【Nenad】:GP和OOP非常不同,这主要是由于GP从不显式地表达出设计元素之间的关联来。然而,它们也可以被非常高效地组合运用。

WTL中使用了一种GP连同OOP的设计。我在其中大量使用了模板来实作出传统的OOP中的类。我很乐意指出的是,WTL中并没有使用一种“纯”设计,它也没有遵循任何的设计指导方针或者设计规格。可是,我还是认为WTL使用到了C++语言中的最主要的精髓处——对于一个特定的问题使用一种最适合它的适当典范。

【C++ View】:Recently, the famous C++ pioneer Stanley Lippman joined Microsoft and became a member of Visual C++.NET group. How do you think about this? What message do you think your company like to pass to public? Does this mean Microsoft want to make VC.NET a full-standardized C++ compiler and hold C++ as your core system language?

【C++ View】:最近,著名的C++元老级大师Stanley Lippman加入了Microsoft并成为其VC.NET开发小组中的一员。请问您对于此事是如何看待的?您认为Microsoft试图向公众传播一种什么样的信息呢?这是否也意味着Microsoft希望VC.NET成为一个完全标准化的C++编译器,并继续保持C++的核心系统语言地位呢?

【Nenad】:I think that shows that Microsoft is committed to advance the C++ compiler and language, and ready to get the best people to help. I am sure that VC++.NET will continue to be powerful tool for developing applications, and that it will also include additional capabilities for the .NET development. Compliance with the C++ Standard is an ongoing work, and we will see further improvements there, too.

【Nenad】:我认为这显示了Microsoft对于促进C++编译器以及语言继续发展的决心,并为此找到了最佳人选来获取帮助。我确信VC.NET将会继续是开发应用程序的强有力工具,并且它同时还将包含有.NET开发能力。目前我们正在进行兼容C++标准方面的工作,不久我们就会看到成效。

【C++ View】:I'm learning WTL and ATL, since you are the author of WTL and a member of ATL group, can you give me some advice?

【C++ View】:我现在正在学习WTL以及ATL,既然您是WTL的作者,同时又是ATL开发小组中的一员,您能不能给我一些建议呢?

【Nenad】:There are several areas of programming that are very important for WTL and ATL: knowledge of the C++ language in general, understanding of templates, COM for ATL, and Windows UI programming for WTL. Solid knowledge in these areas is very beneficial for WTL and ATL developers, and it also helps to understand the source code for both libraries.

I would also like to encourage everybody to write programs. That is the best way to learn how to use any library, or a programming language or operating system. Writing programs often brings problems that must be solved that are not addressed in books. Reading about something is very useful to start learning, writing programs is the best next step.

【Nenad】:对于WTL和ATL来说,有好几个编程方面的领域是十分重要的:大体上的C++语言知识,了解模板,COM(对ATL而言),以及Windows UI编程(对WTL而言)。在这些领域有着坚实的基础对于WTL以及ATL开发人员来说有着很大的好处,同时对于理解这两个的源代码也能够起到帮助作用。

我同样也很乐意去鼓励大家多写程序。这也是学习如何使用一个程序库,或者一门编程语言,或者一个操作系统的一个最好的方法。在写程序的过程中经常会出现一些书本上没有提及但又必须被解决的问题。在开始学习时读一些东西是很有用的,而写程序则是向纵深发展的最佳方式。

【C++ View】:They say we are in the gate of Post-PC times, it will be a embedded world, and there will be embedded smart device everywhere, and the embedded industry will build a far large market compare to PC's. Do you believe it? Do you think WTL and other C++ template libraries are available and appropriate for embedded development? Are there available for Internet development?

【C++ View】:有人说,我们现在已经处于后PC时代的门口,未来将会是一个嵌入系统的世界,嵌入式的智能设备将会无所不在,并且对比PC来说,嵌入系统的产业将会是一个更大的市场。您是否相信这些呢?您是否认为WTL以及其他的一些C++模板库对于嵌入式开发也适用呢?它们是否适合Internet开发?

【Nenad】:Yes, I think that large number of various devices that we use everyday will become small, specialized computers. That doesn't mean that the number and importance of PCs will go down, just that there are many other devices that will be enhanced to be programmable and connected. Those new devices will provide a great opportunity for software developers, because they will all have software and somebody has to write it.

Many of the C++ libraries are quite appropriate for embedded development, and WTL would also be in cases where Windows based user interface is important (for example, Pocket PC platform). Great flexibility and small footprint are always very important features for embedded development, so template libraries are in the very good position there.

【Nenad】:是的,我认为我们现今所使用的各种设备中的大部分在以后都将会演变成为一些小的,具有专门用途的计算机。但这并不意味着PC的数目以及重要性将会由此降低,只不过是表明还有着许多其他的设备需要被加强以使得我们可以对其进行编程并且连接。由于必须需要有软件的支持,而软件又需要有人来写,这些新的设备将会给软件开发人员带来极大的机遇。

有许多的C++函数库都可用于嵌入系统的开发,WTL也将会在那些Windows用户界面较为重要的开发中(例如,在Pocket PC平台上面开发)占有一席之地。对于嵌入式开发来说,良好的弹性,微小的内存耗用永远都会是很重要的特性,而模板库在这方面占据了一个非常好的地位。

【C++ View】:In the past 7 years or more, COM is Microsoft's core technology. And we now can see that in the next decade, the core role may be .NET. My question is, what's wrong with COM? Where will COM be? Will it disappear? Will it be substituted by something else? What's the relationship between COM and .NET? Is .NET based on COM? Is it worthy of learning COM now?

【C++ View】:在过去的7年(甚至更长的一段时间)内,COM都是Microsoft中的核心技术。现在我们可以预见到,在下一个十年间,这个核心将会变为.NET。我的问题就是,COM有什么过错?COM将何去何从?它是否会逐渐消失呢,还是会被其他的一些技术给替代?COM和.NET之间的关系是什么样的情况?.NET是否是基于COM之上呢?现在学习COM是不是还值得?

【Nenad】:Maybe you shouldn't ask what is wrong with COM, but just think of .NET as the evolution of COM. .NET extends what was started with COM- creating reusable binary components - and brings additional important features: rich metadata, great run-time, built-in security, versioning, etc. All of these new features are important for development today, and it is really great that .NET has extensive support for them. Interoperability between .NET and COM is also provided, so that the previously developed COM components can still be used in the .NET environment.

I still think that it is a good idea to learn COM - it is a great first step even for people who want to learn .NET, and it also provides better understanding of the design and implementation of .NET itself.

【Nenad】:或许你不应该问COM有什么过错,而是应该把.NET看成COM的进化。.NET扩展了COM最初的目的——创建可重用的二进制程序组件——并向其中添加了很多重要的特性:丰富的元数据,了不起的运行库,内建的安全机制,版本机制等。对于现今的软件开发来说,所有的这些新的特性都非常重要,所以.NET能够广泛地支持它们,是一件很伟大的产品。Microsoft同时也提供了在.NET和COM之间进行互操作的能力,这使得以前所开发出来的COM组件在.NET环境中同样也能够得到使用。

我仍然认为学习COM是一个很好的主意——它甚至对于那些希望学习.NET的人们来说也是一个很好的开端,学习COM同时也有助于我们更深入地理解 .NET本身的设计和实现。

【C++ View】:I know you must be a C++ fan. Now the language is facing lots of challenges. To counterattack, Dr. Stroustrup suggest to develop many useful libraries, and teach the programmers to use C++ as a high level language. Now there are several wonderful modern C++ libraries. Aside of ATL, WTL and STL, there are still Boost library, MTL, ACE/TAO, DTL, etc. It seems the C++ community is preparing a movement. Do you think the movement will success? Why? What are your colleagues'(in Microsoft VC.NET group) attitude towards such a movement?

【C++ View】:我猜想您肯定是一个C++爱好者。现在这门语言面对着许多的挑战。作为反击措施,Stroustrup博士提议开发许多有用的库,并引导C++程序员把C++当作一门高级语言来使用。现在我们已经可以得到好几个极好的现代的C++库,除去ATL、WTL以及STL之外,还有Boost库、MTL、ACE/TAO、DTL等。一切都显示着C++社区正在酝酿着一次变革。请问您觉得这场变革能否成功?为什么?您的那些Microsoft中的VC.NET开发小组中的同事对于此态度是怎样的?

【Nenad】:C++ is a great language and its importance remains high, even with the new challenges. Libraries are an excellent addition to the language itself, as they provide very useful reusable code for developers. The existence of many great C++ libraries shows the size and strength of the C++ community. I think that is already a success, and that it will continue. You can be sure that the VC++.NET group is aware of the existing libraries, and I expect them to continue to enhance the support for them.

【Nenad】:C++是一门伟大的语言,即便遇到了新的挑战,它仍然将是非常重要的。程序库对于语言本身是极好的补充,它们为开发者提供了一些十分有用的可重用代码。存在如此众多的、了不起C++程序库,这件事情本身就表明了C++社区的庞大和强大。我认为这场变革已经成功了,并且会一直成功下去。你们可以放心,VC.NET开发组是不会对这些已有的程序库熟视无睹的,我预期他们会不断地加强对于这些库的支持。

【C++ View】:The last question. Since lots of people don’t acquaint themselves with WTL, now we have a chance for you, the father of WTL, to introduce WTL in a short speech here. What would you like to speak?

【C++ View】:最后一个问题。既然许多人并不了解WTL,作为WTL之父,您现在有机会在这里做一个演讲,请简短地介绍一下WTL。

【Nenad】:WTL is a template based library for user interface development. It extends ATL to provide classes for implementing user interface for applications, components, and controls. It provides classes for various user interface elements: top-level windows, MDI, standard and common controls, common dialogs, property sheets and pages, GDI objects, UI updating, scrollable windows, splitter windows, command bars, etc.

WTL is implemented using the same template architecture as ATL, so it is a natural fit for ATL developers. It also doesn't alter or hide Windows specific constructs, thus allowing Windows programmers to use WTL without surprises. The important design goal of WTL was to avoid inter-dependencies - classes themselves do not reference other WTL classes. That means that your program will contain just the code that you actually use, and nothing else. Coupled with the use of templates, this allows creation of very small programs without run-time dependencies.

WTL delivers the object oriented way to program for the Windows user interface, while keeping the code size small. It also provides a great foundation that developers can extend with their own classes.

And finally - WTL was written with a hope that developers will enjoy using it. I hope you will use it and enjoy it, too.

WTL是一个基于模板的、专为开发用户界面的程序库。它扩展了ATL,并提供了一些类用来实现应用程序的用户界面、组件和控件。它提供了各种类来支持各种各样的用户界面元素:顶级窗口、MDI、标准控件和通用控件、通用的对话框、属性表以及属性页、GDI对象、UI更新、可卷动的窗口、分割窗口、命令条等等……

WTL的实现使用了和ATL一样的模板架构,所以对于ATL开发者显得很自然。同时它并没有改变或者是隐藏那些Windows相关结构,那些Windows程序员在使用WTL时也不会感到很吃惊。WTL的一个主要设计原则就是避免在没有引用到其他WTL类时,出现不必要的内部依赖。这意味着我们的程序将只包含有我们实际上所使用的代码,除此之外再无其他的东西。加上了模板的使用后,这样做得到的结果就是一些非常小的,不依赖于运行库的程序。

WTL专注于用面向对象的方法来编写Windows的用户界面程序,同时保持代码的尺寸很小。同时,它也为开发者提供了一个很好的基础,可以写新的类来扩展WTL。

最后,我在编写WTL时就希望开发者能够喜欢在开发中使用它。我同样也希望您能够使用它并喜欢上它。

posted @ 2006-07-05 00:14 will 阅读(229) | 评论 (0)编辑 收藏