PHOTOSHOP等图形图象处理软件,其中有一个魔术棒的功能,当选取某一点后,相同颜色的区域将被一条流动“蚂蚁线”包围。请问如何实现这一效果,具体的算法如何?谢谢!
解决方案 »
- ServerSocket发送不出数据
- 利用delphi编程,实现上位机监控plc(FX2N和CP1H)
- EXCEL问题:如何让EXCEL单元格内容不可见(最好显示为****)?但又不影响其它单元格调用这个数据。
- 设置断点调试时,鼠标放在变量上却看不到变量的值了?怎么办,急问,多谢回复
- 请问:为什么我做的VCL控件在“Standard”控件页中看不见?
- 请问 关于 FindFirst的问题 我想查一种以上的后缀文件的时侯该怎么写? (在线等待)
- 求个为帮忙:项目中遇到的问题(在线等待)
- 我想把DELPHI与SQL SERVER 动态管理起来
- 一个关于label标签的问题?(好像很弱)帮帮忙好么?
- 我的form为什么隐藏不了
- 请问一个进程怎么取得自己的物理地址?
- 那位有显示三维离散点的程序,(急用)
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;type
TAreaFrm = class(TForm)
Image1: TImage;
PaintBox1: TPaintBox;
Timer1: TTimer;
Panel1: TPanel;
PaintBox2: TPaintBox;
procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormCreate(Sender: TObject);
procedure PaintBox1Paint(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
procedure Timer1Timer(Sender: TObject);
private
FClickCounter: Integer;
FSelectRect: TRect;
FPoint: TPoint;
procedure DrawSelectionRect;
procedure RemoveTheRect;
procedure DrawTheRect;
Procedure WMEraseBkGnd(var Msg: TWMEraseBkGnd); message WM_ERASEBKGND;
{ Private declarations }
public
Bmp: TBitmap;
{ Public declarations }
end;var
AreaFrm: TAreaFrm;
Counter: Byte;
CounterStart: Byte;
Looper: LongInt;const
CM_AREACLIP_DONE = WM_USER + 1000;implementationuses Types;{$R *.dfm}procedure MovingDots(X, Y: Integer; TheCanvas: TCanvas); stdcall;
begin
Inc(Looper);
Counter := Counter shl 1; // Shift the bit left one
if Counter = 0 then
Counter := 1; // If it shifts off left, reset it
if (Counter and 224) > 0 then // Are any of the left 3 bits set?
TheCanvas.Pixels[X, Y] := clBlack // Erase the pixel
else
TheCanvas.Pixels[X, Y] := clWhite; // Draw the pixel
end;function NormalizeRect(R: TRect): TRect;
begin
// This routine normalizes a rectangle. It makes sure that the Left,Top
// coords are always above and to the left of the Bottom,Right coords.
with R do
if Left > Right then
if Top > Bottom then
Result := Rect(Right, Bottom, Left, Top)
else
Result := Rect(Right, Top, Left, Bottom)
else if Top > Bottom then
Result := Rect(Left, Bottom, Right, Top)
else
Result := Rect(Left, Top, Right, Bottom);
end;procedure TAreaFrm.PaintBox1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
Temp: Integer;
begin
if FClickCounter = 0 then
begin
if IsRectEmpty(FSelectRect) then
begin
FSelectRect.Left := X;
FSelectRect.Right := X;
FSelectRect.Top := Y;
FSelectRect.Bottom := Y;
//DrawSelectionRect;
Inc(FClickCounter);
end
else
begin
{DrawSelectionRect;
// 把选择框矩形置为空
FSelectRect := Rect(0, 0, 0, 0);
// 重画Image的画布
Invalidate;}
end;
end
else if FClickCounter > 0 then
begin
if FSelectRect.Left > FSelectRect.Right then
begin
Temp := FSelectRect.Left;
FSelectRect.Left := FSelectRect.Right;
FSelectRect.Right := Temp;
end;
if FSelectRect.Top > FSelectRect.Bottom then
begin
Temp := FSelectRect.Top;
FSelectRect.Top := FSelectRect.Bottom;
FSelectRect.Bottom := Temp;
end;
//DrawSelectionRect;
DrawTheRect; // 开始拷屏到Bmp
Bmp.Width := FSelectRect.Right - FSelectRect.Left;
Bmp.Height := FSelectRect.Bottom - FSelectRect.Top;
BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
Image1.Canvas.Handle, FSelectRect.Left, FSelectRect.Top, SRCCOPY); // 把选择框矩形置为空
FSelectRect := Rect(0, 0, 0, 0);
// 将计数器清0
Dec(FClickCounter); ReleaseCapture; // 这是第二次点击所以要把矩形内部的图像拷到Bmp中,并通知主窗体可以接受Bmp了
SendMessage(Application.MainForm.Handle, CM_AREACLIP_DONE, 0, 0);
end;
end;procedure TAreaFrm.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
//var
//Temp: Integer;
begin
{if IsDown then
begin
if FSelectRect.Left > FSelectRect.Right then
begin
Temp := FSelectRect.Left;
FSelectRect.Left := FSelectRect.Right;
FSelectRect.Right := Temp;
end;
if FSelectRect.Top > FSelectRect.Bottom then
begin
Temp := FSelectRect.Top;
FSelectRect.Top := FSelectRect.Bottom;
FSelectRect.Bottom := Temp;
end;
IsDown := False;
end;}
end;procedure TAreaFrm.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
begin
{if FClickCounter > 0 then
if (X <> FSelectRect.Right) or (Y <> FSelectRect.Bottom) then
begin
// 画两次,第一次消除前一个矩形,后一次画新矩形
DrawSelectionRect;
FSelectRect.Right := X;
FSelectRect.Bottom := Y;
DrawSelectionRect;
end;} if FClickCounter > 0 then
begin
if (X <> FSelectRect.Right) or (Y <> FSelectRect.Bottom) then
begin
// Erase any existing rectangle
RemoveTheRect;
FSelectRect.Right := X;
FSelectRect.Bottom := Y;
DrawTheRect;
end;
end; StretchBlt(PaintBox2.Canvas.Handle, 0, 0,
PaintBox2.Width, PaintBox2.Height,
PaintBox1.Canvas.Handle, X - 10, Y - 10, 20, 20, SRCCOPY);
end;procedure TAreaFrm.DrawSelectionRect;
begin
// 绘制橡皮筋矩形
// 也可以采用其它GDI绘图函数来画,都一样,只是要记得
// 在原位置再画一遍,擦除掉原来的矩形!
PaintBox1.Canvas.Polygon([Point(FSelectRect.Left, FSelectRect.Top),
Point(FSelectRect.Right, FSelectRect.Top),
Point(FSelectRect.Right, FSelectRect.Bottom),
Point(FSelectRect.Left, FSelectRect.Bottom)]);
end;procedure TAreaFrm.FormCreate(Sender: TObject);
begin
// 鼠标按下的计数器 0 = 没有按过 1 = 已经按过一次
FClickCounter := 0; Bmp := TBitmap.Create;
Bmp.PixelFormat := pf24bit; DoubleBuffered := True;
//PaintBox1.Canvas.Pen.Style := psDash;
{PaintBox1.Canvas.Pen.Style := psSolid;
PaintBox1.Canvas.Pen.Width := 1;
PaintBox1.Canvas.Pen.Color := clWhite;
PaintBox1.Canvas.Pen.Mode := pmXor;} // Setup Animated Rubberband
with PaintBox1 do
begin
Canvas.Pen.Color := clWhite;
Canvas.Brush.Color := clBlack;
end;
CounterStart := 128;
Timer1.Interval := 300;
Timer1.Enabled := True;
Looper := 0;
end;
begin
// to do
end;procedure TAreaFrm.FormDestroy(Sender: TObject);
begin
Bmp.Free;
end;procedure TAreaFrm.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Temp: Integer;
begin
if FSelectRect.Left <= 0 then
FSelectRect.Left := 0;
if FSelectRect.Top <= 0 then
FSelectRect.Top := 0;
if FSelectRect.Right >= Screen.Width then
FSelectRect.Right := Screen.Width;
if FSelectRect.Bottom >= Screen.Height then
FSelectRect.Bottom := Screen.Height; if FSelectRect.Left > FSelectRect.Right then
begin
Temp := FSelectRect.Left;
FSelectRect.Left := FSelectRect.Right;
FSelectRect.Right := Temp;
end;
if FSelectRect.Top > FSelectRect.Bottom then
begin
Temp := FSelectRect.Top;
FSelectRect.Top := FSelectRect.Bottom;
FSelectRect.Bottom := Temp;
end;
//DrawSelectionRect;
DrawTheRect; case Key of
VK_ESCAPE:
begin
//MessageBeep(0);
FSelectRect := Rect(0, 0, 0, 0);
Dec(FClickCounter);
ReleaseCapture; Hide;
Close;
Application.Restore;
end;
VK_RETURN:
begin
if FSelectRect.Left > FSelectRect.Right then
begin
Temp := FSelectRect.Left;
FSelectRect.Left := FSelectRect.Right;
FSelectRect.Right := Temp;
end;
if FSelectRect.Top > FSelectRect.Bottom then
begin
Temp := FSelectRect.Top;
FSelectRect.Top := FSelectRect.Bottom;
FSelectRect.Bottom := Temp;
end;
//DrawSelectionRect;
DrawTheRect; // 开始拷屏到Bmp
Bmp.Width := FSelectRect.Right - FSelectRect.Left;
Bmp.Height := FSelectRect.Bottom - FSelectRect.Top;
BitBlt(Bmp.Canvas.Handle, 0, 0, Bmp.Width, Bmp.Height,
Image1.Canvas.Handle, FSelectRect.Left, FSelectRect.Top, SRCCOPY); // 把选择框矩形置为空
FSelectRect := Rect(0, 0, 0, 0);
// 将计数器清0
Dec(FClickCounter); ReleaseCapture; // 这是第二次点击所以要把矩形内部的图像拷到Bmp中,并通知主窗体可以接受Bmp了
SendMessage(Application.MainForm.Handle, CM_AREACLIP_DONE, 0, 0);
end;
VK_DOWN:
begin
if ssCtrl in Shift then
begin
RemoveTheRect;
FSelectRect.Top := FSelectRect.Top + 1;
FSelectRect.Bottom := FSelectRect.Bottom + 1;
DrawTheRect;
SetCursorPos(FSelectRect.Right, FSelectRect.Bottom);
end
else
begin
GetCursorPos(FPoint);
Inc(FPoint.Y);
SetCursorPos(FPoint.X, FPoint.Y);
end;
end;
VK_UP:
begin
if ssCtrl in Shift then
begin
RemoveTheRect;
Dec(FSelectRect.Top);
Dec(FSelectRect.Bottom);
DrawTheRect;
SetCursorPos(FSelectRect.Right, FSelectRect.Bottom);
end
else
begin
GetCursorPos(FPoint);
Dec(FPoint.Y);
SetCursorPos(FPoint.X, FPoint.Y);
end;
end;
VK_LEFT:
begin
if ssCtrl in Shift then
begin
RemoveTheRect;
Dec(FSelectRect.Left);
Dec(FSelectRect.Right);
DrawTheRect;
SetCursorPos(FSelectRect.Right, FSelectRect.Bottom);
end
else
begin
GetCursorPos(FPoint);
Dec(FPoint.X);
SetCursorPos(FPoint.X, FPoint.Y);
end;
end;
VK_RIGHT:
begin
if ssCtrl in Shift then
begin
RemoveTheRect;
Inc(FSelectRect.Left);
Inc(FSelectRect.Right);
DrawTheRect;
SetCursorPos(FSelectRect.Right, FSelectRect.Bottom);
end
else
begin
GetCursorPos(FPoint);
Inc(FPoint.X);
SetCursorPos(FPoint.X, FPoint.Y);
end;
end;
end;
end;procedure TAreaFrm.WMEraseBkGnd(var Msg: TWMEraseBkGnd);
begin
Msg.Result := 1;
end;procedure TAreaFrm.DrawTheRect;
var
X1, Y1, X2, Y2: Integer;
begin
// Determines starting pixel color of Rect
Counter := CounterStart;
// Use LineDDA to draw each of the 4 edges of the rectangle
with FSelectRect do
begin
X1 := Left;
Y1 := Top;
X2 := Right;
Y2 := Bottom;
end; LineDDA(X1, Y1, X2, Y1, @MovingDots, LongInt(PaintBox1.Canvas));
LineDDA(X2, Y1, X2, Y2, @MovingDots, LongInt(PaintBox1.Canvas));
LineDDA(X2, Y2, X1, Y2, @MovingDots, LongInt(PaintBox1.Canvas));
LineDDA(X1, Y2, X1, Y1, @MovingDots, LongInt(PaintBox1.Canvas));
end;procedure TAreaFrm.RemoveTheRect;
var
R: TRect;
begin
//R := NormalizeRect(Rect(X1, Y1, X2, Y2)); // Rectangle might be flipped
R := NormalizeRect(FSelectRect);
InflateRect(R, 1, 1); // Make the rectangle 1 pixel larger
InvalidateRect(Handle, @R, True); // Mark the area as invalid
InflateRect(R, -2, -2); // Now shrink the rectangle 2 pixels
ValidateRect(Handle, @R); // And validate this new rectangle.
// This leaves a 2 pixel band all the way around
// the rectangle that will be erased & redrawn
UpdateWindow(Handle);
end;procedure TAreaFrm.Timer1Timer(Sender: TObject);
begin
CounterStart := CounterStart shr 2; // Shl 1 will move rect slower
if CounterStart = 0 then
CounterStart := 128; // If bit is lost, reset it
DrawTheRect; // Draw the rectangle
end;end.
Copyright (C) 1990-2001 William Miller--- LICENSE ---This notice may not be removed from or altered in any source distribution.You are free to use Apprehend 2001 in compiled form for any purpose. Apprehend 2001 in source code or object form (including but not limited to .PAS,
.DCU, .OBJ), in whole or in part, modified or unmodified, may not be
redistributed for profit or as part of another commercial or shareware
software package without express written permission from me.This software is provided 'as-is', without any express or implied warranty.
In no event shall the author be held liable for any damages arising from the
use of this software.
William Miller
[email protected]
http://www.software.adirondack/ny.us