#include <objsafe.h>//OCX控件在IE8浏览器下不能使用问题

 

一、OCX控件开发常见的问题

1、OCX控件在IE8浏览器下不能使用问题

原因:IE8会拦截OCX控件的方法。

      解决方法:在OCX控件开发时加入安全接口。

    (1)在有”Crtl“字样的头文件”.h“中加入如下代码:

  1. #include <objsafe.h>   
        #include <objsafe.h> 
并在头文件类的内部加入如下安全接口,代码如下:
  1. //ISafeObject  
  2.     DECLARE_INTERFACE_MAP()  
  3.     BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)  
  4.     STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (   
  5.           /* [in] */ REFIID riid,  
  6.           /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,  
  7.           /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions  
  8.     );  
  9.     STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (   
  10.           /* [in] */ REFIID riid,  
  11.           /* [in] */ DWORD dwOptionSetMask,  
  12.           /* [in] */ DWORD dwEnabledOptions  
  13.     );  
  14.     END_INTERFACE_PART(ObjSafe);  
  15. //ISafeObject  
//ISafeObject
	DECLARE_INTERFACE_MAP()
	BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
	STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) ( 
	      /* [in] */ REFIID riid,
	      /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
	      /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions
	);
	STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) ( 
	      /* [in] */ REFIID riid,
	      /* [in] */ DWORD dwOptionSetMask,
	      /* [in] */ DWORD dwEnabledOptions
	);
	END_INTERFACE_PART(ObjSafe);
//ISafeObject
(2)在有”Ctrl“字样的CPP文件中添加如下代码:注下面类名这里都以”CxxxCtrl“为本例的类名,加入到你代码中请注意替换。
  1. BEGIN_INTERFACE_MAP( CxxxCtrl, COleControl )  
  2. INTERFACE_PART(CxxxCtrl, IID_IObjectSafety, ObjSafe)  
  3. END_INTERFACE_MAP()  
  4.   
  5. /////////////////////////////////////////////////////////////////////////////  
  6. // Dispatch map  
  7. // IObjectSafety member functions  
  8. ULONG FAR EXPORT CxxxCtrl::XObjSafe::AddRef()  
  9. {  
  10.     METHOD_PROLOGUE(CxxxCtrl, ObjSafe)  
  11.     return pThis->ExternalAddRef();  
  12. }  
  13. ULONG FAR EXPORT CxxxCtrl::XObjSafe::Release()  
  14. {  
  15.     METHOD_PROLOGUE(CxxxCtrl, ObjSafe)  
  16.     return pThis->ExternalRelease();  
  17. }  
  18. HRESULT FAR EXPORT CxxxCtrl::XObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)  
  19. {  
  20.     METHOD_PROLOGUE(CxxxCtrl, ObjSafe)  
  21.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);  
  22. }  
  23. const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;  
  24. const DWORD dwNotSupportedBits = ~ dwSupportedBits;  
  25. //.............................................................................  
  26. // CxxxCtrl::XObjSafe::GetInterfaceSafetyOptions  
  27. // Allows container to query what interfaces are safe for what. We're  
  28. // optimizing significantly by ignoring which interface the caller is  
  29. HRESULT STDMETHODCALLTYPE CxxxCtrl::XObjSafe::GetInterfaceSafetyOptions(   
  30. /* [in] */ REFIID riid,  
  31. /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,  
  32. /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)  
  33. {  
  34.     METHOD_PROLOGUE(CxxxCtrl, ObjSafe)  
  35.     HRESULT retval = ResultFromScode(S_OK);  
  36.     // does interface exist?  
  37.     IUnknown FAR* punkInterface;  
  38.     retval = pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);  
  39.     if (retval != E_NOINTERFACE) { // interface exists  
  40.         punkInterface->Release(); // release it--just checking!  
  41.     }  
  42.     // we support both kinds of safety and have always both set,  
  43.     // regardless of interface  
  44.     *pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;  
  45.     return retval; // E_NOINTERFACE if QI failed  
  46. }  
  47. /////////////////////////////////////////////////////////////////////////////  
  48. // CxxxCtrl::XObjSafe::SetInterfaceSafetyOptions  
  49. // Since we're always safe, this is a no-brainer--but we do check to make  
  50. // sure the interface requested exists and that the options we're asked to  
  51. // set exist and are set on (we don't support unsafe mode).  
  52. HRESULT STDMETHODCALLTYPE CxxxCtrl::XObjSafe::SetInterfaceSafetyOptions(   
  53. /* [in] */ REFIID riid,  
  54. /* [in] */ DWORD dwOptionSetMask,  
  55. /* [in] */ DWORD dwEnabledOptions)  
  56. {  
  57.         METHOD_PROLOGUE(CxxxCtrl, ObjSafe)  
  58.         // does interface exist?  
  59.     IUnknown FAR* punkInterface;  
  60.     pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);  
  61.     if (punkInterface) { // interface exists  
  62.         punkInterface->Release(); // release it--just checking!  
  63.     }else   
  64.     {   
  65.         // interface doesn't exist  
  66.         return ResultFromScode(E_NOINTERFACE);  
  67.     }   
  68.         // can't set bits we don't support  
  69.     if (dwOptionSetMask & dwNotSupportedBits) {   
  70.         return ResultFromScode(E_FAIL);  
  71.     }   
  72.         // can't set bits we do support to zero  
  73.     dwEnabledOptions &= dwSupportedBits;  
  74.         // (we already know there are no extra bits in mask )  
  75.     if ((dwOptionSetMask & dwEnabledOptions) != dwOptionSetMask) {  
  76.         return ResultFromScode(E_FAIL);  
  77.     }           
  78.         // don't need to change anything since we're always safe  
  79.     return ResultFromScode(S_OK);  
  80. }  
