System::Drawing::Graphics - how do I use in managed C++?

P

Peter Oliphant

There doesn't seem to be any documentation on how to create and/or use an
instance of System::Drawing::Graphics. On-line MSDN talks about this class,
and says:

" The Graphics class provides methods for drawing objects to the display
device. A Graphics object is associated with a specific device context. "

Great. So how about explaining HOW to do this? Or perhaps a code example? Or
at least a CONSTRUCTOR (or some explanation on how to create an instance)?
For example, why isn't there a link on 'associated with a specific device
context' showing how to associate a device context with a Graphics object? A
lot of MSDN seems to be 'circular' and sometimes lacking practical info in
it's explanations...
 
T

Tomas Restrepo \(MVP\)

Peter,
There doesn't seem to be any documentation on how to create and/or use an
instance of System::Drawing::Graphics. On-line MSDN talks about this
class, and says:

" The Graphics class provides methods for drawing objects to the display
device. A Graphics object is associated with a specific device context. "

Great. So how about explaining HOW to do this? Or perhaps a code example?
Or at least a CONSTRUCTOR (or some explanation on how to create an
instance)? For example, why isn't there a link on 'associated with a
specific device context' showing how to associate a device context with a
Graphics object? A lot of MSDN seems to be 'circular' and sometimes
lacking practical info in it's explanations...

Normally, you don't create a Graphics object yourself, but instead get
handed one during the Paint event for the control/form you're painting (or
if you overload the OnPaint() method of the control/form).

If you need one, I usually just use the CreateGraphics() method of the
Control class on the control I want to paint on.
 
P

Peter Oliphant

Maybe I should just say what I'm trying to do...hehe.

I want to draw points, lines, rectangles, and ellipses (solid/wire-frame)
of a given color (and possibly thickness) similar to how a control is placed
on a container/form.

To date I've created a solid rectangle by 'cheating' in the following way: I
created a Label with no text in it! This can then be used to create a line
by making it thin. This doesn't seem like it's the way it should be done,
but I can't find anyway to just draw a line on the form (which I thought was
what the Graphics class was for)...

How do I do this 'correctly'?

[==P==]
 
W

William DePalo [MVP VC++]

Peter Oliphant said:
Maybe I should just say what I'm trying to do...hehe.

I want to draw points, lines, rectangles, and ellipses (solid/wire-frame)
of a given color (and possibly thickness) similar to how a control is
placed on a container/form.

To go over a little background:

There are two times when you need to "paint" your form.

One is when the window manager tells you that you must. It will do this
whenever it detects that there is a change to that portion of the desktop
enclosed by your form. For example when your form is first created the
window manager realizes that what was "under" your form before should now be
replaced by something of your application's choosing. Or as another example,
when the user moves a window that uncovers your form the window manager
realizes that there is an update that needs to be made to the form.

At the level of the API, the window manager sends a WM_PAINT message to a
window. At the managed code level, the window manager calls the OnPaint()
method of the form. It is there where you need to implement the bulk your
paint algorithm.

The other time to paint is when your application knows that its form needs a
new paint job. As Tomas has already pointed out, you can do that at any time
by calling CreateGraphics().

To simplify an application's code, sometimes only the first case is actually
implemented. To deal with application / user requested paints an application
can simply call the Invlidate() method of the Form class. This causes the
window manager to dispatch a WM_PAINT message natively or the OnPaint()
method on the .Net platform.

Of course, in your case, your application must keep track of all the lines,
ellipses etc that it needs to paint. The window manager can't possibly do
that.

In case you are new to this stuff, I've pasted the code to a managed
application that draws some text, a line and an ellipse. I'm not sure
posting it is wise because it is a little off the beaten path.

You see I am going to listen to Charles Petzold (
http://www.charlespetzold.com/ ) speak this week on the topic of whether
using the wizards in Visual Studio rots the mind. :) I've thought about
that in the past have been thinking about it more in advance of his talk. So
my little sample does WinForms in Managed C++ _without_ using _any_ of the
wizards in VS.

To do that, I choose to create an _empty_ WIN32 APPLICATION and then I set
the "Use Managed Extensions" option manually.

Regards,
Will

// Class implementation Po2.cpp

#include "po2.h"

void HelloWorld::Main()
{
Application::Run( new HelloWorld() );
}

HelloWorld::HelloWorld()
{
Text = "Hello, world!";
BackColor = Color::White;

penRed = new Pen(Color::Red);
penBlue = new Pen(Color::Blue);
}

void HelloWorld::OnPaint(PaintEventArgs *pea)
{
Graphics __gc *grfx = pea->Graphics;
Rectangle rc;

grfx->DrawString("Hello, World!", Font, Brushes::Black, 0, 0);

rc = get_ClientRectangle();
rc.Width -= 1;
rc.Height -= 1;

grfx->DrawLine(penRed, 0, 0, rc.Width, rc.Height);

grfx->DrawEllipse(penBlue, rc);
}

// Hack avoids including <windows.h>

int __stdcall WinMain(int, int, int, int)
{
HelloWorld::Main();
return 0;
}

// Class declaration po2.h

#using <System.dll>
#using <mscorlib.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::ComponentModel;

public __gc class HelloWorld : public Form
{
private:

Pen __gc *penRed;
Pen __gc *penBlue;

public:

HelloWorld();
static void Main();

protected:

void OnPaint(PaintEventArgs __gc *);
};
 
P

Peter Oliphant

Thanx, William! : )

[==P==]

William DePalo said:
To go over a little background:

There are two times when you need to "paint" your form.

One is when the window manager tells you that you must. It will do this
whenever it detects that there is a change to that portion of the desktop
enclosed by your form. For example when your form is first created the
window manager realizes that what was "under" your form before should now
be replaced by something of your application's choosing. Or as another
example, when the user moves a window that uncovers your form the window
manager realizes that there is an update that needs to be made to the
form.

At the level of the API, the window manager sends a WM_PAINT message to a
window. At the managed code level, the window manager calls the OnPaint()
method of the form. It is there where you need to implement the bulk your
paint algorithm.

The other time to paint is when your application knows that its form needs
a new paint job. As Tomas has already pointed out, you can do that at any
time by calling CreateGraphics().

To simplify an application's code, sometimes only the first case is
actually implemented. To deal with application / user requested paints an
application can simply call the Invlidate() method of the Form class. This
causes the window manager to dispatch a WM_PAINT message natively or the
OnPaint() method on the .Net platform.

Of course, in your case, your application must keep track of all the
lines, ellipses etc that it needs to paint. The window manager can't
possibly do that.

In case you are new to this stuff, I've pasted the code to a managed
application that draws some text, a line and an ellipse. I'm not sure
posting it is wise because it is a little off the beaten path.

You see I am going to listen to Charles Petzold (
http://www.charlespetzold.com/ ) speak this week on the topic of whether
using the wizards in Visual Studio rots the mind. :) I've thought about
that in the past have been thinking about it more in advance of his talk.
So my little sample does WinForms in Managed C++ _without_ using _any_ of
the wizards in VS.

To do that, I choose to create an _empty_ WIN32 APPLICATION and then I set
the "Use Managed Extensions" option manually.

Regards,
Will

// Class implementation Po2.cpp

#include "po2.h"

void HelloWorld::Main()
{
Application::Run( new HelloWorld() );
}

HelloWorld::HelloWorld()
{
Text = "Hello, world!";
BackColor = Color::White;

penRed = new Pen(Color::Red);
penBlue = new Pen(Color::Blue);
}

void HelloWorld::OnPaint(PaintEventArgs *pea)
{
Graphics __gc *grfx = pea->Graphics;
Rectangle rc;

grfx->DrawString("Hello, World!", Font, Brushes::Black, 0, 0);

rc = get_ClientRectangle();
rc.Width -= 1;
rc.Height -= 1;

grfx->DrawLine(penRed, 0, 0, rc.Width, rc.Height);

grfx->DrawEllipse(penBlue, rc);
}

// Hack avoids including <windows.h>

int __stdcall WinMain(int, int, int, int)
{
HelloWorld::Main();
return 0;
}

// Class declaration po2.h

#using <System.dll>
#using <mscorlib.dll>
#using <System.Drawing.dll>
#using <System.Windows.Forms.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::ComponentModel;

public __gc class HelloWorld : public Form
{
private:

Pen __gc *penRed;
Pen __gc *penBlue;

public:

HelloWorld();
static void Main();

protected:

void OnPaint(PaintEventArgs __gc *);
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top