How to: set the width of a pen?

  • Thread starter Thread starter Boris Nienke
  • Start date Start date
B

Boris Nienke

hi,

currently i use:
Pen MyPen = new Pen(Color.Black);

But how to set the width of the pen? It's just 1 Pixel as default but i
like to have 2 or 3 Pixel width for simple drawings

any chance?

Boris
 
Unfortunately, you cannot set the width of the pen. Try using the
"FillRectangle" method of the graphics object.
 
Unfortunately, you cannot set the width of the pen. Try using the
"FillRectangle" method of the graphics object.

:'(

FillRectangle won't work because i need it for freehand-drawings - and a
rectangle can only be linear (horizontal, vertical)

Any other way around? Maybe with pinvoking something?

Boris
 
FillRectangle was the only way I could see to get around the missing width.
You could go through PInvoke to do your drawing, but it probably won't be
pretty.
 
FillRectangle was the only way I could see to get around the missing width.
You could go through PInvoke to do your drawing, but it probably won't be
pretty.

well... i doesn't need to be "pretty" :-)
i needs to WORK ;-)

Say you have two points and you like to draw a line between them. How to
use FillRectangle if these points are not on a horizontal or vertical line?
For example - diagonal?

or this one (X, Y)

Point1 = (10, 10)
Point2 = (35, 60)

Boris
 
It doesn't sound like, in this case, you can use FillRectangle efficiently.
Most of the time you can work around the missing width by using
FillRectangle, but in your case it doesn't sound like it will work. You
should look into PInvoke or maybe look into a "signature capture"-type
component (http://www.intelliprog.com/netcf/richink.html) to see if that can
do what you want.
 
At this point, you might grab a book on graphics programming and duplicate
what Microsoft is probably doing when they draw with a wider pen. Usually,
this involves creating a function which can generate each discrete point
along a path between two endpoints, in your case (10,10) and (35, 60). At
each point along the way, then, you do something that corresponds to drawing
at that point with a pen of the size you want. This might involve drawing a
circle there, or a rectangle, or some other closed and filled shape
representing the shape of the pen.

Paul T.
 
Hi,

I had the same problem. I was using PINVOKE but it was
slow. Now I use the FillPolygon-procedure of the Graphics-
Class.

private void DrawPolyline(Graphics g, Point[] P, int
Start, int cnt, int PenWidth)
{
Point[] px = new Point[(cnt-1)*4];

int i, j, pw;
double xx, yy;
double dx, dy;

pw = PenWidth / 2;
for(i = Start, j = 0; i < Start+cnt-1; i++, j++)
{
xx = P[i+1].X-P.X;
yy = P[i+1].Y-P.Y;

if((Math.Abs(xx) <= 5) && (Math.Abs(yy) <= 5))
{
// nichts machen, da der Punkt annähernd auf der
selben Stelle ist
}
if(xx == 0)
{
dx = pw;
dy = 0;
}
else
if(yy == 0)
{
dx = 0;
dy = pw;
}
else
{
dy = Math.Sqrt((double)(PenWidth*PenWidth) / (1+
((yy*yy)/(xx*xx))));
dx = Math.Sqrt((double)(PenWidth*PenWidth) -
(dy*dy));
dy /= 2;
dx /= 2;
}
if((xx == 0) && (yy == 0))
{
}
else
if((xx >= 0) && (yy >= 0))
{
dx = -dx;
dy = dy;
}
else
if((xx >= 0) && (yy < 0))
{
dx = dx;
dy = dy;
}
else
if((xx < 0) && (yy >= 0))
{
dx = -dx;
dy = -dy;
}
else
if((xx < 0) && (yy < 0))
{
dx = dx;
dy = -dy;
}

px[j*2].X = (int) (P.X - dx);
px[j*2].Y = (int) (P.Y - dy);
px[j*2+1].X = (int) (P[i+1].X - dx);
px[j*2+1].Y = (int) (P[i+1].Y - dy);
px[(px.Length-1)-j*2-1].X = (int) (P[i+1].X + dx);
px[(px.Length-1)-j*2-1].Y = (int) (P[i+1].Y + dy);
px[(px.Length-1)-j*2].X = (int) (P.X + dx);
px[(px.Length-1)-j*2].Y = (int) (P.Y + dy);
}
try
{
g.FillPolygon(brushLine, px);
else
g.DrawPolygon(penNV, px); // zu Debugzwecken
wird nur die Hülle gezeigt
g.FillEllipse(brushLine, P[Start].X-pw, P[Start].Y-
pw, PenWidth, PenWidth);
g.FillEllipse(brushLine, P[Start+cnt-1].X-pw, P
[Start+cnt-1].Y-pw, PenWidth, PenWidth);
}
catch
{
MsgBox.Show("Exception");
}
}
 
yes, sure :-)