BEGIN_INTERFACE_MAP( CxxxCtrl, COleControl )
INTERFACE_PART(CxxxCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Dispatch map
// IObjectSafety member functions
ULONG FAR EXPORT CxxxCtrl::XObjSafe::AddRef()
{
    METHOD_PROLOGUE(CxxxCtrl, ObjSafe)
	return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CxxxCtrl::XObjSafe::Release()
{
    METHOD_PROLOGUE(CxxxCtrl, ObjSafe)
	return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CxxxCtrl::XObjSafe::QueryInterface(REFIID iid, void FAR* FAR* ppvObj)
{
    METHOD_PROLOGUE(CxxxCtrl, ObjSafe)
	return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
const DWORD dwSupportedBits = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~ dwSupportedBits;
//.............................................................................
// CxxxCtrl::XObjSafe::GetInterfaceSafetyOptions
// Allows container to query what interfaces are safe for what. We're
// optimizing significantly by ignoring which interface the caller is
HRESULT STDMETHODCALLTYPE CxxxCtrl::XObjSafe::GetInterfaceSafetyOptions( 
/* [in] */ REFIID riid,
/* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,
/* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)
{
	METHOD_PROLOGUE(CxxxCtrl, ObjSafe)
	HRESULT retval = ResultFromScode(S_OK);
	// does interface exist?
	IUnknown FAR* punkInterface;
	retval = pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
	if (retval != E_NOINTERFACE) { // interface exists
		punkInterface->Release(); // release it--just checking!
	}
	// we support both kinds of safety and have always both set,
	// regardless of interface
	*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits;
	return retval; // E_NOINTERFACE if QI failed
}
/////////////////////////////////////////////////////////////////////////////
// CxxxCtrl::XObjSafe::SetInterfaceSafetyOptions
// Since we're always safe, this is a no-brainer--but we do check to make
// sure the interface requested exists and that the options we're asked to
// set exist and are set on (we don't support unsafe mode).
HRESULT STDMETHODCALLTYPE CxxxCtrl::XObjSafe::SetInterfaceSafetyOptions( 
/* [in] */ REFIID riid,
/* [in] */ DWORD dwOptionSetMask,
/* [in] */ DWORD dwEnabledOptions)
{
        METHOD_PROLOGUE(CxxxCtrl, ObjSafe)
        // does interface exist?
	IUnknown FAR* punkInterface;
	pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
	if (punkInterface) { // interface exists
		punkInterface->Release(); // release it--just checking!
	}else 
	{ 
		// interface doesn't exist
		return ResultFromScode(E_NOINTERFACE);
	} 
        // can't set bits we don't support
	if (dwOptionSetMask & dwNotSupportedBits) { 
		return ResultFromScode(E_FAIL);
	} 
        // can't set bits we do support to zero
	dwEnabledOptions &= dwSupportedBits;
        // (we already know there are no extra bits in mask )
	if ((dwOptionSetMask & dwEnabledOptions) != dwOptionSetMask) {
		return ResultFromScode(E_FAIL);
	}         
        // don't need to change anything since we're always safe
	return ResultFromScode(S_OK);
}
如果加安全代码后,还是不能正常加载,那你要确认一下,你的操作系统是64位系统吗?若是,再看一下你IE是不是也使用64位的。若是的话,那就没有办法了,我在前面的博文中已经说明了,64位的IE是不支持32位OCX控件,请使用更高的IE版本调试或者。。。建议使用IE10及以上,IE9也同样存在这样的问题。如果不是,那你再看一下找一下其他原因,或者在评论中阐述你的问题出现的现象,博友们一起帮你研究与解决。

2、OCX控件引入对话框界面后,OCX控件无法响应键盘”backspack“键。

原因:IE浏览器截获该事件,出现一按”backpack“键,网页就回退,无法正常在OCX控件上操作。

解决方法:有两种,一使用MFC中的钩子方法(不推荐,本文不详细解说),另一种是OCX控件中添加处理事件的函数来处理,具体说明请查看官网  http://support.microsoft.com/kb/168777/nl    

(1)在”Ctrl“的字样的头文件上加入如下三个函数声明及一个鼠标事件。

  1. virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);  
  2. HRESULT OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg);  
  3. BOOL PreTranslateMessage(MSG* pMsg);  
	virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
	HRESULT OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg);
	BOOL PreTranslateMessage(MSG* pMsg);
      一个鼠标事件 afx_msg int OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message); 

