9/05/2010

MSDN Forums random thoughts

User Qurrel wants to know how to differentiate mouse clicks in CHTMLView so a context menu can be truly contextual. The documentation of CHTMLView could be more useful if it said when to override the function, not just how to use the function. This requires a collaboration between the Visual C++ team and the Windows SDK team.

User JosexD wants to know how to get the serial number of the motherboard and processor. The thread is marked as answered by a Microsoft Admin a year and a half ago, I guess to express him/herself JosexD twice voted the answer as helpful instead.

User LorenD wants to know why a MPEG-2 video is playing in his DirectShow-based software on Windows XP but not on Windows 7. The answer isn’t satisfactory, but that is how the standard behavior of video playing is. Maybe that’s why so many video players embed ffmpeg instead of relying on DirectShow?

It looks like a lot of people can’t find MSDN forums. Maybe other forums should have better navigation to point user to different brands, like consumer questions to Microsoft Answers, developer questions to MSDN forums, design questions to Expression, and network administrator questions to Technet.

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