well... i'm very surprised that nobody else had this problem yet. I mean,
it's a pocketPC with a stylus as interface between the machine and the
human. So i think it's the normal way to offer some place where the user
can draw/scribble something?
So i was surprised that there is a "Pen"-Object with a ".Color" but no
".Width" - strange! I think that's all possible using eVB or eVC isn't it?

Don't get me wrong - i will not blame the users of these group! You are all
very helpfull and would never have started with .Net without all of you.

But is it just me who wants to do "very special things" or is it the CF
which is much too limited?
I really thought that someone has found a solution or created a new
component or object which supports a bit more than just drawing lines of
1-pixel-width.

And: if MS is drawing with a wider pen, they use "Pen.Width = 3" (for
example) ;-) ...but of course not in .Net

So i'm still searching for a solution - opennetcf.org was down yesterday so
i will try to look there again today...

Boris
 
Hi,

once again. There was a click to much in my first post.

I have had the same problem. Now I'm using the
Graphics.FillPolygon method. I calculate the polygon for a
point-array (or a lot of line pices) by hand.

Look at the code-sample below.

My english isn't good, so I can't describe the function in
a proper way.

I will use my natural language instead.

Now in german.
Ich berechne für jedes Punktepaar den Abstand in X und Y-
Richtung. Danach berechne ich um welche Pixelzahl sich die
Eckpunkte des Polygons in X- und Y-Richtung verschieben
(Kleiner Tipp. Das Verhältnis dx/dy steht in direktem
Zusammenhang mit dem Verhältnis von XX/YY). Als letztes
sorge ich dafür das die Polygone nahtlos an einander
anfügen. Das Zeichnen der Ellipsen am Anfang und Ende
rundet das Ganze etwas ab. Für die besten Ergebnisse
zeichnet man jeden Linienabschnitt extra (damit am Anfang
und Ende die Ellipse gezeichnet wird), das kostet
allerdings ordentlich Rechenzeit.

Ich habe mir das Ganze ausgedacht, um eine halbwegs
anständig aussehende Linie in einer halbwegs verträglichen
Zeit zeichnen zu können. Für Verbesserungen oder einen
ganz anderen Weg bin ich dankbar.

Mark

*********************

private void DrawPolyline(Graphics g, Point[] P, int
Start, int cnt, int PenWidth)
{
Point[] px = new Point[(cnt-1)*4];

int i, j, pw;
double xx, yy;
double dx, dy;

pw = PenWidth / 2;
for(i = Start, j = 0; i < Start+cnt-1; i++, j++)
{
xx = P[i+1].X-P.X;
yy = P[i+1].Y-P.Y;

if((Math.Abs(xx) <= 5) && (Math.Abs(yy) <= 5))
{
// nichts machen, da der Punkt annähernd auf der
selben Stelle ist
}
if(xx == 0)
{
dx = pw;
dy = 0;
}
else
if(yy == 0)
{
dx = 0;
dy = pw;
}
else
{
dy = Math.Sqrt((double)(PenWidth*PenWidth) / (1+
((yy*yy)/(xx*xx))));
dx = Math.Sqrt((double)(PenWidth*PenWidth) -
(dy*dy));
dy /= 2;
dx /= 2;
}
if((xx == 0) && (yy == 0))
{
}
else
if((xx >= 0) && (yy >= 0))
{
dx = -dx;
dy = dy;
}
else
if((xx >= 0) && (yy < 0))
{
dx = dx;
dy = dy;
}
else
if((xx < 0) && (yy >= 0))
{
dx = -dx;
dy = -dy;
}
else
if((xx < 0) && (yy < 0))
{
dx = dx;
dy = -dy;
}

px[j*2].X = (int) (P.X - dx);
px[j*2].Y = (int) (P.Y - dy);
px[j*2+1].X = (int) (P[i+1].X - dx);
px[j*2+1].Y = (int) (P[i+1].Y - dy);
px[(px.Length-1)-j*2-1].X = (int) (P[i+1].X + dx);
px[(px.Length-1)-j*2-1].Y = (int) (P[i+1].Y + dy);
px[(px.Length-1)-j*2].X = (int) (P.X + dx);
px[(px.Length-1)-j*2].Y = (int) (P.Y + dy);
}
g.FillPolygon(brushLine, px);
g.FillEllipse(brushLine, P[Start].X-pw, P[Start].Y-
pw, PenWidth, PenWidth);
g.FillEllipse(brushLine, P[Start+cnt-1].X-pw, P
[Start+cnt-1].Y-pw, PenWidth, PenWidth);
}


**************************
 
Hello,

thank you for this code - i will try it when i'm back home.

