void GVSearchListBox::DrawItem(LPDRAWITEMSTRUCT lpdis) { std::lock_guard<std::recursive_mutex> l(mutex_); switch (lpdis->itemAction) { case ODA_DRAWENTIRE: { if (lpdis->itemState & ODS_SELECTED) { DrawSelected(lpdis); } else { DrawEntire(lpdis); } } break; case ODA_SELECT: { if (lpdis->itemState & ODS_SELECTED) { DrawSelected(lpdis); } else { DrawEntire(lpdis); } } break; default: break; } RECT rect(lpdis->rcItem); HPEN hpen = CreatePen(PS_SOLID, 1, RGB(248, 248, 248)); HBRUSH hbrush = CreateSolidBrush(RGB(248, 248, 248)); SelectObject(lpdis->hDC, hpen); SelectObject(lpdis->hDC, hbrush); Rectangle(lpdis->hDC, rect.left + 12, rect.bottom - 1, rect.right - 12, rect.bottom); DeleteObject(hpen); DeleteObject(hbrush); DrawAvatar(lpdis); DrawMessage(lpdis); DrawVia(lpdis); }
//+--------------------------------------------------------------------------- // // Member: CDispRoot::DrawRoot // // Synopsis: Draw this display tree. // // Arguments: pContext draw context // pClientData client data used by clients in DrawClient // hrgnDraw region to draw in destination coordinates // prcDraw rect to draw in destination coordinates // // Notes: if hrgnDraw and prcDraw are both NULL, the bounding rect of // this root node is used // //---------------------------------------------------------------------------- void CDispRoot::DrawRoot( CDispDrawContext* pContext, void* pClientData, HRGN hrgnDraw, const RECT* prcDraw) { // BUGBUG (donmarsh) - for now we must use this root's own context, due // to the context stack used for drawing. Eventually, we should eliminate // the context pointer argument to DrawRoot. Assert(pContext == &_drawContext); AssertSz(!_fDrawLock, "Illegal call to DrawRoot inside Draw()"); AssertSz(_cOpen==0, "DrawRoot called while Display Tree is open"); Assert(_pRenderSurface != NULL); Assert(!IsSet(CDispFlags::s_interiorFlagsNotSetInDraw)); // set redraw region (will become a rect if possible) CRegion rgnRedraw; if(hrgnDraw != NULL) { rgnRedraw = hrgnDraw; } else if(prcDraw != NULL) { rgnRedraw = *prcDraw; } else { rgnRedraw = _rcContainer; } // check for early exit conditions if(!rgnRedraw.Intersects(_rcContainer)) { return; } // set initial context values pContext->SetClientData(pClientData); pContext->SetNoClip(); pContext->_offset = _rcContainer.TopLeft().AsSize(); pContext->_pFirstDrawNode = NULL; pContext->SetRedrawRegion(&rgnRedraw); // BUGBUG (donmarsh) -- this is a little ugly, but our the _rcVisBounds // for CDispRoot must be zero-based, because it is transformed by the // offset in CDispNode::Draw, and if _rcVisBounds == _rcContainer like // one would expect, _rcVisBounds gets transformed twice. _rcVisBounds.MoveToOrigin(); if(_pFirstChildNode == NULL) { pContext->SetDispSurface(_pRenderSurface); _pRenderSurface->SetBandOffset(_afxGlobalData._Zero.size); CRect rcClip; rgnRedraw.GetBounds(&rcClip); CRegion rgnClip(rcClip); _pRenderSurface->SetClipRgn(&rgnClip); DrawSelf(pContext, NULL); _pRenderSurface->SetClipRgn(NULL); ::SelectClipRgn(_pRenderSurface->GetRawDC(), NULL); goto Cleanup; } // DrawRoot does not allow recursion _fDrawLock = TRUE; // speed optimization: draw border and scroll bars for first node // without buffering or banding, then subtract them from the redraw // region. if(_pFirstChildNode==_pLastChildNode && _pFirstChildNode->IsContainer() && _pFirstChildNode->IsVisible()) { CDispContainer* pContainer = DYNCAST(CDispContainer, _pFirstChildNode); pContext->SetDispSurface(_pRenderSurface); _pRenderSurface->SetBandOffset(_afxGlobalData._Zero.size); CRect rcClip; rgnRedraw.GetBounds(&rcClip); CRegion rgnClip(rcClip); _pRenderSurface->SetClipRgn(&rgnClip); pContainer->DrawBorderAndScrollbars(pContext, &_rcContent); _rcContent.OffsetRect(_rcContainer.TopLeft().AsSize()); _pRenderSurface->SetClipRgn(NULL); // restore clipping on destination surface to redraw region // (this is important when we're using filters and we have a // direct draw surface) if(rgnRedraw.IsComplex()) { ::SelectClipRgn(_pRenderSurface->GetRawDC(), rgnRedraw.GetRegionAlias()); } else { HRGN hrgnClip = ::CreateRectRgnIndirect(&rgnRedraw.AsRect()); ::SelectClipRgn(_pRenderSurface->GetRawDC(), hrgnClip); ::DeleteObject(hrgnClip); } rgnRedraw.Intersect(_rcContent); // early exit if all we needed to draw was the border and scroll bars if(rgnRedraw.IsEmpty()) { goto Cleanup; } } else { _rcContent = _rcContainer; } // early exit if all we needed to draw was the border and scroll bars if(!_rcContent.IsEmpty()) { // try to allocate offscreen buffer BOOL fOffscreen = SetupOffscreenBuffer(pContext); Assert(!fOffscreen || _pOffscreenBuffer); // allocate stacks for redraw regions and context values CRegionStack redrawRegionStack; pContext->SetRedrawRegionStack(&redrawRegionStack); CDispContextStack contextStack; pContext->SetContextStack(&contextStack); // PreDraw pass processes the tree from highest layer to lowest, // culling layers beneath opaque layers, and identifying the lowest // opaque layer which needs to be rendered during the Draw pass PreDraw(pContext); // if we didn't consume the redraw region, we'll have to start rendering // from the root if(!pContext->GetRedrawRegion()->IsEmpty()) { pContext->_pFirstDrawNode = this; redrawRegionStack.PushRegionForRoot(pContext->GetRedrawRegion(), this, _rcContainer); contextStack.Init(); } else { Assert(pContext->_pFirstDrawNode != NULL); AssertSz(redrawRegionStack.MoreToPop(), "Mysterious redraw region stack bug!"); delete pContext->GetRedrawRegion(); contextStack.Restore(); } if(!fOffscreen) { _pRenderSurface->SetBandOffset(_afxGlobalData._Zero.size); DrawEntire(pContext); } else if(_pOffscreenBuffer->Height() >= _rcContent.Height()) { _pOffscreenBuffer->SetBandOffset(_rcContent.TopLeft().AsSize()); DrawEntire(pContext); _pOffscreenBuffer->Draw(_pRenderSurface, _rcContent); } else { DrawBands(pContext, &rgnRedraw, redrawRegionStack); } pContext->SetClientData(NULL); // clear redraw region trails redrawRegionStack.Restore(); for(;;) { CDispNode* pOpaqueNode = (CDispNode*)redrawRegionStack.PopKey(); if(pOpaqueNode == NULL) { break; } pOpaqueNode->ClearFlagToRoot(CDispFlags::s_savedRedrawRegion); } // delete all regions except the first redrawRegionStack.DeleteStack(&rgnRedraw); } Cleanup: // BUGBUG (donmarsh) -- restore _rcVisBounds to coincide with _rcContainer _rcVisBounds = _rcContainer; _fDrawLock = FALSE; }