ws1999
asked on
another region problem as Zoom in and out
previous day i have asked question about region , now another question confused me too about region.
i use paintbox to draw an image on, and i specify some region of this image, i also create a zoomin and zoomout procedure to make the image large and small for more clear operation. but meantime i hope the region that i specified before can also be zoomin and out according to the size of image. but i really don't know whether there is some possible way to do this.
ws1999
i use paintbox to draw an image on, and i specify some region of this image, i also create a zoomin and zoomout procedure to make the image large and small for more clear operation. but meantime i hope the region that i specified before can also be zoomin and out according to the size of image. but i really don't know whether there is some possible way to do this.
ws1999
hello again ws1999, I don't think there are any windows region functions to expand a region (or shrink one). You may condider creating a "Mask" 1bit bitmap from the region (FillRgn or PainTRgn) and the expanding that bitmap and then getting a region from that Mask. Do you use alot of graphic operations (FillRgn, FrameRgn)) with the region, or do you mostly use it for clipping, to prevent drawing outside the region?
ASKER
yes, i use most of the FrameRgn to outline the region, for me the definition of region is most important.
ws1999
ws1999
ASKER
the mask function i still not quite clear, when make mask, it black the whole image, i don't know what that mean?
there might be other ways to do that kind of painting, maybe with a path, you might read the API help index "Paths" and "Path functions". U said somethig about the regions were generated by the user. How do they generate them? with CreatePolygonRgn or by using the mouse to draw on a paintbox? The reason I ask is that you can generate ALOT more different types of paths (with LineTo, Arc, Chord, Pie, PolyPolygon, PolyBezier, TextOut and others) and use StrokePath( ) to outline the path. AND you can convert a path to a region.
A mask is a 2 color black and white 1bit bitmap. (it can be a 24bit also but it is only black and white). The White area is the section OUTSIDE the region, and the Black area represents the section INSIDE the region. If you have a 200x200 white bitmap and you have a region smaller than 200x200. You call FillRgn on the white bitmap with a black brush and the black area represents the shape of the region. One reason it's called a Mask, because in windows Icons there are 2 bitmaps, a piture bitmap and a Mask (2 color) bitmap, the transparent area of an Icon comes from the Mask. It masks where the Icon image can be painted on the hDC. You might look at API Help index "MaskBlt". it used a mask to prevent drawing on a hDC. There is a procedure in that Make a region app of mine that will make a black and white bitmap into a region.
ASKER
i want the user to draw themseleves on the canvas to make a region.
Ok, i would learn about the path.
Is there any path demo from your side?
Thanks
Ok, i would learn about the path.
Is there any path demo from your side?
Thanks
I have something with a BeginPath, but it is not so simple. I still do not have a grip on what you are trying to get as a result of user input. You say "i want the user to draw themseleves on the canvas to make a region." Why? Are you just going to frame the region? It might help me to suggest something if I had an idea about the result you want to present the user. I don't think many would say that Delphi VCL is real good for Graphics editing. It does simplify many hDC drawing tasks. But you are stepping outside the VCL with regions. Paths are also windows API, and have many parametrs. I will try and find something for paths.
ASKER
the software i made is a color design software, different part has a different color, so the user decide which part the color can be changed,after they frame the region, in another program they can click the different part so has a color combination to see whether the combination is harmony. That's all, all these are designed by delphi.
ws1999
ws1999
does the user draw these different parts? or are they squares or polygons? How many different parts can there be less than 10, less than 100, less than 1000?
ASKER
yeah, the user draw the parts, the shape can be any shape, any number,
OK, I considered what you have said you wanted and Here is some code that that might do some of what you have described so far, It uses a complex variable array, and saves the bitmap and arry of points to a file. It can open the file and show the bitmap and outlines of the figures you drew before. This is a Form with a TPaintBox, a TOpenPictureDilog, an TOpenDialog, a TSaveDialog and 2 buttons
private
{ Private declarations }
PntCount, PntAmt, Areas, FigNum: Word;
Drawing: Boolean;
PathBmp: TBitmap;
FigureArray: Array of Array of TPoint;
procedure TForm1.FormCreate(Sender: TObject);
begin
PathBmp := TBitmap.Create;
PathBmp.Width := PaintBox1.Width;
PathBmp.Height := PaintBox1.Height;
PathBmp.Canvas.Font.Name := 'Arial';
PathBmp.Canvas.Font.Size := 20;
PathBmp.Canvas.TextOut(10, 80,'No Image Yet');
Drawing := False;
FigNum := 0;
SetLength(FigureArray,2);
end;
procedure TForm1.PaintBox2Paint(Send er: TObject);
begin
PaintBox1.Canvas.Draw(0,0, PathBmp);
end;
procedure TForm1.butGetImageClick(Se nder: TObject);
begin
{this button opens an Image Open Dialog to pick a bitmap}
OpenPictureDialog1.Filter := 'Bitmap (*.bmp)|*.bmp';
OpenPictureDialog1.FilterI ndex := 0;
if OpenPictureDialog1.Execute then
begin
PathBmp.LoadFromFile(OpenP ictureDial og1.FileNa me);
{set PaintBox1 to width and height of PBoxBmp}
if PathBmp.Height < 433 then
PaintBox1.Height := PathBmp.Height else
PaintBox1.Height := 433;
if PathBmp.Width < 521 then
PaintBox1.Width := PathBmp.Width else
PaintBox1.Width := 521;
PaintBox1.Refresh;
end;
end;
procedure TForm1.PaintBox2MouseDown( Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
PaintBox1.Canvas.MoveTo(X, Y);
StartX := X;
StartY := Y;
SetLength(FigureArray,FigN um+1);
PntAmt := 128;
PntCount := 1;
SetLength(FigureArray[FigN um],PntAmt );
FigureArray[FigNum,0] := Point(X,Y);
end;
procedure TForm1.PaintBox2MouseMove( Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if Drawing then
begin
PaintBox1.Canvas.LineTo(X, Y);
FigureArray[FigNum,PntCoun t].x := X;
FigureArray[FigNum, PntCount].y := Y;
Inc(PntCount);
if PntCount > PntAmt-3 then
begin
PntAmt := PntAmt+128;
SetLength(FigureArray[FigN um],PntAmt );
end;
end;
end;
procedure TForm1.PaintBox2MouseUp(Se nder: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
nSize, i: Integer;
begin
Drawing := False;
PaintBox1.Canvas.LineTo(St artX,Start Y);
FigureArray[FigNum,PntCoun t].x := StartX;
FigureArray[FigNum, PntCount].y := StartY;
SetLength(FigureArray[FigN um],PntCou nt+1);
{below this line is just a test of the FigureArray
and should not be in an app}
PaintBox2.Canvas.Draw(0,0, PathBmp);
PaintBox2.Canvas.Pen.Color := clRed;
PaintBox2.Canvas.Pen.Width := 3;
for i := 0 to FigNum do
PaintBox2.Canvas.Polyline( FigureArra y[i]);
PaintBox2.Canvas.Pen.Color := clBlack;
PaintBox2.Canvas.Pen.Width := 1;
Inc(FigNum);
end;
procedure TForm1.sbut_PntsToFileClic k(Sender: TObject);
var
PntFileStm: TFileStream;
i: Integer;
Num, Areas: Word;
begin
with SaveDialog1 do
begin
DefaultExt := '';
FileName := 'PntsPic1.pbmp';
Filter := 'PntsPic .pbmp|*.pbmp|All Files|*.*';
FilterIndex := 0;
end;
if SaveDialog1.Execute then
begin
Areas := Length(FigureArray);
PntFileStm := TFileStream.Create(SaveDia log1.FileN ame, fmCreate or fmShareDenyWrite);
{a FileStream is a way to write many thing to one file}
Num := 22134;
{it is good to have a file type idenitier, I use 22134, if this is
a file that was not made by this app, then it would not have this ID number}
PntFileStm.Write(Num,SizeO f(Word));
{each write to a file stream advances the file pointer to the end of write}
PntFileStm.Write(Areas,Siz eOf(Areas) );
for i := 0 to Areas-1 do
begin
Num := Length(FigureArray[i]);
{get the length of the Array so you can set length on Read}
PntFileStm.Write(Num,SizeO f(Num));
PntFileStm.Write(FigureArr ay[i],Size Of(FigureA rray[i]));
{unless you know the length of this array it is useless}
end;
PathBmp.SaveToStream(PntFi leStm);
PntFileStm.Free;
end;
end;
procedure TForm1.sbut_ReadFileClick( Sender: TObject);
var
PntFileStm: TFileStream;
i: Integer;
Amt, Num: Word;
begin
with OpenDialog1 do
begin
DefaultExt := '';
FileName := '';
Filter := 'PntsPic .pbmp|*.pbmp|All Files|*.*';
FilterIndex := 0;
end;
if OpenDialog1.Execute then
begin
PntFileStm := TFileStream.Create(OpenDia log1.FileN ame, fmOpenRead or fmShareDenyWrite);
if PntFileStm.Size > 6 then
begin
PntFileStm.Read(Num,SizeOf (Num));
{check for 22134, if you read a file not made by this app you will get
bad reads}
if Num = 22134 then
begin
PntFileStm.Read(Amt,SizeOf (Amt));
SetLength(FigureArray,Amt) ;
for i := 0 to Amt-1 do
begin
PntFileStm.Read(Num,SizeOf (Num));
SetLength(FigureArray[i], Num);
PntFileStm.Read(FigureArra y[i],SizeO f(FigureAr ray[i]));
end;
PathBmp.LoadFromStream(Pnt FileStm);
PntFileStm.Free;
{below this line is a test of the file read and should not be in an app}
PaintBox1.Canvas.Draw(0,0, PathBmp);
PaintBox2.Canvas.Pen.Color := clRed;
PaintBox2.Canvas.Pen.Width := 3;
for i := 0 to Length(FigureArray)-1 do
PaintBox2.Canvas.Polyline( FigureArra y[i]);
PaintBox2.Canvas.Pen.Color := clBlack;
PaintBox2.Canvas.Pen.Width := 1;
end else
ShowMessage('This is an Invalid .pbmp file');
end;
end;
- - - - - - - - - - - - - - - - - - - - - - - - - - -
you can use FigureArray[2] to draw just the third figure with
PolyLine(FigureArray[2]). Try this out and let me know if it is like what you want.
private
{ Private declarations }
PntCount, PntAmt, Areas, FigNum: Word;
Drawing: Boolean;
PathBmp: TBitmap;
FigureArray: Array of Array of TPoint;
procedure TForm1.FormCreate(Sender: TObject);
begin
PathBmp := TBitmap.Create;
PathBmp.Width := PaintBox1.Width;
PathBmp.Height := PaintBox1.Height;
PathBmp.Canvas.Font.Name := 'Arial';
PathBmp.Canvas.Font.Size := 20;
PathBmp.Canvas.TextOut(10,
Drawing := False;
FigNum := 0;
SetLength(FigureArray,2);
end;
procedure TForm1.PaintBox2Paint(Send
begin
PaintBox1.Canvas.Draw(0,0,
end;
procedure TForm1.butGetImageClick(Se
begin
{this button opens an Image Open Dialog to pick a bitmap}
OpenPictureDialog1.Filter := 'Bitmap (*.bmp)|*.bmp';
OpenPictureDialog1.FilterI
if OpenPictureDialog1.Execute
begin
PathBmp.LoadFromFile(OpenP
{set PaintBox1 to width and height of PBoxBmp}
if PathBmp.Height < 433 then
PaintBox1.Height := PathBmp.Height else
PaintBox1.Height := 433;
if PathBmp.Width < 521 then
PaintBox1.Width := PathBmp.Width else
PaintBox1.Width := 521;
PaintBox1.Refresh;
end;
end;
procedure TForm1.PaintBox2MouseDown(
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
PaintBox1.Canvas.MoveTo(X,
StartX := X;
StartY := Y;
SetLength(FigureArray,FigN
PntAmt := 128;
PntCount := 1;
SetLength(FigureArray[FigN
FigureArray[FigNum,0] := Point(X,Y);
end;
procedure TForm1.PaintBox2MouseMove(
Y: Integer);
begin
if Drawing then
begin
PaintBox1.Canvas.LineTo(X,
FigureArray[FigNum,PntCoun
FigureArray[FigNum, PntCount].y := Y;
Inc(PntCount);
if PntCount > PntAmt-3 then
begin
PntAmt := PntAmt+128;
SetLength(FigureArray[FigN
end;
end;
end;
procedure TForm1.PaintBox2MouseUp(Se
Shift: TShiftState; X, Y: Integer);
var
nSize, i: Integer;
begin
Drawing := False;
PaintBox1.Canvas.LineTo(St
FigureArray[FigNum,PntCoun
FigureArray[FigNum, PntCount].y := StartY;
SetLength(FigureArray[FigN
{below this line is just a test of the FigureArray
and should not be in an app}
PaintBox2.Canvas.Draw(0,0,
PaintBox2.Canvas.Pen.Color
PaintBox2.Canvas.Pen.Width
for i := 0 to FigNum do
PaintBox2.Canvas.Polyline(
PaintBox2.Canvas.Pen.Color
PaintBox2.Canvas.Pen.Width
Inc(FigNum);
end;
procedure TForm1.sbut_PntsToFileClic
var
PntFileStm: TFileStream;
i: Integer;
Num, Areas: Word;
begin
with SaveDialog1 do
begin
DefaultExt := '';
FileName := 'PntsPic1.pbmp';
Filter := 'PntsPic .pbmp|*.pbmp|All Files|*.*';
FilterIndex := 0;
end;
if SaveDialog1.Execute then
begin
Areas := Length(FigureArray);
PntFileStm := TFileStream.Create(SaveDia
{a FileStream is a way to write many thing to one file}
Num := 22134;
{it is good to have a file type idenitier, I use 22134, if this is
a file that was not made by this app, then it would not have this ID number}
PntFileStm.Write(Num,SizeO
{each write to a file stream advances the file pointer to the end of write}
PntFileStm.Write(Areas,Siz
for i := 0 to Areas-1 do
begin
Num := Length(FigureArray[i]);
{get the length of the Array so you can set length on Read}
PntFileStm.Write(Num,SizeO
PntFileStm.Write(FigureArr
{unless you know the length of this array it is useless}
end;
PathBmp.SaveToStream(PntFi
PntFileStm.Free;
end;
end;
procedure TForm1.sbut_ReadFileClick(
var
PntFileStm: TFileStream;
i: Integer;
Amt, Num: Word;
begin
with OpenDialog1 do
begin
DefaultExt := '';
FileName := '';
Filter := 'PntsPic .pbmp|*.pbmp|All Files|*.*';
FilterIndex := 0;
end;
if OpenDialog1.Execute then
begin
PntFileStm := TFileStream.Create(OpenDia
if PntFileStm.Size > 6 then
begin
PntFileStm.Read(Num,SizeOf
{check for 22134, if you read a file not made by this app you will get
bad reads}
if Num = 22134 then
begin
PntFileStm.Read(Amt,SizeOf
SetLength(FigureArray,Amt)
for i := 0 to Amt-1 do
begin
PntFileStm.Read(Num,SizeOf
SetLength(FigureArray[i], Num);
PntFileStm.Read(FigureArra
end;
PathBmp.LoadFromStream(Pnt
PntFileStm.Free;
{below this line is a test of the file read and should not be in an app}
PaintBox1.Canvas.Draw(0,0,
PaintBox2.Canvas.Pen.Color
PaintBox2.Canvas.Pen.Width
for i := 0 to Length(FigureArray)-1 do
PaintBox2.Canvas.Polyline(
PaintBox2.Canvas.Pen.Color
PaintBox2.Canvas.Pen.Width
end else
ShowMessage('This is an Invalid .pbmp file');
end;
end;
- - - - - - - - - - - - - - - - - - - - - - - - - - -
you can use FigureArray[2] to draw just the third figure with
PolyLine(FigureArray[2]). Try this out and let me know if it is like what you want.
ASKER
yes, slick812,that is just what i want, and i have succeed,
before the points awarded to you , i have another small question about region(sorry i have to save my poor points :-) ).
i write the following code:
region_old := region_now;
CombineRgn(region_now,regi on_now,reg ion2,RGN_O R);
i mean to save the old region data, before the combine.
i think after the combine the region_now should be different from the region_old.
but i found whatever i do the region_old always keep the same with the region_now(it has been changed) ,i use the equalRgn function to test, and they are really the same, what's the reason, how can i save the old region data?
thanks
before the points awarded to you , i have another small question about region(sorry i have to save my poor points :-) ).
i write the following code:
region_old := region_now;
CombineRgn(region_now,regi
i mean to save the old region data, before the combine.
i think after the combine the region_now should be different from the region_old.
but i found whatever i do the region_old always keep the same with the region_now(it has been changed) ,i use the equalRgn function to test, and they are really the same, what's the reason, how can i save the old region data?
thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
thanks slick812