From: Goran on
On Mar 12, 4:07 pm, "Peter Olcott" <NoS...(a)OCR4Screen.com> wrote:
> I will study your concrete example an attempt to implement
> it. My great difficulty is with the tedious little
> syntactical details, thus Joe's abstract examples don't work
> for me. I can't simply let my GDI object get destroyed
> because the objects must retain their state in case
> subsequent operations must be performed on them.

I see in your code below that you use a memory DC. Without having any
further info, only thing I have to say is that normally a memory DC is
used to draw something, then e.g. stored in a bitmap or BitBlt-ed on
screen. From that standpoint, normal drawing we all know is to select
your GDI objects into the DC, call drawing code, then un-select them.
If that is what you are doing, then you have no correlation between
your GDI objects (e.g. bitmaps, pens, fonts, brushes) except that they
have to outlive time when they are selected into the DC for drawing.
So I honestly do not see your difficulty. Just make sure that, during
the drawing code, you do stuff by the book (hence e.g. my
CTempGdiObjectSelection), and as for lifetime of your GDI object,
well, just handle their lifetime (hence my shared_ptr-based map
there).

> I open a bitmap and it may be written to, or saved or
> another bitmap may be opened. If another bitmap is opened, I
> must create another CBitmap object of this new size.
> Currently I only have the single CBitmap object as an object
> member variable.

So make that two of them. Note also that there's nothing wrong in
creating whatever GDI object you might need on the heap.

> I am guessing that I could implement your design by making
> pairs of GDI object member and toggling between them upon
> every re-use. For example CBitmap cbitmap[2]; and then
> toggle its subscript between one and zero.

Here, either I am not very smart, either there's a lot of things you
have in your head that weren't put into writing here, because I don't
understand what you are talking about :-).

> I looked at your design again and there were too many things
> that I did not understand.

I'd say, points to take from it:

1. use something like CTempGdiObjectSelection to ensure correct GDI
object selection idiom, which is "select it/draw/un-select it".

2. use some C++ object lifetime handling technique to handle your GDI
object (font, bitmap, pen...) lifetime. Hence I proposed shared_ptr -
it gets you far. If you indeed use a std::map, attention to
map::operator[], that might not do what you think (hence my insistence
on that "const").

3. divorce lifetime of a DC and GDI objects used to draw on it (you
seem to be having trouble with this). In other words, when you select
an object into a DC, do not try to destroy it. But I don't understand
why you even started down that route.

> Here is my currently working code. It does not work if I
> remove the:
>   this->cfont.DeleteObject();
> It does work with repeated invocations, thus must be
> deleting the selected CFont object.
>
> //  Displays a Font Selection DialogBox with
> //  default "Times New Roman", Bold, Italic, 8 Point
> //
> inline void ScreenCaptureType::SelectFont() {
>   this->cfont.DeleteObject();
>
>   int PointSize  = 8;
>   int FontHeight = -MulDiv(PointSize,
> GetDeviceCaps(MemoryDC.m_hDC, LOGPIXELSY), 72);
>   LOGFONT LogFont = {FontHeight, 0, 0, 0, FW_BOLD, 1, 0, 0,
> ANSI_CHARSET, OUT_DEFAULT_PRECIS,
>   CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
> FF_DONTCARE, L"Times New Roman"};
>   CFontDialog dlg(&LogFont);
>   if (dlg.DoModal() == IDOK)
>     cfont.CreateFontIndirect(&LogFont);
>   this->MemoryDC.SelectObject(&cfont);
>
> }

Without knowing anything about the rest of your code, the purpose of
this function is to select some font into a memory DC (providing that
MemoryDC indeed is a CMemoryDC). Normally, one selects a font into a
DC to do some drawing, so I personally find it hugely surprising that
a modal dialog is displayed just before selecting it into a DC. I see
that working well in some bigger design only if said font is the only
font that will be used while drawing. But, as I said before, I don't
actually understand your difficulty at all, so I might be completely
off the mark.

By the way, please, PLEASE do something about that CreateFontIndirect
call. It stands out like a sore thumb. It's a friggin resource
allocation and that can fail (if so, it returns FALSE). Imagine that
this indeed happens. Would you want to do
MemoryDC.SelectObject(&cfont) then?

Goran.
From: Goran on
On Mar 14, 5:46 am, "Peter Olcott" <NoS...(a)OCR4Screen.com> wrote:
> So what is an example of simple clean minimal syntax for
> making sure that a single set of GDI object member variables
> always does get properly deleted?  The best that I could
> come up with is to duplicate everything such as CFont
> cfont[2]; and toggle the subscript.
> This seems like far too much of  a kludge.

(I'll presume that you want to use multiple fonts to draw on some DC).
If so, this works:

0. create any GDI objects (e.g. fonts)
1. (optional) create your DC ( or receive it in OnPaint :-) )
2. select any font into DC, draw, un-select it
Rinse, repeat 2 (you can also "stack" what you do in 2 if you wish so)
3. (optional) destroy DC (don't if it's not yours)
4. let all go out of scope (IOW, let your enclosing class be
destroyed).

Goran.
From: Peter Olcott on
The point is that the function listed below can be called
repeatedly, and it does not work if the
this->font.DeleteObject();
is removed which as far as I can tell must mean that a GDI
object is definitely being deleted while selected in a
device context. Proof that a GDI object is being deleted
while selected into a device context contradicts Joe's
statement that it can't be done.

What I suspect is there is something that I am missing here,
and Joe is not wrong, yet the explicit contradiction still
remains unresolved.

"Goran" <goran.pusic(a)gmail.com> wrote in message
news:bc8e5ce9-773d-42df-b509-097b70e021d1(a)33g2000yqj.googlegroups.com...
On Mar 12, 4:07 pm, "Peter Olcott" <NoS...(a)OCR4Screen.com>
wrote:
> I will study your concrete example an attempt to implement
> it. My great difficulty is with the tedious little
> syntactical details, thus Joe's abstract examples don't
> work
> for me. I can't simply let my GDI object get destroyed
> because the objects must retain their state in case
> subsequent operations must be performed on them.

I see in your code below that you use a memory DC. Without
having any
further info, only thing I have to say is that normally a
memory DC is
used to draw something, then e.g. stored in a bitmap or
BitBlt-ed on
screen. From that standpoint, normal drawing we all know is
to select
your GDI objects into the DC, call drawing code, then
un-select them.
If that is what you are doing, then you have no correlation
between
your GDI objects (e.g. bitmaps, pens, fonts, brushes) except
that they
have to outlive time when they are selected into the DC for
drawing.
So I honestly do not see your difficulty. Just make sure
that, during
the drawing code, you do stuff by the book (hence e.g. my
CTempGdiObjectSelection), and as for lifetime of your GDI
object,
well, just handle their lifetime (hence my shared_ptr-based
map
there).

> I open a bitmap and it may be written to, or saved or
> another bitmap may be opened. If another bitmap is opened,
> I
> must create another CBitmap object of this new size.
> Currently I only have the single CBitmap object as an
> object
> member variable.

So make that two of them. Note also that there's nothing
wrong in
creating whatever GDI object you might need on the heap.

> I am guessing that I could implement your design by making
> pairs of GDI object member and toggling between them upon
> every re-use. For example CBitmap cbitmap[2]; and then
> toggle its subscript between one and zero.

Here, either I am not very smart, either there's a lot of
things you
have in your head that weren't put into writing here,
because I don't
understand what you are talking about :-).

> I looked at your design again and there were too many
> things
> that I did not understand.

I'd say, points to take from it:

1. use something like CTempGdiObjectSelection to ensure
correct GDI
object selection idiom, which is "select it/draw/un-select
it".

2. use some C++ object lifetime handling technique to handle
your GDI
object (font, bitmap, pen...) lifetime. Hence I proposed
shared_ptr -
it gets you far. If you indeed use a std::map, attention to
map::operator[], that might not do what you think (hence my
insistence
on that "const").

3. divorce lifetime of a DC and GDI objects used to draw on
it (you
seem to be having trouble with this). In other words, when
you select
an object into a DC, do not try to destroy it. But I don't
understand
why you even started down that route.

> Here is my currently working code. It does not work if I
> remove the:
> this->cfont.DeleteObject();
> It does work with repeated invocations, thus must be
> deleting the selected CFont object.
>
> // Displays a Font Selection DialogBox with
> // default "Times New Roman", Bold, Italic, 8 Point
> //
> inline void ScreenCaptureType::SelectFont() {
> this->cfont.DeleteObject();
>
> int PointSize = 8;
> int FontHeight = -MulDiv(PointSize,
> GetDeviceCaps(MemoryDC.m_hDC, LOGPIXELSY), 72);
> LOGFONT LogFont = {FontHeight, 0, 0, 0, FW_BOLD, 1, 0, 0,
> ANSI_CHARSET, OUT_DEFAULT_PRECIS,
> CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH |
> FF_DONTCARE, L"Times New Roman"};
> CFontDialog dlg(&LogFont);
> if (dlg.DoModal() == IDOK)
> cfont.CreateFontIndirect(&LogFont);
> this->MemoryDC.SelectObject(&cfont);
>
> }

Without knowing anything about the rest of your code, the
purpose of
this function is to select some font into a memory DC
(providing that
MemoryDC indeed is a CMemoryDC). Normally, one selects a
font into a
DC to do some drawing, so I personally find it hugely
surprising that
a modal dialog is displayed just before selecting it into a
DC. I see
that working well in some bigger design only if said font is
the only
font that will be used while drawing. But, as I said before,
I don't
actually understand your difficulty at all, so I might be
completely
off the mark.

By the way, please, PLEASE do something about that
CreateFontIndirect
call. It stands out like a sore thumb. It's a friggin
resource
allocation and that can fail (if so, it returns FALSE).
Imagine that
this indeed happens. Would you want to do
MemoryDC.SelectObject(&cfont) then?

Goran.


From: Peter Olcott on
The problem is that the only way that I know how to unselect
a GDI object is to select another GDI object. I can't select
another GDI object because I have to get rid of the first
one to make room to create the second one. If there is
another way to unselect a GDI object besides selecting
another GDI object, then this would be easy.

Ideally I only want to have a single CFont and a single
CBitmap and a single MemoryDC that I use over and over.
These must all be stored as object members, and will live as
long as the app lives.

"Goran" <goran.pusic(a)gmail.com> wrote in message
news:06b6b099-4b40-4809-868b-982febcb6066(a)t23g2000yqt.googlegroups.com...
On Mar 14, 5:46 am, "Peter Olcott" <NoS...(a)OCR4Screen.com>
wrote:
> So what is an example of simple clean minimal syntax for
> making sure that a single set of GDI object member
> variables
> always does get properly deleted? The best that I could
> come up with is to duplicate everything such as CFont
> cfont[2]; and toggle the subscript.
> This seems like far too much of a kludge.

(I'll presume that you want to use multiple fonts to draw on
some DC).
If so, this works:

0. create any GDI objects (e.g. fonts)
1. (optional) create your DC ( or receive it in OnPaint
:-) )
2. select any font into DC, draw, un-select it
Rinse, repeat 2 (you can also "stack" what you do in 2 if
you wish so)
3. (optional) destroy DC (don't if it's not yours)
4. let all go out of scope (IOW, let your enclosing class be
destroyed).

Goran.


From: Goran on
On Mar 14, 6:29 pm, "Peter Olcott" <NoS...(a)OCR4Screen.com> wrote:
> The problem is that the only way that I know how to unselect
> a GDI object is to select another GDI object. I can't select
> another GDI object because I have to get rid of the first
> one to make room to create the second one. If there is
> another way to unselect a GDI object besides selecting
> another GDI object, then this would be easy.

OK, then you seem to have a major case of bad understanding of the
API. SelectObject returns previously selected object (of the given
type).

So you do:

CGdiObject* pOld = pDC->SeletObject(&mySuperFont);
// Draw, baby, draw...
pDC->SeletObject(pOld);

That's it!

You don't ever, ever care about that first pOld - this baby "belongs"
to a DC you are using, and is most likely one of "stock" gdi objects
that are not yours to do anything with.

> Ideally I only want to have a single CFont and a single
> CBitmap and a single MemoryDC that I use over and over.
> These must all be stored as object members, and will live as
> long as the app lives.

Well, I have to ask, why all that? It doesn't seem normal. For
example, if your purpose is to "draw" a bitmap for later use, then, if
my memory serves me correctly, you

* create a memory DC,
* call CreateCompatibleBitmap,
* call SelectObject for your font
* draw stuff on DC
* unselect the font from DC, destroy font and DC.

There's your bitmap, you can keep it.

If not, tell us what do you do with the three?

You also seem to be misguided in wanting to reuse e.g. the font. I
don't think you want it around while it's not used. If nothing else,
it's a resource strain on your system. Just create it when you're
drawing - what's wrong with that?

Goran.