Why the shadow of the character remains there after redraw the window? - c++

Using WTL and Graphics,I rewrite an list view tool,like:
,but after click the Name or Phone Number header to sort, it appears like:.
Seems that the old one still there, but not so clear,whats wrong?
The Core Draw Code:
void _DrawItem(HDC hDC, LPDRAWITEMSTRUCT lpDrawItemStruct)
{
...
CDCHandle dcx;
Gdiplus::Graphics grap(hDC);
CRect rcTmp;
GetClientRect(&rcTmp);
dcx.Attach(hDC);
BOOL bBackColor = TRUE;
if ((lpDrawItemStruct->itemID % 2) == 0)
{
bBackColor = FALSE;
}
Gdiplus::SolidBrush mySolidBrush(Gdiplus::Color(235, 235, 235,235));
if (pItem->getOver() || pItem->getChecked())
{
mySolidBrush.SetColor(Gdiplus::Color(215, 0, 0, 215));
}else{
if (bBackColor)
{
mySolidBrush.SetColor(Gdiplus::Color(235, 235, 235, 235));
}else{
mySolidBrush.SetColor(Gdiplus::Color(255, 255, 255, 255));
}
}
grap.FillRectangle(&mySolidBrush, lpDrawItemStruct->rcItem.left , lpDrawItemStruct->rcItem.top, nColumWidth,
lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);

Just a guess but your alpha transparency value is not opaque so filling the rect with 235,235,235,235 will blend with the old content. Probably need a 255 in there for alpha.

Related

How to change the color scheme of CDateTimeCtrl in MFC?

I need to change the colors of the background, the text, the color of the dropdown button of
CDateTimeCtrl in MFC. I created new class derived from CDateTimeCtrl and tried overwritten OnCtlColor and CtlColor, but these functions are never called (the message map has been added using the Class Wizard). How should I achieve this without writing a completely new datetimectrl class of my own?
You can try something like this:
// header
CBrush* m_pBkgBrush { nullptr };
COLORREF m_bkgColor { RGB(255, 255, 255) };
COLORREF SetBackgroundColor(BOOL bSysColor, COLORREF cr);
and implementation now:
CYourDateTimeCtrl::CYourDateTimeCtrl()
: CDateTimeCtrl()
, m_bkgColor(::GetSysColor(COLOR_WINDOW))
{
m_pBkgBrush = new CBrush(::GetSysColor(COLOR_WINDOW));
}
CYourDateTimeCtrl::~CYourDateTimeCtrl()
{
if (nullptr != m_pBkgBrush)
delete m_pBkgBrush;
}
COLORREF CYourDateTimeCtrl::SetBackgroundColor(BOOL bSysColor, COLORREF cr)
{
COLORREF color = m_bkgColor;
m_bkgColor = bSysColor ? ::GetSysColor(COLOR_WINDOW) : cr;
if (color != m_bkgColor)
{
delete m_pBkgBrush;
m_pBkgBrush = new CBrush(m_bkgColor);
Invalidate();
}
return color;
}
BOOL CYourDateTimeCtrl::OnEraseBkgnd(CDC* pDC)
{
CBrush* pOldBrush = pDC->SelectObject(m_pBkgBrush);
CRect rect;
pDC->GetClipBox(&rect);
pDC->PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOldBrush);
return TRUE;
}
When you use, you do:
MyMonthCalCtrl.SetBackgroundColor(FALSE, RGB(255, 255, 0));
I hope it helps.

How to change CTabCtrl tab colors?

