ATL问题集(32至50)

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

#32如何动态创建ocx

答:看下面代码

#include <atlbase.h>

 CComModule _Module;

#include <atlcom.h>

#include <atlwin.h>

#pragma comment(lib,"atl")

 

CComQIPtr<IWebBrowser2> m_spBrowser;

CAxWindow content_wnd;

......

if(  _tcslen(m_tcHtmlFileName) > 0 )

{

RECT rc;

GetClientRect( &rc );

if(m_spBrowser==NULL)

{

LPOLESTR pstrbrowserid;

StringFromCLSID(IID_IWebBrowser2,&pstrbrowserid);

_bstr_t bstrbrowser(pstrbrowserid);

CoTaskMemFree(pstrbrowserid);

if(content_wnd.IsWindow())

content_wnd.DestroyWindow();

content_wnd.Create( m_hWnd, rc, LPCTSTR(bstrbrowser), WS_CHILD&brvbar;WS_VISIBLE&brvbar;WS_HSCROLL&brvbar;WS_VSCROLL );//create a browser control

HRESULT hrbrowser;

hrbrowser = content_wnd.QueryControl( IID_IWebBrowser2, reinterpret_cast<void**>(&m_spBrowser) );

}

 

#33如何获取窗体上ocx的接口指针?

解决方法:

CWindow::GetDlgControl()

CAxWindow中的QueryControl

拿上面的例子:

hrbrowser = content_wnd.QueryControl( IID_IWebBrowser2, reinterpret_cast<void**>(&m_spBrowser) );

 

#34如何调整控件的大小

要调整控件大小,只需使用标准的 MoveWindow SetWindowPos API(或它们的 CWindow 包装)调整宿主窗口的大小即可。为响应收到的窗口消息,宿主对象自动调整控件大小以填充宿主窗口。

 

#35 #import Java com组件后生成的.tlh文件中的汉字“参数”问题

解决办法:

1、先保存好这个tlh文件的时间戳

2、打开.tlh文件,手动把"参数"改称"var"

3、然后保存文件,并手动把时间戳改回1种保存的时间辍

f5-----ok

 

#36如何使用IStream

我以前写的代码:

void bufStorageWrite()

{

CoInitialize(NULL);

IStream *pStream = NULL;

HRESULThr = S_OK;

HGLOBAL hGLobal =  GlobalAlloc(GMEM_FIXED,SIZE_T(nCount*sizeof(Coord3D)));

::CreateStreamOnHGlobal(hGLobal,true,&pStream);

if(pStream)

{

DWORD dwData[2] = {1,0};

Coord3D coord = {1,2,3,4};

clock_t t1 = clock();

for(int i=0; i<nCount; i++)

{

pStream->Write(&coord,sizeof(Coord3D),NULL);//(&dwData, 2*sizeof(DWORD), NULL);

}

clock_t t2 = clock();

cout<<_T("bufStorageWrite WriteTime ")<<t2-t1<<endl;

 

pStream->Release();

}

 

CoUninitialize();

}

 

#37如何操作DATE类型?

看看下面代码,加上#include <atlconv.h>

void CVarUseDlg::OnDate()

{

       VARIANT timeSelection;

       COleDateTime timeNow;

       DATE curDate;

       HRESULT hr;

       //获取当前时间.

       timeNow = COleDateTime::GetCurrentTime();

      

       //设置一个时间给VARIANT

       timeSelection.vt = VT_DATE;

       timeSelection.date = timeNow.m_dt;

      

       //Convert Variant into string using Variant Change Type.

       hr = VariantChangeType(&timeSelection, &timeSelection, 0, VT_BSTR);

       CString sCurTime(timeSelection.bstrVal);

      

      

       //Get Time as System Time.

       SYSTEMTIME mySysTime;

       timeNow.GetAsSystemTime(mySysTime);

      

       //Use COleDateTime functionality to get change SYSTEMTIME into DATE.

       COleDateTime pastTime(mySysTime);

       curDate = pastTime.m_dt;

 

 

       //Use COldeDateTime Format command to get date as CString.

       LPCTSTR format = _T("%X %z");  //Current time and time zone.

       //Note see "strftime" help for valid formating strings.  

       CString sTime = pastTime.Format(format);

 

}

 

#38我用VB写了一个DLL,用VC怎么调用啊?

#import "your.dll" no_namespace前加上下面这句:

#import "msvbvm60.dll" no_namespace rename("EOF", "EndOfFile") rename("RGB","ColorRGB")

使用VB来开发控件的时候,需要将VB的虚拟机装上去

msvbvm60VB做的控件都要用到的一个DLL

 

#39 那怎么发布使用了dllActivex呢?  

1、如果需要创建cab文件,首先需要Cabarc或者Makecab,它们随着Cabinet  SDK的安装就有了,Cabinet  SDK的下载地址是http://msdn.microsoft.com/workshop/management/cab/cabdl.asp  
Cabarc
可以创建、查看或者解出cab里面的文件,而Makecab则只可以用来创建cab文件。
 
2
、制作cab文件时需要将所有的相关文件都包含进去,可以通过DependsVC自带的)检查需要的文件。使用inf文件将这些东西都写进去。
 
