422,026 Members | 1,154 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 422,026 IT Pros & Developers. It's quick & easy.

Drawing xor line on picture box. HELP!

P: n/a
Hi,
Please help me, how I can make a line drawing on PictureBox similar to
MS paint. I thinking about this: click and hold button, move mouse and
relase button.

I'm trying useing this g.DrawLine(..), but I have a lot of line.

In C++ is a parameter XORPUT, but in C# I can't find it.
Maciek
Jun 27 '08 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Wed, 07 May 2008 13:14:11 -0700, Macias <ma************@gmail.com>
wrote:
Please help me, how I can make a line drawing on PictureBox similar to
MS paint. I thinking about this: click and hold button, move mouse and
relase button.

I'm trying useing this g.DrawLine(..), but I have a lot of line.

In C++ is a parameter XORPUT, but in C# I can't find it.
..NET has essentially implicitly deprecated XOR drawing. The only drawing
modes (Graphics.CompositingMode) are "copy" and "blend". This appears to
be basically inherited from GDI+, which as near as I can tell has the same
limitation.

If you really need XOR, you'll have to use p/invoke to use GDI directly on
a DC you get from your Graphics instance. However, my experience has been
that XOR drawing isn't actually needed. The usual reason for using XOR
was to avoid having to redraw large portions of your window; rather than
invalidating and redrawing, you could just XOR a line, then XOR again to
erase it.

But computers are MUCH faster these days and with double-buffered
windows/controls the most expensive graphical operation would happen even
if you're XORing. Done properly it's usually plenty fast to invalidate an
area that's changed and draw it again from scratch.

If you have a concise-but-complete example of code now that's not
performing as you'd like while trying to draw lines without XOR, and you
post that concise-but-complete example here, then we can try to help find
ways to improve that code in a purely .NET way. It's not impossible to
delegate the drawing to GDI via p/invoke, but it's probably more trouble
than you really need to go to. You're probably better off getting advice
on "the .NET way". :)

Pete
Jun 27 '08 #2

P: n/a
I make drawing like this:

private void pb_MouseMove(object sender, MouseEventArgs e)
{
Point CurentCoord = new Point(e.X, e.Y);
if (md)
{

using (Graphics g = Graphics.FromImage(img))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality =
CompositingQuality.HighSpeed;
Rectangle rect = this.ClientRectangle;
using (Pen p = new Pen(ColorBox.BackColor, 2))
{
g.DrawLine(p, ClickCoord, CurentCoord);
pb.Image = img;
}
}
}

but still I've a lot of lines when I moveing mouse. But I want to have
only one.
Please correct my pice of program.

Maciek

On 7 Maj, 22:58, "Peter Duniho" <NpOeStPe...@nnowslpianmk.comwrote:
On Wed, 07 May 2008 13:14:11 -0700, Macias <maciej.bojc...@gmail.com>
wrote:
Please help me, how I can make a line drawing on PictureBox similar to
MS paint. I thinking about this: click and hold button, move mouse and
relase button.
I'm trying useing this g.DrawLine(..), but I have a lot of line.
In C++ is a parameter XORPUT, but in C# I can't find it.

.NET has essentially implicitly deprecated XOR drawing. The only drawing
modes (Graphics.CompositingMode) are "copy" and "blend". This appears to
be basically inherited from GDI+, which as near as I can tell has the same
limitation.

If you really need XOR, you'll have to use p/invoke to use GDI directly on
a DC you get from your Graphics instance. However, my experience has been
that XOR drawing isn't actually needed. The usual reason for using XOR
was to avoid having to redraw large portions of your window; rather than
invalidating and redrawing, you could just XOR a line, then XOR again to
erase it.
But computers are MUCH faster these days and with double-buffered
windows/controls the most expensive graphical operation would happen even
if you're XORing. Done properly it's usually plenty fast to invalidate an
area that's changed and draw it again from scratch.

If you have a concise-but-complete example of code now that's not
performing as you'd like while trying to draw lines without XOR, and you
post that concise-but-complete example here, then we can try to help find
ways to improve that code in a purely .NET way. It's not impossible to
delegate the drawing to GDI via p/invoke, but it's probably more trouble
than you really need to go to. You're probably better off getting advice
on "the .NET way". :)

Pete
Jun 27 '08 #3

P: n/a
On Wed, 07 May 2008 14:36:31 -0700, Macias <ma************@gmail.com
wrote:
I make drawing like this:

