关于对TMEMO/TEDIT内的被选择文本进行拖动的问题(100分)

  • 主题发起人 主题发起人 daxian
  • 开始时间 开始时间
D

daxian

Unregistered / Unconfirmed
GUEST, unregistred user!
我想实现对TMEMO/TEDIT内的被选择文本进行拖动,就象
WordPad一样.可以把被选择文本拖动到本TMEMO/TEDIT
内的任何一个位置,或其它TMEMO/TEDIT内.
 
我做了一下...
EM_POSFROMCHAR 好象不好使,想用它判断是否在选择区内,却总返回0??再看看
 
先跟踪一下, 我好像知道一点.
 
EM_GETSEL (edit control)
EM_GETSELTEXT (rich edit control)

EM_SCROLLCARET (move to new position)

EM_REPLACESEL (u may call twice, one for cutting old and one for pasting in new position)
 
但是当开始拖动时,select就被取消了.
那个dragdrop控件可以做到这一点,而且有源代码, 要不要我发给你?
 
我是指只有当鼠标移动到被选择文本上时,才允许拖动。
 
给你发了一个控件,请查收. 里面有源代码和demo.
 
如果要用控件的话tlmdmemo就可以了,我看了半天源码,由于它是从自己的类中派生
出来的,所以没有什么利用的价值,要用就直接用吧。

不用的话,下面有些简单的代码,不太完善,不过100分我看还是值的 ;)

unit drag;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
procedure Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure Memo1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Memo1KeyPress(Sender: TObject; var Key: Char);
procedure Memo1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
CanMove:Boolean=False;
CurrentStart,CurrentLength:Integer;
OnSelect:Boolean=False;
MousePD:Boolean=False;

implementation

{$R *.DFM}

procedure TForm1.Memo1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
var Row,Col,i,j:Integer;
Str:String;
begin
if CanMove then begin
screen.Cursor:=crArrow;
end else
screen.cursor:=crDefault;
if not OnSelect then begin
if not MousePD then begin
j:=0;
Row:=1;
Str:=Copy(Memo1.Lines.Text,0,Memo1.SelStart);
while not (Pos(#13#10,Str)=0) do begin
str:=copy(str,Pos(#13#10,Str)+2,Memo1.SelStart-Pos(#13#10,Str));
Row:=Row+1;
end;
Col:=Length(Str);
Str:=Memo1.SelText;
while not (Pos(#13#10,Str)=0) do begin
delete(Str,1,Pos(#13#10,Str)+1);
inc(j);
end;
i:=SendMessage(TMemo(Sender).Handle,EM_CHARFROMPOS,0,MakeLParam(x,y));
CanMove:=(i>=(row-1)*65538-2*row+2+(col mod 2)+Memo1.SelStart)and(i<=(row+j-1)*65538+Memo1.SelStart+Memo1.SelLength-row-j);
end else begin
if CanMove then begin
screen.Cursor:=crDrag;
SetCaretPos(x-2,y-2);//???
end else
screen.cursor:=crDefault;
end;
end;
end;

procedure TForm1.Memo1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if CanMove then begin
Memo1.SelStart:=CurrentStart;
Memo1.SelLength:=CurrentLength;
MousePD:=True;
Abort;
end else begin
OnSelect:=True;
end;
end;

procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char);
begin
CurrentStart:=TMemo(Sender).SelStart;
CurrentLength:=TMemo(Sender).SelLength;
end;

procedure TForm1.Memo1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if MousePD and CanMove then begin
Memo1.Perform(EM_REPLACESEL,0,0);
// 此处有些问题,需移动光标到此,但setcaretpos不行! :(
// Memo1.ScreenToClient(Memo1.ClientToScreen(point(x,y)));// Perform(EM_SETSEL,10,10);
// Memo1.PasteFromClipboard;
end;
OnSelect:=False;
MousePD:=False;
CurrentStart:=TMemo(Sender).SelStart;
CurrentLength:=TMemo(Sender).SelLength;
end;

end.
 
eYes:
EM_SCROLLCARET 不是移动光标的,只是使光标出现在当前视区的。有什么好办法
移动光标吗?我上面的代码就差在这里了。

BTW:我的mail收到了吗?向你要半透明panel的那封?
 
EM_SETSEL or EM_EXSETSEL
 
下面是我参考 menxin 的代码所重新编写,并经过测试通过
//---------------------------------------------------------------------------
/******************************************************************
文本块拖动 Ver 1.00 For BCB
By Sun Yi (daxian@163.net)
1999/10/14
注意:
1. 如有好的修改,希望能够给我一份
2. 有一个BUG,拖动时插入符无法移动到文本的最后位置。
******************************************************************/
// 文本块拖动 开始
//鼠标移动事件
void __fastcall TForm1::mEditMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
TCustomEdit *mEdit = (TCustomEdit *)Sender;
int i ;

Screen->Cursor = crDefault;
i = mEdit->Perform(EM_CHARFROMPOS, 0, MakeLParam((WORD)X, (WORD)Y));
i = LOWORD(i);
if((i >= mEdit->SelStart) &amp;&amp; (i < mEdit->SelStart + mEdit->SelLength))
{
if(Sender->ClassNameIs("TMemo"))
((TMemo *)Sender)->DragMode = dmAutomatic;
else if(Sender->ClassNameIs("TEdit"))
((TEdit *)Sender)->DragMode = dmAutomatic;
Screen->Cursor = crArrow;
}
else
if(Sender->ClassNameIs("TMemo"))
((TMemo *)Sender)->DragMode = dmManual;
else if(Sender->ClassNameIs("TEdit"))
((TEdit *)Sender)->DragMode = dmManual;
}
//---------------------------------------------------------------------------
//拖移事件
void __fastcall TForm1::mEditDragOver(TObject *Sender, TObject *Source,
int X, int Y, TDragState State, bool &amp;Accept)
{
TCustomEdit *mEdit = (TCustomEdit *)Sender;
int i, cx = 0, cy = 0;

if(X < 6) cx = -1;
if(Y < 6) cy = -1;
if(X > mEdit->Width - 12) cx = 1;
if(Y > mEdit->Height - 12) cy = 1;
mEdit->Perform(EM_LINESCROLL, cx, cy);

i = mEdit->Perform(EM_CHARFROMPOS, 0, MakeLParam((WORD)X, (WORD)Y));
if(i<0)
return;
i = mEdit->Perform(EM_POSFROMCHAR, LOWORD(i), 0 );
mEdit->SetFocus();
//BUG出现的位置,根据MSDN,EM_POSFROMCHAR消息的解释与实际不符
if(i >= 0) //???(i = -1 ?)
SetCaretPos(LOWORD(i), HIWORD(i));
}
//---------------------------------------------------------------------------
//拖放事件
void __fastcall TForm1::mEditDragDrop(TObject *Sender, TObject *Source,
int X, int Y)
{
TCustomEdit *mSrcEdit = (TCustomEdit *)Source;
TCustomEdit *mEdit = (TCustomEdit *)Sender;
int i, len;
POINT mPt;

GetCaretPos(&amp;mPt);
i = mEdit->Perform(EM_CHARFROMPOS, 0,
MakeLParam((WORD)mPt.x, (WORD)mPt.y));
i = LOWORD(i);
len = mSrcEdit->SelLength;
if(mSrcEdit == mEdit)
{
if(i > mSrcEdit->SelStart + mSrcEdit->SelLength)
i -= mSrcEdit->SelLength;
else if(i > mSrcEdit->SelStart)
i = mSrcEdit->SelStart;
//在这里可用自己的方法实现
//mSrcEdit->CutToClipboard();
mSrcEdit->Perform(WM_CHAR, 0x18,
(OemKeyScan('/x03') << 16) | 0x00000001);
mEdit->SelStart = i;
}
else
{
//在这里可用自己的方法实现
//mSrcEdit->CopyToClipboard();
mSrcEdit->Perform(WM_CHAR, 0x03,
(OemKeyScan('/x03') << 16) | 0x00000001);
mEdit->SelStart = i;
}
//在这里可用自己的方法实现
//mEdit->PasteFromClipboard();
mEdit->Perform(WM_CHAR, 0x16,
(OemKeyScan('/x03') << 16) | 0x00000001);
mEdit->SelStart = mEdit->SelStart - len;
mEdit->SelLength = len;
}
// 文本块拖动 结束
//---------------------------------------------------------------------------

 
多人接受答案了。
 
后退
顶部