You say, that this code is faster then using "native" functions with
PInvoke? strange.

I will see if it is fast enough...

Maybe i have to switch to GAPI or something... will see

Boris

Hi,

once again. There was a click to much in my first post.

I have had the same problem. Now I'm using the
Graphics.FillPolygon method. I calculate the polygon for a
point-array (or a lot of line pices) by hand.

Look at the code-sample below.

My english isn't good, so I can't describe the function in
a proper way.

I will use my natural language instead.

Now in german.
Ich berechne für jedes Punktepaar den Abstand in X und Y-
Richtung. Danach berechne ich um welche Pixelzahl sich die
Eckpunkte des Polygons in X- und Y-Richtung verschieben
(Kleiner Tipp. Das Verhältnis dx/dy steht in direktem
Zusammenhang mit dem Verhältnis von XX/YY). Als letztes
sorge ich dafür das die Polygone nahtlos an einander
anfügen. Das Zeichnen der Ellipsen am Anfang und Ende
rundet das Ganze etwas ab. Für die besten Ergebnisse
zeichnet man jeden Linienabschnitt extra (damit am Anfang
und Ende die Ellipse gezeichnet wird), das kostet
allerdings ordentlich Rechenzeit.

Ich habe mir das Ganze ausgedacht, um eine halbwegs
anständig aussehende Linie in einer halbwegs verträglichen
Zeit zeichnen zu können. Für Verbesserungen oder einen
ganz anderen Weg bin ich dankbar.

Mark

*********************

private void DrawPolyline(Graphics g, Point[] P, int
Start, int cnt, int PenWidth)
{
Point[] px = new Point[(cnt-1)*4];

int i, j, pw;
double xx, yy;
double dx, dy;

pw = PenWidth / 2;
for(i = Start, j = 0; i < Start+cnt-1; i++, j++)
{
xx = P[i+1].X-P.X;
yy = P[i+1].Y-P.Y;

if((Math.Abs(xx) <= 5) && (Math.Abs(yy) <= 5))
{
// nichts machen, da der Punkt annähernd auf der
selben Stelle ist
}
if(xx == 0)
{
dx = pw;
dy = 0;
}
else
if(yy == 0)
{
dx = 0;
dy = pw;
}
else
{
dy = Math.Sqrt((double)(PenWidth*PenWidth) / (1+
((yy*yy)/(xx*xx))));
dx = Math.Sqrt((double)(PenWidth*PenWidth) -
(dy*dy));
dy /= 2;
dx /= 2;
}
if((xx == 0) && (yy == 0))
{
}
else
if((xx >= 0) && (yy >= 0))
{
dx = -dx;
dy = dy;
}
else
if((xx >= 0) && (yy < 0))
{
dx = dx;
dy = dy;
}
else
if((xx < 0) && (yy >= 0))
{
dx = -dx;
dy = -dy;
}
else
if((xx < 0) && (yy < 0))
{
dx = dx;
dy = -dy;
}

px[j*2].X = (int) (P.X - dx);
px[j*2].Y = (int) (P.Y - dy);
px[j*2+1].X = (int) (P[i+1].X - dx);
px[j*2+1].Y = (int) (P[i+1].Y - dy);
px[(px.Length-1)-j*2-1].X = (int) (P[i+1].X + dx);
px[(px.Length-1)-j*2-1].Y = (int) (P[i+1].Y + dy);
px[(px.Length-1)-j*2].X = (int) (P.X + dx);
px[(px.Length-1)-j*2].Y = (int) (P.Y + dy);
}
g.FillPolygon(brushLine, px);
g.FillEllipse(brushLine, P[Start].X-pw, P[Start].Y-
pw, PenWidth, PenWidth);
g.FillEllipse(brushLine, P[Start+cnt-1].X-pw, P
[Start+cnt-1].Y-pw, PenWidth, PenWidth);
}


**************************

-----Original Message-----
hi,

currently i use:
Pen MyPen = new Pen(Color.Black);

But how to set the width of the pen? It's just 1 Pixel as default but i
like to have 2 or 3 Pixel width for simple drawings

any chance?

Boris
.
 
I've had the same problem and have gotten around it by
doing the following.

To draw a line with the width of 2 pixels, you draw 3
lines. The first line you draw the normal coodinates, then
2nd adding 1 to each Y coordinate, and the 3rd you add 1
to each X coordinates. Here is an example:

DrawLine(New Pen(Color.black), lastPoint.X, lastPoint.Y,
X, Y)
DrawLine(New Pen(Color.black), lastPoint.X, lastPoint.Y+1,
X, Y+1)
DrawLine(New Pen(Color.black), lastPoint.X+1,lastPoint.Y,
X+1, Y)
 
