Thread: Are DC Pen handles independant?

  1. #1
    Registered User
    Join Date
    Mar 2011

    Are DC Pen handles independant?

    I use both client device contexts (hDc) and memory device contexts (hMemDc) for drawing.

    I retrieved a handle for a stock object, hPen = GetStockObject(DC_PEN) and inadvertantly selected the same pen handle into both DC's:

    SelectObject(hDc, hPen);
    SelectObject(hMemDc, hPen);

    Apparently, the pens remained independant. I could change the two pens to two different colors, eg, SetDCPenColor(hDc, 0x0000FF); and SetDCPenColor(hMemDc, 0x00FF00);

    Using the two pens in their respective DC's, later in the code, the pens retain their individual colors.

    My questions:

    Was this just luck that it worked? Should the pens for each DC have their own own unique handles?

    Or do pens become unique once selected into a DC?


  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008

    You've stumbled into the world of virtual identifiers.

    If you had selected a created a pen--via `CreatePen'--with a specific color, the effects of the `SetDCPenColor' call would not have been seen until you invoked `SelectObject(hDc, GetStockObject(DC_PEN));' and the color of the created pen would remain unchanged.

    The `SetDCPenColor'--and related--API does not set the color of the pen currently held by the context.

    The `SetDCPenColor' API only mutates the virtual object--here the `Pen'--owned by the context.

    (I don't want to confuse you, but I can't think of a better way to explain virtual identifiers.)

    You can think of `HTHING' as pointers to elements within an array.

    PEN * global = malloc(sizeof(*global) * maximum_pens); /* whatever */
    Each `HTHING' is an identifier--here the address stored by the associated variable--referring to one of the global objects--here the `global' array--as a calculated offset. In other words for this example, the identifier `1' would actually be `*(global + 1)' when evaluated by the API.

    Now, that explains a good bit about what `HTHING' does "under the hood".

    However, that only covers real identifiers. The API also needs virtual identifiers because some resources are private--not global. We can create virtual identifiers by reserving a given range of values--here we consider negatives. In other words for this example, the identifier `-1' would actually be `*(context->resources[1])' when evaluated by the API.

    I've obviously glossed over a lot of stuff, but the "stock objects", in a very general way, work as these virtual identifiers. (Well, I completely fabricated the examples. A real implementation of virtual identifiers is a lot more complex yet safer and more robust.) The `GetStockObject(DC_PEN)' object--the `HPEN' result--is really an identifier that tells the API to use the `HPEN' owned by the device context so not a real `HPEN'.

    Actually answering the questions:

    1): No. Setting the color of the, internal, pen owned by the context is the expected behavior.
    2): No. You can cache shared resource and select them into different contexts as needed. The limiting factor, as for sharing, is that you can't share the same bitmap for multiple contexts at the same time.
    3): No. You can do an experiment using created bitmaps--bitmaps are easily muted while fonts and pens need to be created with most attributes fixed--to see this in practice, but the above explanations for virtual identifiers should explain what you are seeing.

    Last edited by phantomotap; 07-31-2014 at 04:55 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #3
    Registered User
    Join Date
    Mar 2011
    Thanks for the comprehensive explanation.

    So when I select a DC_PEN into a DC, I am in effect simply telling the DC to use it's own DC_PEN?

    Is HPEN simply an ID value then, and not a pointer to some "pen structure"?

    Successive calls to GetStockObject(DC_PEN) would return the same value?
    (I would test, but don't what type HPEN is)


  4. #4
    Registered User
    Join Date
    Mar 2011
    I found the type of HPEN:

    HPEN is typedef'd as a HANDLE, which is typedef'd as a PVOID, which is typedef'd as a void pointer.

    I tried retrieving two different handles for a DC_PEN stock object.
    I got the same value for both handles: 01B00019


  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Waterloo, Texas
    H* just means a HANDLE, an opaque type that doesn't necessarily map to a physical address. It's internal structure is really irrelevant though, it just represents some allocated resource (in this case a LOGPEN structure plus maybe some ancillary information). Anyway, there's no telling why they decided to do things the way they did, just another one of those oddball idiosyncrasies of the WIN32 API, I guess...
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
        return std::pow
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. windows.h handles in c
    By mramazing in forum C Programming
    Replies: 9
    Last Post: 07-15-2008, 04:02 AM
  2. Independant console development using Visual C++ 6
    By -leech- in forum Game Programming
    Replies: 9
    Last Post: 09-09-2002, 02:36 PM
  3. handles?
    By mik in forum C++ Programming
    Replies: 1
    Last Post: 11-01-2001, 10:54 AM
  4. Help With Handles
    By JrKoas38 in forum Windows Programming
    Replies: 1
    Last Post: 09-22-2001, 11:35 AM