private void pb_MouseMove(object sender, MouseEventArgs e)
{
Point CurentCoord = new Point(e.X, e.Y);
if (md)
{

using (Graphics g = Graphics.FromImage(img))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality =
CompositingQuality.HighSpeed;
Rectangle rect = this.ClientRectangle;
using (Pen p = new Pen(ColorBox.BackColor, 2))
{
g.DrawLine(p, ClickCoord, CurentCoord);
pb.Image = img;
}
}
}

but still I've a lot of lines when I moveing mouse. But I want to have
only one.
Please correct my pice of program.
What is the precise reason for using a PictureBox to contain the image?
Are you sure you really need that? Or would it suffice to override
OnPaint() in your form or a custom control class? I ask, because the use
of the PictureBox is going to necessarily impose additional overhead on
the redrawing.

The basic issue you've got is that you've apparently started with a given
Image instance, and to that you want to add a line. However, since you're
adding a new line every time the mouse moves, you get a lot of lines,
instead of just the one for the most recent mouse position.

One of the simplest approaches I see based on the code you posted would be
to not draw into the original Image, but rather create a new one:

private void pb_MouseMove(object sender, MouseEventArgs e)
{
Point CurentCoord = new Point(e.X, e.Y);
if (md)
{
Image imgT = new Bitmap(img);

using (Graphics g = Graphics.FromImage(imgT))
{
g.CompositingMode = CompositingMode.SourceOver;
g.CompositingQuality =
CompositingQuality.HighSpeed;
Rectangle rect = this.ClientRectangle;
using (Pen p = new Pen(ColorBox.BackColor, 2))
{
g.DrawLine(p, ClickCoord, CurentCoord);
pb.Image = imgT;
}
}
}

Optionally (and most likely) in the MouseUp event you'd replace the "img"
reference with the Image currently in the PictureBox.

This is far from an ideal solution though. It can get very expensive to
be creating a new bitmap every time the mouse moves. I haven't use the
PictureBox control much; it's possible you could create one temporary
image that you repeatedly copy your original image into, and then reassign
that to the PictureBox.Image property. That would at least avoid the
constant instantiation of Bitmaps, but you'd still have a little extra
overhead every time you copy the original image into the temporary image..

It would be much better if you weren't using the PictureBox, but instead
were drawing the Image directly yourself in the appropriate place (form or
custom control). This way you could simply draw both the base Image and
then the line each time the OnPaint() method was called. You'd still
override OnMouseMove() but the only thing you'd do there is update your
line coordinates and invalidate the area of the form or control containing
the old position of the line and the new position of the line.

This way, rather than creating new bitmaps every time the mouse moves, all
you have to do is redraw the relevant area based on the current mouse
position.

Without knowing more about the specific goal you have for your program,
it's hard to offer more detailed advice than the above. Hopefully that
gets you going in the right direction.

Pete
Jun 27 '08 #4

P: n/a
On May 7, 3:14 pm, Macias <maciej.bojc...@gmail.comwrote:
Hi,
Please help me, how I can make a line drawing on PictureBox similar to
MS paint. I thinking about this: click and hold button, move mouse and
relase button.

I'm trying useing this g.DrawLine(..), but I have a lot of line.

In C++ is a parameter XORPUT, but in C# I can't find it.

Maciek
Have you looked at the ControlPaint.DrawReversibleLine method?
Perhaps that will do what you need.

Chris
Jun 27 '08 #5

P: n/a
On Thu, 08 May 2008 07:02:12 -0700, Chris Dunaway <du******@gmail.com>
wrote:
Have you looked at the ControlPaint.DrawReversibleLine method?
Perhaps that will do what you need.
Interesting...I've never seen that class before.

I'm a bit confused though; maybe you can elaborate on the purpose of that
class. All of the examples that I looked at in the class documentation
show using the class to draw directly in a non-painting event handler.
Normally this would be a major no-no, since drawing done in that context
isn't persistent.

So then I thought "well, maybe this is some special kind of drawing the
ControlPaint class internally persists somehow". But then I see the
methods take a Graphics instance just like other drawing methods, and that
seems to suggest ControlPaint's not doing anything other than adding some
new features to Graphics (in fact, I suppose they might have been
extension methods had extension methods been around when ControlPaint was
designed).

Are the examples bogus? Or is there something more to ControlPaint than
just adding some extra ways to draw to a Graphics instance?

(Yeah, I could use Reflector and look myself, but I don't have Windows
running at the moment and I figure it'd be better to ask someone who might
have more practical experience with the class anyway).

Pete
Jun 27 '08 #6

This discussion thread is closed

Replies have been disabled for this discussion.