Changing CPen data after created

I wanted to draw with blending effect. The color changes eventually from color A to color B. Therefore I have to set the pen color frequently. But I found that no books or MS Visual C++ help file talks about changing the data of a pen. They just told me how to create a pen. If I create a pen and destroy it and then create another one, the on draw function will surely become very slow. How can I change the color of a pen after it is created?
sccheungAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

galkinCommented:
Create two pens with diffrent colors and select them into DC periodically. To completely avoid flickering use memory DC and draw onto your window from this memory DC.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sccheungAuthor Commented:
If two pens is created, I still have to change the data of each pen before selecting them into the DC. Please tell me how. I do not need two colors only. I want to fill a rectangle with blending effect. e.g. from yellow to blue: the first line is draw with yellow using LineTo. The second line is closer to blue. The third line is more closer to blue......The middle part lines is green......The last line is blue. Therefore if the rectangle is 200x200 pixels, I need 200 pens or I have to know how to change the color of a already created. The problem is not flikering. The problem is the user have to wait for a long long time when it is displayed. When I am using Delphi, I can simply use"Canvas.Pen.Color := [The color I want]". But in the MSVC help file, I can only find "CPen", "CreatePen", "CreatePenIndirect"...... When I try to use "GetLogPen", I get a access violation error!
0
galkinCommented:
So you need not only create to pens but also two brushes or change images inside rectangle to simulate effect. You must create pens and brushes and draw rectangle offscreen on memory DC. When you need to chage visual aspect of your rectangle(change pen etc.) blit image from memory DC on your window DC. Since image is already ready in memory DC this operation will be very fast and can even be done during one frame.
0
Cloud Class® Course: C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

nietodCommented:
There is no way around it.  You have to create and select in a pen for each color.  That could be hundreds of pens.

However, creating and selecting in a pen is not too slow.  creating is pretty fast, the only slow part is that it must dynamicallu allocate the pen.  Selecting is pretty fast too, the slow part here is that windows may do some color maping calculations.

The color mapping slow down cannot be avoided in any graphics environment, the dynamic allocation is the only extra slow down in the windows environment.  And there is no way around it.
0
nietodCommented:
Note you can speed things up by not using too many pens.  For example if mathematically there are 200 colors between A and B, but you are on a 16 color display, then at most there will be 16 colors used in the line!  Most likely there will be even less than 16 since will probably not map the colors you request to each of the colors available.

This is getting out of my area of expertise, but you could (probably) determine what colors windows will map to and select only those colors, it will probably be only a few colors throughout the line.
0
sccheungAuthor Commented:
How to completely destroy a pen? I tried to create a CPen, destroy it and then create another one. But I always get assertion failure. The debugger give me this:
BOOL CGdiObject::Attach(HGDIOBJ hObject)
{
      ASSERT(m_hObject == NULL);      // only attach once, detach on destroy <-The debugger pointer points to here
      if (hObject == NULL)
            return FALSE;
      CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
      ASSERT(pMap != NULL);
      pMap->SetPermanent(m_hObject = hObject, this);
      return TRUE;
}
Can you tell me how to completely destroy a CPen?
I do it like this:
for (int i=0; ......
{
      pMyPen->CreatePen(PS_SOLID, 1, ......
      pDC->SelectObject(pMyPen);
//Use the pen
      pMyPen->DeleteObject();
}
0
galkinCommented:
// first you must create pen using either parameters passed to
// CPen constructor or create pen class instance using default // constructor and then call CPen::CreatePen which takes the
// same parameters as cPen constructor
// for example I create black pen first
CPen pen(PS_SOLID, 1, 0x000000);
CPen *pOldPen = (CPen *)pDC->SelectObject(&pen);
// draw with the pen selected into DC
// when you are done with this pen reselect old pen into DC
pDC->SelectObject(pOldPen);
//You don't need to destroy pen using DeleteObject since
// CPen class destructor does it itself
// Now you can create another pen for example I create blue pen
// Here you can only create pen using CreatePen function since //constructor has already been called
pen.CreatePen(PS_SOLID, 1, 0x0000ff);
// then you do the same steps: selecting pen into DC drawing,
// and then reselecting old pen
pOldPen = (CPen *)pDC->SelectObject(&pen);
// draw with blue pen
//when you are done with blue pen reselect old pen into dc
pDC->SelectObject(pOldPen);
// then create another pen and do the same...
0
sccheungAuthor Commented:
I've tried your suggestion, but I still get the same error! Finally, I suceeded! Here is my code:
      CPen *pMyPen, *pOriPen;
      pMyPen = new CPen;
for (......
{
   pMyPen->CreatePen(......
   pOriPen = (CPen *)pDC->SelectObject(pMyPen);
   // Use the pen to draw
   pDC->SelectObject(pOriPen);
   pMyPen->DeleteObject();
}

I don't understand why I have to delete the object. But the error disappear when I added that line.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.