What's New for MFC Developers?(zz)

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

--------------------------------------------------------------------------------
作者:kamphkb 來源:http://msdn.microsoft.com/msdnnews/2001/sept/vcnet/vcnet.asp
 
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 My_Str;
...

MFC7.0增加了一個新的字符串類叫CFixedStringT<>。這種定長字符串提供一種用戶定義長度的方法,在耗盡內在的空間前無需額外的內存。CFixedStringT被用於基於棧的變量或聯合容器中的元素時,效率非常高。它顯著地減少了基於堆的分配。
【譯者:這裏俺也糊塗了,呵呵,請各位指正。原文如下:
CFixedStringT's are very efficient when used as stack-based variables or as keys in associativecontainers, dramatically reducing the number of heap-based allocations.】

下面的例子創建一個有1024個字符的實例:

// allocating 1024 character internal buffer
CFixedStringT< CString, 1024 > string;


新的UI特性及升級
MFC7.0提供DHTML對話框支持,有一套DHTML編輯器類,新的圖形API(GDI+),更新了對BITMAP支持(CImage),添加一個通用對話框包裝類(CLinkCtrl),更新控件和對話框支持2k和XP,增強了ActiveX control容器和提高了消息映射的類型安全。讓我們逐一看看吧。

DHTML對話框及DHTML編輯器類
DHTML對話框把豐富多彩的HTML用戶界面帶到桌面應用程序上來。現在你的桌面App擁有時髦的圖形界面和一般web應用程序沒有的爽快的交互性。MFC7.0提供了CDHtmlDialog和CMultiPageDHtmlDialog來支持DHTML。DHTML對話框可以從資源文件或任何有效的URL中顯示HTML頁面。如果你曾用過CHtmlView,就知道獲取和設置HTML元素需要通過IHTMLDocument2對象,而且處理HTML的事件是非常痛苦的事。CDHtmlDialog極大地簡化了這種交互,使用一套類似DDX的擴展宏和DHTML事件映射。DDX_DHtml_宏和傳統的DDX_宏同樣在DoDataExchange函數中使用。它允許獲取和設置各種HTML元素的屬性。例如,DDX_DHtml_CheckBox綁定複選框的值,DDX_DHtml_ElementInnerHtml設置和獲取某個元素的HTML。綁定一個HTML元素到DDX需要這個元素有的一個'id='的屬性,就像下面的代碼所示:


Filename:

Read-only

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()

這些事件映射類似MFC的樣式,包括DECLARE_DHTML_EVENT_MAP的定義和在BEGIN_DHTML_EVENT_MAP與END_DHTML_EVENT_MAP之間的定義。CMultiPageDHtmlDialog適合導向和屬性頁有關的對話框。它可以在一個對話框中裝載多個頁面並且使用內在事件映射響應事件。這個新版本還提供了所見即所得(WYSIWYG)的DHTML編輯器。這意味着在你的程序中調整一個HTML元素並不比調整一個文本控件困難。類似MFC6.0對於rich edit控件的支持,MFC7.0提供了CHtmlEditCtrl,還有類似的文檔視圖類:CHtmlEditView/CHtmlEditDoc。但你仍然需要自行調整UI元素,如字體、風格、顏色、等等。


GDI+
GDI+ 是一個新的圖形子系統,提供一整套圖形API渲染2D圖象,圖片和文字。它是.NET中唯一的API,但在C++中,它補充了GDI的渲染能力。通過GDI+可以獲得:更強的2D製圖,alpha通道支持,通用座標轉換和浮點支持,還有漸變筆刷,cardinal splines,scalable regions和新的編程模式。GDI+以C風格的API形式發佈,雖然一套C++類將其包裝,但不被MFC支持而是在.NET中使用。使用GDI+,使用gdiplus.h並且鏈接gdiplus.lib。還必須在使用前初始化這個庫。GDI+是XP的一部分,如要在98、me、nt4.0和2k上使用就要拷貝GdiPlus.DLL到相應的目錄。GDI+使用了與GDI不同的編程模型。在GDI+中必須在每次畫圖命令中傳入筆或刷子。圖形元素不在和筆與栓子一起工作;勾勒邊框和填充被分開成不同的函數來實現(如DrawRectangle和FillRectangle)。下面的例子演示畫一個矩形(3.5 英寸 × 4.4 英寸)。

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( &pen, RectF( 0.0F, 0.0F, 3.5F, 4.4F ));
}

