很基础的图形绘制的问题,知道的就简单了,分多哦!(在线等)(300分)

  • 主题发起人 主题发起人 KN
  • 开始时间 开始时间
K

KN

Unregistered / Unconfirmed
GUEST, unregistred user!
我现在正在学习关于UI编程,我现在自己编了个小程序来测试各种各样的图形绘制过程或函数,正在我编写用鼠标在TPaintBox上拖动一个绘制好的矩形时候发现在拖动时背景图不停闪烁,我的原来实现思想是在OnPaint中重新绘制背景和这个拖动中的矩形,由于闪烁我上网看了很多资料都说不清楚,我也越看越糊涂,根据我在网上看到的,我现在就提出我的疑问:
1.解决这个问题是基本思想是什么?
2.关于区域的绘制是怎么回事?怎么才能做到只绘制这个区域,其他地方不变?我看源代码经常是使用如下:
Canvas.ClipRect;
CreateRectRgn(...);
CombineRgn(...);
SelectObject(Canvas.Handle, RGN);
DeleteObject(RGN);
上面的我都知道是什么意思,但是我不知道他们到底是怎么实现区域绘制的,是不是解决闪烁就是跟它们有关系呢?
3.还有的资料说到使用Buffer,大概我理解是把要绘制的放入内存,然后再从内存中读出来,我不知道我理解的对不对,正确来说应该是怎么个说法?是不是其实就是和上面第2点讲的有关,如果不是应该怎么实现呢?
4.最好能给出简单的代码,没有必要的地方可以用“...”代替。

把我写的小程序也放上来,大虾们帮帮忙,谢谢:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;

type
TForm1 = class(TForm)
PBox: TPaintBox;
procedure PBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormCreate(Sender: TObject);
procedure PBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure PBoxMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PBoxPaint(Sender: TObject);
private
{ Private declarations }
CoordX, CoordY: Integer;
Down: Boolean;
procedure DrawRect(X, Y: Integer; Canvas: TCanvas);
procedure DrawDashDotRect(X, Y: Integer; Canvas: TCanvas);
procedure DrawBackGround;
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.DrawRect(X, Y: Integer; Canvas: TCanvas);
begin
with Canvas do
begin
Brush.Color := clRed;
Brush.Style := bsSolid;
FillRect(Rect(X, Y, X + 90, Y + 90));
Pen.Color := clGreen;
Pen.Style := psSolid;
Rectangle(X, Y, X + 90, Y + 90);
end;
end;

procedure TForm1.PBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Down := True;
CoordX := X;
CoordY := Y;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Down := False;
end;

procedure TForm1.PBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
DrawBackGround;
DrawDashDotRect(X, Y, PBox.Canvas);
DrawRect(10, 10, PBox.Canvas);
end;

procedure TForm1.DrawDashDotRect(X, Y: Integer; Canvas: TCanvas);
begin
if Down then
with Canvas do
begin
Brush.Style := bsClear;
Pen.Color := clBlack;
Pen.Style := psDashDot;
Rectangle(X, Y, X + 90, Y + 90);

Brush.Style := bsClear;
Pen.Color := clBlue;
Pen.Style := psSolid;
Rectangle(ClipRect.Left, ClipRect.Top, ClipRect.Right, ClipRect.Bottom);
end;
end;

procedure TForm1.PBoxMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Down := False;
end;

procedure TForm1.PBoxPaint(Sender: TObject);
begin
DrawBackGround;
DrawRect(10, 10, PBox.Canvas);
end;

procedure TForm1.DrawBackGround;
var
Brush: TBrush;
begin
Brush := TBrush.Create;
Brush.Color := clBtnFace;
Brush.Style := bsSolid;
FillRect(PBox.Canvas.Handle, Rect(0, 0, PBox.Width, PBox.Height), Brush.Handle);
FreeAndNil(Brush);
end;

end.
 
