我以前用MFC写了一套监控系统,C/S模式,程序中的类封装都从CObject继承,
还大量用了MFC的链表,map等。此外,程序中的描述参数(矢量化的图形、系统的配置描述等),都序列化成MFC的文档。
    
    现在,想在这套系统中支持B/S模式,即在intranet或internet上运行,具体设想是:server端运行IIS,同时运行我的后台服务(计划将我的后台写成NT的service),非实时内容用asp提供,实时内容由我的后台服务通过socket提供;客户端准备写一个ActiveX,嵌在IE中接收实时数据,以及完成同server交互。
    
    现在问题来了:由于这套系统还在运行中,原来的参数结构不允许大幅度变更,原来的C/S模式要求继续保留,而要在internet上运行,用MFC写ActiveX肯定不行,否则要带一大堆DLL,没发用;server端的服务用MFC写也不合适吧。于是我准备用ATL来写,问题是,改写原来的代码,工作量巨大,同时,要保留原来的参数,以及MFC实现的RTTI等。    于是我研读了VC7中MFC和ATL的实现,发现microsoft已经将很多原MFC中的代码改写,可以在MFC和ATL中共用,同时ATL中也有了很多新的封装,如DC,PEN,Brush、各种链表等。我想,如果将MFC中的部分代码抠出来,将会在满足上面的条件下,实现新的模式。
    
    于是乎,拿起牛刀,狂砍MFC......
    目前,应该说大部分迁移基本完成,包括CObject及所需的类,MFC的RTTI、
序列化、动态生成、CArchive、CFile、部分链表等。    现在的疑惑是:
    1. 这样做是不是很变态?我是不是正在做着前无古人,后无来者的工作?有没有更好的实现方法?
    2.还有一个难点,我对迁移中CString的序列化总是不对(也就是对>>和<<的重载),可能是我对C++的template用法还不熟吧?哪位大虾帮着看看:以下是MFC的实现
typedef ATL::CStringT< wchar_t, StrTraitMFC< wchar_t > > CStringW;
typedef ATL::CStringT< char, StrTraitMFC< char > > CStringA;
typedef ATL::CStringT< TCHAR, StrTraitMFC< TCHAR > > CString;template< typename BaseType, class StringTraits >
CArchive& AFXAPI operator<<(CArchive& ar,
const ATL::CStringT<BaseType, StringTraits>& str)
{
AfxWriteStringLength(ar, str.GetLength(), sizeof(BaseType) == sizeof(wchar_t));
ar.Write(str, str.GetLength()*sizeof(BaseType)); return ar;
}template< typename BaseType, class StringTraits >
CArchive& AFXAPI operator>>(CArchive& ar,
ATL::CStringT<BaseType, StringTraits>& str)
{
int nCharSize;  // 1 = char, 2 = wchar_t
UINT nLength = UINT( AfxReadStringLength(ar, nCharSize) );
if (nCharSize == sizeof(char))
{
ATL::CTempBuffer< char > pszBufferA(nLength+1); pszBufferA[nLength] = '\0';
UINT nBytesRead = ar.Read(pszBufferA, nLength*sizeof(char));
if (nBytesRead != (nLength*sizeof(char)))
AfxThrowArchiveException(CArchiveException::endOfFile);
str = pszBufferA;
}
else
{
ASSERT(nCharSize == sizeof(wchar_t)); ATL::CTempBuffer< wchar_t > pszBufferW( nLength+1 ); pszBufferW[nLength] = L'\0';
UINT nBytesRead = ar.Read(pszBufferW, nLength*sizeof(wchar_t));
if (nBytesRead != (nLength*sizeof(wchar_t)))
AfxThrowArchiveException(CArchiveException::endOfFile);
str = pszBufferW;
} return ar;
}以下是ATL的定义
#if !defined(_ATL_CSTRING_NO_CRT) && defined(_ATL_MIN_CRT)
#define _ATL_CSTRING_NO_CRT
#endif#ifndef _ATL_CSTRING_NO_CRT
typedef CStringT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT< wchar_t > > > CAtlStringW;
typedef CStringT< char, StrTraitATL< char, ChTraitsCRT< char > > > CAtlStringA;
typedef CStringT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > > CAtlString;
#else  // _ATL_CSTRING_NO_CRT
typedef CStringT< wchar_t, StrTraitATL< wchar_t > > CAtlStringW;
typedef CStringT< char, StrTraitATL< char > > CAtlStringA;
typedef CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString;
#endif  // _ATL_CSTRING_NO_CRT#ifndef _AFX
typedef CAtlStringW CStringW;
typedef CAtlStringA CStringA;
typedef CAtlString CString;
#endif  呵呵,够长了吧,劳您费眼了 :) 
  也不知道我这300分大餐,谁能吃到?  考,还不让放这么多,那就100分将就吧。

解决方案 »

  1.   

    你做的事情我的兄弟都干过。
    在vc6时代ms还没改写mfc这些东西呢。2年前的东西了,能否找到要看运气,你做了此事,绝对不变态。我们的东西是rds的扩展,不光是mfc大,我还不信她的THREAD SAFE呢。
      

  2.   

    谢谢谢谢,心里有点底了!各位能否帮忙看看那个CString怎么序列化啊?VC6下我一定能够搞定它,只是现在变成了模板,总是不成功啊:(
      

  3.   

    我以为没必要!
    atl写服务程序也可以用mfc
    控件用mfc写也可以,没听说一个程序发布出去都需要带一大把dll如果想锻炼一下,或者多学习一些c++的东西
    再加上老板允许你这么做,那才有必要改写一己之见,呵呵
      

  4.   

    服务端确实可以用ATL+MFC,可是客户端的控件呢,用MFC写,要么动态连接,要带MFC的DLL啊,静态连接有太大,modem拨号上网,下载有问题啊。
      

  5.   

    而且,用MFC写ActiveX,好象有限制的,如自由线程之类;另外,我试了一下,程序效率很差,闪烁很厉害,我需要一定的实时性啊。
      

  6.   

    虽然是“简单任务”;
    难道你是“超人”;
    能够一个人完成“不可能完成的任务”;
    难道微软写MFC的许多人,用尽了项目管理,都是白扯,淡了。
    什么UML什么CMM都是狗屎,在中国程序员这行不通。
    “给我一个支点我能撬动地球”,“给我飞机我去撞大楼。”
    学习研究可以,如果想实用,实在是不敢认同。
    除非你是天才,那你开发软件根本不需别人帮助,别来找我们,自己开发一个WINDOWS吧。