3
inf搞法:inf文件描述cab中所有的ocxdll文件,inf通过一些命名区域来提供需要的信息。
 
 
怎么写
inf  
最开始一般是[Version]区:
 
eg:  [Version]  
       signature="$XXXX$"  
       AdvancedINF=2.0  
接下来就是最重要的[Add.Code]区:
 
eg:  [Add.Code]  
       Ctrl1.dll=C1Section  
       Ctrl2.dll=Ctrl2.dll  
前面是要下载的文件名,后面是对应这个文件的区域名,可以是任何名字,不过一般都是和文件的名字相同,这样方便维护。还有需要注意是在[Add.Code]区出现的文件要根据依赖性进行排序,例如前面说的ctrl1.dll要依赖于ctrl2.dll,则ctrl2.dll要出现在ctrl1.dll的前面。因为安装时是按照相反的顺序进行的,也就是说先安装ctrl2.dll,然后才是ctrl1.dll,哧哧,记清楚了,不要搞反了。
 
再接下来是各个文件的区域了
 
[Ctrl1.dll]  
file-win32-x86=thiscab  
RegisterServer=yes  
clsid={.....}  
DestDir=    
FileVersion=1,0,0,0  
[Ctrl1.dll]
区域中的第一个file值告诉ie到哪里去得到这个dllfile一共包括三个部分,第一部分是file,这个永远都是这样的(至少目前来说);第二部分告诉声明支持的OSwin32表示windowsmac就是苹果MAC  OX了;第三部分是CPU类型,比如说x86  ppc  (Power  PC)  mips或者alpha了。
 
file
的值可以取三个一个URLignorethiscab,如果是URL则说明到URL所在的位置去下;如果是ignore说明对于这种OSCPU,不需要下载这个文件(ctrl1.dll);如果是thiscab很明显就在当前的cab文件中了。
 
接下来是RegisterServer,可以取两个值yesno,如果为yes则说明ie要注册该dll,如果是no就不必了;
 
再下来是DestDir,它的值是dll将要存到本地硬盘的位置,如果它的值是10,则将dll放到/Windows或者/WinNT下;如果是11,则放到/Windows/System或者
 
/WinNT/System32
下;如果是空(就是没有值)则会放到/Windows或者/WinNT下的Downloaded  Program  Files目录下;
 
最后是FileVersion,这个就比较明显了,说明了ctrl1.dll的版本号。
 
有时候我们使用VB来开发控件的时候,需要将VB的虚拟机装上去,它需要一些其它的说明的,简单地讲一下吧:
 
[Add.Code]中增加一项MSVBVM60.DLL=MSVBVM60.DLL(以VB6为例)下面是
 
MSVBVM60.DLL
区域:
 
[MSVBVM60.DLL]  
           hook=MSVBVM60.cab_Installer  
           FileVersion=6,0,81,76  
FileVersion
很明显,是版本号,就不再说发,就说说hook吧。
 
hook
区域是在安装的时候需要执行的区域,它分为两种,一种是有条件的,另外一种是无条件的,无条件的hook区域是必须执行的,反之则根据条件判断是否执行。以[Setup  Hooks]标记的区域是无条件区域,如下所示
 
[Setup  Hooks]  
       hookname=section-name  
 
[section-name]  
run=%EXTRACT_DIR%/setup.exe  
无条件区域常用来通过一个inf文件执行一个安装程序,这就是我们在资源管理器右键点击一个inf文件时在执行安装这样的菜单的原因了
 
ie下载了一个cab文件,如果文件中没有[Add.Code],则处理[Setup  Hooks]区域,运行run所指定程序,哧哧,上面就是setup.exe
 
条件区域则为在一定条件下执行,前面为MSVBVM60.DLL指定的hook区域就是一个条件区域,如果在MSVBVM60.DLL指定的CLSID或者version不能满足需要而且没有file这个命名值,则执行hook所指定的区域。
 
[MSVBVM60.cab_Installer]  
file-win32-x86=http://activex.microsoft.com/controls/vb6/VBRun60.cab  
run=%EXTRACT_DIR%/VBRun60.exe  
上面[MSVBVM60.cab_Installer]是一个hook区域,它也包含了一个file,指定一个URL,表示MSVBVM60.DLL可以从这个URL下载得到;run则说明了执行哪一个文件
 
这里有必要说明一下的是,MS对一些常用的
Redistributable  Microsoft  DLLs  
可以通过指定CODEBASE属性为http://activex.microsoft.com/controls,这样在cab文件中就中需要包含这些文件,在计算机上有一个文件redist.txt上面的dll就是
Redistributable  Microsoft  DLLs  
 
 
创建一个cab文件:
 
cabarc  N  ctrl1.cab  ctrl1.inf  ctrl1.dll  
N
表示要创建一个新的文件,ctrl1.cab是创建的文件名,ctrl1.infcabinf,后而是需要加到cab里的文件,可以使用通配符。
 
然后就可以将cab文件放到网页上了
 
<OBJECT  ID="Ctrl1Obj"  
               CLASSID="clsid:....................................."  
               CODEBASE="http://server.com/ctrl1.cab#version=8,0,0,5007">  
</OBJECT>  
这里也在一个version,不过这里的version是指控件的version,而inf里的是文件的version
 
 
 
制作电子签名:  
首先从下面的网址下载制作签名的工具SignCode,地址是
 
http://msdn.microsoft.com/workshop/gallery/tools/authenticode/authcode.asp  
从签名授权中心如VeriSign或者你的局域网上运行的
Microsoft  Certificate    
Server
授权服务器得到一个certificate,在申请授权的过程你会得到一个私钥。
 
也可以使用MakeCert.exeCert2Spc.exe创建的私钥进行测试,方法是首先使用MakeCert创建一个X.509certificate.cer文件)
 
       MakeCert  -sv  MyKey.pvk  n  "CN=My  Software  Company"  MyCert.cer  
然后利用Cert2Spc.cer文件转换成为PKCS  #7软件发布Certificate(.spc文件)
 
       Cert2Spc  MyCert.cer  MyCert.spc  
利用你下载的SignCode对你的cab文件进行电子签名
 
       SignCode  -spc  MyCert.spc  -v  MyKey.pvk  -t  http://  
               timestamp.verisign.com/scripts/timstamp.dll  ctrl1.cab  
SignCode
还可以指定一些其它的参数,就不说了,太长了,哧哧。
 
虽然可以利用测试的.cer.spc文件,但是在发布的时候,必须申请。
 
 
其实东西在SDK中都有说明,不过都是E文的,慢慢看就没有什么发
 
---------------------------------------------------------------  
 
再补充一点,如果只是测试,你可以SignCode时回车,根据提示一步步往下选,命令行参数又臭又长,还经常出错,这样会节省不少你的时间
 
---------------------------------------------------------------  
 
这是因为ocx关联了你的两个dll,在系统调用ocx中的注册函数是需要调用你的dll但系统无法找到,所以加载ocx失败造成注册失败
 
 
解决的办法是在cab的安装文件里把dll安装到系统的目录下,或者动态加载dll,或者指定加载dll的目录

 

#40 如何在应用程序中判断DLLCOM)已注册?  
 
读注册表/HKEY_CLASSES_ROOT/APPID,看你的DLL是否注册,  

代码如下:

HKEY  valueKey;  
 if  (ERROR_SUCCESS!=RegOpenKeyEx(HKEY_CLASSES_ROOT,  
                       "?????",0,KEY_READ,&valueKey))    
 {           //?????
为类ID,"CLSID//{3B5B0834-5D5D-46C9-AFC9-FD746EDCC272}"  
         //
未注册成功  
       return;  
  }  
  else  
             //
已经注册成功

 

#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.dllmsvcrt.dll,如果需要ole就打包olepro32.dlloleaut32.dll
.  
---------------------------------------------------------------  
 
检查一下是否在修改程序时,vc自动创建部分的代码中的id修改了

 

 

#44 如何利用COM,用VCwordExcel等文件中插入图片?

 

 

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);  
 
           //
docsword程序连接,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时,CMyTestCtrlOnDestroy和析构函数
 
都不会被执行,在Container中调试时,却都会被执行。请问这是为什么?
 
(注:CMyTestAppExitInstance在关闭IE时,会被执行)
 
 
那么,我在CMyTestCtrl的构造函数或OnCreate中分配的资源,在哪儿释放才好呢?
 
---------------------------------------------------------------  
 
重载WM_CLOSE或者
WM_DESTROY  
---------------------------------------------------------------  
重载
COleControl::OnClose  
对应于
IOleControl::Close  
---------------------------------------------------------------  
WM_DESTROY

 

 

#47 ActiveX控件键盘输入问题

自己开发了一个ActiveX控件,从COleControl继承,在VBControl  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->debugexecutable  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中运行的脚本调用,你的代码将从一个配定组件中被调用。  MSinternet信息服务器处理一个来自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相关的概念还没弄清楚,查了许多资料,资料上也讲得迷迷糊糊的,所以向大家请教一下:  
       
一、经常看到DLLOLEActiveXCOM等技术资料,他们之间到底是些什么关系,有什么区别与联系?小弟只知道ActiveXCOM有密切的联系,而COM又以DLL文件形式存在,ActiveX又以.ocx形式存在,对OLE到底是什么东西有什么用也没弄明白。  
       
二、对于GUIDCLSID经常弄不清楚,(他们的样子很相象),作用也不太明白。好象COM一定要在注册表注册,不知OLECOM组件是否一定需要注册啊?不注册能用吗?  
 
 
望各位高手能详细指教一下(不要笑话小弟白痴啊,我真的没弄明白)  
---------------------------------------------------------------  
 
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的,例如IIDInterface  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设置


 转贴请注明出处!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值