Link to home
Start Free TrialLog in
Avatar of ws1999
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
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

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?
Avatar of ws1999
ws1999

ASKER

yes, i use most of the FrameRgn to outline the region, for me the definition of region is most important.

ws1999
Avatar of 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.
Avatar of ws1999

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

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.
Avatar of ws1999

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
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?
Avatar of ws1999

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(Sender: TObject);
begin
PaintBox1.Canvas.Draw(0,0, PathBmp);
end;

procedure TForm1.butGetImageClick(Sender: TObject);
begin
{this button opens an Image Open Dialog to pick a bitmap}
OpenPictureDialog1.Filter := 'Bitmap (*.bmp)|*.bmp';
OpenPictureDialog1.FilterIndex := 0;
if OpenPictureDialog1.Execute then
  begin
  PathBmp.LoadFromFile(OpenPictureDialog1.FileName);
  {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,FigNum+1);
PntAmt := 128;
PntCount := 1;
SetLength(FigureArray[FigNum],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,PntCount].x := X;
  FigureArray[FigNum, PntCount].y := Y;
  Inc(PntCount);
  if PntCount > PntAmt-3 then
    begin
    PntAmt := PntAmt+128;
    SetLength(FigureArray[FigNum],PntAmt);
    end;
  end;
end;

procedure TForm1.PaintBox2MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
nSize, i: Integer;
begin
Drawing := False;
PaintBox1.Canvas.LineTo(StartX,StartY);
FigureArray[FigNum,PntCount].x := StartX;
FigureArray[FigNum, PntCount].y := StartY;
SetLength(FigureArray[FigNum],PntCount+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(FigureArray[i]);
PaintBox2.Canvas.Pen.Color := clBlack;
PaintBox2.Canvas.Pen.Width := 1;
Inc(FigNum);

end;

procedure TForm1.sbut_PntsToFileClick(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(SaveDialog1.FileName, 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,SizeOf(Word));
{each write to a file stream advances the file pointer to the end of write}
  PntFileStm.Write(Areas,SizeOf(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,SizeOf(Num));
  PntFileStm.Write(FigureArray[i],SizeOf(FigureArray[i]));
{unless you know the length of this array it is useless}
  end;

  PathBmp.SaveToStream(PntFileStm);
  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(OpenDialog1.FileName, 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(FigureArray[i],SizeOf(FigureArray[i]));
        end;
      PathBmp.LoadFromStream(PntFileStm);
      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(FigureArray[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.
Avatar of ws1999

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,region_now,region2,RGN_OR);

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
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ws1999

ASKER

thanks slick812