Visual C++ .NET: What's New for MFC Developers?

Visual C++ .NET

What's New for MFC Developers?


By Anson Tsao and Walter Sullivan

[早就计划翻译这篇文章,但遗憾的是,因为本职工作太忙,无法如愿!]

It has been three years since the last major update to MFC and ATL. With all the press on Microsoft® .NET, MFC and C++ developers may be feeling left out. But don't worry—with the upcoming release of Visual Studio .NET, not only do developers using Visual C++® get a brand new IDE with tight integration for server-side development and a much improved C++ compiler, MFC and ATL have also received significant new features. The clear message is that MFC continues to be a great framework for developing sophisticated, rich client applications for all Windows® platforms. In this article, we'll provide you with a survey of the new features that you can use in your MFC applications.

· There's a new MFC DLL (MFC70.DLL) that is no longer backward binary-compatible with MFC42.DLL, but your source is still compatible (although message maps have been made more type-safe, so that may break some code).

· MFC and ATL are much better integrated, and common classes such as CString are now shared between the two libraries.

· Header files are synchronized with the latest Platform SDK, supporting UI features in Windows 2000 and Windows XP such as themes and manifest resources, Active Accessibility®, and new common dialog boxes.

· Many new UI classes have been added, including support for using DHTML in dialog boxes and enhanced bitmap support with CImage.

· New utility classes can be used in both MFC and ATL applications, such as regular expressions, performance counters support, and security.

· Now there's support for consuming Web Services in MFC applications and writing Web Services and applications with ATL Server classes.

· High-performance access to databases has never been easier using the new OLE DB attributes and classes.

· STL has been updated.

** Integrating MFC and ATL **
Wouldn't it be nice to use CString in thin ATL ActiveX® controls, or use ATL to implement COM objects in large MFC applications? Well, now you can. In MFC 7.0 a number of utility classes have been made shared classes: CString, CPoint, CRect, CSize, and CImage. These classes can be used in ATL with no MFC dependencies.
CString has been totally rewritten based on the template class CStringT<>. Different specializations of CStringT<> allow for different character types (char, wchar_t, TCHAR) and dependency on the C runtime (CRT). You can also provide custom memory management for CString classes.
MFC 7.0 adds a new string type called CFixedStringT<>. Fixed strings provide a user-defined amount of storage within the string itself so there's no need for additional memory allocation until the internal storage is exhausted. CFixedStringT's are very efficient when used as stack-based variables or as keys in associative containers, dramatically reducing the number of heap-based allocations.
The following example shows how to create a fixed string with a 1024-character internal buffer.

// allocating 1024 character internal buffer


CFixedStringT&lt; CString, 1024 &gt;    string;

** New UI Features and Updates ** ** **
MFC 7.0 has new DHTML dialog support, a new set of DHTML editor classes, new graphics API with GDI+, updated bitmap support with CImage, a new common control wrapper class (CLinkCtrl), updated controls and dialogs for Windows 2000 and Windows XP, enhanced ActiveX control containment, and improved type safety in message maps. Let's take a look at each of these new and updated features.

DHTML Dialog Support and Editor Classes
The new DHTML dialog support brings graphics-rich HTML user interfaces to desktop applications. Now your desktop apps can have both the snazzy graphics that users have come to expect and the snappy interaction that's not possible with generic Web applications. MFC 7.0 has two classes to support using DHTML as dialog boxes: CDHtmlDialog and its specialization, CMultiPageDHtmlDialog. DHTML dialog boxes can load the HTML pages either from an application's resources or any valid URL.
If you have used CHtmlView before, you know that setting and getting data from HTML elements requires you to traverse the IHTMLDocument2 COM objects, and responding to events from HTML controls is even more painful. CDHtmlDialog greatly simplifies the interaction with the HTML elements with a set of extensions to the familiar DDX_ dialog data exchange macros and a DHTML event map.
The DDX_DHtml_ macros are used in DoDataExchange in much the same way as DDX_ macros are used in traditional dialog boxes. They allow you to set and get various properties of named HTML elements. For example, DDX_DHtml_CheckBox is bound to the value of a checkbox control, and DDX_DHtml_ElementInnerHtml sets and retrieves the HTML between the start and end tags of an element. To bind HTML elements to DDX, the elements must have the 'id=' attribute, as you can see in the following code.

 1<html><body>
 2    
 3    
 4        Filename: <span id="filename"></span><br/>
 5    
 6    
 7        <input accesskey="r" id="readonly" type="checkbox"/>
 8    
 9    
