What's New for MFC Developers?(翻译)

What's New for MFC Developers?
By Anson Tsao and Walter Sullivan
翻译:依栏望海( [email protected]
【译者:因为时间关系,俺在一些省略了一些细节的翻译,不过俺还是都点到了。有兴趣的朋友
可以继续做。大家可以随意转载,但请不要修改本文内任何文字。如果可以的话,转载时请用
mail通知俺。谢谢!有任何想和俺交流的更是欢迎之至!15:29 2002-1-8】

MFC和ATL已经有三年没有大的更新了。在Microsoft.NET的强大宣传下,MFC和C++开发者感到被抛弃了。
不过,不用担心——在即将到来的Visual Studio.NET中,Visual C++的开发者不仅得到一个和服务器
端开发全面而紧密的崭新的IDE,大大改良的C++编译器,MFC和ATL也得到了新的重要特性。有一个清晰
消息就是MFC依然会是在所有windows平台上,拥有众多客户程序,最好最悠久的framework。在这篇文章里,
我们将带你纵览这些可以用在您的MFC程序上的新的特性。

·使用新的MFC DLL (MFC70.DLL),不再兼容MFC42.DLL,但你的源程序依然保持兼容性(消息映射更加类
型安全,所以可能导致某些代码违例)。

·MFC和ATL更加结合紧密了,一些通用的类如CString可以同时被两个库使用。

·头文件与新的Platform SDK同步,支持2k和XP中的新UI特性,如主题(themes),manifest resources,
Active Accessibility和新的通用对话框。

·增加了不少UI的类,包括支持DHTML的对话框和支持扩展BITMAP的CImage。

·新的工具类可以在MFC和ATL中使用,比如正则表达式,计数器和安全。

·MFC应用程序有力地支持web Services。ATL服务器类编写Web Services和应用程序。

·使用新的OLE DB特性使得高效率地访问数据库从来就没有像现在这样容易。

·STL被更新

一体化MFC和ATL

能否在ATL中使用CString,或者在大型的MFC中使用ATL实现COM对象?哈,现在可以了。在MFC 7。0中
有不少的工具类可以在ATL和MFC之间共享:CString,CPoint,CRect,CSize和CImage。而且,ATL可以在
无需MFC支持的情况下使用。
CString被完全改写了,现在基于模板类CStringT<>。它支持各种字符类型(char, wchar_t, TCHAR)和
建立在CRT的基础上。你还可以在CString中自行管理内存的分配。
【译者:比如
typedef struct my_chr {
unsigned int a;
unsigned int b;
unsigned int c;
} MY_CHR;

CStringT

  1<my_chr> My_Str;   
  2...   
  3  4
  5  
  6
  7
  8MFC7.0增加了一个新的字符串类叫CFixedStringT&lt;&gt;。这种定长字符串提供一种用户定义长度的方法,在耗尽   
  9内在的空间前无需额外的内存。CFixedStringT被用于基于栈的变量或联合容器中的元素时,效率非常高。   
 10它显著地减少了基于堆的分配。   
 11【译者:这里俺也糊涂了,呵呵,请各位指正。原文如下:   
 12CFixedStringT's are very efficient when used as stack-based variables or as keys in associative   
 13containers, dramatically reducing the number of heap-based allocations.   
 14 15
 16  
 17
 18
 19下面的例子创建一个有1024个字符的实例: 
 20
 21  
 22
 23
 24// allocating 1024 character internal buffer   
 25CFixedStringT&lt; CString, 1024 &gt; string; 
 26
 27  
 28
 29
 30  
 31
 32
 33新的UI特性及升级   
 34MFC7.0提供DHTML对话框支持,有一套DHTML编辑器类,新的图形API(GDI+),更新了对BITMAP支持(CImage),   
 35添加一个通用对话框包装类(CLinkCtrl),更新控件和对话框支持2k和XP,增强了ActiveX control容器和提高了   
 36消息映射的类型安全。让我们逐一看看吧。 
 37
 38  
 39
 40
 41  
 42DHTML对话框及DHTML编辑器类   
 43DHTML对话框把丰富多彩的HTML用户界面带到桌面应用程序上来。现在你的桌面App拥有时髦的图形界面和一般   
 44web应用程序没有的爽快的交互性。MFC7.0提供了CDHtmlDialog和CMultiPageDHtmlDialog来支持DHTML。DHTML   
 45对话框可以从资源文件或任何有效的URL中显示HTML页面。如果你曾用过CHtmlView,就知道获取和设置HTML元素   
 46需要通过IHTMLDocument2对象,而且处理HTML的事件是非常痛苦的事。CDHtmlDialog极大地简化了这种交互,使   
 47用一套类似DDX的扩展宏和DHTML事件映射。DDX_DHtml_宏和传统的DDX_宏同样在DoDataExchange函数中使用。它   
 48允许获取和设置各种HTML元素的属性。例如,DDX_DHtml_CheckBox绑定复选框的值,DDX_DHtml_ElementInnerHtml   
 49设置和获取某个元素的HTML。绑定一个HTML元素到DDX需要这个元素有的一个'id='的属性,就像下面的代码所示: 
 50
 51  
 52
 53
 54<html><body>   
 55Filename: <span id="filename"></span><br/>
 56<input accesskey="r" id="readonly" type="checkbox"/>
 57<u>R</u>ead-only   
 58</body></html>   
 59void CPropertiesDlg::DoDataExchange(CDataExchange* pDX) {   
 60CDHtmlDialog::DoDataExchange(pDX);   
 61//{{AFX_DATA_MAP(CPropertiesDlg)   
 62//}}AFX_DATA_MAP   
 63DDX_DHtml_ElementInnerText(pDX, _T("filename"), m_strFileName);   
 64DDX_DHtml_CheckBox(pDX, _T("readonly"), m_nReadOnly); }   
 65To respond to HTML control events, you have to define a DHTML event map: 
 66
 67  
 68
 69
 70BEGIN_DHTML_EVENT_MAP(CDHtmlExploreDlg)   
 71DHTML_EVENT_ONCLICK(_T("browse"), OnBrowse)   
 72DHTML_EVENT_CLASS(DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER,   
 73T("hotElement"), OnMouseOverElement)   
 74END_DHTML_EVENT_MAP() 
 75
 76  
 77
 78
 79  
 80这些事件映射类似MFC的样式,包括DECLARE_DHTML_EVENT_MAP的定义和在BEGIN_DHTML_EVENT_MAP与END_DHTML_EVENT_MAP   
 81之间的定义。   
 82CMultiPageDHtmlDialog适合导向和属性页有关的对话框。它可以在一个对话框中装载多个页面并且使用内在事件映射   
 83响应事件。   
 84这个新版本还提供了所见即所得(WYSIWYG)的DHTML编辑器。这意味着在你的程序中调整一个HTML元素并不比调整   
 85一个文本控件困难。类似MFC6.0对于rich edit控件的支持,MFC7.0提供了CHtmlEditCtrl,还有类似的文档视图   
 86类:CHtmlEditView/CHtmlEditDoc。但你仍然需要自行调整UI元素,如字体、风格、颜色、等等。 
 87
 88  
 89
 90
 91  
 92GDI+   
 93GDI+ 是一个新的图形子系统,提供一整套图形API渲染2D图象,图片和文字。它是.NET中唯一的API,但在C++中,   
 94它补充了GDI的渲染能力。   
 95通过GDI+可以获得:更强的2D制图,alpha通道支持,通用坐标转换和浮点支持,还有渐变笔刷,cardinal splines,   
 96scalable regions和新的编程模式。   
 97GDI+以C风格的API形式发布,虽然一套C++类将其包装,但不被MFC支持而是在.NET中使用。使用GDI+,使用gdiplus.h   
 98并且链接gdiplus.lib。还必须在使用前初始化这个库。GDI+是XP的一部分,如要在98、me、nt4.0和2k上使用就要拷贝   
 99GdiPlus.DLL到相应的目录。   
100GDI+使用了与GDI不同的编程模型。在GDI+中必须在每次画图命令中传入笔或刷子。图形元素不在和笔与栓子一起工作;   
101勾勒边框和填充被分开成不同的函数来实现(如DrawRectangle和FillRectangle)。下面的例子演示画一个矩形   
102(3.5 英寸 × 4.4 英寸)。 
103
104  
105
106
107  
108using namespace Gdiplus;   
109void CMyView::OnDraw( CDC* theDC )   
110{   
111Graphics graphics( *theDC );   
112Pen pen( Color( 128, 255, 0, 0 ), 2.0 ); // Alpha value set   
113// Realworld units   
114graphics.SetPageUnit( UnitInch );   
115// Floating point coordinates   
116graphics.DrawRectangle( &amp;pen, RectF( 0.0F, 0.0F, 3.5F, 4.4F ));   
117} 
118
119  
120
121
122  
123用CImage管理Bitmap   
124期待已久的Bitmap支持终于在这个版本实现了。CImage可以读取和存储JPEG、GIF、BMP和PNG格式的图形文档。   
125但是一些函数不被旧系统支持(如95),还有一些函数在不同的os上的具体实现不一样。CImage可以在MFC和   
126ATL中使用。它也包装了DIB的功能,可以直接操作象素点。让我们来看看CImage提供了什么吧: 
127
128  
129
130
131·Alpha象素点混和透明和半透明效果 
132
133  
134
135
136·PlgBlt可以随意的映射一个矩形到一个并行四边形 
137
138  
139
140
141·TransparentBlt可以根据一种指定的颜色进行透明操作 
142
143  
144
145
146·MaskBlt可以混和两张图片到一个输出设备上 
147
148  
149
150
151·CImage::GetDC可以直接向一幅bitmap画图。 
152
153  
154
155
156下面给出一个例子: 
157
158  
159
160
161CImage image;   
162Image.Load( "test.gif" );   
163CBitmap* pBitmap = CBitmap::FromHandle( image.m_hBitmap ); 
164
165  
166
167
168  
169CLinkCtrl通用对话框类   
170CLinkCtrl包装了SYSLINK控件,可以轻松地在windows上放置超链接,但只在XP上使用。它支持一个或多个   
171超链接,你可以在OnNotify中处理NM_CLICK和NM_RETURN消息响应点击事件。 
172
173  
174
175
176  
177对2k和XP的支持   
178所有的通用控件,CCheckListbox,文件处理和打印都被更新以支持2k和XP。CWnd的方法也被更新以支持   
179新的特性如分层窗口(layered windows)和活动窗口(animated windows)。CListView在XP中支持平铺风格。   
180MFC7.0支持XP的主题(themes)。   
181CWnd现在支持Active Accessibility。   
182新的CPrintDialogEx更新了打印对话框。 
183
184  
185
186
187  
188增强的ActiveX容器   
189MFC7.0和ATL支持无窗口的ActiveX,并且容器可以被改写。现在MFC也享受和Visual Basic一样的容器优化。   
190现在你可以改写COleControlSite以增加属于自己的容器行为。 
191
192  
193
194
195  
196类型安全的消息映射   
197MFC7.0加强了对消息处理函数返回值的校验。比如在OK中返回void而不是LRESULT的话,编译器会认为是一个   
198错误。 
199
200  
201
202
203  
204应有尽有的工具类   
205新的工具类有:正则表达式类(regular expression class)、64位日期时间函数、集合模板类、安全类、   
206包装CryptoAPI的函数和类、支持计数的宏和线程池支持。我们会在后面一一简要介绍。 
207
208  
209
210
211  
212正则表达式类(regular expression class)   
213这个模板类用于字符串的查询和比较,同时支持MBCS和Unicode。一共有两个模板类:CAtlRegExp和   
214CAtlReMatchContext。   
215下面给出一个例子:   
216CAtlRegExp&lt;&gt; re; // using the default character trait   
217re.Parse( "ab.d" );   
218CAtlReMatchContext mc;   
219re.Match( "abcd", &amp;mc ); // returns TRUE, successful match   
220re.Match( "bbcd", &amp;mc ); // returns FALSE, no match 
221
222  
223
224
225  
22664位日期时间函数   
227你的代码也许不会有千年问题,但标准的C运行库会在2038年1月18号19:14:07后出错。而新的64位日期时间函数   
228可以坚持到3000年12月31号。   
229CTime、CTimeSpan和C运行库都被更新支持__int64数据类型,包括CTimeSpan::GetDays64,   
230CTimeSpan::GetTotalHours64, CTimeSpan::GetHours64, CTimeSpan::Serialize64,   
231CTime::GetTime64,和CTime::Serialize64;还有_ctime64, _wctime64, _ftime64, _futime64, _gmtime64,   
232_localtime64, _time64, _utime64, _wutime64; _findfirst64, _wfindfirst64, _findnext64, _wfindnext64;   
233and _stat64,和_wstat64。 
234
235  
236
237
238  
239ATL的集合类和矩阵类   
240ATL7.0提供五个新的集合类:AtlArray,CAtlList,CAtlMap,CRBMap,和CRBMultiMap。它们可以更好的支持   
241非标准的数据类型。使用一些可以描述元素品质的类,这些类描述元素如何被拷贝,移动,比较清除。   
242有CAutoPtrElementTraits, CAutoVectorPtrElementTraits, CComQIPtrElementTraits, CStringElementTraits,   
243等等。这些ATL集合类不支持序列化。使用它们要同时指定元素类型和描述元素的品质: 
244
245  
246
247
248CRBMap&lt; CString, CStringElementTraits<cstring>,   
249CAutoPtr<cmyobject>, CAutoPtrElementTraits<cmyobject> &gt;;   
250这里定义了一个字典,映射CString给CMyObject的自动指针。CMyObject的元素会在集合类销毁时自动销毁。 
251
252  
253
254
255  
256
257
258安全类   
259安全类包装了NT所有的安全机制。ATL7.0包装了: 
260
261  
262
263
264·访问控制列表(CAcl) 
265
266  
267
268
269·任意访问控制列表(CDacl) 
270
271  
272
273
274·系统访问控制列表() 
275
276  
277
278
279·SID安全标识(CSid) 
280
281  
282
283
284·访问节点(CAccessToken) 
285
286  
287
288
289·访问结点组(CTokenGroups) 
290
291  
292
293
294·访问结点许可(CTokenPrivileges) 
295
296  
297
298
299·安全描述(CSecurityDesc) 
300
301  
302
303
304·安全属性(CSecurityAttributes) 
305
306  
307
308
309·一些全局函数 
310
311  
312
313
314不幸的是ATL 7.0不提供高级的安全模型,你仍然需要深入了解win32的安全机制。 
315
316  
317
318
319  
320Cryptographic类   
321Cryptographic类包装了win32的CryptoAPI,提供加密、解码、散列、数字签名和密匙管理。 
322
323  
324
325
326  
327
328
329That's it! If you don't want to use C++ attributes, there are corresponding classes and macros   
330that you can use instead. You should also be aware that setting counters to specific values is   
331generally safe without having to worry about thread synchronization, but performing calculations   
332on the counters, such as incrementing or decrementing, requires the use of atomic operations   
333such as InterlockedIncrement or synchronization using critical sections. 
334
335  
336
337
338性能测试(Performance Counters)   
339在你的程序中使用性能测试,需要实现三种类对象:性能监测管理对象,性能对象和性能测试器。   
340下面演示怎样定义性能监测管理对象: 
341
342  
343
344
345[ perfmon( name="MyApplication", register=true )]   
346class CMyApplicationPerfMon   
347{   
348}; 
349
350  
351
352
353然后可以使用性能测试器: 
354
355  
356
357
358void SetCounter( ULONG value )   
359{   
360if ( g_pStatsObject )   
361g_pStatsObject-&gt;SampleCounter = value;   
362} 
363
364  
365
366
367使用它们不必担心线程同步的问题,但是测试器需要原子操作,如InterlockedIncrement或synchronization。 
368
369  
370
371
372  
373
374
375线程池   
376MFC 7.0线程池是基于NT I/O Completion Port。CThreadPool是一个支持工作线程的模板类。   
377当一个线程可以工作时,你的工作线程的执行函数会被调用。工作线程的查询和执行遵循FIFO(先入先   
378出)原则。使用线程池必须: 
379
380  
381
382
383·一次一个线程地初始化 
384
385  
386
387
388·逐一执行在请求队列中的线程 
389
390  
391
392
393·一次一个线程地销毁 
394
395  
396
397
398·在工作线程类中声明一个RequestType typedef,它会在执行时被处理 
399
400  
401
402
403RequestType是一个不透明的类型,不能大于sizeof(ULONG_PTR)(即,x86 PC上的32位),所以你不可以   
404使用类的实例或大的原始类型(如浮点)。   
405下面是一个示例: 
406
407  
408
409
410class CMyWorker   
411{   
412public:   
413typedef CMyData* RequestType;   
414BOOL Initialize( void* initParam );   
415void Execute( CMyData* request, void* initParam, OVERLAPPED* pOverlapped );   
416void Terminate( void* initParam );   
417}; 
418
419  
420
421
422下面是怎样在线程池初始化和查询一个任务: 
423
424  
425
426
427CThreadPool&lt; CMyWorker &gt; threadPool;   
428  
429threadPool.Initialize();   
430threadPool.QueueRequest( new CMyData());   
431threadPool.Shutdown( 1000L ); 
432
433  
434
435
436  
437Web服务,Web应用程序和Network类   
438MFC7.0支持Web服务程序,编写Web服务和使用ATL服务器类编写Web应用程序。在下面的段落里,我们将   
439演示访问Web服务和调用服务的方法。还将解释如何生成HTML和把它写入IStream,怎样使用HTTP客户端和   
440怎样用MFC发mail。 
441
442  
443
444
445  
446To call the methods exposed by the Web Service, simply instantiate an instance of the proxy   
447class and call its methods, just like a native C++ class! 
448
449  
450
451
452#include "myservice.h"   
453???   
454MyService::CMyService service;   
455HRESULT hr = Service.MyMethod( CComBSTR( L"A Parameter" )); 
456
457  
458
459
460在MFC中支持Web服务   
461和DCOM不一样,Web服务容易透过防火墙访问,提供了一种真正的宽松的连接。使用Web服务不会比用#import   
462来的困难。使用命令行程序SProxy.exe就可以生成访问Web服务的C++客户端代码。生成的proxy类包含所有   
463你需要的一切。下面是个例子: 
464
465  
466
467
468sproxy /out:myservice.h   
469http://myserver/myservice.dll?Handler=GenMyServiceWSDL 
470
471  
472
473
474调用Web服务的方法,你只要初始化这个proxy类并直接调用其方法即可,就像普通的C++类: 
475
476  
477
478
479#include "myservice.h"   
480...   
481MyService::CMyService service;   
482HRESULT hr = Service.MyMethod( CComBSTR( L"A Parameter" )); 
483
484  
485
486
487  
488HTML生成器   
489CHtmlGen类和模板CHtmlGenBase&lt;&gt;支持该功能。CHtmlGen把一个完全的HTML写入IStream。使用它   
490只要用一个IStream初始化之并调用相应的方法即可。 
491
492  
493
494
495CHtmlGen out;   
496out.initialize( aStream );   
497out.html();   
498out.head();   
499out.title( "Test HTML" );   
500out.headEnd();   
501out.body();   
502out.a( " http://www.microsoft.com ", "Microsoft" );   
503out.bodyEnd();   
504out.htmlEnd(); 
505
506  
507
508
509  
510HTTP客户   
511CAtlHttpClient是一个轻量级的HTTP客户类,可以发出请求并获得回应。它支持代理和各种验证   
512(当前,支持Basic和NTLM)。CAtlHttpClient会同步发出请求,所以最好放置在多线程中。 
513
514  
515
516
517CAtlHttpClient client;   
518client.Navigate( _T( http://www.microsoft.com ));   
519CString contentType;   
520client.GetHeaderValue(_T("Content-Type"), contentType );   
521BYTE* pBody = client.GetBody(); 
522
523  
524
525
526CBasicAuthObject和CNTLMAuthObject支持验证。下面是一个范例: 
527
528  
529
530
531CNTLMAuthObject ntlmAuth;   
532client.AddAuthObject( _T("NTLM"), &amp;ntlmAuth ); 
533
534  
535
536
537  
538
539
540SMTP支持MIME编码消息支持   
541SMTP支持使你无需其他的mail客户端支持。CSMTPConnection直接连接一个SMTP服务器并   
542发送MIME编码的mail。CMimeMessage更可以在mail上加附件、原始数据和其他MIME编码   
543的消息。这个示例演示如何构造MIME消息: 
544
545  
546
547
548CMimeMessage message;   
549message.SetSender( _T(" [email protected] " ));   
550message.AddReceipient( receipient );   
551message.SetSubject( _T("A test message" ));   
552message.AddText( _T("This is a test message"));   
553CSMTPConnection connection;   
554connection.Connect( someSMTPServer );   
555connection.SendMessage( message ); 
556
557  
558
559
560  
561高效地OLE DB数据库访问   
562【译者:这段废话真多,总之就是比以前编程更容易了。不过,DB总是比较复杂的,短短   
563的一段也说明不了什么问题。偷懒不翻译了 :)】 
564
565  
566
567
568  
569更新的STL   
570添加的hash_map,hash_multimap和hash_set类基于新的hash-table-based扩展类。   
571它们类似于std::map,std::multimap和std::set,但有着非常不一样的性能特性。   
572Hash-table-based比binary tree-based在查找方面快得多。和map与set不同,hash   
573类不是有序的。   
574新版的STL也消除了basic_string著名的多线程问题。不再使用计数器,而已严格地   
575用拷贝来实现。   
576最后,STL有了更好的DLL支持。再也不是本地静态数据成员了。 
577
578  
579
580
581  
582
583
584Conclusion   
585Visual Studio .NET is a giant step forward for enhancing programmer   
586productivity, and the Microsoft .NET initiative will likely change the   
587programming landscape in the coming years. With this release of Visual C++,   
588MFC 7.0 has been updated to live in this new world of Web Services, while   
589gaining better C++ standard compliance, full integration with ATL, and numerous   
590enhancements to UI and utility classes. Best of all, these new features can be   
591added to your existing MFC applications. 
592
593  
594
595
596  
597总结   
598MFC得到了更好地接近了C++标准,完全地和ATL结合,在UI和工具方面大大增强。   
599最好的还是这些新特性可以加入到已存在的代码中。 
600
601  
602
603
604  
605关于作者: 
606
607  
608
609
610Anson Tsao有12年的行业经验,从事大型的Windows和C++的开发,最近加入   
611Microsoft Visual C++ Libraries小组。 
612
613  
614
615
616Walter Sullivan已经在Microsoft工作了11年,他的所有时间几乎都花在   
617Visual C++ product小组上面。他现在领导Microsoft C++ Class Libraries   
618程序管理的工作。 
619
620  
621
622
623About Translator   
624Just a C++ fans. :) Call me Kamp. I care code performance before, and now care   
625the performance of a certain project as a whole.</cmyobject></cmyobject></cstring></my_chr>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus