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.
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.