有个api ,“锁住窗口更新”LockWindowUpdate ,看看有没有用,
画前锁,画后开


怎样高速画图?

正在学习高速画图,请高手指点一下,分,我那还有
 
delphi5开发人员指南
有个绘图的程序,你拿过来好好看看,研究一下吧
 
一、不要直接对TPaintBox操作;
二、建立一个位图,图象的更新先对位图操作,然后更新到TPaintBox。
下面的代码对楼主的代码稍改动了一下,解决了画片闪烁问题。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;

type
TForm1 = class(TForm)
PBox: TPaintBox;
procedure PBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormCreate(Sender: TObject);
procedure PBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure PBoxMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
CoordX, CoordY: Integer;
Down: Boolean;
procedure DrawRect(X, Y: Integer; ACanvas: TCanvas);
procedure DrawDashDotRect(X, Y: Integer; ACanvas: TCanvas);
procedure DrawBackGround(ACanvas:TCanvas);
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

var
FBmp:TBitmap;

procedure TForm1.DrawRect(X, Y: Integer; ACanvas: TCanvas);
begin
with ACanvas do
begin
Brush.Color := clRed;
Brush.Style := bsSolid;
FillRect(Rect(X, Y, X + 90, Y + 90));
Pen.Color := clGreen;
Pen.Style := psSolid;
Rectangle(X, Y, X + 90, Y + 90);
end;
end;

procedure TForm1.PBoxMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Down := True;
CoordX := X;
CoordY := Y;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Down := False;
FBmp:=TBitmap.Create;
FBmp.Width:=PBox.Width;
FBmp.Height:=PBox.Height;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
FBmp.Free;
end;

procedure TForm1.PBoxMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
DrawBackGround(FBmp.Canvas);
DrawDashDotRect(X, Y, FBmp.Canvas);
DrawRect(10, 10, FBmp.Canvas);
PBox.Canvas.Draw(0,0,FBmp);
end;

procedure TForm1.DrawDashDotRect(X, Y: Integer; ACanvas: TCanvas);
begin
if Down then
with ACanvas do
begin
Brush.Style := bsClear;
Pen.Color := clBlack;
Pen.Style := psDashDot;
Rectangle(X, Y, X + 90, Y + 90);

Brush.Style := bsClear;
Pen.Color := clBlue;
Pen.Style := psSolid;
Rectangle(ClipRect.Left, ClipRect.Top, ClipRect.Right, ClipRect.Bottom);
end;
end;

procedure TForm1.PBoxMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Down := False;
end;

procedure TForm1.DrawBackGround(ACanvas:TCanvas);
begin
with ACanvas do
begin
Brush.Color:=clBtnFace;
Brush.Style:=bsSolid;
FillRect(Rect(0,0,FBmp.Width,FBmp.Height));
end;
end;

end.
 
忘了一段。
procedure TForm1.PBoxPaint(Sender: TObject);
begin
DrawBackGround(FBmp.Canvas);
DrawRect(10, 10, FBmp.Canvas);
{上面两句可以写在FormCreate事件中}
PBox.Canvas.Draw(0,0,FBmp);
end;
 
smokingroom:
谢谢你的答案,虽然你的做法能够解决我现在这个小程序上的问题,但是那只是一部分,这个方法好象只能治标不治本,我还是很想知道关于我原来的问题。
setfon:
当然知道,但是具体怎么实现的能说下吗?

现在分数系统上限是300分,如果能真的帮我解决问题,我另外开贴再给300分。
谢谢大家的帮助。
 
什么叫治标不治本?这就是解决问题的方法,什么叫使用缓冲?这就叫使用缓冲!
 
smokingroom:
其实我就是想知道
Canvas.ClipRect;
CreateRectRgn(...);
CombineRgn(...);
SelectObject(Canvas.Handle, RGN);
DeleteObject(RGN);
是怎么解决闪烁问题的。
 
后退
顶部