10            <u>R</u>ead-only
11    
12    
13    </body></html>

void CPropertiesDlg::DoDataExchange(CDataExchange* pDX) {

    CDHtmlDialog::DoDataExchange(pDX); 


    //{{AFX_DATA_MAP(CPropertiesDlg) 


    //}}AFX_DATA_MAP 


    DDX_DHtml_ElementInnerText(pDX, _T("filename"), m_strFileName); 


    DDX_DHtml_CheckBox(pDX, _T("readonly"), m_nReadOnly); }

To respond to HTML control events, you have to define a DHTML event map:

BEGIN_DHTML_EVENT_MAP(CDHtmlExploreDlg) 


DHTML_EVENT_ONCLICK(_T("browse"), OnBrowse)


DHTML_EVENT_CLASS(DISPID_HTMLELEMENTEVENTS_ONMOUSEOVER,     


                  T("hotElement"), OnMouseOverElement) 


END_DHTML_EVENT_MAP()

The event map is set up in the familiar MFC fashion, including DECLARE_DHTML_EVENT_MAP in the class definition and defining the map entries between BEGIN_DHTML_EVENT_MAP and END_DHTML_EVENT_MAP in the implementation file.
CMultiPageDHtmlDialog is useful for wizard and property page style dialog boxes. It allows you to load multiple pages into the same dialog boxes and respond to the events from each page using embedded event maps.
This release also gives you a WYSIWYG DHTML editor to generate or modify HTML documents. This means that embedding HTML editing capability in your application is not much more difficult than adding a text control. Similar to the MFC 6.0 support for the rich edit control, MFC 7.0 exposes HTML editing through a control class, CHtmlEditCtrl, and the view/document combo of CHtmlEditView/CHtmlEditDoc. You will, however, still need to provide the UI elements to change fonts, styles, color, and so on.
GDI+
GDI+ is a new graphics subsystem for Windows and provides a new set of graphics APIs for rendering 2D graphics, images, and text. GDI+ is the only API for drawing in the .NET Framework, but in native C++ it is a complement to the current GDI to provide more advanced rendering capabilities.
Here's what you get with GDI+: antialiased 2D drawing, alpha channel support, universal transformations and floating point coordinates, gradient brushes, cardinal splines, scalable regions, and a new programming model.
GDI+ is exposed through conventional C APIs, but there's also a set of C++ classes that encapsulates its functionality. Unfortunately, the GDI+ classes are not written in the style of MFC, instead they are named with the .NET Framework conventions. Nevertheless, they can be easily used in MFC apps. To use GDI+, you have to include the gdiplus.h header file and link with gdiplus.lib. You also have to initialize the library before calling any of its functions. The GDI+ feature can be easily redistributed. GDI+ is standard on Windows XP. For Windows 98, Windows Me, Windows NT® 4.0, and Windows 2000, you can simply copy GdiPlus.DLL into your app's directory.
GDI+ uses a different programming model from GDI. Instead of selecting brushes and pens into a device context, in GDI+ you pass the pen or brush into every drawing command. Graphics elements are no longer drawn with both the pen and brush together; they are outlined and filled using separate functions (such as DrawRectangle and FillRectangle).
The following code shows how you would draw an outline of a rectangle (3.5 inches × 4.4 inches) in response to OnDraw.

using namespace Gdiplus;