Hello and happy new year, (it is acceptable to say it until Thursday)
I am trying to change the color of the tabs in the CTabCtrl class. I am trying to create my own ReskinCTablCtrl so that I can just call it in separate classes and easily use it throughout my program.
Currently I am able to change the background color of the CTabCtrl but I cannot modify the tab's themselves.
I used ON_WM_ERASEBKGND() for painting the background and it worked without a problem:
BOOL ReskinCTabCtrl::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
CBrush myBrush(RGB(51, 51, 51)); // dialog background color
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SetBkColor(RGB(51, 51, 51));
pDC->FillRect(&rect, &myBrush);
return bRes;
}
However, I have been unsuccesfull at changing the tab colors themselves. They are still the default MFC colors. I have tried to implement ON_WM_PAINT() and ON_WM_DRAWITEM() without any success. I think I can get to the specific tab rect with using both OnDraw and DrawItem similar to the second link example that I have posted in the end of this question.
void ReskinCTabCtrl::OnPaint() {
...
// paint the tabs first and then the borders
int nTab = GetItemCount();
int nSel = GetCurSel();
if (!nTab) // no pages added
return;
while (nTab--)
{
if (nTab != nSel)
{
dis.itemID = nTab;
dis.itemState = 0;
VERIFY(GetItemRect(nTab, &dis.rcItem));
dis.rcItem.bottom -= 2;
DrawItem(&dis);
DrawItemBorder(&dis);
}
}
...
}
I would really appreciate at least some direction to go about this problem, perhaps some more examples or what methods I should focus on using. I don't need the tabs to be different colors, maybe there is an easy way of doing this?
I've been trying to follow some examples like the following links but I still couldn't figure out the right way to do it.
https://support.microsoft.com/en-us/help/179909/how-to-change-the-background-color-of-a-tab-control
https://www.codeproject.com/Articles/1786/Ownerdraw-Tab-Controls-Borders-and-All
Enable OwnerDraw for tab control, either in resource editor, or set TCS_OWNERDRAWFIXED in OnInitDialog
CTabCtrl has message reflection for WM_DRAWITEM therefore we don't want to override WM_DRAWITEM/OnDrawItem from parent class. Instead override in CTabCtrl::DrawItem(LPDRAWITEMSTRUCT).
Unfortunately the result is rather ugly. It's sort of like overriding DrawItem in a button.
If Visual Style is available and enabled, then you can override CTabCtrl::OnPaint and draw everything manually. Example:
void CMyTabCtrl::OnPaint()
{
CPaintDC dc(this);
dc.SelectObject(GetFont());
CPen pen, pen_active;
COLORREF color_off = RGB(240, 240, 240);
COLORREF color_active = RGB(200, 240, 240);
CBrush brush_off, brush_active;
brush_off.CreateSolidBrush(color_off);
brush_active.CreateSolidBrush(color_active);
pen.CreatePen(PS_SOLID, 1, RGB(200, 200, 200));
pen_active.CreatePen(PS_SOLID, 1, color_active);
CRect rcitem;
GetItemRect(0, &rcitem);
CRect rc;
GetClientRect(&rc);
rc.bottom = rcitem.bottom;
dc.FillSolidRect(&rc, GetSysColor(COLOR_3DFACE));
GetClientRect(&rc);
rc.top = rcitem.bottom - 1;
dc.SelectObject(&pen);
dc.SelectObject(&brush_active);
dc.Rectangle(&rc);
for(int i = 0; i < GetItemCount(); i++)
{
dc.SelectObject(&pen);
if(i == GetCurSel())
{
dc.SelectObject(&brush_active);
dc.SetBkColor(color_active);
}
else
{
dc.SelectObject(&brush_off);
dc.SetBkColor(color_off);
}
GetItemRect(i, &rcitem);
rcitem.right++;
dc.Rectangle(&rcitem);
if(i == GetCurSel())
{
dc.SelectObject(pen_active);
dc.MoveTo(rcitem.left+1, rcitem.bottom - 1);
dc.LineTo(rcitem.right, rcitem.bottom - 1);
}
TCITEM item = { 0 };
wchar_t buf[32];
item.pszText = buf;
item.cchTextMax = 32;
item.mask = TCIF_TEXT;
GetItem(i, &item);
dc.DrawText(buf, &rcitem, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
}
BOOL CMyTabCtrl::OnEraseBkgnd(CDC*)
{
return TRUE;
}

declarative alpha changer

I'd like to write a QDeclarativeItem FadeEdges that I instantiate from QML, such as in this example:
FadeEdges {
Text {
id: sometext
text: "some text"
}
}
After sometext repaints, I'd like to reduce the alphas (from fully opaque to transparent) of the pixels it painted at its edges. So its rendered edges will appear faded. My question is what mechanisms, if any, are available to make this change in child alpha values.
I've tried to install event filters and setting setFiltersChildEvents(). No PaintEvents seem to be sent.
It is not an exact answer to my own question but I suppose it will do for starters. Only the QGraphicsEffect::draw member function needs to be overridden (margins_ is a QMargins member variable):
void FadeEdgesEffect::draw(QPainter* painter)
{
QLinearGradient lg;
lg.setColorAt(qreal(0), QColor(0, 0, 0, 0));
lg.setColorAt(qreal(1), QColor(0, 0, 0, 255));
qreal const width(boundingRect().width());
qreal const height(boundingRect().height());
QPoint offset;
QPixmap pixmap(sourcePixmap(Qt::LogicalCoordinates, &offset));
{
QPainter p(&pixmap);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
if (margins_.left())
{
lg.setStart(qreal(0), qreal(0));
lg.setFinalStop(margins_.left(), qreal(0));
p.fillRect(QRectF(0, 0, margins_.left(), height), lg);
}
// else do nothing
if (margins_.right())
{
lg.setStart(qreal(width), qreal(0));
lg.setFinalStop(width - margins_.right(), qreal(0));
p.fillRect(QRectF(width - margins_.right(),
0, margins_.right(), height), lg);
}
// else do nothing
if (margins_.bottom())
{
lg.setStart(qreal(0), height);
lg.setFinalStop(qreal(0), height - margins_.top());
p.fillRect(QRectF(0, height - margins_.bottom(),
width, margins_.bottom()), lg);
}
// else do nothing
if (margins_.top())
{
lg.setStart(qreal(0), qreal(0));
lg.setFinalStop(0, margins_.top());
p.fillRect(QRectF(0, 0, width, margins_.top()), lg);
}
// else do nothing
}
painter->drawPixmap(offset, pixmap);
}

background image not getting loaded in SDL

i want to display an image(.png) in a frame in SDL.But,somehow only the frame appears and image does not get loaded.i am reading the image details from an XML file.this is the sample code i am trying:
Class myclass{
mysurface2(io.loadAndSet(myftndata->getXmlStr("backfile"), true) ),
myfframe(new fframe(img2,
myftn->getXmlInt("backWidth"),
myftn->getXmlInt("backHeight"), 0, 0)),
myobjects()
{
if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
throw string("SDL Error!!!: ");
}
atexit(SDL_Quit);
}
};
void myclass::drawImg() const {
SDL_FillRect( screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255) );
SDL_Rect dest = {0, 0, 0, 0};
SDL_BlitSurface( screen, NULL, screen, &dest );
}
void myclass::move()
{
while ( not done )
{
drawImg();
SDL_Flip(screen);
}
}
Please note: i have an entire framework,which i cannot give here.The above is my code that i am trying.
You are blitting the screen to the screen, which is a zero-operation. You should change the first screen in the blit function to the SDL_Surface* that represents your image.
Are you using a library (e.g. SDL_Image) for loading the .png file? Because SDL can only load .bmp files.