Yes it does seem a bit dim

It is one of the ways that .NET CF was made smaller somtimes I think the
functionality taken away
was not really though about. Normally they just take away superflous
functionality so that there is a way
to do what you want but you may have to go the long way. Unfortunately this
removing functionality is crippling
and having to resort to PInvoke raises portability issues.

I personally draw several lines around my centre line to make it thicker

eg

Draw(x,y,x1,y1)
Draw(x+1,y,x1+1,y1)

or

Draw(x,y,x1,y1)
Draw(x,y+1,x1,y1+1)

Which one I use I am still refining depending on the difference on x,y and
x1,y1

I too have been workig on this sort of application. I can't use the RichInk
control as it does not seem to be creatable
on my client's Toshiba e570. ie the code works on my iPAQs 3660 and h5550
but not on his machine.

How do you do you capture and redraw - mine seems a bit clunky and the
writing is a bit angular - I may have to resort
to splines to get a smoother image.

Maybe a new version of the framework will have this functionality but I
wouldn't expect it soon.
 
Answere inline:

Yes it does seem a bit dim

absolutely - and this is not the only one... i'm hardly "impressed" about
the limited BASIC-functions of such a modern concept.
Unfortunately this removing functionality is crippling
and having to resort to PInvoke raises portability issues.

yes. And even if you don't use PInvokes, you will get applications which
are working different.
Take the "DateTimeEdit" for example. This is a windows-common-control for
years (if not decades) but not available in .Net (yes - now there's one
available from MS - but it is a good example). Now what happens?
One developer will use a standard Edit and use Convert to get a date.
An other will code it's own Date-Edit with a popup-calender
An other will code it's own Date-Edit with a better Popup-Calender but
without Time-Edit
etc.

now the client will install 2 .Net applications and has to use TRHEE
different styles to enter a Date:
1. in PocketOutlook and EVERY OTHER native PocketPC Application
2. two (or more) different styles in .Net Apps

I don't think that this is the modern way of building applications. And the
client will not understand nor accept this, because the PocketPC device is
then switched from a smart device to a complex device where you have to
think bevor entering data...
I personally draw several lines around my centre line to make it thicker

Well this may work in some cases - i will try this too. The Problem: it is
getting slower with each line.

do you have problems with gaps between some lines if you draw a thicker
line? And how to make sure that it is always - for example - 5 pixels wide?
(in every angle)
How do you do you capture and redraw - mine seems a bit clunky and the
writing is a bit angular - I may have to resort
to splines to get a smoother image.

splines would be nice - havn't looked if they are available in .NET :-( ...
and: when using splines - how to draw them 2 or 4 pixels wide?

currently i'm using a PaintBox to capture MouseDown/-Move/-Up events. In
these events i save the mouse-position and draw lines between the last and
the current position (and a single Pixel in the MouseDown event to be able
to draw single taps as points)

This works good on my ipaq2210 but of course could be faster and better (i
really like to have antialiasing and such things. So i really think about
switching to GAPI or something (i think i've read something about a .Net
wrapper for it)
Maybe a new version of the framework will have this functionality but I
wouldn't expect it soon.

i really don't expect this in near future because this would destroy the
whole concept. Think what would happen:
- there are devices with .Net Version 1 build in
- You are developing for Version 2
- Now what happens? The client cannot simple download and use your
application! Either you have to deploy the whole Version 2 of .Net (big
download) or the client has to search (and know!) him/herself where to get
the new CF and how to install it - and it will consume rare memory of the
device...
- and as far as i understand it should be compatible to Version 1 - but
will it really? This is a risk of the client he propably likes to be
aware... and then switches to an other product (not .Net?) which works good
and maybe has the same features ;)

I really have mixed emotions about .Net (especially the CF)... it's nice to
code and you can reuse code for the desktop. The software is running on
PocketPC2002 and 2003 (and 2000 too i think) and CE4 devices ....
But as soon as you have to use PInvokes to get the features you need it may
be the better way to use eVB or eVC directly :-( (both i find horroble ;-)
)

Boris
 
In many cases, the client doesn't care about having a standard format for
date/time picking, but he really wants to deploy his solution *now*. If the
capabilities of the .NET CF allow the application, even though it's not
'standard', to be released three months, say, early, I don't know of many
people who would prefer to wait for a more standardized C++ application.
Maybe, if you are selling a commercial application, like Word or Excel or
something (although you may have noticed that Office *frequently* has a
different user interface than every other desktop application out there), it
would be a big deal. Most customers that I deal with are concerned about
results, not with whether the code is 'good' or 'right'. If .NET CF
development isn't faster, then use C++ and you'll have access to whatever
Windows CE supports...

Paul T.
 
Back
Top