(2)在”Ctrl“字样的CPP文件中加入如下代码:

  1. BOOL CxxxCtrl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult)  
  2. {  
  3.     switch (message)  
  4.     {  
  5.     case WM_REPORT_BATCHWRITEPU_CLOSEFLAGE:  
  6.         this->FireSetCloseFlag((short)wParam);  
  7.         break;  
  8.     }  
  9.     return COleControl::OnWndMsg(message, wParam, lParam, pResult);  
  10. }  
  11. HRESULT CxxxCtrl::OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg)  
  12. {  
  13.     static BOOL bInsideFunc = FALSE;  
  14.     if (!bInsideFunc)  
  15.     {  
  16.         bInsideFunc = TRUE;  
  17.         HRESULT hr = COleControl::OnActivateInPlace(bUIActivate, pMsg);  
  18.         bInsideFunc = FALSE;  
  19.         return hr;  
  20.     }  
  21.     return S_OK;  
  22. }  
  23. BOOL CxxxCtrl::PreTranslateMessage(MSG* pMsg)   
  24. {  
  25.     switch (pMsg->message)  
  26.     {  
  27.     case WM_KEYDOWN:  
  28.     case WM_KEYUP:  
  29.         switch (pMsg->wParam)  
  30.         {  
  31.         case VK_UP:  
  32.         case VK_DOWN:  
  33.         case VK_LEFT:  
  34.         case VK_RIGHT:  
  35.         case VK_HOME:  
  36.         case VK_END:  
  37.             ::SendMessage (GetFocus()->GetSafeHwnd(), pMsg->message, pMsg->wParam, pMsg->lParam);  
  38.             return TRUE;  
  39.         }  
  40.         break;  
  41.     }  
  42.     return COleControl::PreTranslateMessage(pMsg);  
  43. }    
BOOL CxxxCtrl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
	switch (message)
	{
	case WM_REPORT_BATCHWRITEPU_CLOSEFLAGE:
		this->FireSetCloseFlag((short)wParam);
		break;
	}
	return COleControl::OnWndMsg(message, wParam, lParam, pResult);
}
HRESULT CxxxCtrl::OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg)
{
	static BOOL bInsideFunc = FALSE;
	if (!bInsideFunc)
	{
		bInsideFunc = TRUE;
		HRESULT hr = COleControl::OnActivateInPlace(bUIActivate, pMsg);
		bInsideFunc = FALSE;
		return hr;
	}
	return S_OK;
}
BOOL CxxxCtrl::PreTranslateMessage(MSG* pMsg) 
{
	switch (pMsg->message)
	{
	case WM_KEYDOWN:
	case WM_KEYUP:
		switch (pMsg->wParam)
		{
		case VK_UP:
		case VK_DOWN:
		case VK_LEFT:
		case VK_RIGHT:
		case VK_HOME:
		case VK_END:
			::SendMessage (GetFocus()->GetSafeHwnd(), pMsg->message, pMsg->wParam, pMsg->lParam);
			return TRUE;
		}
		break;
	}
	return COleControl::PreTranslateMessage(pMsg);
}  
并加入鼠标事件处理:
  1. int <span style="font-family: Arial, Helvetica, sans-serif;">CxxxCtrl</span>::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)   
  2. {  
  3.     // TODO: Add your message handler code here and/or call default   
  4.     OnActivateInPlace(TRUE, NULL); //事件加入后,请加入此行代码。  
  5.     return COleControl::OnMouseActivate(pDesktopWnd, nHitTest, message);  
  6. }  
int <span style="font-family: Arial, Helvetica, sans-serif;">CxxxCtrl</span>::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	// TODO: Add your message handler code here and/or call default	
	OnActivateInPlace(TRUE, NULL); //事件加入后,请加入此行代码。
	return COleControl::OnMouseActivate(pDesktopWnd, nHitTest, message);
}
并OnCreate事件上也加上  
  1. OnActivateInPlace(TRUE, NULL);   
OnActivateInPlace(TRUE, NULL); 
该代码,记得在你的对话框创建前。

3、其他一些问题如果你遇上了,请看一下下面一篇博文,看看是不是有解决方案在其中。博文地址:http://blog.csdn.NET/xiaoxiaoyu85/article/details/6821205    

原文地址:https://www.cnblogs.com/andyliu1988/p/6084444.html