Filling a Partially Rounded Rectangle with GDI+

I have a rounded rectangle that I make like so
dc.RoundRect(textBorder, CPoint(20, 20));
Later on I draw a line through it about 1/3 of the way down.
dc.LineTo(textBorder.right, textBorder.top + 15);
Now I would like to fill just the part above the line with a solid color. In other words I need to fill a partially rounded rectangle, because the top of the rectangle is rounded, but the bottom of it is truncated by the line. Is there an easy way to do this?
Have you tried using a combination of CreateRoundRectRegion and then FillRgn to fill the non-rectangular area?
This the example given in the docs for CreateRoundRectRegion:
CRgn rgnA, rgnB, rgnC;
VERIFY(rgnA.CreateRoundRectRgn( 50, 50, 150, 150, 30, 30 ));
VERIFY(rgnB.CreateRoundRectRgn( 200, 75, 250, 125, 50, 50 ));
VERIFY(rgnC.CreateRectRgn( 0, 0, 50, 50 ));
int nCombineResult = rgnC.CombineRgn( &rgnA, &rgnB, RGN_OR );
ASSERT( nCombineResult != ERROR && nCombineResult != NULLREGION );
CBrush brA, brB, brC;
VERIFY(brA.CreateSolidBrush( RGB(255, 0, 0) ));
VERIFY(pDC->FillRgn( &rgnA, &brA)); // rgnA Red Filled
VERIFY(brB.CreateSolidBrush( RGB(0, 255, 0) ));
VERIFY(pDC->FillRgn( &rgnB, &brB)); // rgnB Green Filled
VERIFY(brC.CreateSolidBrush( RGB(0, 0, 255) )); // rgnC Blue
VERIFY(pDC->FrameRgn( &rgnC, &brC, 2, 2 ));
In general, when you want to do something with non-rectangular areas you have to start looking into regions.