void CMyView::OnDraw( CDC* theDC )


{


    Graphics graphics( *theDC );


    Pen pen( Color( 128, 255, 0, 0 ), 2.0 );    // Alpha value set 


    // Realworld units


    graphics.SetPageUnit( UnitInch );


    // Floating point coordinates


    graphics.DrawRectangle( &amp;pen, RectF( 0.0F, 0.0F, 3.5F, 4.4F ));


}

** CImage for Managing Bitmaps **
The long-awaited update to bitmap support is also in this release of MFC. CImage can load and save images in JPEG, GIF, BMP, and PNG file formats. However, a number of the functions are not supported in older versions of Windows (like Windows 95), and a few functions behave differently in different OSs, so make sure you check for version compatibility. CImage is a shared class, usable in both MFC and ATL. CImage also encapsulates the device-independent bitmap (DIB) section functionality, allowing you to directly manipulate bitmap bits.
What are the cool things you can do with CImage?

· AlphaBlend supports pixel-level color blending for transparent and semi-transparent effects.

· PlgBlt maps a rectangle in the bitmap to a parallelogram in the destination, optionally with a bit mask.

· TransparentBlt specifies a color as the transparent color.

· MaskBlt combines the bitmap with a mask bitmap when drawing to the destination.

· CImage::GetDC allows you to draw directly onto the CImage bitmap.

You can also use CImage where MFC expects CBitmap by doing the following:

CImage    image;


Image.Load( "test.gif" );


CBitmap*    pBitmap = CBitmap::FromHandle( image.m_hBitmap );

** CLinkCtrl Common Control Wrapper Class **
The only new common control wrapper class added to MFC 7.0 is CLinkCtrl. A convenient way of placing hyperlinks in windows, it is only available for Windows XP, wrapping the Win32® SYSLINK control. CLinkCtrl supports one or more

  1<a> hyperlink anchors and can link to any valid URL. You can respond to the hyperlink clicks by responding to OnNotify (NM_CLICK and NM_RETURN) messages.   
  2**Windows 2000 and Windows XP Support**   
  3All Win32 and common controls, CCheckListbox, file, and print dialog boxes have been updated to include Windows 2000 and Windows XP support. CWnd methods have also been updated to reflect new UI features such as layered windows and animated windows. CListView now supports tiled views on Windows XP.   
  4MFC 7.0 apps are now created with a default manifest resource, allowing them to respond to Windows XP themes right out of the box. You can further override individual themes for controls by calling SetWindowTheme. As you can see in  Figure 1  , Windows XP themes change the visual styles of the caption bar, scroll bars, and other aspects of a window.   
  5  
  6Figure 1  Windows XP Themes    
  7  
  8CWnd has been updated to add Active Accessibility support. Calling EnableActiveAccessibility allows you to override the default support to add your own non-windowed elements. MFC handles normal windows as well as windowless ActiveX controls. Windowless controls are lightweight ActiveX controls that are optimized for faster rendering.   
  9Windows 2000 and Windows XP have new File Open and Save dialog boxes (see  Figure 2  ). MFC 7.0 applications using the CFileDialog class automatically take advantage of the new user interface.   
 10  
 11Figure 2  New File Open Dialog Box    
 12  
 13For printing support, Windows 2000 has more extensible print property sheets (see  Figure 3  ), replacing the older print dialog box. The new CPrintDialogEx encapsulates this functionality. You can customize the print property sheet by either extending the lower portion of the General page or adding your own property sheets.   
 14  
 15Figure 3  Print Property Sheets    
 16**  
 17Enhanced ActiveX Control Containment  **   
 18MFC 7.0 added support for containing windowless ActiveX controls and the control container is now overridable. Many new control containers such as Visual Basic® 6.0 can take advantage of this performance optimization, and now MFC does, too. ATL has support for building windowless ActiveX controls.   
 19Now that the container hosts ActiveX controls, the control container is accessible to your application. You can override pieces of the COleControlSite to add custom containment behavior. This greatly increases the flexibility you now have with MFC.   
 20**Type-safe Message Maps**   
 21And finally, MFC 7.0 message maps have been made more type-safe by providing stricter type checking of return values and parameters of the message handler functions. This will alert the developer to unsafe handlers that previous versions of MFC let slip. For example, it used to be OK to return void (instead of LRESULT) on an ON_MESSAGE or ON_REGISTERED_MESSAGE handler, and the compiler would not generate any warning. With MFC 7.0, the compiler will generate an error message.   
 22**Smorgasbord of Utilities**   
 23New utilities in MFC include a regular expression class, 64-bit date and time functions, template collection classes, security classes, wrappers for the Win32 CryptoAPI functions, classes and macros to support performance counters, and support for thread pools. In the next few sections we'll briefly describe these new utilities.   
 24**Regular Expression Class**   
 25The regular expression class adds to MFC's string searching and pattern matching capabilities. Regular expression support is provided by two templates: CAtlRegExp and CAtlReMatchContext. These templates can be specialized to support both Multibyte Character Set (MBCS) and Unicode strings.   
 26To use regular expressions, CAtlRegExp must first be initialized with the search expression using the Parse method, as you can see here: 
 27    
 28    
 29    CAtlRegExp&lt;&gt;    re;      // using the default character trait
 30    
 31    
 32    re.Parse( "ab.d" );
 33    
 34    
 35    CAtlReMatchContext mc;
 36    
 37    
 38    re.Match( "abcd", &amp;mc ); // returns TRUE, successful match
 39    
 40    
 41    re.Match( "bbcd", &amp;mc ); // returns FALSE, no match
 42
 43Then the CAtlRegExp object can be used to match against a text string. The results of any matches are returned to the CAtlReMatchContext object. If matches are found in the string, CAtlReMatchContext::GetMatch returns the starting and ending positions of the matched sequences.   
 44**64-bit Time and Date Functions**   
 45Your code may be safe from the Year 2000 bug, but did you know that the time and date functions in the standard C runtime library will fail after 19:14:07 on January 18, 2038? The new 64-bit time and date functions can be used to represent a date until midnight of December 31, 3000.   
 46CTime and CTimeSpan have new methods to use 64-bit time/date values, including CTimeSpan::GetDays64, CTimeSpan::GetTotalHours64, CTimeSpan::GetHours64, CTimeSpan::Serialize64, CTime::GetTime64, and CTime::Serialize64.   
 47All these methods use the __int64 native compiler type. C runtime library functions have also been updated to support 64-bit time/date: _ctime64, _wctime64, _ftime64, _futime64, _gmtime64, _localtime64, _time64, _utime64, _wutime64; _findfirst64, _wfindfirst64, _findnext64, _wfindnext64; and _stat64, _wstat64.   
 48**ATL Collections and Array Classe** s    
 49ATL 7.0 adds five new template collection classes: CAtlArray, CAtlList, CAtlMap, CRBMap, and CRBMultiMap (described in  Figure 4  ). Why do you need more collection classes when you already have MFC and STL collections? The new classes expand on the existing collections to allow for element types that are not 100 percent compatible with primitive type comparison and copying semantics such as smart pointers, auto pointers, and so on. The new collections accomplish this by using element trait classes, which define how the elements are copied, moved, compared, and hashed. A number of element traits are already defined for commonly used element types: CAutoPtrElementTraits, CAutoVectorPtrElementTraits, CComQIPtrElementTraits, CStringElementTraits, and so on. Unlike MFC collections, ATL collections do not support serialization.   
 50To use the collections, specify both the element type and element trait in the templates, like so: 
 51    
 52    
 53    CRBMap&lt; CString, CStringElementTraits<cstring>, 
 54    
 55    
 56           CAutoPtr<cmyobject>, CAutoPtrElementTraits<cmyobject> &gt;;
 57
 58This defines a dictionary, mapping CString's to CMyObject auto pointers. CMyObject's elements are deleted automatically when they are removed from the collection.   
 59**Security Classes**   
 60Security classes provide wrappers for all the common Windows NT security structures for access control. ATL 7.0 defines wrappers for: 
 61
 62·  Access control lists with CAcl 
 63
 64·  Discretionary access control lists with CDacl 
 65
 66·  System access control lists with CSacl 
 67
 68·  Security Identifier (SID) with CSid 
 69
 70·  Access token with CAccessToken 
 71
 72·  Access token groups with CTokenGroups 
 73
 74·  Access token privileges with CTokenPrivileges 
 75
 76·  Security descriptors with CSecurityDesc 
 77
 78·  Security attributes with CSecurityAttributes 
 79
 80·  A number of global functions 
 81
 82Unfortunately, ATL 7.0 does not provide higher-level abstractions to the Windows NT security model; you still have to understand Win32 security to make use of these classes.   
 83**Cryptographic Classes**   
 84Cryptographic classes are wrappers to the Win32 CryptoAPI, providing functionality for encrypting, decrypting, hashing, digital signature, and key management (see  Figure 5  ). Just like the security classes, you have to understand the Win32 CryptoAPI to make use of these classes.   
 85**Performance Counters**   
 86Performance counters are very useful for monitoring the health and performance of a running application by providing various operating statistics at runtime. A new set of classes and macros have been added to support performance counters, and they are very easy to add into your own application using C++ attributes.   
 87To provide performance counters from your application, you need to implement three types of objects: a Performance Monitor Object Manager, Performance Objects, and Performance Counters.   
 88There is usually only one Performance Monitor Object Manager in your app; it exposes a number of Performance Objects, each contains one or more Performance Counters. The performance counter classes need to reside in a DLL, so you may need to create a separate DLL for your app for the counters.   
 89Here's how to define the Performance Monitor Object Manager: 
 90    
 91    
 92    [ perfmon( name="MyApplication", register=true )]
 93    
 94    
 95    class CMyApplicationPerfMon
 96    
 97    
 98    {
 99    
100    
101    };
102
103Figure 6  shows how to define a Performance Object and Performance Counter.   
104To use the counters in your application, you need to initialize the Performance Monitor Object Manager and create an instance of the Performance Object, as you can see in  Figure 7  .   
105With the Performance Object, you can update the performance counters directly as members of the Performance Object: 
106    
107    
108    void    SetCounter( ULONG value )
109    
110    
111    {
112    
113    
114        if ( g_pStatsObject )
115    
116    
117            g_pStatsObject-&gt;SampleCounter = value;
118    
119    
120    }
121
122That's it! If you don't want to use C++ attributes, there are corresponding classes and macros that you can use instead. You should also be aware that setting counters to specific values is generally safe without having to worry about thread synchronization, but performing calculations on the counters, such as incrementing or decrementing, requires the use of atomic operations such as InterlockedIncrement or synchronization using critical sections.   
123**Thread Pools**   
124Thread pools are very useful in high-performance server apps where you want to maximize the concurrency of your app while minimizing the context switching overhead. The optimal number of concurrent threads is generally a multiple of the number of processors on your server, and the thread pool allows you to queue up worker tasks to be executed.   
125The MFC 7.0 thread pool implementation is based on the Windows NT I/O Completion Port. CThreadPool is a templated class that you can specialize with your own worker class. When a thread is available, your worker's Execute function will be called. Workers are queued and executed on a FIFO basis.   
126To define your worker class, you need to follow the Worker archetype by defining: 
127
128·  Initialize, which is called once per thread. 
129
130·  Execute, which is called once for every request queued. 
131
132·  Terminate, which is called once per thread. 
133
134·  In the worker class, declare the RequestType typedef, which defines the type of data to be processed by Execute. 
135
136&lt;SPAN lang</cmyobject></cmyobject></cstring></a>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus