Custom CRect Question

I have a custom rectangle class that inherits from CRect:

class CCustomRect : public CRect
{
private:
  CPoint m_maxPt;
  COLORREF m_color;
  TCHAR text[50];
public:
  CCustomRect(RECT* source, CPoint pt, COLORREF rgb);
  RECT* RectBase();
  void Update(RECT* r);
}

Inheritance has worked well until I found myself needing to create the 
RectBase function (above) to return the rectangle dimensions.

CRect does not seem to have any methods that can be called to return the 
base class's RECT value.

I could take CRect::Size and construct a rectangle to return, but this seems 
a bit much.

My other alternative seems to be to not inherit from CRect, but rather 
include it as a member variable. I don't really like this idea, though.

Is there a simple way to write the code for RectBase? CRect has several 
operators, including the "operator =" that copies the dimensions of a 
rectangle to CRect. Could my custom class use this operator in some way, or 
did I negate that ability whenever I inherited the CRect class?

Any thoughts? Suggestions? 


0
jp2code
7/20/2007 3:55:27 PM
vc.mfc 33608 articles. 0 followers. Follow

17 Replies
1122 Views

Similar Articles

[PageSpeed] 24

You shouldn't even need RectBase function.
CRect has an operator that converts a CRect class into a LPRECT or LPCRECT.

in other words
CCustomRect Rect;
GetWindowRect(&Rect);

should compile without a single message from the compiler.

Anyway, as far as inherting from a CRect or containing a CRect object goes, 
it all depends on what you are doing, and what is CCustomRect used for. 
What is CCustomRect used for?

If you are enhacing CRect then inherit from it.  If you need an object that 
happens to have a Rectangle as an attribute then contain is the way to go.


 class CCustomRect
 {
 private:
  CPoint m_maxPt;
  COLORREF m_color;
  TCHAR text[50];
  CRect Rect;
 public:
  CCustomRect(const RECT *source, CPoint pt, COLORREF rgb);
  CCustomRect(const RECT &source, CPoint pt, COLORREF rgb);
  const RECT& RectBase() { return Rect; }
  void Update(const RECT &r);
  void Update(const RECT *r);
 }

AliR.


"jp2code" <poojo.com/mail> wrote in message 
news:OEaelZuyHHA.3564@TK2MSFTNGP04.phx.gbl...
>I have a custom rectangle class that inherits from CRect:
>
> class CCustomRect : public CRect
> {
> private:
>  CPoint m_maxPt;
>  COLORREF m_color;
>  TCHAR text[50];
> public:
>  CCustomRect(RECT* source, CPoint pt, COLORREF rgb);
>  RECT* RectBase();
>  void Update(RECT* r);
> }
>
> Inheritance has worked well until I found myself needing to create the 
> RectBase function (above) to return the rectangle dimensions.
>
> CRect does not seem to have any methods that can be called to return the 
> base class's RECT value.
>
> I could take CRect::Size and construct a rectangle to return, but this 
> seems a bit much.
>
> My other alternative seems to be to not inherit from CRect, but rather 
> include it as a member variable. I don't really like this idea, though.
>
> Is there a simple way to write the code for RectBase? CRect has several 
> operators, including the "operator =" that copies the dimensions of a 
> rectangle to CRect. Could my custom class use this operator in some way, 
> or did I negate that ability whenever I inherited the CRect class?
>
> Any thoughts? Suggestions?
> 


0
AliR3470 (3236)
7/20/2007 4:29:08 PM
"jp2code" <poojo.com/mail> wrote in message 
news:OEaelZuyHHA.3564@TK2MSFTNGP04.phx.gbl...

>I have a custom rectangle class that inherits from CRect:
>
> CRect does not seem to have any methods that can be called to return the 
> base class's RECT value.

CRect is effectively derived from RECT (actually from tagRECT but I guess 
this is because RECT has to work in both C and C++ - don't quote me)  so you 
can have

RECT & CMyRect::rect()
{
    return *(RECT *)(CRect *)this;
}

const RECT & CMyRect::rect() const
{
    return *(const RECT *)(const CRect *)this;
}

if you really want to be pedantic :-)

[ I am always wary of using RECT at all, and prefer CRect,  because its copy 
constructor and assignment operator is implicit, and it offends my sense of 
Cplusplusiness, though perhaps it shouldn't.    I have also never liked the 
RECT * conversion of CRect - it just feels horrible converting an object to 
a pointer.]

Dave
-- 
David Webber
Author of 'Mozart the Music Processor'
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mzusers/mailinglist.htm


0
dave9996 (486)
7/20/2007 4:37:36 PM
Thanks Mr. Webber.

That's what I was needing. I had done something similar, but I was returning 
a pointer (RECT*) instead of the address (RECT&).

Would this have caused different results? The whole topic of pointers verses 
addresses has always been a little muddled in my brain.

> CRect is effectively derived from RECT (actually from tagRECT but I guess 
> this is because RECT has to work in both C and C++ - don't quote me)  so 
> you can have
>
> RECT & CMyRect::rect()
> {
>    return *(RECT *)(CRect *)this;
> }
>
> const RECT & CMyRect::rect() const
> {
>    return *(const RECT *)(const CRect *)this;
> }
>
> if you really want to be pedantic :-)
>
> [ I am always wary of using RECT at all, and prefer CRect,  because its 
> copy constructor and assignment operator is implicit, and it offends my 
> sense of Cplusplusiness, though perhaps it shouldn't.    I have also never 
> liked the RECT * conversion of CRect - it just feels horrible converting 
> an object to a pointer.]
>
> Dave
> -- 
> David Webber
> Author of 'Mozart the Music Processor'
> http://www.mozart.co.uk
> For discussion/support see
> http://www.mozart.co.uk/mzusers/mailinglist.htm
>
> 


0
jp2code
7/20/2007 6:38:50 PM
"jp2code" <poojo.com/mail> wrote in message 
news:uQrL50vyHHA.4476@TK2MSFTNGP06.phx.gbl...

> That's what I was needing. I had done something similar, but I was 
> returning a pointer (RECT*) instead of the address (RECT&).
>
> Would this have caused different results? The whole topic of pointers 
> verses addresses has always been a little muddled in my brain.

Pointers *are* addresses.

If you have

int n=3;

and

int *pn = &i;

Then the pointer pn is the address where the number 3 (in this case) resides 
in memory.   pn and n are not interchangeable!   n is the number; pn is its 
address.  You can get the number from the address (it's *pn) and the address 
from the number (it's &n) but they are different things.

References are more subtle.  They're like pointers which can be used for 
many syntax purposes interchangeably with the the object itself.  So if you 
have

int &r = n;

r is another way of referring to n.   It's a pseudo-pointer, if you like, to 
n, (in that the information it indirectly encapsulates is actually the 
address of n)  but now you can use it for many purposes as if it were n.

Coming back to RECT abd CRect:

The CRect class is essentially a wrapper around RECT.   Because of the 
inheritance, its data elements  (left, top, right, bottom) are exactly those 
of RECT, and so CRect *is* a RECT with methods added, trnasforming it from C 
to C++.

Now for some reason, which I think is a BIG mistake, when they designed 
CRect they gave it two members of the form

 CRect::operator LPRECT();
 CRect::operator LPCRECT() const;

which cast a CRect to a pointer to a RECT.  It just muddies the waters: 
objects do *not* need to be cast to pointers to themselves.

Consider Windows API functions which take a pointer to a RECT.  For example:

BOOL GetClientRect( HWND hWnd, RECT *prect );

In the old days of C one called it with

RECT R;
GetClientRect( hWnd, &R );        // &R is apointer to R

and one can call it with

CRect r;
GetClientRect( hWnd, &r );        // &r is apointer to r

But the existence of the cast operator means you can also write

CRect r;
GetClientRect( hWnd, r );

r is a CRect, but in fact it is cast to a pointer to itself when 
GetClientRect is called.

Why on earth would anyone want to do that just to avoid typing the & - it 
just looks totally confusing!!!????   Someone tell me I'm not alone here!

Dave
---- 
David Webber
Author of 'Mozart the Music Processor'
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mzusers/mailinglist.htm


















>> CRect is effectively derived from RECT (actually from tagRECT but I guess 
>> this is because RECT has to work in both C and C++ - don't quote me)  so 
>> you can have
>>
>> RECT & CMyRect::rect()
>> {
>>    return *(RECT *)(CRect *)this;
>> }
>>
>> const RECT & CMyRect::rect() const
>> {
>>    return *(const RECT *)(const CRect *)this;
>> }
>>
>> if you really want to be pedantic :-)
>>
>> [ I am always wary of using RECT at all, and prefer CRect,  because its 
>> copy constructor and assignment operator is implicit, and it offends my 
>> sense of Cplusplusiness, though perhaps it shouldn't.    I have also 
>> never liked the RECT * conversion of CRect - it just feels horrible 
>> converting an object to a pointer.]
>>
>> Dave
>> -- 
>> David Webber
>> Author of 'Mozart the Music Processor'
>> http://www.mozart.co.uk
>> For discussion/support see
>> http://www.mozart.co.uk/mzusers/mailinglist.htm
>>
>>
>
> 

0
dave9996 (486)
7/20/2007 10:21:12 PM
On Fri, 20 Jul 2007 10:55:27 -0500, "jp2code" <poojo.com/mail> wrote:

>I have a custom rectangle class that inherits from CRect:
>
>class CCustomRect : public CRect
>{
>private:
>  CPoint m_maxPt;
>  COLORREF m_color;
>  TCHAR text[50];
*****
Is there some odd reason you enjoy creating code that can have buffer overflow errors?  Is
there any reason not to use a CString here, which would make a LOT more sense!

Also, if you adopt the m_ naming convention, use it consistently (m_text), or don't use it
at all, but a mixed representation like this leads only to confusion!
*****
>public:
>  CCustomRect(RECT* source, CPoint pt, COLORREF rgb);
****
Is it ever valid to have a NULL source rectangle?  If not, make it RECT &.  Then the
compiler will tend to catch errors.  Presumably, the body looks like

CCustomRect::CCustomRect(RECT * source, CPoint pt, COLORREF rgb) : CRect(source) { m_color
= rgb; m_maxPt = pt; text[0] = _T('\0'); }

but it might have been nice to show that.  But I would *strongly* advise against using
something as quaint as a TCHAR[50] for a string!
*****
>  RECT* RectBase();
*****
Get rid of the above line, it serves no useful purpose.
*****
>  void Update(RECT* r);
>}
>
>Inheritance has worked well until I found myself needing to create the 
>RectBase function (above) to return the rectangle dimensions.
*****
Why?  You can simply use your class in any context in which a RECT would be valid!
*****
>
>CRect does not seem to have any methods that can be called to return the 
>base class's RECT value.
*****
Not clear why you need this at all; in any case, the CRect class has operator LPRECT()
which will give you an address of the object.  Since, for some reason, you chose to return
a RECT *, the operator is already defined.  
*****						
>
>I could take CRect::Size and construct a rectangle to return, but this seems 
>a bit much.
>
>My other alternative seems to be to not inherit from CRect, but rather 
>include it as a member variable. I don't really like this idea, though.
*****
Since you have inherited from CRect, you have inherited operator LPRECT() and operator
LPCRECT().  And note that a CRect is interchangeable with a RECT in arguments.
******
>
>Is there a simple way to write the code for RectBase? CRect has several 
>operators, including the "operator =" that copies the dimensions of a 
>rectangle to CRect. Could my custom class use this operator in some way, or 
>did I negate that ability whenever I inherited the CRect class?
*****
It seems that you are trying to do something the hard way.  You don't need an operator for
this purpose!   Have you actually tried to simply use your class in a place a CRect is
required?  It compiles and works perfectly without any effort!  I just tried it and it
works just fine.
					joe

*****
>
>Any thoughts? Suggestions? 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/22/2007 6:24:10 AM
You mean "pointers vs. REFERENCES", because both pointers and references are addresses.

Largely, it appears to be a fine point of syntax, rather than anything really deep.
However, a reference variable must always be assigned a value, e.g.,

Thing * x;
is a valid declaration, but
Thing & x;
is not.  You can write
Thing & x = x_reference_returning_expression_here;
but you cannot write
Thing & x = NULL;

Once a reference is assigned, it cannot be changed, e.g.,

Thing * x;
....
x = x_pointer_returning_expression_here;
....
x = different_x_pointer_returning_exprfession_here;

but that would not be legal for Thing & x; it must be initialized and cannot thereafter be
changed.   The most common form of this is as parameters.  It means you don't need to
specify the & operator at the call site.

Thing x;
SomeFunction(x);

void SomeFunction(Thing & x)
   {
    if(x.value == 3)
      ... do something
   }

Thing x;
SomeOtherFunction(&x);
void SomeOtherFunction(Thing * x)
    {
     if(x->value == 3)
       ... do something else
    }

For example,the most efficient way to pass a CString to a function is to use const CString
&, e.g.,

CString s;
SomeFuntion(s);

void SomeFunction(const CString & s) ....

It is also convenient that you can eliminate the & at the call site

CString s;
SomeDifferentFunction(s);

void SomeDifferentFunction(CString & s)
   {
    s += _T("Test");
   }

allows the modification of s.  One side effect is that with references, it is much harder
to pass a NULL argument inadvertently.
					joe

On Fri, 20 Jul 2007 13:38:50 -0500, "jp2code" <poojo.com/mail> wrote:

>Thanks Mr. Webber.
>
>That's what I was needing. I had done something similar, but I was returning 
>a pointer (RECT*) instead of the address (RECT&).
>
>Would this have caused different results? The whole topic of pointers verses 
>addresses has always been a little muddled in my brain.
>
>> CRect is effectively derived from RECT (actually from tagRECT but I guess 
>> this is because RECT has to work in both C and C++ - don't quote me)  so 
>> you can have
>>
>> RECT & CMyRect::rect()
>> {
>>    return *(RECT *)(CRect *)this;
>> }
>>
>> const RECT & CMyRect::rect() const
>> {
>>    return *(const RECT *)(const CRect *)this;
>> }
>>
>> if you really want to be pedantic :-)
>>
>> [ I am always wary of using RECT at all, and prefer CRect,  because its 
>> copy constructor and assignment operator is implicit, and it offends my 
>> sense of Cplusplusiness, though perhaps it shouldn't.    I have also never 
>> liked the RECT * conversion of CRect - it just feels horrible converting 
>> an object to a pointer.]
>>
>> Dave
>> -- 
>> David Webber
>> Author of 'Mozart the Music Processor'
>> http://www.mozart.co.uk
>> For discussion/support see
>> http://www.mozart.co.uk/mzusers/mailinglist.htm
>>
>> 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/23/2007 6:37:15 AM
But on the whole, did you really need such a function?  For example, you don't need it to
do an assignment, e.g.,

	CMyRect mr;
	...set values
	CRect r = mr;

works perfectly and does not require a special operator to get the CRect!  Show why you
think you need this function!
				joe

On Fri, 20 Jul 2007 13:38:50 -0500, "jp2code" <poojo.com/mail> wrote:

>Thanks Mr. Webber.
>
>That's what I was needing. I had done something similar, but I was returning 
>a pointer (RECT*) instead of the address (RECT&).
>
>Would this have caused different results? The whole topic of pointers verses 
>addresses has always been a little muddled in my brain.
>
>> CRect is effectively derived from RECT (actually from tagRECT but I guess 
>> this is because RECT has to work in both C and C++ - don't quote me)  so 
>> you can have
>>
>> RECT & CMyRect::rect()
>> {
>>    return *(RECT *)(CRect *)this;
>> }
>>
>> const RECT & CMyRect::rect() const
>> {
>>    return *(const RECT *)(const CRect *)this;
>> }
>>
>> if you really want to be pedantic :-)
>>
>> [ I am always wary of using RECT at all, and prefer CRect,  because its 
>> copy constructor and assignment operator is implicit, and it offends my 
>> sense of Cplusplusiness, though perhaps it shouldn't.    I have also never 
>> liked the RECT * conversion of CRect - it just feels horrible converting 
>> an object to a pointer.]
>>
>> Dave
>> -- 
>> David Webber
>> Author of 'Mozart the Music Processor'
>> http://www.mozart.co.uk
>> For discussion/support see
>> http://www.mozart.co.uk/mzusers/mailinglist.htm
>>
>> 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/23/2007 6:39:23 AM
> Is there some odd reason you enjoy creating code that can have buffer 
> overflow errors?  Is
> there any reason not to use a CString here, which would make a LOT more 
> sense!

I used to write code that relied a little too heavily on CString and CString 
functions, and it got to where I was not using some well known, reliable, 
and fast C/C++ tools for doing the same things. So, my manager told me to 
stop using CString for a while.

> Also, if you adopt the m_ naming convention, use it consistently (m_text), 
> or don't use it
> at all, but a mixed representation like this leads only to confusion!

Understood. Thanks for the reprimand. My manager does not require this, and 
it is just something I have started doing on my own to match the coding 
conventions from some of these MVPs. Often, I adopt code that is 20 years 
old that does not have a "pre m_". To change those variables would mean 
making lots of changes, but I try to make sure that any variables I add 
follow this technique so that I have better programming techniques.

> ...make it RECT &.  Then the compiler will tend to catch errors.

Done. Thanks for the tip!

Your suggestions have been greatly appreciated!

Thank you. 


0
jp2code
7/23/2007 1:40:01 PM
I must admit: I have found old code that I wrote that neglected to send the 
address of the CRect. Since the compiler did not catch it, I never knew I 
did anything wrong.

Later, I would see how the code was written, and wonder how it ever 
compiled.

Now I know!

I did fix the botched up code, though.

"David Webber" wrote:
> In the old days of C one called it with
>
> RECT R;
> GetClientRect( hWnd, &R );        // &R is apointer to R
>
> and one can call it with
>
> CRect r;
> GetClientRect( hWnd, &r );        // &r is apointer to r
>
> But the existence of the cast operator means you can also write
>
> CRect r;
> GetClientRect( hWnd, r );
>
> r is a CRect, but in fact it is cast to a pointer to itself when 
> GetClientRect is called.


0
jp2code
7/23/2007 1:45:17 PM
I'm designing my own progress bar, which will contain rectangles of 
sub-progress bar information.

When I initialize the custom progress bar, I will pass it the "rectangled" 
dimensions of the desktop window. The custom class will size itself (and its 
sub-progress bars) at a percentage of the viewable region of a small 
device's screen, and return the overall dimensions of the outer, enclosing 
progress bar.

If I get it to work, it will look very nice! (Key here is IF)

> But on the whole, did you really need such a function?  For example, you 
> don't need it to
> do an assignment, e.g.,
>
> CMyRect mr;
> ...set values
> CRect r = mr;
>
> works perfectly and does not require a special operator to get the CRect! 
> Show why you
> think you need this function!
> joe
>


0
jp2code
7/23/2007 1:51:54 PM
See below...
On Mon, 23 Jul 2007 08:40:01 -0500, "jp2code" <poojo.com/mail> wrote:

>> Is there some odd reason you enjoy creating code that can have buffer 
>> overflow errors?  Is
>> there any reason not to use a CString here, which would make a LOT more 
>> sense!
>
>I used to write code that relied a little too heavily on CString and CString 
>functions, and it got to where I was not using some well known, reliable, 
>and fast C/C++ tools for doing the same things. So, my manager told me to 
>stop using CString for a while.
****
Silly reason.  I have stopped using any of the primitive and outdated C string library,
and use CString entirely.  Why do you think these are "reliable", or for that matter, that
they are "fast"?  

Avoiding CString is saying "I like to write unreliable code that allows my program to be
attacked by buffer overflow exploits, fail because I miscalculated some fixed length, and
then failed to check buffer limits".  So you have a manager that wants to see the
reliability of products decrease?  Does your manager have the foggiest clue what
abandoning CString *really* means?  
*****
>
>> Also, if you adopt the m_ naming convention, use it consistently (m_text), 
>> or don't use it
>> at all, but a mixed representation like this leads only to confusion!
>
>Understood. Thanks for the reprimand. My manager does not require this, and 
>it is just something I have started doing on my own to match the coding 
>conventions from some of these MVPs. Often, I adopt code that is 20 years 
>old that does not have a "pre m_". To change those variables would mean 
>making lots of changes, but I try to make sure that any variables I add 
>follow this technique so that I have better programming techniques.
****
I consider most of these naming conventions to have negative value.  I tend to REMOVE the
m_ and HN prefixes from code that passes over my desk, because it increases the
readability.

Adding variables that use a different convention is far, far, far worse a practice.  Use
one convention or the other, but never mix them.  This is a catastrophe, because the
reader never knows what to expect!
				joe

*****
>
>> ...make it RECT &.  Then the compiler will tend to catch errors.
>
>Done. Thanks for the tip!
>
>Your suggestions have been greatly appreciated!
>
>Thank you. 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/23/2007 4:42:29 PM
It isn't very hard to do this.  But it still doesn't explain why you need some special
operator to extract the rectangle part of the subclass.
					joe

On Mon, 23 Jul 2007 08:51:54 -0500, "jp2code" <poojo.com/mail> wrote:

>I'm designing my own progress bar, which will contain rectangles of 
>sub-progress bar information.
>
>When I initialize the custom progress bar, I will pass it the "rectangled" 
>dimensions of the desktop window. The custom class will size itself (and its 
>sub-progress bars) at a percentage of the viewable region of a small 
>device's screen, and return the overall dimensions of the outer, enclosing 
>progress bar.
>
>If I get it to work, it will look very nice! (Key here is IF)
>
>> But on the whole, did you really need such a function?  For example, you 
>> don't need it to
>> do an assignment, e.g.,
>>
>> CMyRect mr;
>> ...set values
>> CRect r = mr;
>>
>> works perfectly and does not require a special operator to get the CRect! 
>> Show why you
>> think you need this function!
>> joe
>>
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/24/2007 4:56:20 AM
"Joseph M. Newcomer" wrote:
> It isn't very hard to do this.

For a seasoned pro like you, I'm sure it is easy. But I don't have many 
years of development under my belt, and I hardly ever have to draw anything 
to the screen. It has taken me too long to find examples that can be molded 
to what I want to do. I am also the only VC developer, and (by default) the 
only MFC developer here. The other two developers here are Linux, Borland, 
and Assembly developers. When I went to school, I learned on Visual Studio. 
Now I'm using eMbedded VC.

> ...it still doesn't explain why you need some special
> operator to extract the rectangle part of the subclass.

Originally, I wanted the rectangle dimensions so I would know what size 
object to paint on the screen. Since reading responses to this thread and 
the "Drawing Layers" thread, my approach has changed - hopefully for the 
better!

I've read more than one request for my code, so here it is (without the 
headers). The object "m_img" in CMainDlg::DisplayImage (called from 
CMainDlg::OnPaint) is not defined below, because it works. I'm sure my 
coding style will disturb some (white space disturbs me), but everyone is 
different.

My hope is that someone like Mr. joe Flounder can see what I'm trying to do 
and point out any wrong practices.


//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// ZRectBar class
ZRectBar::ZRectBar(RECT &r, COLORREF rgb) {
  m_cr = rgb;
  m_pt[eBL] = CPoint(r.bottom, r.left);
  m_pt[eBR] = CPoint(r.bottom, r.left); // innitialize to left size
  m_pt[eBM] = CPoint(r.bottom, r.right);
  m_pt[eTL] = CPoint(r.top, r.left);
  m_pt[eTR] = CPoint(r.top, r.left);    // innitialize to left size
  m_pt[eTM] = CPoint(r.top, r.right);
}
//---------------------------------------------------------------------------
ZRectBar::~ZRectBar() {
}
//---------------------------------------------------------------------------
void ZRectBar::Update(double ratio) { // only updates right side
  m_pt[eTR].x = int(m_pt[eTM].x * ratio + 0.5);
  m_pt[eTR].y = int(m_pt[eTM].y * ratio + 0.5);
  m_pt[eBR].x = int(m_pt[eBM].x * ratio + 0.5);
  m_pt[eBR].y = int(m_pt[eBM].y * ratio + 0.5);
}
//---------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
// ZProgressBar class
ZProgressBar::ZProgressBar(RECT &r) : m_active(FALSE) {
  if (m_rb[eBASE] != NULL) delete m_rb[eBASE];
  if (m_rb[eSESS] != NULL) delete m_rb[eSESS];
  if (m_rb[eFRAM] != NULL) delete m_rb[eFRAM];
  SetPosition(r);
}
//---------------------------------------------------------------------------
ZProgressBar::~ZProgressBar() {
  delete[] &m_rb;
}
//---------------------------------------------------------------------------
DWORD ZProgressBar::PaintDC(CDC* dc) {
  CPen penBase(PS_SOLID, 1, m_rb[eBASE]->m_cr);
  CPen* oldpen = dc->SelectObject(&penBase);
  CBrush brushBase(m_rb[eBASE]->m_cr);
  CBrush* oldbrush = dc->SelectObject(&brushBase);
  dc->Polygon(m_rb[eBASE]->m_pt, 4);
  // Frame
  CPen penFram(PS_SOLID, 1, m_rb[eFRAM]->m_cr);
  dc->SelectObject(&penFram);
  CBrush brushFram(m_rb[eFRAM]->m_cr);
  dc->SelectObject(&brushFram);
  dc->Polygon(m_rb[eFRAM]->m_pt, 4);
  // Session
  CPen penSess(PS_SOLID, 1, m_rb[eSESS]->m_cr);
  dc->SelectObject(&penSess);
  CBrush brushSess(m_rb[eSESS]->m_cr);
  dc->SelectObject(&brushSess);
  dc->Polygon(m_rb[eSESS]->m_pt, 4);

  dc->SelectObject(oldpen);
  dc->SelectObject(oldbrush);
  return 0;
}
//---------------------------------------------------------------------------
void ZProgressBar::SetPosition(RECT& r) {
  CPoint center(CRect(r).CenterPoint());
  CRect rect;
  COLORREF cr;
  int x(3 * center.x / 4);   // =  3/4 * center.x
  int y(1 * center.y / 10);  // = 1/10 * center.y
  int top1(center.y - y),    top2(center.y - (y - 5));
  int left(center.x - x),    right(center.x + x);
  int bottom1(center.y + y), bottom2(center.y + (y - 5));
  if (m_rb[eBASE] == NULL) {
    rect = CRect(CPoint(top1, left), CPoint(bottom1, right));
    cr = RGB(0xC0, 0xC0, 0xC0); // silver
    m_rb[eBASE] = new ZRectBar(rect, cr);
  }
  if (m_rb[eFRAM] == NULL) {
    rect = CRect(CPoint(top1, left), CPoint(bottom1, left));
    cr = RGB(0xFF, 0x00, 0x00); // red
    m_rb[eFRAM] = new ZRectBar(rect, cr);
  }
  if (m_rb[eSESS] == NULL) {
    rect = CRect(CPoint(top2, left), CPoint(bottom2, left));
    cr = RGB(0x00, 0x80, 0xFF); // blue-ish
    m_rb[eSESS] = new ZRectBar(rect, cr);
  }
}
//---------------------------------------------------------------------------
void ZProgressBar::Update(ZInfoPacket *pkt) {
  m_active = TRUE;
  if ((pkt->sessions != 0) && (pkt->frames != 0)) { // prevent division by 
zero
    m_rb[eSESS]->Update(double(pkt->session / pkt->sessions));
    m_rb[eFRAM]->Update(double(pkt->frame   / pkt->frames));
  }
}
//---------------------------------------------------------------------------
void CMainDlg::DisplayImage(CPaintDC *dc) {
  BOOL ok(m_bitmap.GetBitmap(&m_img.Bmp));
  CBitmap *poldbmp;
  if (ok) {
    CDC mDC;
    mDC.CreateCompatibleDC(dc);
    poldbmp = mDC.SelectObject(&m_bitmap);
    if (poldbmp != NULL) {
      m_pic = m_img.SetBounds(&m_rect);
      if (m_progressBar->Active() == TRUE) {
        m_progressBar->PaintDC(&mDC); // paint the progress bar to memDC 
before copying it
      }
      ok = dc->StretchBlt(m_pic.left, m_pic.top, m_pic.Width(), 
m_pic.Height(), &mDC,
                  m_img.BmpR.left, m_img.BmpR.top, m_img.BmpR.Width(), 
m_img.BmpR.Height(), SRCCOPY);
      if (!ok) {
        outList.ConcatTail(CString(TEXT("\n")) + 
CString(SysErrorMessage(GetLastError())));
      }
      mDC.SelectObject(poldbmp); // restore the DC to original state
      //mDC.DeleteDC();
      m_bitmap.DeleteObject();
    }
    mDC.ReleaseAttribDC();
  } else {
    ShowLastError(TEXT("GetBitmap Failed"));
    m_img.SetKind(kNONE); // prevents an err loop
    Invalidate(); // messes up the background
  }
}
//---------------------------------------------------------------------------


0
jp2code
7/24/2007 1:51:51 PM
But it really isn't very hard.  I teach this on the first day of MFC programming, where we
draw some text inside a rectangle on the screen.  Two hours later, the students are
dragging the text and rectangle around.  It well and truly isn't very hard.

You need one good book on Windows programming that has a chapter on graphics in it.  Note
that the Linux, Borland, and Assembly programmers will not find anything about how to draw
rectangles in their C/C++ books either.  But a single book on X-windows programming will
tell you about creating a GC (Graphics Context) and drawing to it.  Borland is a company
that produces all kinds of things, so I don't know what they're using, but if it is
Delphi, then the Delphi language was designed to support WIndows graphics, and it WILL
have a chapter on drawing rectangles, because it is just like having a Windows book.  No
assembly programmer has a clue as to how to draw a rectangle, and they certainly won't
find it in the Intel assembly code manuals or the Microsoft Assembler manual.  So the art
is looking in the right place.  But that doesn't make it hard.  Really.  

Key is to understand that x increases to the right and y increases downward.  After you've
mastered that, the rest is pretty easy.  Rectangle draws 4-sided vertical/horizontal
aligned things, MoveTo/LineTo draw lines, Ellipse draws ellipses and circles.  At this
point, you've mastered 90% of what you ever need to know to do drawing of all non-text
stuff.

The other 10% you pick up as needed.  Bitmaps are messy, no question, but once you have an
example piece of code (from the MSDN)  you now have 90% of what you ever need to know
about bitmaps.  Polygons are a bit harder, pie-chart graphics, curves, and Beziers follow,
but the number of times I've had to use those is very small.  I always have to reread the
manual when I use them.

You will be surprised at how easy it is once you get started.

By the way, text isn't hard either, just tedious.

There are over 30 parameters of the DC you can manipulate, but the key ones are
	dc.SelectObject(&pen);
	dc.SelectObject(&brush);
	dc.SelectObject(&font);
	dc.SetBkMode(...);
	dc.SetTextColor(...);
	dc.SetROP2(...); of which you usually need R2_COPY and one of
		R2_XORPEN, R2_NOTXORPEN, and R2_NOTPEN
	
and after that, the need for other parameters drops off rapidly.

Finally, there are mapping modes.  These are both cool and powerful, and you typically
don't get into these for a while.  The calls are
	dc.SetMapMode(...)
	dc.SetWindowOrg(...)
	dc.SetViewportOrg(...)
	dc.SetWindowExt(...)
	dc.SetViewportExt(...)
and for these you can download my Viewport Explorer (I got tired of having to read the
manual each time I used these, which was about twice a year).

There are esoteric things like paths, transform matrices, and clipping regions, and you
can deal with them as you need to, but I don't use them too often.  

So there's your study outline for graphics.  There are a huge number of DC calls for
drawing and manipulation of DC state, but I've given you the study guide for 99% of what
you need to know in the explicit list of calls above.

You can also download the programs for the Win32 book from my MVP Tips site and explore
the more esoteric aspects of pens, brushes, DCs, bitmap calls, etc.
					joe
*****



On Tue, 24 Jul 2007 08:51:51 -0500, "jp2code" <poojo.com/mail> wrote:

>"Joseph M. Newcomer" wrote:
>> It isn't very hard to do this.
>
>For a seasoned pro like you, I'm sure it is easy. But I don't have many 
>years of development under my belt, and I hardly ever have to draw anything 
>to the screen. It has taken me too long to find examples that can be molded 
>to what I want to do. I am also the only VC developer, and (by default) the 
>only MFC developer here. The other two developers here are Linux, Borland, 
>and Assembly developers. When I went to school, I learned on Visual Studio. 
>Now I'm using eMbedded VC.
>
>> ...it still doesn't explain why you need some special
>> operator to extract the rectangle part of the subclass.
>
>Originally, I wanted the rectangle dimensions so I would know what size 
>object to paint on the screen. Since reading responses to this thread and 
>the "Drawing Layers" thread, my approach has changed - hopefully for the 
>better!
>
>I've read more than one request for my code, so here it is (without the 
>headers). The object "m_img" in CMainDlg::DisplayImage (called from 
>CMainDlg::OnPaint) is not defined below, because it works. I'm sure my 
>coding style will disturb some (white space disturbs me), but everyone is 
>different.
>
>My hope is that someone like Mr. joe Flounder can see what I'm trying to do 
>and point out any wrong practices.
>
>
>//---------------------------------------------------------------------------
>/////////////////////////////////////////////////////////////////////////////
>// ZRectBar class
>ZRectBar::ZRectBar(RECT &r, COLORREF rgb) {
>  m_cr = rgb;
>  m_pt[eBL] = CPoint(r.bottom, r.left);
>  m_pt[eBR] = CPoint(r.bottom, r.left); // innitialize to left size
>  m_pt[eBM] = CPoint(r.bottom, r.right);
>  m_pt[eTL] = CPoint(r.top, r.left);
>  m_pt[eTR] = CPoint(r.top, r.left);    // innitialize to left size
>  m_pt[eTM] = CPoint(r.top, r.right);
>}
****
You can probably compute these on the fly rather than one at a time.  Just store the CRect
and the color.
****
>//---------------------------------------------------------------------------
>ZRectBar::~ZRectBar() {
>}
>//---------------------------------------------------------------------------
>void ZRectBar::Update(double ratio) { // only updates right side
>  m_pt[eTR].x = int(m_pt[eTM].x * ratio + 0.5);
>  m_pt[eTR].y = int(m_pt[eTM].y * ratio + 0.5);
>  m_pt[eBR].x = int(m_pt[eBM].x * ratio + 0.5);
>  m_pt[eBR].y = int(m_pt[eBM].y * ratio + 0.5);
>}
>//---------------------------------------------------------------------------
>/////////////////////////////////////////////////////////////////////////////
>// ZProgressBar class
>ZProgressBar::ZProgressBar(RECT &r) : m_active(FALSE) {
>  if (m_rb[eBASE] != NULL) delete m_rb[eBASE];
>  if (m_rb[eSESS] != NULL) delete m_rb[eSESS];
>  if (m_rb[eFRAM] != NULL) delete m_rb[eFRAM];
>  SetPosition(r);
>}
>//---------------------------------------------------------------------------
>ZProgressBar::~ZProgressBar() {
>  delete[] &m_rb;
>}
>//---------------------------------------------------------------------------
>DWORD ZProgressBar::PaintDC(CDC* dc) {
>  CPen penBase(PS_SOLID, 1, m_rb[eBASE]->m_cr);
****
Given you apparently want a solid rectangle, you can simply select the HOLLOW_PEN and you
don't need to create a pen of the same color as the brush
*****
>  CPen* oldpen = dc->SelectObject(&penBase);
>  CBrush brushBase(m_rb[eBASE]->m_cr);
>  CBrush* oldbrush = dc->SelectObject(&brushBase);
>  dc->Polygon(m_rb[eBASE]->m_pt, 4);
*****
But Rectangle would be simpler....
****
>  // Frame
>  CPen penFram(PS_SOLID, 1, m_rb[eFRAM]->m_cr);
>  dc->SelectObject(&penFram);
>  CBrush brushFram(m_rb[eFRAM]->m_cr);
>  dc->SelectObject(&brushFram);
>  dc->Polygon(m_rb[eFRAM]->m_pt, 4);
>  // Session
>  CPen penSess(PS_SOLID, 1, m_rb[eSESS]->m_cr);
>  dc->SelectObject(&penSess);
>  CBrush brushSess(m_rb[eSESS]->m_cr);
>  dc->SelectObject(&brushSess);
>  dc->Polygon(m_rb[eSESS]->m_pt, 4);
*****
You are probably making this whole problem more complex than it needs to be.  You dissect
the rectangle parameters, then reassemble them in a complex fashion, when just keeping a
small number of values should suffice.  Don't think of the problem in terms of rectangles;
those are a tiny implementation detail.  Think instead of percentages of the total and
percentages of the values you are trying to display, and the problem becomes MUCH simpler!
*****
>
>  dc->SelectObject(oldpen);
>  dc->SelectObject(oldbrush);
>  return 0;
>}
>//---------------------------------------------------------------------------
>void ZProgressBar::SetPosition(RECT& r) {
>  CPoint center(CRect(r).CenterPoint());
>  CRect rect;
>  COLORREF cr;
>  int x(3 * center.x / 4);   // =  3/4 * center.x
>  int y(1 * center.y / 10);  // = 1/10 * center.y
>  int top1(center.y - y),    top2(center.y - (y - 5));
>  int left(center.x - x),    right(center.x + x);
>  int bottom1(center.y + y), bottom2(center.y + (y - 5));
>  if (m_rb[eBASE] == NULL) {
>    rect = CRect(CPoint(top1, left), CPoint(bottom1, right));
>    cr = RGB(0xC0, 0xC0, 0xC0); // silver
*****
If this is supposed to be the background, it should be
	cr = ::GetSysColor(COLOR_3DFACE);
so it follows the user's color scheme
*****
>    m_rb[eBASE] = new ZRectBar(rect, cr);
****
You don't need a 'new' here, and it probably isn't a good idea.  I think this code is
needlessly complex...you are having problems because you are trying to create difficult
solutions for simple problems
****
>  }
>  if (m_rb[eFRAM] == NULL) {
>    rect = CRect(CPoint(top1, left), CPoint(bottom1, left));
>    cr = RGB(0xFF, 0x00, 0x00); // red
>    m_rb[eFRAM] = new ZRectBar(rect, cr);
>  }
>  if (m_rb[eSESS] == NULL) {
>    rect = CRect(CPoint(top2, left), CPoint(bottom2, left));
>    cr = RGB(0x00, 0x80, 0xFF); // blue-ish
>    m_rb[eSESS] = new ZRectBar(rect, cr);
>  }
>}
>//---------------------------------------------------------------------------
>void ZProgressBar::Update(ZInfoPacket *pkt) {
>  m_active = TRUE;
>  if ((pkt->sessions != 0) && (pkt->frames != 0)) { // prevent division by 
>zero
*****
This appears to be the important part of the work.  But I need to understand what all
these parameters are really doing in terms of the display
*****
>    m_rb[eSESS]->Update(double(pkt->session / pkt->sessions));
>    m_rb[eFRAM]->Update(double(pkt->frame   / pkt->frames));
>  }
>}
>//---------------------------------------------------------------------------
*****
WHat is confusing here is trying to figure out exactly what you are doing.

I think what I heard is that you need a progress bar with three components in it, for
example'

##########***************$$$$$$$$$$$$$$$$$

where each of those represents a color.  Is this essentially correct?

Trying to figure out if this is what intended from the code is a bit difficult.

Rather than showing me the code, give a precise definition of what you are trying to
accomplish, not in terms of rectangles, but in terms of the logical goal.  What are the
actual parameters of what you are trying to display?  

I can't quite figure out what you mean by 

*****When I initialize the custom progress bar, I will pass it the "rectangled" 
*****dimensions of the desktop window. The custom class will size itself (and its 
*****sub-progress bars) at a percentage of the viewable region of a small 
*****device's screen, and return the overall dimensions of the outer, enclosing 
*****progress bar.

First, I think this is the wrong approach.  The owner of the progress bar will size the
progress bar to some size.  So everything else is in terms of some other set of
parameters, such as total progress percentage, and sub-percentages.  (Note that I had a
14-year-old doing a "gas gauge" of two colors in less than an hour of total investment of
learning, for the remaining fuel and weapons of a "tank" in a video game we were writing,
but that was because we started with a specification instead of the code.  I don't have a
clear specification of what you are trying to do, and I think the code is vastly more
complicated than it needs to be as a consequence of having a complex specification).

So tell me not about "rectangled" values but tell me about what values are being displayed
in terms of the abstract values, and the code will probably be very simple to write.  I
can tell you right now it will not involve Polygon calls, or 'new' calls, or worrying
about sending rectangles in.  Tell me what those numbers mean without showing a single
line of code.  Tell me what the user is going to see.  Without a clear explanation of the
goals of the code, I can't figure out what the code is trying to accomplish, but I have a
real suspicion that the code here is vastly more complex than it needs to be.
*****
               
