Gdiplus::RectF Sprite::GetAbsRect() { Sprite *sp = m_parent; Gdiplus::RectF rcSelf = GetRect(); Gdiplus::RectF rcParent; while(sp) { rcParent = sp->GetRect(); rcSelf.Offset(rcParent.X, rcParent.Y); sp = sp->m_parent; } return rcSelf; }
void Sprite::Invalidate() { // 0指针访问 不挂是因为x64系统一个bug 记得打开调试中的Win32异常断点 HostWindow *wnd = GetHostWindow(); if (wnd) { RECT rc; Gdiplus::RectF rf = GetAbsRect(); rc.left = (LONG)(rf.GetLeft() - 0.5f); rc.top = (LONG)(rf.GetTop() - 0.5f); // TODO FIXME 这个值是试出来的 不知其所以然 rc.right = (LONG)(rf.GetRight() + 1.5f); // 缩小窗口TabCtrl会有拖影 这里改成2 就可以消除拖影现象 rc.bottom = (LONG)(rf.GetBottom() + 1.5f); // 很诡异 可能是因为GdiPlus认为x取大的 width也取大的 ::InvalidateRect(wnd->GetHWND(), &rc, TRUE); } }
void VGraphicPath::_ComputeBounds() { if (fComputeBoundsAccurate) { if (fPathMin == GP_BOUNDS_MIN_DEFAULT || fPathMax == GP_BOUNDS_MAX_DEFAULT) fBounds = VRect(0,0,0,0); else fBounds.SetCoords( (GReal)fPathMin.x, (GReal)fPathMin.y, (GReal)(fPathMax.x-fPathMin.x), (GReal)(fPathMax.y-fPathMin.y)); } else { #if ENABLE_D2D if (fPathD2D != NULL) { if (fGeomSink == NULL) { D2D1_RECT_F bounds; fPathD2D->GetBounds( NULL, &bounds); fBounds.SetCoords( bounds.left, bounds.top, bounds.right-bounds.left, bounds.bottom-bounds.top); return; } } #endif #if !GRAPHIC_MIXED_GDIPLUS_D2D if (!VWinD2DGraphicContext::IsAvailable()) { #endif Gdiplus::RectF bounds; fPath->GetBounds( &bounds); fBounds = VRect ( bounds.GetLeft(), bounds.GetTop(), bounds.GetRight()-bounds.GetLeft(), bounds.GetBottom()-bounds.GetTop()); #if !GRAPHIC_MIXED_GDIPLUS_D2D } #endif } }
// http://blog.csdn.net/magic_feng/article/details/6618206 Sprite * Sprite::DispatchMouseEvent(MouseEvent *event) { std::stack<Sprite *> stack; std::stack<Sprite *> reverse; stack.push(this); Sprite *sp = NULL; while(!stack.empty()) { sp = stack.top(); stack.pop(); reverse.push(sp); // visit in reversed order. Sprite *sp2 = sp->m_lastChild; while (sp2) { stack.push(sp2); sp2 = sp2->m_prevSibling; } } while (!reverse.empty()) { sp = reverse.top(); reverse.pop(); Gdiplus::RectF rc = sp->GetAbsRect(); //LOG("HitTest:"<< rc.X << "," <<rc.Y << "," << rc.Width << "," << rc.Height); if (rc.Contains(event->x, event->y)) { MouseEvent e2 = *event; e2.x -= rc.X; e2.y -= rc.Y; sp->OnMouseEvent(g_L, &e2); } } return NULL; }
void Sprite::OnDraw( Gdiplus::Graphics &g, const Gdiplus::RectF &rcDirty ) { if (!m_bVisible) { return; // 子节点也不会被绘制 } // 前序遍历 让父节点先绘制 //Gdiplus::RectF rc = GetRect(); //if (10 == rc.Width && 10 == rc.Height) //{ // LOGW(<<L"Orignal Size 10 10"); // 检查下有没有多余的重绘 //} if (m_bClipChildren) { Gdiplus::RectF rcClip = GetRect(); rcClip.X = 0.0f; rcClip.Y = 0.0f; g.SetClip(rcClip); } PaintEvent ev; ev.graphics = &g; ev.rcDirty = rcDirty; SendNotify(ePaint, &ev); //this->ClientDraw(g, rcDirty); Sprite *sp = m_firstChild; while(sp) { // 如果需要重绘部分矩形和sp相交则重画它 否则不重画 // 这里还有个问题就是 父矩形必须比子矩形要大 否则可能父的相交不到 而子的相交的到 // 可能要强制这一原理 类似于浏览器 会撑大 Gdiplus::RectF rc2 = sp->GetRect(); Gdiplus::RectF rcAbs = sp->GetAbsRect(); rcAbs.X -= 0.5f; // FIXME 有时无法得到重画导致边界1像素消失 rcAbs.Y -= 0.5f; rcAbs.Width += 1.0f; rcAbs.Height += 1.0f; if (rcDirty.IntersectsWith(rcAbs)) { g.TranslateTransform(rc2.X, rc2.Y); sp->OnDraw(g, rcDirty); g.TranslateTransform(-rc2.X, -rc2.Y); } sp = sp->m_nextSibling; } if (m_bClipChildren) { g.ResetClip(); } }
void Sprite::SetRect( Gdiplus::RectF rect ) { // 检查下宽高是否小于0 是则设为0 然后0宽或0高要在OnDraw这些里面特殊处理一下 rect.Width = max(0.0f, rect.Width); rect.Height = max(0.0f, rect.Height); if (!m_rect.Equals(rect)) { Gdiplus::RectF rcOld = m_rect; // TODO OnMove Invalidate(); // 旧矩形 m_rect = rect; Invalidate(); // 新矩形 // 原先回掉的顺序错了 导致在OnSize里面GetRect和OnSize的参数不一样 诡异错误 if (rect.Width != rcOld.Width || rect.Height != rcOld.Height) { // OnSize(rect.Width, rect.Height); Gdiplus::SizeF size; rect.GetSize(&size); SendNotify(eSizeChanged, &size); } } }
void CPHTMLIFrameElement::PlaceControls(HWND hWndParent, CHTMFlowBlockContext* /*pC*/) { ASSERT(0); #if 0 CLHTMLIFrameElement* pElement = static_cast<CLHTMLIFrameElement*>(m_pNode); if (m_pBox) { Gdiplus::RectF rcf = m_pBox->GetAbsInnerRect(); CRect rc((int)rcf.X, (int)rcf.Y, (int)rcf.GetRight(), (int)rcf.GetBottom()); if (pElement->m_pFrameContent == NULL) { CComObject<CLHTMLFrameContent>::CreateInstance(&pElement->m_pFrameContent); pElement->m_pFrameContent->AddRef(); // TODO CPElement* pParent = this; while (pParent) { CComQIPtr<IOleInPlaceFrame> frame = static_cast<ILViewNode*>(pParent); if (frame) { pElement->m_pFrameContent->m_pInPlaceFrame = frame; break; } pParent = pParent->m_parent; } pElement->m_pFrameContent->m_hWnd = hWndParent; pElement->Load(); } if (pElement->m_pFrameContent) { if (pElement->m_pFrameContent->m_spOleObject) { if (pElement->m_pFrameContent->m_pViewSite == NULL) { #if 0 pElement->m_pFrameContent->m_spOleObject->DoVerb(OLEIVERB_SHOW, NULL, pElement->m_pFrameContent, 0, hWndParent, &rc); #endif } else { pElement->m_pFrameContent->m_pViewSite->SetRect(rc); } } } } if (pElement->m_pFrameContent) { if (pElement->m_pFrameContent->m_pViewSite) { ASSERT(pElement->m_pFrameContent->m_pViewSite->m_pIOleDocView); BOOL bShow = m_pBox != NULL; pElement->m_pFrameContent->m_pViewSite->m_pIOleDocView->Show(bShow); } } #endif }