6/24/2010

分析Hilo项目

image

Hilo项目是微软的一个用于演示Windows 7 API和Visual C++ 2010的功能的一个开源项目。这个项目不仅演示了Windows API的使用,而且也提供了设计和开发高性能Windows程序的建议。这个项目的目标在它的twitter主页表现无遗:将开发本地代码重新作为重点。

这个项目是基于免费的Visual C++ Express和Windows 7 SDK,这意味着更多的程序员可以尝试这个项目而不必购买Visual Studio 2010。这有助于扩展这个项目的影响力。不过这也意味着不能使用成熟MFC和ATL类库。作为替代,Hilo项目包含了以下类

  • ComPtr COM指针管理
  • WindowApplication 消息循环处理
  • Window 窗口API封装
  • WindowFactory 窗口类和窗口过程
  • WindowLayout 窗口布局
  • WindowMessageHandler 窗口消息分发

可以很明显地看到,这些类都被放在了一个比较容易重用的DLL模块里面,文档中也允许程序员在自己的程序中直接拿来使用。

由于WIndows Vista/7中WDDM 1.0的驱动是没有GDI硬件加速的,直到WDDM1.1才有有限度的支持,所以在不支持DirectX 10.1的显卡下GDI会很慢。在对于用户界面技术的选择上,Hilo项目组根据这个现象选择了在现代硬件上更快、更节省内存和CPU(当然,这也意味着更耗显存和GPU)的DirectX,而不是比较慢的GDI。这也减少了窗口的数目,整个程序现在只有一个窗口。这样做的好处是发明MFC的消息映射的时候所针对的项目需求,例如大量的窗口、很小内存、派生类需要继承消息处理函数现在都不成为问题了,所以在这唯一的一个窗口的过程里面可以放一个大大的switch语句。

Hilo在模块化这方面做得比较深好,基本上看到类名字就知道这个类是做什么的,不像看文档里面成员函数看到眼花的CWnd,可以看到Hilo对窗口的各个方面处理是分开的。而且虽然Hilo并不是一个COM服务器,但是在耦合的时候是使用COM的接口而不是直接使用类的名字,这样在编译的时候就可以执行类型检同时也保留可扩展性。MFC就做得比较差,不但CObject::IsKindOf需要在运行的时候判断,而且有引用视图类的头文件之前必须先包含文档类的头文件的问题。

比较遗憾的是,在推广本地代码开发方面,Hilo项目似乎做得还不够。Visual C++ Express的使用者主要是学生和业余人员,而这个项目演示的代码复用、COM和模板对于他们来说需要花一些时间来理解。另外,项目的许可协议看起来也让人一头雾水,里面把Hilo描述为软件而不是源代码。不过Visual C++项目组宣布这个项目的时候声称Hilo只是本地开发示例系列的第一个例子,作为原型来说,Hilo的作用在把“酷”这个词和Windows本地开发联系起来这个方面还是做得不错的。上一次VC开发被人称为酷的时间应该是远在98年了吧……

6/11/2010

二十万分之一

因为有些人问起中国互联网状况白皮书的数据,所以做了一些个人统计来做比较。


我在网上发表言论的位置主要是在技术论坛。2000之前的数据没有了,因为网易虚拟社区被解散,以前的帖子也不能访问。不过我贡献的一些精华贴在http://www.moon-soft.com/program/bbs/docelite9532.htm还是可以看到。这里统计的是2000年之后的数据。


从2000年到2010年6月,我在CSDN社区的参与讨论的问题大概有两万,速度大概是每年2000个的样子.根据CSDN的统计(截至2009年5月600万),这相当于CSDN每年总问题数的三百分之一。说起来很奇怪,我都不去灌水乐园的,难道灌水乐园的问题不参与统计?还是被和谐的太多?


我在微软的MSDN论坛参与讨论的问题也有一万多,MSDN论坛是2005年创建的,所以我的发帖速度大概是每年3000个问题,每个问题可能有多个回复,所以发帖量要比这个还要多。另外,在微软的新闻组的帖子有一千多,新闻组是2003年才去,所以速度是每年大概两百多贴,和在QQ问问中回答问题的速度差不多。


非技术论坛方面,在寄托天下和未名这两个海外人比较集中的社区也灌了几千贴,大多是和海外生活有关,例如签证、留学、移民、德克萨斯等,有个标准水车的头衔。在一些游戏论坛的帖子大概有几千,发帖比较多的地方是在机战世界论坛,算下来每年大概冠几百贴没有技术含量的水,数量大概是技术问题的十分之一。


博客方面,每年大概几十贴。比较经常更新的有CSDN和博客堂这两个,新浪和网易的在我这里访问速度太慢,估计是用户太多的原因,所以不怎么用。blogspot和msn space是兴致所至去更新一下。微博客方面,2008年起大概有一千贴的样子,平均每年500贴。新闻评论比较少写,大概一年只有几十贴的样子。总计的话,每年也就600吧。


综合起来,我每年大概要发表6000条帖子、评论和博客。按照国务院发表的中国互联网状况白皮书的数据,这相当于全国人民每年发表的信息的二十万分之一。


题外话


刚才又上机战世界论坛,看见一帖被雷到了:

家长:啊,老师,不好意思,我儿子和女朋友私奔了,我给他们请两天假

这年代还有人学琼瑶小说私奔啊。

3/22/2010

DirectUI和无窗口用户界面

DirectUI/DirectUser是一个用户界面框架(http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.automationelementinformation.frameworkid.aspx)。用Spy++可以在MSN Messenger、Windows XP、Office、IE和Windows Media Player中看到窗口类名字是DirectUIHWND的窗口。

从文件描述来看,DUI70.dll和DUser.dll看起来是这个框架的实现文件,而没有导入这些DLL的软件应该是复制了这个库的代码。举例来说,Windows Vista和IE7的测试版的IEFrame.dll导入了DUser.dll(http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/6b801577-1699-4093-8a58-198c64b120e0)而正式版使用IEUI.DLL。这应该是微软不愿意公开支持这个功能变化频繁的类库,而反垄断案禁止非Windows组件调用未公开Windows API的缘故。

