2014-07-24 1 views
1

문제는 : 나는 마우스 (사각형의 크기가 증가)를 이동하는 동안, 모든 좋은 나는 등 시차, 유물을 가지고 있겠지, 바탕 화면에 몇 가지 사각형을 그립니다 : enter image description here시간에 맞추어 캔버스를 다시 칠하는 방법은 무엇입니까?

하지만보다 낮은에 사각형 크기를 조정할 때 그것은 beed, 나는 인공물을 가지고 : enter image description here

빨간색 사각형은 다른 모든 버그입니다.

완벽한 해결책은 캔버스를 다시 그리는 것입니다. 그러나 마우스가 움직이는 동안 나는 그것을 항상 할 수 없습니다.

이동 후 마우스 절대 중지시 해결 방법이 있습니까?

업데이트

코드 :

unit Unit2; 

interface 

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

type 
    TForm2 = class(TForm) 
    Timer1: TTimer; 
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 
     Shift: TShiftState; X, Y: Integer); 
    procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); 
    procedure FormCreate(Sender: TObject); 
    procedure FormMouseUp(Sender: TObject; Button: TMouseButton; 
     Shift: TShiftState; X, Y: Integer); 
    procedure FormDestroy(Sender: TObject); 
    private 
    { Private declarations } 
    isDown: Boolean; 
    downX, downY: Integer; 
    public 
    { Public declarations } 
    Bild: TBitMap; 
    end; 

implementation 

{ 형태 소품 : 의 BorderStyle = bsNone AlphaBlend 사실 150 Transparentcolor = TRUE, clBlack }

{$R *.dfm} 

procedure TForm2.FormCreate(Sender: TObject); 
begin 
    Bild := TBitMap.Create; 
end; 

procedure TForm2.FormDestroy(Sender: TObject); 
begin 
    Bild.Free; 
end; 

procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
begin 
    isDown := true; 
    downX := X; 
    downY := Y; 
end; 

procedure TForm2.FormMouseMove(Sender: TObject; Shift: TShiftState; 
    X, Y: Integer); 
const 
    cVal = 4; 
begin 
    if isDown then 
    begin 
    Self.Canvas.Lock; 
    Self.Repaint; 
    Self.Canvas.Pen.Color := clNone; 
    Self.Canvas.Pen.Width := 1; 

    Self.Canvas.Pen.Style := psDot; 
    //Self.Canvas.Pen.Mode := pmNotCopy; 
    Self.Canvas.Brush.Color := clGreen; 
    Self.Canvas.Rectangle(downX, downY, X, Y); 
    Self.Canvas.Pen.Style := psSolid; 
    Self.Canvas.Brush.Color := clNone; 
    Self.Canvas.Unlock; 
    { Self.Canvas.Rectangle(downX - cVal, downY - cVal, downX + cVal, downY + cVal); 
    Self.Canvas.Rectangle(X - cVal, Y - cVal, X + cVal, Y + cVal); 
    Self.Canvas.Rectangle(X - cVal, downY - cVal, X + cVal, downY + cVal); 
    Self.Canvas.Rectangle(downX - cVal, Y - cVal, downX + cVal, Y + cVal); 

    Self.Canvas.Rectangle(downX - cVal, (downY + Y) div 2 - cVal, downX + cVal, 
     (downY + Y) div 2 + cVal); 
    Self.Canvas.Rectangle(X - cVal, (downY + Y) div 2 - cVal, X + cVal, 
     (downY + Y) div 2 + cVal); 

    Self.Canvas.Rectangle((downX + X) div 2 - cVal, downY - cVal, 
     (downX + X) div 2 + cVal, downY + cVal); 
    Self.Canvas.Rectangle((downX + X) div 2 - cVal, Y - cVal, (downX + X) div 2 + cVal, 
     Y + cVal); } 
    end; 
end; 

function CaptureRect(aRect: TRect; out aBmp: TBitmap): Boolean; 
var 
    ScreenDC: HDC; 
begin 
    Result := False; 
    try 
    with aBmp, aRect do 
    begin 
     Width := Right - Left; 
     Height := Bottom - Top; 
     ScreenDC := GetDC(0); 
     try 
     BitBlt(Canvas.Handle, 0, 0, Width, Height, ScreenDC, Left, Top, SRCCOPY); 
     finally 
     ReleaseDC(0, ScreenDC); 
     end; 
    end; 
    except 
    end; 
end; 

procedure TForm2.FormMouseUp(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
var 
    r: TRect; 
begin 
    isDown := false; 
    r.Left := downX; 
    r.Top := downY; 
    r.Right := X; 
    r.Bottom := Y; 
    CaptureRect(r, Bild); 
    Self.Close; 
end; 

end. 
+2

'pmXor' 모드로 펜으로 * 오래된 사각형을 덮어 쓸 수 있습니다. – TLama

+0

아니,이 작동하지 않았다. – AlexLL

+2

코드가 있습니까? 그리고 자신이 소유하지 않은 창을 그릴 수 있다고 생각하게 만드는 이유는 무엇입니까? 다른 앱이 창에서 그림을 그리기 시작하면 어떨까요? 프로그램이 작동을 멈 추면 놀랄 것입니까? 코드를 변경하여이를 처리하려고합니까, 아니면 다른 프로그램을 비난하겠습니까? 그림이 어떻게 작동하는지 이해합니까? 특히 윈도우는'WM_PAINT' 메시지에 대한 응답으로 언제든지 자신을 업데이트 할 수 있어야하고, 영속 상태를 가질 필요는 없습니다. –

답변

6

당신의 문제는 당신이 틀린 장소에 그림을 그린다는 것입니다. OnMouseMove 이벤트 처리기에서 그림을 중지하십시오. 페인팅 코드를 페인트 처리기로 이동합니다. 예를 들어 양식의 OnPaint 처리기.

그런 다음 OnMouseMove 이벤트 핸들러, 실제로 OnMouseDownOnMouseUp에, 페인트주기를 강제로, 형태, 또는 Win32에서 InvalidateRect 기능에 Invalidate를 호출합니다.

+0

고마워요! 문제는 사라졌습니다. – AlexLL

0

그림판 i 대신 계층화 된 창. 이는 인공물이없는 큰 속도를 제공 할 것이며 Windows는 드로잉을 처리합니다.

계층 창은 CreateWindowEx 함수로 창을 만들 때 WS_EX_LAYERED를 지정하여 만든 창입니다. 나중에이 윈도우의 내용을 설정하기 위해 UpdateLayeredWindow를 사용할 수 있습니다. 그렇게하면 캔버스의 내용을 수정하지 않고 캔버스 위에 칠할 수 있습니다.

물론이 방법은 문제를 해결할 수있는 고급 방법입니다. 따라서 Windows API에 대한 지식이 필요합니다.

+0

"Paint into layered windows?"라는 말보다 더 간단하게 설명해 주실 수 있습니까? 내 영어 사전은 사실을 이해하기에 그렇게 완벽하지 않습니다. – AlexLL

+0

bsNone 및 width & height가있는 창을 사용하는 경우 화면 크기와 동일합니다. – AlexLL

+0

@AlexLL 코드를 표시하지 않으려 고하면, 현재 수행중인 작업을 추측 할 필요가 있습니다. 그것은 전혀 생산적이지 않습니다.도움이 필요하면 우리 모두에게 자신이하는 일을 분명히하기 위해 더 많은 노력을 기울일 것입니다. 그렇게 할 때까지는 무의미하고 고통스러운 운동이 될 것입니다. –

관련 문제