1、COM组建初始化问题
问题:MSDN中说到,要使用SHBrowseForFolder必须先用CoInitialize 初始化COM库。处理完后,用CoUninitialize关闭com库。但我用vc6和vs2012试过SHBrowseForFolder,不用初始化COM库,都没有问题,这是为啥?
原因说明:其实LZ估计创建的是MFC工程,创建工程时,MFC框架会自动添加初始化COM库的代码,即在CXXXXXXApp::InitInstance()中添加了对AfxOleInit调用,AfxOleInit内部进行了COM库的初始化,且看MSDN对AfxOleInit的说明:
Call this function to initialize the OLE support for an MFC application. When this function is called, the following actions occur:
Initializes the COM library on the current apartment of the calling application. For more information, see OleInitialize.
2、托盘图标区域弹出菜单不消失问题
原因说明:托盘图标消息响应函数中弹出的菜单确实有点特殊,和一般的菜单不一样。看一下MSDN中对TrackPopupMenu的说明:
To display a context menu for a notification icon, the current window must be the foreground window before the application calls TrackPopupMenu or TrackPopupMenuEx. Otherwise, the menu will not disappear when the user clicks outside of the menu or the window that created the menu (if it is visible).
所以,在调用TrackPopupMenuEx函数弹出菜单之前,应该将当前主窗口设置为foreground窗口,代码如下所示:
// 加上这一句,点其它的地方,托盘菜单才会消失 ::SetForegroundWindow( m_tnd.hWnd ); // 弹出菜单 CPoint pos; GetCursorPos( &pos ); CWnd* pWnd = AfxGetMainWnd(); menu.TrackPopupMenu( TPM_RIGHTALIGN | TPM_BOTTOMALIGN | TPM_LEFTBUTTON, pos.x, pos.y, AfxGetMainWnd(), NULL ); menu.DestroyMenu();
TrackPopupMenu延伸:MSDN中对该函数的概述中有一句:The TrackPopupMenu function displays a shortcut menu at the specified location andtracks the selection of items on the menu. 这句话的言下之意是什么呢?意思是,该函数是阻塞式的,弹出菜单后不会立即返回,他会继续追踪用户接下来点击了那个菜单项。当然也有可能用户点击非菜单区域菜单自动关闭。但在duilib中,dui菜单中对应的TrackPopupMenu则不是阻塞式的,它仅仅是创建了菜单窗口并将之显示出来,会立即返回。之前在处理某个功能点时遇到过这样的问题。因为之前界面程序使用MFC实现,之前逻辑控制是没问题的,用dui后逻辑则出现了问题,后来追查代码发现duilib中的TrackPopupMenu则非阻塞式的。
3、关于MSDN
微软提供的MSDN非常的强大、非常的细致,不仅对接口进行详细的说明,而且对不同应用场景下要注意的细节点做了详细的说明。所以当我们疑惑时,或者遇到问题时,建议优先查阅MSDN中的相关说明,MSDN是最权威的。曾经在排查图片无法绘制到目标DC上的问题时候,很是奇怪,明明内存中已经载入了有效的图片,但就是无法绘制到目标DC上,目标DC上一直是黑的,图片绘制无效。后来查看MSDN中才得知,当一个位图对象,被同时选进两个不同的DC中时,会导致gdi绘图函数比如BitBlt、StretchBlt等返回失败。原来是这样,于是排查了代码,是因为初期的代码写的不够规范引起的问题。