ATL问题集(精典整理2)

 /*文是将网上的一些文章,自已遇到的问题进行整理,有些是翻译,所有只供学习讨论,如有版权还归原作者――作者:王卫星csdnid:wangweixing2000*/

#41 我想在程序中连续注册好几个控件,如果用regsvr32 命令会出现多个注册成功的对话框有没有什么方法可以解决那?
  /u是注销。
  /s是不弹出注册成功的对话框
  regsvr32 ... /s
  代码实现如下:
  HMODULE hModule = LoadLibrary(strFilePath);
  if(hModule == NULL)
  {
   strMessage.Format("LoadLibrary(/"%s/") 失败!",strFilePath);
   MessageBox(NULL,strMessage,"RegisterServer32",MB_ICONEXCLAMATION);
   return FALSE;
  }
   FARPROC pFarProc = GetProcAddress(hModule,"DllRegisterServer");
   if(pFarProc == NULL)
   {
   MessageBox(NULL,"GetProcAddress(/"DllRegisterServer/") Failed","RegisterServer32",MB_ICONEXCLAMATION);
   }
   else
   {
   (*pFarProc)();
   }
  
  #42 IWebBrowser2疑惑.,有时能获取控件的句柄有时没法获取,怎么回事?
  
  CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_pWebBrowser2;
  //---------------------- 使用CLSID_WebBrowser--------------------
  HRESULT hrrs = CoCreateInstance(CLSID_WebBrowser, NULL,CLSCTX_INPROC,IID_IWebBrowser2,(void**)&m_pWebBrowser2);
  //---------------------- 使用CLSID_InternetExplorer---------------
  HRESULT hrrs = CoCreateInstance(CLSID_InternetExplorer, NULL,CLSCTX_INPROC,IID_IWebBrowser2,(void**)&m_pWebBrowser2);
  //---------------------- 获取句柄---------------------------------
  HWND hIE;
  hrrs = m_pWebBrowser2->get_HWND((long*)&hIE);
  以上两个方法来获取IWebBrowser2,两种都能获取,可是第一种为什么得不到窗口句柄,而第二种可以呢?请指教 ,有个么办法使第一种也能得到
  Browser窗口句柄呢?
  ---------------------------------------------------------------
  解答:
  CLSID_WebBrowser:是微软web预览控件的实现类的id,它同过属性Parent来得到窗口句柄,因为控件没法知道它被放在哪个容器里,所以不会实现HWND属性!
  CLSID_InternetExplorer:是微软ie浏览器自动化实现类的id,它通过属性HWND得到!因为得到句柄一定封装好了. 哈哈!
  
  #43 作了个ActiveX控件,嵌入网页中使用,版本更新时,客户端不能更新,如何解决?
  
  网页中调用控件部分代码
  <OBJECT classid="clsid:C69A0449-8786-11D4-B209-00104B13AFD4" CODEBASE="PLWeb.cab#version=1,0,0,2" height=605 id=PLWeb1
   style="LEFT: 0px; TOP: 0px" width=995 VIEWASTEXT>
   <param name="_Version" value="65536">
   <param name="_ExtentX" value="26326">
   <param name="_ExtentY" value="16007">
   <param name="_StockProps" value="0">
   </OBJECT>
  cab包中的内容
  plweb.ocx (1.0.0.2版)
  plweb.inf
  (
   [version]
   signature="$CHICAGO$"
   AdvancedINF=2.0
   [Add.Code]
   PLWeb.ocx=PLWeb.ocx
   [PLWeb.ocx]
   file-win32-x86=thiscab
   ; *** add your controls CLSID here ***
   clsid={C69A0449-8786-11D4-B209-00104B13AFD4}
   ; Add your ocx's file version here.
   FileVersion=1,0,0,2
   DestDir=11
   RegisterServer=yes
  )
  客户端在第一次浏览具有控件的网页时,可以正常下载注册,但如果更新控件版本时,客户端可以下载(在internet的临时文件夹中可以找到新的plweb.cab文件),但是不能注册新版本控件。
   不知道这是什么原因引起的,如何解决?
  ---------------------------------------------------------------
  <OBJECT classid="clsid:C69A0449-8786-11D4-B209-00104B13AFD4" CODEBASE="PLWeb.cab#version=1,0,0,3" height=605 id=PLWeb1
  style="LEFT: 0px; TOP: 0px" width=995 VIEWASTEXT>
  你可以手工在工程中更改版本号来达到升级
  如果没有注册成功,有可能是客户机环境变了.
  你的控件需要运行库支持,现在客户机没有了[重做了系统等]
  打包时注意一下,如果是基于atl的,就打包ATL.dll,如果是基于mfc的就打包mfc42.dll和msvcrt.dll,如果需要ole就打包olepro32.dll和oleaut32.dll等.
  ---------------------------------------------------------------
  检查一下是否在修改程序时,将vc自动创建部分的代码中的id修改了
  
  #44 如何利用COM,用VC在word、Excel等文件中插入图片?
  
  http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q311/7/65.asp&NoWebContent=1
  在上面这个例子中,如果我想再加入在当前鼠标位置插入图片的功能,该怎么写?
  ---------------------------------------------------------------
  void CWebOfficeCtrl::LoadUnit(void)
  {
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   // TODO: 在此添加调度处理程序代码
   LPDISPATCH lpDisp;
   lpDisp=m_pWebOfficeFrame->m_pWebOfficeView->m_pSelection->GetIDispatch();
   _Application_Word m_WordApp;
   _Document_Word m_WordDoc;
   m_WordDoc.AttachDispatch(lpDisp,TRUE);
   //m_WordDoc.Activate();
   m_WordApp=m_WordDoc.GetApplication();
  
   InlineShapes_Word m_WordInlineShapes;
   InlineShape_Word m_WordInlineShape;
   Selection_Word m_WordSelection;
   m_WordSelection=m_WordApp.GetSelection();
   m_WordInlineShapes=m_WordSelection.GetInlineShapes();
   COleVariant vTrue((short)TRUE),vFalse((short)FALSE),vOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
   //AfxMessageBox(m_UnitName,MB_ICONINFORMATION);
   m_WordInlineShape=m_WordInlineShapes.AddPicture(m_UnitName,vFalse,vTrue,vOptional);
   /*
   //2003.11.29 Add By DigitalTitan[设置图元重叠属性]
   Shape_Word m_WordShape;
   m_WordShape=m_WordInlineShape.ConvertToShape();
   WrapFormat_Word m_WordWrapFormat;
   m_WordWrapFormat=m_WordShape.GetWrapFormat();
   //m_WordWrapFormat.SetAllowOverlap(TRUE);3
   m_WordWrapFormat.ReleaseDispatch();
   m_WordShape.ReleaseDispatch();
   //
   */
   m_WordInlineShape.ReleaseDispatch();
   m_WordInlineShapes.ReleaseDispatch();
   m_WordSelection.ReleaseDispatch();
   m_WordDoc.ReleaseDispatch();
   m_WordApp.ReleaseDispatch();
  }
  
  当WORD已经启动时,并打开了几个文件,我想在其中的一个打开的WORD文件的光标位置插入一幅BMP
   if(!WordApp.CreateDispatch("Word.Application",NULL))//创建一个新的word程序
   {
   AfxMessageBox("创建ms_word服务失败");
   exit(1);
   }
   //让用户能够查看自动化的过程
   WordApp.SetVisible(true);
   //让docs和word程序连接,docs代表word中所有文档
   docs=WordApp.GetDocuments();
   COleVariant covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
   //用docs来打开一个文档,并将句柄返回给doc
   //doc=docs.Add(COleVariant("C://ox.doc"),covOptional,covOptional,covOptional);
  //这里要查找我要加入的WORD文件是否打开
  //怎么样在当前光标处加入文件.
  //
  ---------------------------------------------------------------
  1.得到ActivateDocument
  2.得到ActivateDocument中的Shapes
  3.调用Shapes的方法: AddPicture
  只要指定图片文件名,就可以加入图片了。
  ---------------------------------------------------------------
  InlineShapes_Word m_WordInlineShapes;
   InlineShape_Word m_WordInlineShape;
   Selection_Word m_WordSelection;
   m_WordSelection=m_WordApp.GetSelection();
   m_WordInlineShapes=m_WordSelection.GetInlineShapes();
   COleVariant vTrue((short)TRUE),vFalse((short)FALSE),vOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
   //AfxMessageBox(m_UnitName,MB_ICONINFORMATION);
   m_WordInlineShape=m_WordInlineShapes.AddPicture(m_UnitName,vFalse,vTrue,vOptional);
   /*
   //2003.11.29 Add By DigitalTitan[设置图元重叠属性]
   Shape_Word m_WordShape;
   m_WordShape=m_WordInlineShape.ConvertToShape();
   WrapFormat_Word m_WordWrapFormat;
   m_WordWrapFormat=m_WordShape.GetWrapFormat();
   //m_WordWrapFormat.SetAllowOverlap(TRUE);3
   m_WordWrapFormat.ReleaseDispatch();
   m_WordShape.ReleaseDispatch();
   //
   */
  #45 如何使用MFC插入图片到excel?
  #import "G:/Program Files/Common Files/Microsoft Shared/OFFICE11/MSO.DLL"
  #import "G:/Program Files/Common Files/Microsoft Shared/VBA/VBA6/VBE6EXT.OLB"
  #import "G:/Program Files/Microsoft Office/OFFICE11/EXCEL.EXE" rename("RGB", "ExcelRGB") rename("Delete","ExcelDelete") rename("DialogBox","ExcelDialogBox")
  void Cexcel_picDlg::OnBnClickedOk()
  {
   // insert picture to excel
   // environment: vc2003, excel2003, windows2003
   using namespace Excel;
   _variant_t covOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
   DWORD dwStartTime = GetTickCount();
   _ApplicationPtr app;//("Excel.Application");
   HRESULT hr = S_OK;
   CLSID clsid;
   CLSIDFromProgID(L"Excel.Application", &clsid);
   app.CreateInstance(clsid);
   WorkbooksPtr books;
   _WorkbookPtr book;
   long lcid =LOCALE_USER_DEFAULT;
   SheetsPtr sheets;
   app->get_Workbooks(&books);
   book = books->Add(covOptional,lcid/*,&book*/);
   book->get_Worksheets(&sheets);
   IDispatchPtr pDisp;
   sheets->get_Item(_variant_t((short)1),&pDisp);
   _WorksheetPtr sheet(pDisp);
   RangePtr range = sheet->GetRange(_variant_t("A1"),_variant_t("A1"));
   range->Value2 = "aaa";
   LPCSTR m_Path = _T("C://flower8.jpg");
   PicturesPtr pics = sheet->Pictures();
   pics->Insert(m_Path,VARIANT_FALSE);
   app->put_AskToUpdateLinks(lcid,VARIANT_FALSE);
   app->put_AlertBeforeOverwriting(lcid,VARIANT_FALSE);
   app->put_UserControl(VARIANT_FALSE);
   app->put_DisplayAlerts(0,VARIANT_FALSE);
   LPCTSTR file_name = _T("c://aa.xls");
   _variant_t varfilename(file_name);
   DeleteFile(file_name);
   HRESULT hrMethod = book->SaveAs(varfilename,covOptional,covOptional,covOptional,covOptional,covOptional,xlNoChange);
   book->put_Saved(0,VARIANT_TRUE);
   book->Close(COleVariant(VARIANT_FALSE));
   books->Close();
   app->Quit();
  }
  #46 关闭IE时,销毁ACTIVEX控件的问题
  
  我用VC向导创建 MFC ACTIVEX CONTROL,
  默认生成CMyTestApp, CMyTestCtrl, CMyTestPropPage三个类。
  然后,我在IE中调入该控件。当关闭IE时,CMyTestCtrl的OnDestroy和析构函数
  都不会被执行,在Container中调试时,却都会被执行。请问这是为什么?
  (注:CMyTestApp的ExitInstance在关闭IE时,会被执行)
  那么,我在CMyTestCtrl的构造函数或OnCreate中分配的资源,在哪儿释放才好呢?
  ---------------------------------------------------------------
  重载WM_CLOSE或者WM_DESTROY
  ---------------------------------------------------------------
  重载COleControl::OnClose
  对应于IOleControl::Close
  ---------------------------------------------------------------
  WM_DESTROY
  
  #47 ActiveX控件键盘输入问题
  自己开发了一个ActiveX控件,从COleControl继承,在VB和Control Test Container中使用均没有问题,但是在MFC的基于对话框的程序中使用,能响应鼠标输入但不能响应键盘输入。跟踪发现在控件的PreTranslateMessage中有WM_CHAR消息但没有响应OnChar函数,不知哪位大侠知道如何解决。
  ---------------------------------------------------------------
  Accelerator keys, such as ARROW keys, are first received by the message pump of the ActiveX control's container. Even if the control has the focus, it does not receive messages for keystrokes that have special meaning to control containers, such as ARROW and TAB keys. MFC ActiveX controls have a chance to intercept these messages by overriding their PreTranslateMessage function.
  However, PreTranslateMessage is not always called for an MFC ActiveX control.
  RESOLUTION
  Install a Windows WH_GETMESSAGE hook for the modeless dialog box/propertysheet derived class to allow it to intercept keystrokes and handle accelerators.
  ...
  see Knowledge Base articles for more information
  Q168777 PRB: MFC ActiveX Control in IE Doesn't Detect Keystrokes
  Q180402 PRB: MFC ActiveX Control Ignores ARROW Keys on VB Container
  Q187988 PRB: ActiveX Control Is the Parent Window of Modeless Dialog
  Q199431 PRB: Enabling Menu Mnemonics in an MFC ActiveX Control
  Q194294 HOWTO: Add Toolbars and Tooltips to ActiveX Controls
  
  #48 在ASP里如何调试写的(ATL写的)COM呢?
  首先在管理工具->组件服务里面的“COM+应用程序”项下面添加一下空的应用程序,名字随便,然后把写好的组件注册在这个里面,并记下该应用程序的ID,如:{2D62D611-4A90-4196-AA9B-2055AD3A12E7}
  接下来在VC里面project->setting->debug的executable for debug session选项里面填写“系统目录+DLLHOST.exe“,如我的系统填写的是“C:/windows/system32/DLLHOST.EXE”;
  在program arguments选项里面填写刚才的应用程序ID {2D62D611-4A90-4196-AA9B-2055AD3A12E7} ,设置断点,调试运行,你会发现COM程序会中断下来,这样就表示你设置成功了,然后用ASP调用就可以了~
  ---------------------------------------------------------------
  以下摘自 <windows 程序调试> Addison -Wesley
   如果你写的基com dll要被在一个asp中运行的脚本调用,你的代码将从一个配定组件中被调用。 当MS的internet信息服务器处理一个来自ASP的请求时,他激活一个叫做网络应用管理器(web application manager)的配定组件。 这个组件执行该ASP中的脚本发出的激活和方法调用请求。因为网络应用管理组件是在MTS/COM+配置的。你的com dll会在一个代理进程的环境中执行。
   在这个情况下,将调试器附到正确的代理进程的工作就变成了确定哪个服务器包是你的组件宿主的问题。 。。。
  if on windows 2000
   在WIN2000中,管理工具->Internet 服务管理器->查看你的虚拟站点的属性->在指定虚拟目录的tab页中,包含一个叫应用程序保护的选项。(在最下面)
   这个选项可设置为:
  1)LOW (低,IID进程)
  2)Medium(中等,对象池)
  3)high(高,独立)
  这个设置决定组件的宿主服务器包。
  if 1), 在COM+浏览器中找到in-process apllication包的GUID
  if 2),在com+浏览器中找到IIS out-of-process pooled apllication包的GUID
  if 3),在com+浏览器中找到IIS-{website//你的虚拟目录名}包的GUID
  然后,你可以参考上面的答复,将VC附到已运行的代理进程,进行调试了。
  #49 初学者应该知道的一些COM的基本概念
  小弟接触COM也有一段时间了,对很多COM相关的概念还没弄清楚,查了许多资料,资料上也讲得迷迷糊糊的,所以向大家请教一下:
   一、经常看到DLL、OLE、ActiveX、COM等技术资料,他们之间到底是些什么关系,有什么区别与联系?小弟只知道ActiveX与COM有密切的联系,而COM又以DLL文件形式存在,ActiveX又以.ocx形式存在,对OLE到底是什么东西有什么用也没弄明白。
   二、对于GUID、CLSID经常弄不清楚,(他们的样子很相象),作用也不太明白。好象COM一定要在注册表注册,不知OLE、COM组件是否一定需要注册啊?不注册能用吗?
  望各位高手能详细指教一下(不要笑话小弟白痴啊,我真的没弄明白)
  ---------------------------------------------------------------
  COM是一个二进制标准,它是以DLL形式存储的,由于传统DLL没有解决一些诸如内存分配,卸载等关键性问题,所以它不足以成为一个组件模型,而COM定义了这些标准。OLE算是COM的前身,到OLE2后就正式出现为COM标准,它已经在OLE(对象连接与嵌入)上作了极大的改进,成为一个独立的标准,而ActiveX是微软提出的一个专有名词,目的是实现网上的一些应用,它的本质就是COM。
  CLSID是用来标志每个COM组件的,CLSID是属于GUID的,格式一样,只是CLSID有特定用途,换了个名字而已,COM一定要注册,不注册的话就找不到他的具体位置,好像.net以后就不需要注册了。
  我也不太懂,一起学习
  ---------------------------------------------------------------
  上面的说的很好!我补充一点吧!
  CLSID可以这么解释class id,GUID是全局唯一ID,CLSID也是属于GUID的,例如IID是Interface ID。多看看COM本质!
  DLL,OLE->COM->ActiveX,ATL->COM+,DCOM->现在出现.NET中的公共语言环境。
  这是我自己的理解,希望对你有帮助!
  ---------------------------------------------------------------
  COM是一种标准,巧妙的利用了运行时绑定的技术。可以DLL形式存在,也可以exe形式存在。
  ActiveX是COM标准的一个具体应用而已。ocx文件就是动态连接库文件,扩展名不同而已。OLE也是一种技术的名称,叫对象连接与嵌入,主要目的是通过一套约定,来使得不同程序能相互传递数据。ole2以后都是通过的COM技术来实现OLE了。
  GUID是一种常量,这种常量能保证世界上任何地方的任何人在任何时候都能产生一个不同于其他人的值。CLSID就是GUID,只不过看起来明确一点,他是指代class的。类似的还有IID,是指代interface的。
  就好像UINT 就是 unsigned long。只不过看起来舒服些。
   #50 如何修改DCOM应用程序的运行位置(在哪台机器上运行)?
  
  DCOMCNFG.exe中某应用程序“位置”项,选了“在这台计算机上运行应用程序”则“在下列计算机上运行应用程序”的设置就不生效了。
  请问如何不用DCOMCNFG.exe而通过修改程序将“在这台计算机上运行应用程序”项前面的对号去掉(如操作注册表,改哪一项的制值)?
  ---------------------------------------------------------------
  用CoCreateInstanceEx,在参数pServerInfo中,写入服务器的地址
  ---------------------------------------------------------------
  当然有,通过dcom的管理接口
  ---------------------------------------------------------------
  在注册表中你的服务器AppID下加一个RemoteServerName字符串值"www.xxx.com"或IP地址
  也可以使用dcomcnfg设置
  #50 如何修改DCOM应用程序的运行位置(在哪台机器上运行)?
  
  DCOMCNFG.exe中某应用程序“位置”项,选了“在这台计算机上运行应用程序”则“在下列计算机上运行应用程序”的设置就不生效了。
  请问如何不用DCOMCNFG.exe而通过修改程序将“在这台计算机上运行应用程序”项前面的对号去掉(如操作注册表,改哪一项的制值)?
  ---------------------------------------------------------------
  用CoCreateInstanceEx,在参数pServerInfo中,写入服务器的地址
  ---------------------------------------------------------------
  当然有,通过dcom的管理接口
  ---------------------------------------------------------------
  在注册表中你的服务器AppID下加一个RemoteServerName字符串值"www.xxx.com"或IP地址
  也可以使用dcomcnfg设置
   #50 如何修改DCOM应用程序的运行位置(在哪台机器上运行)?
  
  DCOMCNFG.exe中某应用程序“位置”项,选了“在这台计算机上运行应用程序”则“在下列计算机上运行应用程序”的设置就不生效了。
  请问如何不用DCOMCNFG.exe而通过修改程序将“在这台计算机上运行应用程序”项前面的对号去掉(如操作注册表,改哪一项的制值)?
  ---------------------------------------------------------------
  用CoCreateInstanceEx,在参数pServerInfo中,写入服务器的地址
  ---------------------------------------------------------------
  当然有,通过dcom的管理接口
  ---------------------------------------------------------------
  在注册表中你的服务器AppID下加一个RemoteServerName字符串值"www.xxx.com"或IP地址
  也可以使用dcomcnfg设置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值