天天看點

ATL問題集(精典整理2)

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

  

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

  

  #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->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設定

繼續閱讀