您的位置:首页 > 其它

MFC ActiveX 控件在IE下闪烁的问题

2012-04-23 16:50 330 查看
这周打算发布公司新版本的OCX,忽然又收到客户报的一个很老的bug,公司的OCX在IE下使用的时候,拉动滚动条会重叠,而且还有很严重的闪烁的现象。上半年的时候已经查过相关资料,没有找到解决方法,而且老大也说这个是微软的一个bug,我们无法解决。有些戏剧性的是,林mm发了一个微软的网页,称那篇文章详细说明了那个bug的问题,让我看一下,再和客户解释我们为什么不能解决。那个链接是:

http://support.microsoft.com/kb/233391

认真看了一下,微软是声称那个bug在IE5下是有问题的,可是在IE6下,是已经有办法解决了。

解决第一步,依葫芦画瓢,根据微软说的方法重载了OnSetObjectRects,但是实现为空的,代码如下:

BOOL CmfcaxCtrl::OnSetObjectRects(LPCRECT lpRectPos, LPCRECT lpRectClip)

{

return TRUE;

}

兴致勃勃的rebuild all,再用IE测试。发现是不闪烁了,可是初始化时被隐藏的那部分照样没刷新,-_-失败告终。

冲击第二步,再认真看了那篇文章,发现有一个注意项:

注意 已更改解决以下 Microsoft 知识库 (KB) 文章中描述的问题: 在 Internet Explorer 中

307978 FIX: 重叠 IFRAME 中的 MFC 控件收到不必要的 WM _ PAINT 消息

点击进去,第二篇文章讲述了OnSetObjectRects的重载方法:

void MyGetClippingCoordinates(LPCRECT pPosRect, LPCRECT pClipRect,

LPRECT pIntersectRect, LPPOINT pOffsetPoint)

{

int clipLeft = 0;

int clipTop = 0;

if ((pClipRect == NULL) || IsRectEmpty(pClipRect))

{

CopyRect(pIntersectRect, pPosRect);

}

else

{

IntersectRect(pIntersectRect, pPosRect, pClipRect);

clipLeft = pClipRect->left;

clipTop = pClipRect->top;

}

pOffsetPoint->x = min(0, pPosRect->left - clipLeft);

pOffsetPoint->y = min(0, pPosRect->top - clipTop);

}

BOOL CTmpCtrl::OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)

{

// return COleControl::OnSetObjectRects(lprcPosRect, lprcClipRect);

ASSERT(lprcPosRect != NULL);

// Remember the position rectangle.

m_rcPos = *lprcPosRect;

// Calculate complete rectangle, include the tracker if it is present.

CRect rectPos = m_rcPos;

if (m_bUIActive && m_pRectTracker != NULL)

{

// Save new clipping rectangle (for DestroyTracker).

if (lprcClipRect != NULL)

m_pRectTracker->m_rectClip = *lprcClipRect;

// Adjust tracker rectangle to new dimensions.

CRect rectTmp = rectPos;

rectTmp.OffsetRect(-rectTmp.left, -rectTmp.top);

m_pRectTracker->m_rect = rectTmp;

// Adjust the "true" rectangle to include handles/hatching.

UINT nHandleSize = m_pRectTracker->m_nHandleSize - 1;

rectPos.InflateRect(nHandleSize, nHandleSize);

}

// Now clip the rectangle as appropriate.

CRect rectClip;

MyGetClippingCoordinates(rectPos, lprcClipRect, rectClip, &m_ptOffset);

// Move the outer window first, and then move the inner window.

if (!m_bInPlaceSiteWndless)

{

CWnd* pWndOuter = GetOuterWindow();

//BEGIN CHANGE.

if (pWndOuter != NULL)

{

static CRect oldClipRect(0, 0, 0, 0);

if (oldClipRect != rectClip)

::MoveWindow(pWndOuter->m_hWnd,

rectClip.left, rectClip.top,

rectClip.Width(), rectClip.Height(),

TRUE);

oldClipRect = rectClip;

}

//END CHANGE.

if (pWndOuter != this)

MoveWindow(m_ptOffset.x, m_ptOffset.y,

rectPos.Width(), rectPos.Height());

}

return TRUE;

}

再rebuild下,发现外框是不会闪了,但是中间那些view窗口还是能感觉到闪烁,那个方法只是对IE下闪烁问题做了一些缓解,效果还不是很理想。继续再baidu和google,很难找到最有效的解决方法。继续做其他尝试,还是毫无结果。

冲击三,今天无意间又搜到一篇文章,内容和第一篇很像,也是说了OnSetObjectRects的重载方法,代码几乎一模一样,原先还以为微软弄了个冗余的网页,差点忽略过去。那个网页地址为:

http://support.microsoft.com/kb/310384/zh-cn

本着死马当活马医的思想,又试了一下,原以为会和第二次的结果是一样的,令人惊奇的事情就在意外中发生了。用IE测试的时候,没有闪烁,最小化,很自然的平铺过去了。正当我要欢呼的时候,在StatusBar下面出现了令人恶心的重叠。。。。。继续baidu&&google,无果。。。

在msdn上发现了一个人说把

pOffsetPoint->x = min(0, pPosRect->left - clipLeft);

pOffsetPoint->y = min(0, pPosRect->top - clipTop);

改一下,改成(0,0)的效果更好些。尝试下,果然,效果非常好。闪烁+重叠的现象都没发现,顿时感到人生真是美好。

那个bug貌似解决了,等测试结果吧。心情一下子开朗了很多,就一个字,爽
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: