activex 를 만들다보니 여러가지 상황에 놓이게 되는 경우가 많네요. 일단 iframe 과 activex 를 같은 화면에 올려놓고 사용하는 경우가 발생했습니다.
iframe 은 사이즈가 변경되거나 iframe의 내부 코드가 변경되었을 때 상위 부모에 자신의 사이즈가 변경되었으니 전체적으로 화면을 변경해달라는 이벤트를 발생시키나봅니다. 근데 이 사이즈 조절 이벤트가 발생되면 같이 있던 activex 에도 그 이벤트가 전달이 되겠죠. 그럼 activex 은 화면을 다시 그리기 위해 invalidate 할테고 그러면 그려져있는 이미지들을 다시 그리게 되니 화면이 번쩍이게 됩니다.
또 한가지, iframe 에서 marqee 같은거 써주면 계속 이벤트가 발생돼서 activex 아 화면을 그리는데만 쓰는 자원 소모가 심각하게 많아지게 됩니다. 그래서 여기 저기 찾아서 검색해본 결과 다음과 같은 답이 있었답니다.
일단 activex control class 에 다음 메소드를 상속받아 추가합니다.
virtual BOOL OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
그리고 소스코드에 다음을 복사해서 붙여넣으면 해결됩니다.
void AFXAPI 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 CTmtMDICtlCtrl::OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
{
ASSERT(lprcPosRect != NULL);
// Remember the position rectangle for later
m_rcPos = *lprcPosRect;
// Calculate complete rectangle including the tracker (if 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 that rectangle as appropriate
CRect rectClip;
// CHANGE - call your own copy of _GetClippingCoordinates
MyGetClippingCoordinates(rectPos, lprcClipRect, rectClip, &m_ptOffset);
// Move outer window first. then inner window
if (!m_bInPlaceSiteWndless)
{
CWnd* pWndOuter = GetOuterWindow();
//BEGIN CHANGE
if (pWndOuter != NULL)
{
// ::MoveWindow(pWndOuter->m_hWnd, rectClip.left, rectClip.top,
// rectClip.Width(), rectClip.Height(), TRUE);
::MoveWindow(pWndOuter->m_hWnd, rectPos.left, rectPos.top,
rectPos.Width(), rectPos.Height(), TRUE);
}
//END CHANGE
if (pWndOuter != this)
MoveWindow(m_ptOffset.x, m_ptOffset.y, rectPos.Width(), rectPos.Height());
}
return TRUE;
}
이 동작은 activeX 에 리사이즈 하라는 이벤트가 전달 됐을 때 실제 호출자가 IE 인지 아니면 다른 녀석인지를 분간해서 IE 일 경우에만 화면을 resize 하는 코드입니다. 구굴신님 감사해요.
iframe 은 사이즈가 변경되거나 iframe의 내부 코드가 변경되었을 때 상위 부모에 자신의 사이즈가 변경되었으니 전체적으로 화면을 변경해달라는 이벤트를 발생시키나봅니다. 근데 이 사이즈 조절 이벤트가 발생되면 같이 있던 activex 에도 그 이벤트가 전달이 되겠죠. 그럼 activex 은 화면을 다시 그리기 위해 invalidate 할테고 그러면 그려져있는 이미지들을 다시 그리게 되니 화면이 번쩍이게 됩니다.
또 한가지, iframe 에서 marqee 같은거 써주면 계속 이벤트가 발생돼서 activex 아 화면을 그리는데만 쓰는 자원 소모가 심각하게 많아지게 됩니다. 그래서 여기 저기 찾아서 검색해본 결과 다음과 같은 답이 있었답니다.
일단 activex control class 에 다음 메소드를 상속받아 추가합니다.
virtual BOOL OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect);
그리고 소스코드에 다음을 복사해서 붙여넣으면 해결됩니다.
void AFXAPI 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 CTmtMDICtlCtrl::OnSetObjectRects(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
{
ASSERT(lprcPosRect != NULL);
// Remember the position rectangle for later
m_rcPos = *lprcPosRect;
// Calculate complete rectangle including the tracker (if 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 that rectangle as appropriate
CRect rectClip;
// CHANGE - call your own copy of _GetClippingCoordinates
MyGetClippingCoordinates(rectPos, lprcClipRect, rectClip, &m_ptOffset);
// Move outer window first. then inner window
if (!m_bInPlaceSiteWndless)
{
CWnd* pWndOuter = GetOuterWindow();
//BEGIN CHANGE
if (pWndOuter != NULL)
{
// ::MoveWindow(pWndOuter->m_hWnd, rectClip.left, rectClip.top,
// rectClip.Width(), rectClip.Height(), TRUE);
::MoveWindow(pWndOuter->m_hWnd, rectPos.left, rectPos.top,
rectPos.Width(), rectPos.Height(), TRUE);
}
//END CHANGE
if (pWndOuter != this)
MoveWindow(m_ptOffset.x, m_ptOffset.y, rectPos.Width(), rectPos.Height());
}
return TRUE;
}
이 동작은 activeX 에 리사이즈 하라는 이벤트가 전달 됐을 때 실제 호출자가 IE 인지 아니면 다른 녀석인지를 분간해서 IE 일 경우에만 화면을 resize 하는 코드입니다. 구굴신님 감사해요.


덧글