我想在TMemo控件中单击鼠标,查找鼠标单击位置是否在[和]之间,如果在则选中[和]之间的内容,于是写了以下代码(注:两个查找函数是正确的),可是问题出现了,如果TMemo控件中的内容是手动从键盘输入的,则能正确执行,如果是从别的TMemo控件中复制过来的,则不能正确执行,主要是选择的位置出现了随机偏差,何故?100分奉上,敬请高手解答!
procedure TForm1.TimeEditMemoClick(Sender: TObject);
var //测试中...
startPos,endPos,i:integer;
begin
if TimeEditMemo.Text='' then exit;
i:=TimeEditMemo.SelStart;
startPos:=FastPosBackNoCase(TimeEditMemo.Lines.Text,'[',Length(TimeEditMemo.Lines.Text),Length('['),TimeEditMemo.SelStart);
endPos:=FastPosNoCase(TimeEditMemo.Lines.Text,']',Length(TimeEditMemo.Lines.Text),Length(']'),i);
//showmessage(inttostr(startPos)+' '+inttostr(endPos));TimeEditMemo.SelStart:=startPos-1;
TimeEditMemo.SelLength:=endPos-startPos+1;
//ShowMessage(inttostr(TimeEditMemo.CaretPos.Y));
//ShowMessage(inttostr(TimeEditMemo.CaretPos.X));
end;从别的TMemo控件中复制代码如下:
procedure TForm1.RightToLeftButtonClick(Sender: TObject);
begin
TimeEditMemo.Lines.Clear;
TimeEditMemo.Lines.AddStrings(LyricMemo.Lines);
LyricMemo.Clear;
TimeEditMemo.SelStart:=0;
TimeEditMemo.SelLength:=0;
end;
procedure TForm1.TimeEditMemoClick(Sender: TObject);
var //测试中...
startPos,endPos,i:integer;
begin
if TimeEditMemo.Text='' then exit;
i:=TimeEditMemo.SelStart;
startPos:=FastPosBackNoCase(TimeEditMemo.Lines.Text,'[',Length(TimeEditMemo.Lines.Text),Length('['),TimeEditMemo.SelStart);
endPos:=FastPosNoCase(TimeEditMemo.Lines.Text,']',Length(TimeEditMemo.Lines.Text),Length(']'),i);
//showmessage(inttostr(startPos)+' '+inttostr(endPos));TimeEditMemo.SelStart:=startPos-1;
TimeEditMemo.SelLength:=endPos-startPos+1;
//ShowMessage(inttostr(TimeEditMemo.CaretPos.Y));
//ShowMessage(inttostr(TimeEditMemo.CaretPos.X));
end;从别的TMemo控件中复制代码如下:
procedure TForm1.RightToLeftButtonClick(Sender: TObject);
begin
TimeEditMemo.Lines.Clear;
TimeEditMemo.Lines.AddStrings(LyricMemo.Lines);
LyricMemo.Clear;
TimeEditMemo.SelStart:=0;
TimeEditMemo.SelLength:=0;
end;
解决方案 »
- dbgrideh汇总
- 如何向VFP9.0的存储过程传递参数?
- 开发CDMA(AnyData)无线上网,发送什么AT指令让PCMCIA卡拨号上网!急
- 我用fastreport,怎样在一页上打印两个表(再问)
- 一直学delphi的 想开发b/s结构程序 大家用jsp 还是.net呀??
- 怎样判断一个db文件中已经有了名为send的字段?(源码)
- 1000分求救,请“斑竹”和各位“Delphi高手”入内, 提供类似该问题精彩控件下载网址者,也有分哦!
- 如何把一条很长的数据分块储存到数据库中?个位大侠帮帮忙啊
- 问个很菜的问题
- 高分征集各级绝世delphi好书!
- 免费邮件群发系统(多线程版)(含Source可下载)
- 今天晚上一直在线等!!!!!!!!!!!!!!
var //²âÊÔÖÐ...
startPos,endPos,i:integer;
begin
if TimeEditMemo.Text='' then exit;
i:=TimeEditMemo.SelStart;
// startPos:=FastPosBackNoCase(TimeEditMemo.Lines.Text,'[',Length(TimeEditMemo.Lines.Text),Length('['),TimeEditMemo.SelStart);
// endPos:=FastPosNoCase(TimeEditMemo.Lines.Text,']',Length(TimeEditMemo.Lines.Text),Length(']'),i);
startPos:=1;
endPos:=length(TimeEditMemo.Text);
//showmessage(inttostr(startPos)+' '+inttostr(endPos)); TimeEditMemo.SelStart:=startPos-1;
TimeEditMemo.SelLength:=endPos-startPos+1;
//ShowMessage(inttostr(TimeEditMemo.CaretPos.Y));
//ShowMessage(inttostr(TimeEditMemo.CaretPos.X));
end;
请帖出FastPosNoCase的过程。
unit FastStrings;interfaceuses
{$IFNDEF LINUX}
Windows,
{$ENDIF}
SysUtils;//This TYPE declaration will become apparent later
type
TBMJumpTable = array[0..255] of Integer;
TFastPosProc = function (const aSource, aFind: Pointer; const aSourceLen, aFindLen: Integer; var JumpTable: TBMJumpTable): Pointer;
TFastPosIndexProc = function (const aSourceString, aFindString: string; const aSourceLen, aFindLen, StartPos: Integer; var JumpTable: TBMJumpTable): Integer;
TFastTagReplaceProc = procedure (var Tag: string; const UserData: Integer);
//Boyer-Moore routines
procedure MakeBMTable(Buffer: PChar; BufferLen: Integer; var JumpTable: TBMJumpTable);
procedure MakeBMTableNoCase(Buffer: PChar; BufferLen: Integer; var JumpTable: TBMJumpTable);
function BMPos(const aSource, aFind: Pointer; const aSourceLen, aFindLen: Integer; var JumpTable: TBMJumpTable): Pointer;
function BMPosNoCase(const aSource, aFind: Pointer; const aSourceLen, aFindLen: Integer; var JumpTable: TBMJumpTable): Pointer;function FastAnsiReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): string;
procedure FastCharMove(const Source; var Dest; Count : Integer);
function FastCharPos(const aSource : string; const C: Char; StartPos : Integer): Integer;
function FastCharPosNoCase(const aSource : string; C: Char; StartPos : Integer): Integer;
function FastPos(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
function FastPosNoCase(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
function FastPosBack(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
function FastPosBackNoCase(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
function FastReplace(const aSourceString : string; const aFindString, aReplaceString : string;
CaseSensitive : Boolean = False) : string;
function FastTagReplace(const SourceString, TagStart, TagEnd: string;
FastTagReplaceProc: TFastTagReplaceProc; const UserData: Integer): string;
function SmartPos(const SearchStr,SourceStr : string;
const CaseSensitive : Boolean = TRUE;
const StartPos : Integer = 1;
const ForwardSearch : Boolean = TRUE) : Integer;
cDeltaSize = 1.5;var
GUpcaseTable : array[0..255] of char;
GUpcaseLUT: Pointer;//MakeBMJumpTable takes a FindString and makes a JumpTable
procedure MakeBMTable(Buffer: PChar; BufferLen: Integer; var JumpTable: TBMJumpTable);
begin
if BufferLen = 0 then raise Exception.Create('BufferLen is 0');
asm
push EDI
push ESI mov EDI, JumpTable
mov EAX, BufferLen
mov ECX, $100
REPNE STOSD mov ECX, BufferLen
mov EDI, JumpTable
mov ESI, Buffer
dec ECX
xor EAX, EAX
@@loop:
mov AL, [ESI]
lea ESI, ESI + 1
mov [EDI + EAX * 4], ECX
dec ECX
jg @@loop pop ESI
pop EDI
end;
end;procedure MakeBMTableNoCase(Buffer: PChar; BufferLen: Integer; var JumpTable: TBMJumpTable);
begin
if BufferLen = 0 then raise Exception.Create('BufferLen is 0');
asm
push EDI
push ESI mov EDI, JumpTable
mov EAX, BufferLen
mov ECX, $100
REPNE STOSD mov EDX, GUpcaseLUT
mov ECX, BufferLen
mov EDI, JumpTable
mov ESI, Buffer
dec ECX
xor EAX, EAX
@@loop:
mov AL, [ESI]
lea ESI, ESI + 1
mov AL, [EDX + EAX]
mov [EDI + EAX * 4], ECX
dec ECX
jg @@loop pop ESI
pop EDI
end;
end;function BMPos(const aSource, aFind: Pointer; const aSourceLen, aFindLen: Integer; var JumpTable: TBMJumpTable): Pointer;
var
LastPos: Pointer;
begin
LastPos := Pointer(Integer(aSource) + aSourceLen - 1);
asm
push ESI
push EDI
push EBX mov EAX, aFindLen
mov ESI, aSource
lea ESI, ESI + EAX - 1
std
mov EBX, JumpTable@@comparetext:
cmp ESI, LastPos
jg @@NotFound
mov EAX, aFindLen
mov EDI, aFind
mov ECX, EAX
push ESI //Remember where we are
lea EDI, EDI + EAX - 1
xor EAX, EAX
@@CompareNext:
mov al, [ESI]
cmp al, [EDI]
jne @@LookAhead
lea ESI, ESI - 1
lea EDI, EDI - 1
dec ECX
jz @@Found
jmp @@CompareNext@@LookAhead:
//Look up the char in our Jump Table
pop ESI
mov al, [ESI]
mov EAX, [EBX + EAX * 4]
lea ESI, ESI + EAX
jmp @@CompareText@@NotFound:
mov Result, 0
jmp @@TheEnd
@@Found:
pop EDI //We are just popping, we don't need the value
inc ESI
mov Result, ESI
@@TheEnd:
cld
pop EBX
pop EDI
pop ESI
end;
end;
var
LastPos: Pointer;
begin
LastPos := Pointer(Integer(aSource) + aSourceLen - 1);
asm
push ESI
push EDI
push EBX mov EAX, aFindLen
mov ESI, aSource
lea ESI, ESI + EAX - 1
std
mov EDX, GUpcaseLUT@@comparetext:
cmp ESI, LastPos
jg @@NotFound
mov EAX, aFindLen
mov EDI, aFind
push ESI //Remember where we are
mov ECX, EAX
lea EDI, EDI + EAX - 1
xor EAX, EAX
@@CompareNext:
mov al, [ESI]
mov bl, [EDX + EAX]
mov al, [EDI]
cmp bl, [EDX + EAX]
jne @@LookAhead
lea ESI, ESI - 1
lea EDI, EDI - 1
dec ECX
jz @@Found
jmp @@CompareNext@@LookAhead:
//Look up the char in our Jump Table
pop ESI
mov EBX, JumpTable
mov al, [ESI]
mov al, [EDX + EAX]
mov EAX, [EBX + EAX * 4]
lea ESI, ESI + EAX
jmp @@CompareText@@NotFound:
mov Result, 0
jmp @@TheEnd
@@Found:
pop EDI //We are just popping, we don't need the value
inc ESI
mov Result, ESI
@@TheEnd:
cld
pop EBX
pop EDI
pop ESI
end;
end;
//NOTE : FastCharPos and FastCharPosNoCase do not require you to pass the length
// of the string, this was only done in FastPos and FastPosNoCase because
// they are used by FastReplace many times over, thus saving a LENGTH()
// operation each time. I can't see you using these two routines for the
// same purposes so I didn't do that this time !
function FastCharPos(const aSource : string; const C: Char; StartPos : Integer) : Integer;
var
L : Integer;
begin
//If this assert failed, it is because you passed 0 for StartPos, lowest value is 1 !!
Assert(StartPos > 0); Result := 0;
L := Length(aSource);
if L = 0 then exit;
if StartPos > L then exit;
Dec(StartPos);
asm
PUSH EDI //Preserve this register mov EDI, aSource //Point EDI at aSource
add EDI, StartPos
mov ECX, L //Make a note of how many chars to search through
sub ECX, StartPos
mov AL, C //and which char we want
@Loop:
cmp Al, [EDI] //compare it against the SourceString
jz @Found
inc EDI
dec ECX
jnz @Loop
jmp @NotFound
@Found:
sub EDI, aSource //EDI has been incremented, so EDI-OrigAdress = Char pos !
inc EDI
mov Result, EDI
@NotFound: POP EDI
end;
end;function FastCharPosNoCase(const aSource : string; C: Char; StartPos : Integer) : Integer;
var
L : Integer;
begin
Result := 0;
L := Length(aSource);
if L = 0 then exit;
if StartPos > L then exit;
Dec(StartPos);
if StartPos < 0 then StartPos := 0; asm
PUSH EDI //Preserve this register
PUSH EBX
mov EDX, GUpcaseLUT mov EDI, aSource //Point EDI at aSource
add EDI, StartPos
mov ECX, L //Make a note of how many chars to search through
sub ECX, StartPos xor EBX, EBX
mov BL, C
mov AL, [EDX+EBX]
@Loop:
mov BL, [EDI]
inc EDI
cmp Al, [EDX+EBX]
jz @Found
dec ECX
jnz @Loop
jmp @NotFound
@Found:
sub EDI, aSource //EDI has been incremented, so EDI-OrigAdress = Char pos !
mov Result, EDI
@NotFound: POP EBX
POP EDI
end;
end;//The first thing to note here is that I am passing the SourceLength and FindLength
//As neither Source or Find will alter at any point during FastReplace there is
//no need to call the LENGTH subroutine each time !
function FastPos(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
var
JumpTable: TBMJumpTable;
begin
//If this assert failed, it is because you passed 0 for StartPos, lowest value is 1 !!
Assert(StartPos > 0);
if aFindLen < 1 then begin
Result := 0;
exit;
end;
if aFindLen > aSourceLen then begin
Result := 0;
exit;
end; MakeBMTable(PChar(aFindString), aFindLen, JumpTable);
Result := Integer(BMPos(PChar(aSourceString) + (StartPos - 1), PChar(aFindString),aSourceLen - (StartPos-1), aFindLen, JumpTable));
if Result > 0 then
Result := Result - Integer(@aSourceString[1]) +1;
end;function FastPosNoCase(const aSourceString, aFindString : string; const aSourceLen, aFindLen, StartPos : Integer) : Integer;
var
JumpTable: TBMJumpTable;
begin
//If this assert failed, it is because you passed 0 for StartPos, lowest value is 1 !!
Assert(StartPos > 0);
if aFindLen < 1 then begin
Result := 0;
exit;
end;
if aFindLen > aSourceLen then begin
Result := 0;
exit;
end;
//单击Memo,自动选中时间标签或标识标签,如果有的话
procedure TForm1.TimeEditMemoClick(Sender: TObject);
//测试中... 通过发送消息模拟键盘按钮SHIFT+方向键 实现选定内容
//终于搞定了一些未知错误
var
CurrPos:TPoint;
str:string;
i,l,startPos,endPos:integer;
finded:bool;
KeyState: TKeyboardState;
OldCtrl: byte;
begin
if TimeEditMemo.Text='' then exit;
CurrPos:=TimeEditMemo.CaretPos;
startPos:=-1;endPos:=-1;
finded:=false;
str:=TimeEditMemo.Lines.Strings[CurrPos.Y];
//showmessage(str);
for i:=0 to CurrPos.X do
begin
if str[CurrPos.X-i]=']' then exit;
if str[CurrPos.X-i]='[' then
begin
startPos:=CurrPos.X-i;//找到左[符号
for l:=CurrPos.X+1 to Length(str) do
begin
if str[l]='[' then exit;
if str[l]=']' then
begin
endPos:=l; //找到右]符号
finded:=true;
break;
end;
end;
break;//可别漏了此语句哟
end;
end;
//找到后通过模拟键盘SHIFT+->的方式实现选中内容
if finded then
begin
for i:=0 to CurrPos.X-startPos do
SendMessage(TimeEditMemo.Handle,WM_KEYDOWN,VK_LEFT,0);//发送消息移动光标
GetKeyboardState(KeyState);
OldCtrl := KeyState[VK_SHIFT];
KeyState[VK_SHIFT]:=$80;
SetKeyboardState(KeyState);//按下SHIFT键
for i:=0 to endPos-startPos do
SendMessage(TimeEditMemo.Handle,WM_KEYDOWN,VK_RIGHT,0);
KeyState[VK_SHIFT]:=OldCtrl;
SetKeyboardState(KeyState); //恢复SHIFT键状态
end;
end;
感谢各位回复者