Solved

Changing CPen data after created

Posted on 1997-12-23
8
333 Views
Last Modified: 2008-02-01
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?
0
Comment
Question by:sccheung
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 3
  • 2
8 Comments
 
LVL 7

Accepted Solution

by:
galkin earned 50 total points
ID: 1177000
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
 

Author Comment

by:sccheung
ID: 1177001
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
 
LVL 7

Expert Comment

by:galkin
ID: 1177002
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 22

Expert Comment

by:nietod
ID: 1177003
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
 
LVL 22

Expert Comment

by:nietod
ID: 1177004
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
 

Author Comment

by:sccheung
ID: 1177005
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
 
LVL 7

Expert Comment

by:galkin
ID: 1177006
// 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
 

Author Comment

by:sccheung
ID: 1177007
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

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question