function MyFuncIIFtoBooleans(ACondition: boolean; AColorTrue: TColor; AColorFalse: TColor): TColor; begin result := AColorFalse; // if ACondition then result := AColorTrue; end;
{ TPanel }
procedure TPanel.Paint; begin inherited; // ViewFormMain.DrawMyLinesPlease(MyCurrentPos.X, MyCurrentPos.Y); end;
procedure TViewFormMain.Pnl_SignatureMouseLeave(Sender: TObject); begin MyStartDraw := false; end;
procedure TViewFormMain.Pnl_SignatureMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin MyCurrentPos := TPoint.Create(X, Y); // if (MyBeforePos.X = MyCurrentPos.X) and (MyBeforePos.Y = MyCurrentPos.Y) then exit; // if MyStartDraw then begin if ChkBxUsePaintEvent.Checked then Pnl_Signature.Paint else DrawMyLinesPlease(MyCurrentPos.X, MyCurrentPos.Y); end; end;
procedure TViewFormMain.DrawMyLinesPlease(X, Y: Integer); begin if MyStartDraw then begin if MyCanvasToWork.TryLock then // try prevent others writes! try MyCanvasToWork.Pen.Color := MyFuncIIFtoBooleans(ChkBxUsePaintEvent.Checked, clYellow, clWhite); // MyCanvasToWork.Pen.Mode := MyPenMode; MyCanvasToWork.Pen.Style := MyPenStyle; MyCanvasToWork.Pen.Width := MyPenWidth; // MyCanvasToWork.LineTo(X, Y); finally MyCanvasToWork.Unlock; end; // MyBeforePos := MyCurrentPos; end; end;
procedure TViewFormMain.Btn_Bitmap_iTClick(Sender: TObject); var MyBmp: TBitmap; begin // MyBmp := TBitmap.Create; try MyBmp.SetSize(Pnl_Signature.Width, Pnl_Signature.Height); // if BitBlt(MyBmp.Canvas.Handle, 0, 0, Pnl_Signature.Width, Pnl_Signature.Height, MyCanvasToWork.Handle, 0, 0, SRCCOPY) then Img_Resulted.Picture.Bitmap.Assign(MyBmp) else ShowMessage('Sorry, was not possible copy your signature to bitmap!'); finally MyBmp.Free; end; end;
procedure TViewFormMain.Btn_Clear_SignatureClick(Sender: TObject); begin Pnl_Signature.Repaint; end;
end.
此帖子包含附件: 大小:101.4K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
NOTE: -- Im using a "DIDATIC TEXT", then you can change as you need!!!
-- If need store your "POINT(X,Y)" you can use any way: Array, List, TPath, StringList, etc...
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
procedure TForm1.Pnl_SignatureMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); begin if MyStartDraw then begin MyPoints := MyPoints + [TPointF.Create(X, Y)]; // Pnl_Signature.Repaint; end; end;
procedure TForm1.Pnl_SignaturePaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin for var i: integer := 1 to high(MyPoints) do if (MyPoints[i - 1].X <> 1000000) and (MyPoints[i].X <> 1000000) then Canvas.DrawLine(MyPoints[i - 1], MyPoints[i], 1, MyBrush); end;
end.
此帖子包含附件: 大小:115.0K
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
对您来说,“更准确”的定义是什么? 你提供更多细节,因为中文文本的翻译并没有让我了解你真正的愿望。 What would be, for you, the definition of "more accurate"? you give more details, because the translation of the Chinese text didn't tell me much to understand your real desire.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
NOTE: Im not master, just a entusiast
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
0) in "Paint event" it's not necessary "BeginScene" because this is done on the event!
1) maybe the "resolution" used in Bitmap be diferent of Canvas (your current screen resolution), then the problem can be there. I need test it, but im not in Pc in this moment ok?
2) do the "copy process" out of paint event... when all is done to save it, for example!
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
That is to say, the handwriting on Android devices is different from that on paper, but this difference is acceptable.
The main problem is that I cannot save the canvas.bitmap on paintbox as a file or stream.
Currently, I am creating a bitmap to track the image formed by signing in paintbox, but I found that there will be a loss of accuracy after saving the image. ---------- Yes, the resolution of the image on the canvas and the image drawn on the paintbox are different. When these two images are merged and saved, the graphics on the paintbox become rough.
----------------------------------------------
-
It is said that using drawpath is more accurate than using drawpen. Can you help me write drawpath code?
----------------------------------------------
-
BUT, to start: 1) TPath, it's nothing more than "TLIST" with "TPoints"... like I showed to you using ARRAY!!! BUT, using a class "TPATH"/"TPATHDATA" to easy usage!!!
.... FMX.Graphics.pas - RAD11.3 procedure TPathData.AddPath(APath: TPathData); var I: Integer; begin FPathData.Capacity := FPathData.Count + APath.Count; for I := 0 to APath.Count - 1 do FPathData.Add(APath.Points[I]); DoChanged; end;
.... System.Generics.Collections.pas - RAD11.3 function TList<T>.Add(const Value: T): Integer; begin if IsManagedType(T) then begin if (SizeOf(T) = SizeOf(Pointer)) and not (GetTypeKind(T) in [tkRecord, tkMRecord]) then Result := FListHelper.InternalAddMRef(Value, GetTypeKind(T)) else if GetTypeKind(T) = TTypeKind.tkVariant then Result := FListHelper.InternalAddVariant(Value) else Result := FListHelper.InternalAddManaged(Value); end else case SizeOf(T) of 1: Result := FListHelper.InternalAdd1(Value); 2: Result := FListHelper.InternalAdd2(Value); 4: Result := FListHelper.InternalAdd4(Value); 8: Result := FListHelper.InternalAdd8(Value); else Result := FListHelper.InternalAddN(Value); end; end; .........
or be, I think that you can arrives in the same place... but with new knowledges... (this is good)
Do you want try?
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
-------- procedure MyHandSignaturePainting(ACanvas: TCanvas; APoints: TArray<TPointF>; AStrokeBrush: TStrokeBrush); // to "Canvas" of control and bitmap target... begin if (ACanvas = nil) then Exit; // if ACanvas.BeginScene() then // not necessary if into "OnPaint" event... try for var i: integer := 1 to high(APoints) do if (APoints[i - 1].X <> 1000000) and (APoints[i].X <> 1000000) then ACanvas.DrawLine(APoints[i - 1], APoints[i], 1, AStrokeBrush); finally ACanvas.EndScene; end; end;
procedure MyCanvasToBitmap(ACanvas: TCanvas; ABitmap: TBitmap; APoints: TArray<TPointF>; AStrokeBrush: TStrokeBrush); begin if (ACanvas = nil) or (ABitmap = nil) then Exit; // ABitmap.SetSize(ACanvas.Width, ACanvas.Height); // Bitmap has a limit to max sizes... see on help! ABitmap.Clear(TAlphaColorRec.White); // avoiding "black-out"... // MyHandSignaturePainting(ABitmap.Canvas, APoints, AStrokeBrush); end;
procedure MyCopyBitmapTo(const ABitmapIN: TBitmap; var ABitmapOUT: TBitmap); begin if (ABitmapIN = nil) or (ABitmapOUT = nil) then Exit; // try-except-.... ABitmapOUT.SetSize(ABitmapIN.Size); //ABitmapOUT.Clear(TAlphaColorRec.White); // avoiding "black-out"... // ABitmapOUT.CopyFromBitmap(ABitmapIN); end;
---------- procedure TForm1.Pnl_SignaturePaint(Sender: TObject; Canvas: TCanvas; const ARect: TRectF); begin // this event is called many times, since control is created... // MyHandSignaturePainting(Canvas, LPoints, LStrokeBrush); end;
---------- procedure TForm1.Button1Click(Sender: TObject); begin if (Length(LPoints) < 2) then // have points? 0..1... exit; // // using same procedure to "Canvas OnPaint"... // if needs "scaling" on bitmap, then needs do it before printing... // MyCanvasToBitmap(Pnl_Signature.Canvas, imgHandSignature.Bitmap, LPoints, LStrokeBrush);
... end;
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
//您上面的代码与我上面的代码,绘图效果是一样的。我在这里写 The drawing effect of the code above you is the same as that of mine. I'm writing here
procedure TForm3.PaintBox1Paint(Sender: TObject; Canvas: TCanvas); begin for var i: integer := 1 to high(MyPoints) do if (MyPoints[i - 1].X <> 10000) and (MyPoints[i].X <> 10000) then begin DrawBMP.Canvas.BeginScene;//此处打开 DrawBMP的canvas DrawBMP.Canvas.DrawLine(MyPoints[i - 1], MyPoints[i], 1, MyBrush); DrawBMP.Canvas.EndScene;//此处关闭DrawBMP的canvas Canvas.DrawLine(MyPoints[i - 1], MyPoints[i], 1, MyBrush);//PaintBox1的canvas不做任何操作 end; end;
I have already inserted an image in Image1, which is used for signing. Then I draw some text in the PaintBox for signing. Finally, I use a Bitmap to draw the two images together. Now the problem is:
Due to the different resolutions of the image in Image1 and the image in the PaintBox (generally, the resolution of the image in Image1 is much higher than that in the PaintBox), if we do not change the resolution, after drawing the two images together, the image in the PaintBox will be obviously smaller. If we enlarge the image in the PaintBox, there will be obvious jagged edges.
Perhaps we need to use interpolation method to correct the image in the PaintBox?
----------------------------------------------
-
I will place the PaintBox over Image1 and keep them the same size. I have inserted an image in Image1 for signing. Then I draw some text in the PaintBox for signing. Finally, I use a Bitmap to draw the two images together. The current issue is:
Due to the different resolutions of the image in Image1 and the image in the PaintBox (generally, the resolution of the image in Image1 is much higher than that in the PaintBox), if we do not change the resolution, after drawing the two images together, the image in the PaintBox will be obviously smaller. If we enlarge the image in the PaintBox, there will be obvious jagged edges.
Perhaps we need to use interpolation method to correct the image in the PaintBox, or improve the algorithm for drawing text to ensure that it does not lose its quality when zoomed in.
----------------------------------------------
-
show the code for analize...
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
0) Don’t insist on a path that goes to infinity!!! change the route, even if it seems wrong, and, if so, change it again. At some point, the proper route will be revealed, even if there are many.
1) Have you tried writing the points on the bitmap after writing is finished? Even if you don't want it this way, it's good for testing results. Then, analyze the positive and negative points, and then redo what is necessary.
2) Have you tried activating the bitmap's BeginScene in the Mouse-ONDOWN event and deactivating it in the Mouse-ONUP event? This way, they will only be used once each!
3) I think it would be more sensible for the code to only carry out real-time processes that are actually necessary... all other processes should be carried out when necessary, that is, after creating the points, create the final bitmap. So, you can draw the points on the canvas of PaintBox, Panel, etc.... and leave the drawing on the bitmap at the end of your writing on the screen.
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3
我还尝试这样,用image替代paintbox: var LastPoint:TPointF; DrawSF:boolean; procedure TForm2.Button1Click(Sender: TObject); begin img1.Bitmap.Clear(TAlphaColors.Null); end;
procedure TForm2.img1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); var thisPoint: TPointF; begin if DrawSF then begin thisPoint.X := X; thisPoint.Y := Y; with img1.Bitmap.Canvas do begin BeginScene; DrawLine(LastPoint, thisPoint, 1, MyBrush); EndScene; end;
see my little post https://bbs.2ccc.com/topic.asp?topicid=685342
----------------------------------------------
The higher the degree, the greater the respect given to the humblest!RAD 11.3