用CImage管理Bitmap
期待已久的Bitmap支持終於在這個版本實現了。CImage可以讀取和存儲JPEG、GIF、BMP和PNG格式的圖形文檔。但是一些函數不被舊系統支持(如95),還有一些函數在不同的os上的具體實現不一樣。CImage可以

在MFC和
ATL中使用。它也包裝了DIB的功能,可以直接操作象素點。讓我們來看看CImage提供了什麼吧:


·Alpha象素點混和透明和半透明效果

·PlgBlt可以隨意的映射一個矩形到一個並行四邊形

·TransparentBlt可以根據一種指定的顏色進行透明操作

·MaskBlt可以混和兩張圖片到一個輸出設備上

·CImage::GetDC可以直接向一幅bitmap畫圖。


下面給出一個例子:

CImage image;
Image.Load( "test.gif" );
CBitmap* pBitmap = CBitmap::FromHandle( image.m_hBitmap );


CLinkCtrl通用對話框類
CLinkCtrl包裝了SYSLINK控件,可以輕鬆地在windows上放置超鏈接,但只在XP上使用。它支持一個或多個超鏈接,你可以在OnNotify中處理NM_CLICK和NM_RETURN消息響應點擊事件。

對2k和XP的支持
所有的通用控件,CCheckListbox,文件處理和打印都被更新以支持2k和XP。CWnd的方法也被更新以支持新的特性如分層窗口(layered windows)和活動窗口(animated windows)。CListView在XP中支持平鋪風格。MFC7.0支持XP的主題(themes)。CWnd現在支持Active Accessibility。新的CPrintDialogEx更新了打印對話框。


增強的ActiveX容器
MFC7.0和ATL支持無窗口的ActiveX,並且容器可以被改寫。現在MFC也享受和Visual Basic一樣的容器優化。現在你可以改寫COleControlSite以增加屬於自己的容器行爲。


類型安全的消息映射
MFC7.0加強了對消息處理函數返回值的校驗。比如在OK中返回void而不是LRESULT的話,編譯器會認爲是一個錯誤。


應有盡有的工具類
新的工具類有:正則表達式類(regular expression class)、64位日期時間函數、集合模板類、安全類、包裝CryptoAPI的函數和類、支持計數的宏和線程池支持。我們會在後面一一簡要介紹。

正則表達式類(regular expression class)
這個模板類用於字符串的查詢和比較,同時支持MBCS和Unicode。一共有兩個模板類:CAtlRegExp和
CAtlReMatchContext。
下面給出一個例子:
CAtlRegExp<> re; // using the default character trait
re.Parse( "ab.d" );
CAtlReMatchContext mc;
re.Match( "abcd", &mc ); // returns TRUE, successful match
re.Match( "bbcd", &mc ); // returns FALSE, no match


64位日期時間函數
你的代碼也許不會有千年問題,但標準的C運行庫會在2038年1月18號19:14:07後出錯。而新的64位日

期時間函數可以堅持到3000年12月31號。
CTime、CTimeSpan和C運行庫都被更新支持__int64數據類型,包括CTimeSpan::GetDays64,
CTimeSpan::GetTotalHours64, CTimeSpan::GetHours64, CTimeSpan::Serialize64,
CTime::GetTime64,和CTime::Serialize64;還有_ctime64, _wctime64, _ftime64, _futime64, _gmtime64,
_localtime64, _time64, _utime64, _wutime64; _findfirst64, _wfindfirst64, _findnext64, _wfindnext64;and _stat64,和_wstat64。

ATL的集合類和矩陣類
ATL7.0提供五個新的集合類:AtlArray,CAtlList,CAtlMap,CRBMap,和CRBMultiMap。它們可以更好的支持非標準的數據類型。使用一些可以描述元素品質的類,這些類描述元素如何被拷貝,移動,比較清除。有CAutoPtrElementTraits, CAutoVectorPtrElementTraits, CComQIPtrElementTraits,

CStringElementTraits,
等等。這些ATL集合類不支持序列化。使用它們要同時指定元素類型和描述元素的品質:
CRBMap< CString, CStringElementTraits, CAutoPtr, CAutoPtrElementTraits >;這裏定義了一個字典,映射CString給CMyObject的自動指針。CMyObject的元素會在集合類銷燬時自動銷燬。

安全類
安全類包裝了NT所有的安全機制。ATL7.0包裝了:

·訪問控制列表(CAcl)

·任意訪問控制列表(CDacl)

·系統訪問控制列表()

·SID安全標識(CSid)

·訪問節點(CAccessToken)

·訪問結點組(CTokenGroups)

·訪問結點許可(CTokenPrivileges)

·安全描述(CSecurityDesc)

·安全屬性(CSecurityAttributes)

·一些全局函數

不幸的是ATL 7.0不提供高級的安全模型,你仍然需要深入瞭解win32的安全機制。


Cryptographic類
Cryptographic類包裝了win32的CryptoAPI,提供加密、解碼、散列、數字簽名和密匙管理。

That'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.

性能測試(Performance Counters)
在你的程序中使用性能測試,需要實現三種類對象:性能監測管理對象,性能對象和性能測試器。下面演示怎樣定義性能監測管理對象:

[ perfmon( name="MyApplication", register=true )]
class CMyApplicationPerfMon
{
};

然後可以使用性能測試器:

void SetCounter( ULONG value )
{
if ( g_pStatsObject )
g_pStatsObject->SampleCounter = value;
}

使用它們不必擔心線程同步的問題,但是測試器需要原子操作,如InterlockedIncrement或synchronization。

線程池
MFC 7.0線程池是基於NT I/O Completion Port。CThreadPool是一個支持工作線程的模板類。當一個線程可以工作時,你的工作線程的執行函數會被調用。工作線程的查詢和執行遵循FIFO(先入先出)原則。使用線程池必須:

·一次一個線程地初始化

·逐一執行在請求隊列中的線程

·一次一個線程地銷燬

·在工作線程類中聲明一個RequestType typedef,它會在執行時被處理

 

RequestType是一個不透明的類型,不能大於sizeof(ULONG_PTR)(即,x86 PC上的32位),所以你不可以使用類的實例或大的原始類型(如浮點)。
下面是一個示例:

class CMyWorker
{
public:
typedef CMyData* RequestType;
BOOL Initialize( void* initParam );
void Execute( CMyData* request, void* initParam, OVERLAPPED* pOverlapped );
void Terminate( void* initParam );
};


下面是怎樣在線程池初始化和查詢一個任務:


CThreadPool< CMyWorker > threadPool;

threadPool.Initialize();
threadPool.QueueRequest( new CMyData());
threadPool.Shutdown( 1000L );


Web服務,Web應用程序和Network類
MFC7.0支持Web服務程序,編寫Web服務和使用ATL服務器類編寫Web應用程序。在下面的段落裏,我們將演示訪問Web服務和調用服務的方法。還將解釋如何生成HTML和把它寫入IStream,怎樣使用HTTP客戶端和怎樣用MFC發mail。


To call the methods exposed by the Web Service, simply instantiate an instance of the proxy class and call its methods, just like a native C++ class!

#include "myservice.h"
???
MyService::CMyService service;
HRESULT hr = Service.MyMethod( CComBSTR( L"A Parameter" ));

在MFC中支持Web服務
和DCOM不一樣,Web服務容易透過防火牆訪問,提供了一種真正的寬鬆的連接。使用Web服務不會比用#import來的困難。使用命令行程序SProxy.exe就可以生成訪問Web服務的C++客戶端代碼。生成的proxy類包含所有你需要的一切。下面是個例子:

sproxy /out:myservice.h
http://myserver/myservice.dll?Handler=GenMyServiceWSDL


調用Web服務的方法,你只要初始化這個proxy類並直接調用其方法即可,就像普通的C++類:


#include "myservice.h"
...
MyService::CMyService service;
HRESULT hr = Service.MyMethod( CComBSTR( L"A Parameter" ));


HTML生成器
CHtmlGen類和模板CHtmlGenBase<>支持該功能。CHtmlGen把一個完全的HTML寫入IStream。使用它只要用一個IStream初始化之並調用相應的方法即可。

CHtmlGen out;
out.initialize( aStream );
out.html();
out.head();
out.title( "Test HTML" );
out.headEnd();
out.body();
out.a( "http://www.microsoft.com", "Microsoft" );
out.bodyEnd();
out.htmlEnd();


HTTP客戶
CAtlHttpClient是一個輕量級的HTTP客戶類,可以發出請求並獲得迴應。它支持代理和各種驗證(當前,支持Basic和NTLM)。CAtlHttpClient會同步發出請求,所以最好放置在多線程中。


CAtlHttpClient client;
client.Navigate( _T(http://www.microsoft.com ));
CString contentType;
client.GetHeaderValue(_T("Content-Type"), contentType );
BYTE* pBody = client.GetBody();


CBasicAuthObject和CNTLMAuthObject支持驗證。下面是一個範例:

CNTLMAuthObject ntlmAuth;
client.AddAuthObject( _T("NTLM"), &ntlmAuth );

 

SMTP支持MIME編碼消息支持
SMTP支持使你無需其他的mail客戶端支持。CSMTPConnection直接連接一個SMTP服務器併發送MIME編碼的mail。CMimeMessage更可以在mail上加附件、原始數據和其他MIME編碼的消息。這個示例演示如何構造MIME消息:

CMimeMessage message;
message.SetSender( _T("[email protected]" ));
message.AddReceipient( receipient );
message.SetSubject( _T("A test message" ));
message.AddText( _T("This is a test message"));
CSMTPConnection connection;
connection.Connect( someSMTPServer );
connection.SendMessage( message );

高效地OLE DB數據庫訪問
【譯者:這段廢話真多,總之就是比以前編程更容易了。不過,DB總是比較複雜的,短短的一段也說明不了什麼問題。偷懶不翻譯了 :)】


更新的STL
添加的hash_map,hash_multimap和hash_set類基於新的hash-table-based擴展類。它們類似於std::map,std::multimap和std::set,但有着非常不一樣的性能特性。Hash-table-based比binary tree-based在查找方面快得多。和map與set不同,hash類不是有序的。新版的STL也消除了basic_string著名的多線程問題。不再使用計數器,而已嚴格地用拷貝來實現。最後,STL有了更好的DLL支持。再也不是本地靜態數據成員了。

Conclusion
Visual Studio .NET is a giant step forward for enhancing programmer productivity, and the Microsoft .NET initiative will likely change the programming landscape in the coming years. With this release of Visual C++, MFC 7.0 has been updated to live in this new world of Web Services, while gaining better C++ standard compliance, full integration with ATL, and numerous enhancements to UI and utility classes. Best of all, these new features can be added to your existing MFC applications.


總結
MFC得到了更好地接近了C++標準,完全地和ATL結合,在UI和工具方面大大增強。最好的還是這些新特性可以加入到已存在的代碼中。

關於作者:

Anson Tsao有12年的行業經驗,從事大型的Windows和C++的開發,最近加入Microsoft Visual C++ Libraries小組。

Walter Sullivan已經在Microsoft工作了11年,他的所有時間幾乎都花在Visual C++ product小組上面。他現在領導Microsoft C++ Class Libraries程序管理的工作。

About Translator
Just a C++ fans. :) Call me Kamp. I care code performance before, and now care the performance of a certain project as a whole.

            

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章