再看看DUser.dll的函数导出表(http://www.webtropy.com/articles/dll-api.aspx?dll=duser),可以看到Gadget这个词被广泛使用,而没有具体的控件。因为没有窗口句柄,所以控件不会是用的窗口类来区分,而是可能和Windows Vista Sidebar Gadgets一样采用HTML做接口(更正)从Office Communicator的资源来看,是用的XML做的接口。。

从这个类库的名字和行为来看,实际上应该是基于DirectX,和WPF类似的界面类库框架。在微软的招聘网站上可以看到Office Communications项目组的一个职位的介绍中描述说“Native Win32/64 UX experience via DirectUI, and Web UX experience via Silverlight”,说明这个项目组把它和Silverlight同等对待。DirectUIHWND窗口可以在需要性能和安全性的场合看到,例如IE的Tab窗口、Shell中的DefView、Windows登录界面等等。在Windows Vista上使用DirectUI的微软程序和WPF程序一样兼容Desktop Composition和远程桌面,应该是直接或者间接调用的Direct3D。

那么我们怎么做到类似的效果?

无窗口模式的用户界面并不是一个新的概念(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx),VC的应用程序向导就可以创建无窗口ActiveX。但是做过无窗口模式的RichEdit的实现的人都知道,微软的系统控件集中了各种各样的功能,比如各种快捷键、滚动条、界面风格、Accessibility、用户界面自动化等等,要像IE项目组那样几乎完全实现无窗口并不容易。Raymond Chen在(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx)提到可以使用DrawThemeBackground和DrawFrameControl这两个API,不过这只对和Windows界面风格一致的程序有用。要是界面不复杂的话,可以简单的集成IE的Trident引擎,比如使用MFC的CHTMLView和CDHTMLDialog,以及Windows Forms的WebBrowser类。这样做的代价就是程序需要牺牲性能和可能在严格的IE安全性配置下无法工作,Visual Studio.Net开始的各种向导、Google Task、Microsoft Outlook、Outlook Express等就是使用的这种方案。

另外一个方案就是集成WPF或者Silverlight。VC项目组在用户调查中发现,需要使用WPF的Visual C++用户大都用C#编写WPF代码再用C++/CLI和非托管代码做接口(http://social.msdn.microsoft.com/forums/en-US/wpf/thread/dd1e31bb-feb4-4d77-b524-42a282f519b1/),所以他们决定致力于改进更多用户使用的功能,例如编辑器的智能感知,而不提供对WPF的支持。Visual Studio 2010就是使用这种方案。

为什么不能使用未公开的API?参考

http://blogs.msdn.com/oldnewthing/archive/2003/12/23/45481.aspxhttp://blogs.technet.com/stefan_gossner/archive/2005/07/27/undocumented_API_Part1.aspx

题后话:

*如果微软在产品文档中讨论未公开的API,那么API还是未公开的吗?(http://msdn.microsoft.com/en-us/library/aa140182(office.10).aspx)

*Visual Studio代码画廊中有个叫作DirectUI的类库,设计思想和微软的DirectUser库类似(http://visualstudiogallery.msdn.microsoft.com/en-us/1B69C9FE-E422-4799-9EB5-6AC7034C52E1),不过也有人误认为这就是微软用来实现MSN的界面的库。

*IE9将会使用Dierct2D作为渲染引擎,不知道IE项目组在移植完代码之后是否能把控件类库的接口公开

DirectUI/DirectUser是一个用户界面框架(http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.automationelementinformation.frameworkid.aspx)。用Spy++可以在MSN Messenger、Windows XP、Office、IE和Windows Media Player中看到窗口类名字是DirectUIHWND的窗口。

从文件描述来看,DUI70.dll和DUser.dll看起来是这个框架的实现文件,而没有导入这些DLL的软件应该是复制了这个库的代码。举例来说,Windows Vista和IE7的测试版的IEFrame.dll导入了DUser.dll(http://social.msdn.microsoft.com/Forums/en-US/windowsuidevelopment/thread/6b801577-1699-4093-8a58-198c64b120e0)而正式版使用IEUI.DLL。这应该是微软不愿意公开支持这个功能变化频繁的类库,而反垄断案禁止非Windows组件调用未公开Windows API的缘故。

再看看DUser.dll的函数导出表(http://www.webtropy.com/articles/dll-api.aspx?dll=duser),可以看到Gadget这个词被广泛使用,而没有具体的控件。因为没有窗口句柄,所以控件不会是用的窗口类来区分,而是可能和Windows Vista Sidebar Gadgets一样采用HTML做接口。

从这个类库的名字和行为来看,实际上应该是基于DirectX,和WPF类似的界面类库框架。在微软的招聘网站上可以看到Office Communications项目组的一个职位的介绍中描述说“Native Win32/64 UX experience via DirectUI, and Web UX experience via Silverlight”,说明这个项目组把它和Silverlight同等对待。DirectUIHWND窗口可以在需要性能和安全性的场合看到,例如IE的Tab窗口、Shell中的DefView、Windows登录界面等等。在Windows Vista上使用DirectUI的微软程序和WPF程序一样兼容Desktop Composition和远程桌面,应该是直接或者间接调用的Direct3D。

那么我们怎么做到类似的效果?

无窗口模式的用户界面并不是一个新的概念(http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx),Visual C++的应用程序向导就可以创建无窗口ActiveX。但是做过无窗口模式的RichEdit的实现的人都知道,微软的系统控件集中了各种各样的功能,比如各种快捷键、滚动条、界面风格、Accessibility、用户界面自动化等等,要像IE项目组那样几乎完全实现无窗口并不容易。Raymond Chen在http://blogs.msdn.com/oldnewthing/archive/2005/02/11/371042.aspx提到可以使用DrawThemeBackground和DrawFrameControl这两个API,不过这只对和Windows界面风格一致的程序有用。要是界面不复杂的话,可以简单的集成IE的Trident引擎,比如使用MFC的CHTMLView和CDHTMLDialog,以及Windows Forms的WebBrowser类。这样做的代价就是程序需要牺牲性能和可能在严格的IE安全性配置下无法工作,Visual Studio.Net开始的各种向导、Google Task、Microsoft Outlook、Outlook Express等就是使用的这种方案。

另外一个方案就是集成WPF或者Silverlight。VC项目组在用户调查中发现,需要使用WPF的Visual C++用户大都用C#编写WPF代码再用C++/CLI和非托管代码做接口(http://social.msdn.microsoft.com/forums/en-US/wpf/thread/dd1e31bb-feb4-4d77-b524-42a282f519b1/),所以他们决定致力于改进更多用户使用的功能,例如编辑器的智能感知,而不提供对WPF的支持。Visual Studio 2010就是使用这种方案。

为什么不能使用未公开的API?如果要看惊恐故事的话,可以参考http://blogs.msdn.com/oldnewthing/archive/2003/12/23/45481.aspxhttp://blogs.technet.com/stefan_gossner/archive/2005/07/27/undocumented_API_Part1.aspx

题后话:

*如果微软在产品文档中讨论未公开的API,那么API还是未公开的吗?(http://msdn.microsoft.com/en-us/library/aa140182(office.10).aspx

*Visual Studio代码画廊中有个叫作DirectUI的类库,设计思想和微软的DirectUser库类似(http://visualstudiogallery.msdn.microsoft.com/en-us/1B69C9FE-E422-4799-9EB5-6AC7034C52E1),不过也有人误认为这就是微软用来实现MSN的界面的库。

*IE9将会使用Dierct2D作为渲染引擎,不知道IE项目组在移植完代码之后是否能把控件类库的接口公开

3/04/2010

Getting out of Active Document

do{
            if(m_pDocObjectServer==NULL) break;
            CComPtr<IOleObject> pOleObject;
            m_pDocObjectServer->ExternalQueryInterface(&IID_IOleObject,(LPVOID*)&pOleObject);
            if(pOleObject==NULL) break;
            CComPtr<IOleClientSite> pOleClientSite;
            pOleObject->GetClientSite(&pOleClientSite);
            if(pOleClientSite==NULL) break;
            CComPtr<IOleContainer> pOleContainer;
            pOleClientSite->GetContainer(&pOleContainer);
            if(pOleContainer==NULL) break;
            CComQIPtr<IServiceProvider> pServiceProvider(pOleContainer);
            if(pServiceProvider==NULL) break;
            CComQIPtr<IServiceProvider> pTopLevelServiceProvider;
            pServiceProvider->QueryService(SID_STopLevelBrowser, IID_IServiceProvider, (LPVOID*)&pTopLevelServiceProvider);
            if(pTopLevelServiceProvider==NULL) break;
            CComPtr<IWebBrowser2> pWebBrowser2;
            pTopLevelServiceProvider->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2,(LPVOID*)&pWebBrowser2);
            if(pWebBrowser2==NULL) break;           
            pServiceProvider=pWebBrowser2;
            CComPtr<IOleWindow> pOleWindow;
            pServiceProvider->QueryService(SID_SShellBrowser, IID_IOleWindow,(LPVOID*)&pOleWindow);
            if(pOleWindow==NULL) break;           
            HWND hwndBrowserOrTab = NULL;
            pOleWindow->GetWindow(&hwndBrowserOrTab);
            if(hwndBrowserOrTab==NULL) break;           
            CString newTitle;
            newTitle.Format("%s (%d strokes)",
                m_strPathName,
                m_strokeList.GetSize());
            BOOL result=::SetWindowText(hwndBrowserOrTab,(LPCTSTR)newTitle);
            if(result==FALSE)
            {
                int errorCode=GetLastError(); //no error here but looks like no way to update tab caption, which is in a DirectUIHWND window in the frame process.
            }
        }while(FALSE);

11/10/2009

Class Wizard is back to Visual C++ in Visual Studio 2010... Control Shift X.

image

After 4 versions. Finally.

More features: Now you have partial search in options

The Wizard does not always find every handler function.  I got warning when trying to create a handler if there is one already. Delete handler does not work when an existing handler is not detected.

Sometimes I have “value does not fall in expected range” when trying to bring the class wizard if I have source files open.