一、OCX控件开发常见的问题
1、OCX控件在IE8浏览器下不能使用问题
原因:IE8会拦截OCX控件的方法。
解决方法:在OCX控件开发时加入安全接口。
(1)在有”Crtl“字样的头文件”.h“中加入如下代码:
#include <objsafe.h>并在头文件类的内部加入如下安全接口,代码如下:
- //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
//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“为本例的类名,加入到你代码中请注意替换。
- 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);
- }
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“的字样的头文件上加入如下三个函数声明及一个鼠标事件。
- virtual BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult);
- HRESULT OnActivateInPlace(BOOL bUIActivate, LPMSG pMsg);
- 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文件中加入如下代码:
- 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);
- }
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); }并加入鼠标事件处理:
- 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);
- }
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事件上也加上
OnActivateInPlace(TRUE, NULL);该代码,记得在你的对话框创建前。
3、其他一些问题如果你遇上了,请看一下下面一篇博文,看看是不是有解决方案在其中。博文地址:http://blog.csdn.NET/xiaoxiaoyu85/article/details/6821205