>void CMainDlg::DisplayImage(CPaintDC *dc) {
****
CDC & dc 
would be a better choice of parameter here
****
>  BOOL ok(m_bitmap.GetBitmap(&m_img.Bmp));
>  CBitmap *poldbmp;
>  if (ok) {
>    CDC mDC;
>    mDC.CreateCompatibleDC(dc);
>    poldbmp = mDC.SelectObject(&m_bitmap);
>    if (poldbmp != NULL) {
>      m_pic = m_img.SetBounds(&m_rect);
>      if (m_progressBar->Active() == TRUE) {
>        m_progressBar->PaintDC(&mDC); // paint the progress bar to memDC 
>before copying it
****
m_progessBar->PaintDC(mDC); // use CDC & dc for the parameter

Before you start worrying about flicker, it is more important to have a clear piece of
code.  You can optimize for flicker later.
****
>      }
>      ok = dc->StretchBlt(m_pic.left, m_pic.top, m_pic.Width(), 
>m_pic.Height(), &mDC,
>                  m_img.BmpR.left, m_img.BmpR.top, m_img.BmpR.Width(), 
>m_img.BmpR.Height(), SRCCOPY);
*****
The StretchBlt is very suspicious.  I'm concerned about this level of complexity.  You are
trying to draw, if I understand what I think, three "stacked" bars.  StretchBlt doesn't
fit this model at all.
*****
>      if (!ok) {
>        outList.ConcatTail(CString(TEXT("\n")) + 
>CString(SysErrorMessage(GetLastError())));
>      }
>      mDC.SelectObject(poldbmp); // restore the DC to original state
****
No, this is just restoring the old bitmap.  And RestoreDC would be a bette choice.
****
>      //mDC.DeleteDC();
>      m_bitmap.DeleteObject();
>    }
>    mDC.ReleaseAttribDC();
****
Why?
****
>  } else {
>    ShowLastError(TEXT("GetBitmap Failed"));
>    m_img.SetKind(kNONE); // prevents an err loop
>    Invalidate(); // messes up the background
>  }
>}
>//---------------------------------------------------------------------------
>
*****
Overall, your problems are coming not from a failure to understand Windows graphics, but
from failing to have a simple, clean specification of what you are trying to display.  All
you need to do is compute three, or four, rectangles, and draw them.  It is vastly simpler
than what I see here.    The result of a complex specification is a complex
implementation.  Just state a very simple specification of what these mean, and the code
is going to be really easy.
				joe
*****
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/24/2007 7:08:33 PM
The application is a small dialog based form.

As the User makes selections from a drop down menu, the "wallpaper" is 
updated to reflect a relevant subject for the topic and to visually cue the 
User in to the section he is working in.

One of the sections include the option to download a log file from the 
machine or upload a configuration file to the machine. The number of bytes 
in the files are larger than the machine's OS can handle (similar to the 
65,535 limit), so the machine breaks the file size down into sessions and 
frames.

Our progress bar needs to keep track of the current frame, total frames in 
the session, the session number, and total number of sessions.

I already have a "wallpaper" for the main window. If the progress bar is 
active, I need to add the progress bar data to the "wallpaper" image before 
it is displayed.

I hope that helps shed some light on what my code is trying to do.

So, would your "Win32 Programming" be a good book for this?

"Joseph M. Newcomer" wrote:
> Overall, your problems are coming not from a failure to understand Windows 
> graphics, but
> from failing to have a simple, clean specification of what you are trying 
> to display.  All
> you need to do is compute three, or four, rectangles, and draw them.  It 
> is vastly simpler
> than what I see here.    The result of a complex specification is a 
> complex
> implementation.  Just state a very simple specification of what these 
> mean, and the code
> is going to be really easy.
> joe
> *****
> Joseph M. Newcomer [MVP]
> email: newcomer@flounder.com
> Web: http://www.flounder.com
> MVP Tips: http://www.flounder.com/mvp_tips.htm 


0
jp2code
7/24/2007 7:52:44 PM
See below...
On Tue, 24 Jul 2007 14:52:44 -0500, "jp2code" <poojo.com/mail> wrote:

>The application is a small dialog based form.
>
>As the User makes selections from a drop down menu, the "wallpaper" is 
>updated to reflect a relevant subject for the topic and to visually cue the 
>User in to the section he is working in.
>
>One of the sections include the option to download a log file from the 
>machine or upload a configuration file to the machine. The number of bytes 
>in the files are larger than the machine's OS can handle (similar to the 
>65,535 limit), so the machine breaks the file size down into sessions and 
>frames.
>
>Our progress bar needs to keep track of the current frame, total frames in 
>the session, the session number, and total number of sessions.
****
So what this sounds like is you have several "bars", one of which is a progress along the
dimension of sessions completed, one of which is completion of the current session, and
one which is the progress in the current frame.  So this isn't a stacked progress bar, it
sounds like three bars
#############################
$$$$$$$$$$$$$$$$$
**************

so that the top is the total session transmission; when it hits 100%, everything is
transferred.
The second one is the progress along the current session.  When it hits 100%, the top bar
increments by one position, and the second one resets to 0 to indicate the start of the
nex session.
A session consists of a number of frames, and consequently the bottom bar indicates the
percentage of frames in the current session.  When it hits 100%, the second bar increments
by one unit.

Now the real issue is that you have made this REALLY complicated when it doesn';t need to
be.  For example, I would handle this by creating a modeless dialog box which contains
three progress controls.  If I wanted to make it really compact, I'd create a modeless
dialog with no border.  I would then size it to the width of the window.  Then I would
send it messages to set the range and position of each of the bars.  If I wanted
everything really compact, I'd create  progress controls without borders (which is not an
international humanitarian progress control organization).

Now, in the dialog, in its OnSize handler, I'd respond by computing 1/3 the height, and
the full width, and adjust the progress bars so they filled the entire dialog.   

Note that there is virtually no graphical programming required to accomplish this.

Compute the number of sessions.  Send a message
	dlg->SendMessage(UWM_SET_RANGE, (WPARAM)bartype, (LPARAM)value);
	dlg->SendMessage(UWM_SET_POS, (WPARAM)bartype, (LPARAM)value);

where you have something like typedef enum {Sessions, Session, Frame} BARTYPE;

When the transfer completed, I'd hide or destroy the modeless dialog. 

Because this is a modeless dialog, there will be no flicker in doing the update.  

You have taken a REALLY simple problem and made it REALLY complex.

Note that if you WERE to draw these directly on the surface of your bitmap, you would
invalidate ONLY the tiny region you required to have redrawn, say, from the rightmost end
of the old progress position to the rightmost end of the new progress position.  No
flicker.  No need for a memory DC at all!  But why go through so much effort to solve such
a simple problem?  You want three progress bars, use the existing progress bars!  You can
use PBM_SETBARCOLOR to change the colors of the bars so they look different from each
other.
				joe
*****
>
>I already have a "wallpaper" for the main window. If the progress bar is 
>active, I need to add the progress bar data to the "wallpaper" image before 
>it is displayed.
>
>I hope that helps shed some light on what my code is trying to do.
>
>So, would your "Win32 Programming" be a good book for this?
*****
If you were doing graphics, I might recommend it (but recall that I'm very biased about
the book).  But the problem is so much simpler that I wouldn't see spending all that money
to solve it.
				joe
*****
>
>"Joseph M. Newcomer" wrote:
>> Overall, your problems are coming not from a failure to understand Windows 
>> graphics, but
>> from failing to have a simple, clean specification of what you are trying 
>> to display.  All
>> you need to do is compute three, or four, rectangles, and draw them.  It 
>> is vastly simpler
>> than what I see here.    The result of a complex specification is a 
>> complex
>> implementation.  Just state a very simple specification of what these 
>> mean, and the code
>> is going to be really easy.
>> joe
>> *****
>> Joseph M. Newcomer [MVP]
>> email: newcomer@flounder.com
>> Web: http://www.flounder.com
>> MVP Tips: http://www.flounder.com/mvp_tips.htm 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/24/2007 8:56:01 PM
Send me private email and I'll send you a fully-worked-out example of a 3-progress-bar
modeless dialog that sits at the bottom of the window.  Note the dialog is resizable and
watch what it does when you resize it.
					joe

On Tue, 24 Jul 2007 14:52:44 -0500, "jp2code" <poojo.com/mail> wrote:

>The application is a small dialog based form.
>
>As the User makes selections from a drop down menu, the "wallpaper" is 
>updated to reflect a relevant subject for the topic and to visually cue the 
>User in to the section he is working in.
>
>One of the sections include the option to download a log file from the 
>machine or upload a configuration file to the machine. The number of bytes 
>in the files are larger than the machine's OS can handle (similar to the 
>65,535 limit), so the machine breaks the file size down into sessions and 
>frames.
>
>Our progress bar needs to keep track of the current frame, total frames in 
>the session, the session number, and total number of sessions.
>
>I already have a "wallpaper" for the main window. If the progress bar is 
>active, I need to add the progress bar data to the "wallpaper" image before 
>it is displayed.
>
>I hope that helps shed some light on what my code is trying to do.
>
>So, would your "Win32 Programming" be a good book for this?
>
>"Joseph M. Newcomer" wrote:
>> Overall, your problems are coming not from a failure to understand Windows 
>> graphics, but
>> from failing to have a simple, clean specification of what you are trying 
>> to display.  All
>> you need to do is compute three, or four, rectangles, and draw them.  It 
>> is vastly simpler
>> than what I see here.    The result of a complex specification is a 
>> complex
>> implementation.  Just state a very simple specification of what these 
>> mean, and the code
>> is going to be really easy.
>> joe
>> *****
>> Joseph M. Newcomer [MVP]
>> email: newcomer@flounder.com
>> Web: http://www.flounder.com
>> MVP Tips: http://www.flounder.com/mvp_tips.htm 
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
0
newcomer (15975)
7/24/2007 11:48:47 PM
Reply:

Similar Artilces: