You are here:

Delphi/Dragging Memos code

Advertisement


Question
QUESTION: Hi Randy,

I found this code below when browsing and its for Dragging between two Memos.
The author advised to turn it into a component and install it.
So I added the Register stuff and tried to install it.

type
 TMyMemo = class(TMemo)
 private
   FLastSelStart  : Integer;
   FLastSelLength : Integer;
   procedure WMLButtonDown(var Message: TWMLButtonDown);
     message WM_LBUTTONDOWN;
 published
   property LastSelStart : Integer read FLastSelStart
     write FLastSelStart;
   property LastSelLength : Integer read FLastSelLength
     write FLastSelLength;
 end;

Make the implementation of WMLButtonDown look like this:

procedure TMyMemo.WMLButtonDown(var Message: TWMLButtonDown);
var
 Ch : Integer;
begin
 if SelLength  0 then begin
   Ch := LoWord(Perform(EM_CHARFROMPOS,0,
         MakeLParam(Message.XPos,Message.YPos)));
   LastSelStart := SelStart;
   LastSelLength := SelLength;
   if (Ch = SelStart) and (Ch       BeginDrag(True)
   else
     inherited;
 end
 else
   inherited;
end;

Its the WMLButtonDown procedure that gives problems.
I don't really understand it and whatever I modify gives a different error
message.  Any ideas why it won't compile?

Thanks

Michael

ANSWER: It could possibly be the uses clause as you need several units to implement this code.  Here how it should look:

unit MyMemo;

interface

uses
 SysUtils, Classes, Controls, StdCtrls, Messages, Windows;

type
 TMyMemo = class(TMemo)
 private
   FLastSelStart: Integer;
   FLastSelLength: Integer;
   procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;
 published
   property LastSelStart : Integer read FLastSelStart write FLastSelStart;
   property LastSelLength : Integer read FLastSelLength write FLastSelLength;
 end;

procedure Register;

implementation

procedure Register;
begin
 RegisterComponents('Samples', [TMyMemo]);
end;

{ TMyMemo }

procedure TMyMemo.WMLButtonDown(var Message: TWMLButtonDown);
var
 Ch: Integer;
begin
 if SelLength > 0 then begin
   Ch := LoWord(Perform(EM_CHARFROMPOS, 0, MakeLParam(Message.XPos, Message.YPos)));
   LastSelStart := SelStart;
   LastSelLength := SelLength;
   if (Ch >= SelStart) and (Ch <= SelStart + SelLength - 1) then
     BeginDrag(True)
   else
     inherited;
 end
 else
   inherited;
end;

end.


---------- FOLLOW-UP ----------

QUESTION: Thanks Randy your component code installed without any problems.

The Author provided code for two events - the first

procedure TForm1.MyMemo1DragOver(Sender, Source: TObject; X, Y: Integer;
 State: TDragState; var Accept: Boolean);
begin
 Accept := Source is TMyMemo;
end;

is of course simple and compiles ok.

The second is the problem

procedure TForm1.MyMemo1DragDrop(Sender, Source: TObject;
         X, Y: Integer);
var
 Dst, Src : TMyMemo;
 Ch       : Integer;
 Temp     : String;
begin
 Dst := Sender as TMyMemo;
 Src := Source as TMyMemo;
 Ch := LoWord(Dst.Perform(EM_CHARFROMPOS,0,MakeLParam(X,Y)));

 if (Src = Dst) and (Ch = Src.LastSelStart) and
    (Ch     Exit;

 Dst.Text := Copy(Dst.Text,1,Ch)+Src.SelText+
         Copy(Dst.Text,Ch+1,Length(Dst.Text)-Ch);
 Temp := Src.Text;
 Delete(Temp,Src.LastSelStart+1,Src.LastSelLength);
 Src.Text := Temp;
end;


The compiler stops by the (ch  exit; part
with the error   ) expected but exit found
Again I've tried to put it right but without success

Michael

Answer
Looks like you have code that's missing content due to bad copy/paste.  Here's what I was able to come up with.

procedure TForm1.MyMemo1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
 Accept := Source is TMyMemo;
end;

procedure TForm1.MyMemo1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
 Dst : TMyMemo;
 Src : TMyMemo;
 Ch  : Integer;
 Temp: String;
begin
 Dst := Sender as TMyMemo;
 Src := Source as TMyMemo;
 Ch := LoWord(Dst.Perform(EM_CHARFROMPOS, 0, MakeLParam(X, Y)));
 if (Src = Dst) and (Ch >= Src.LastSelStart) and (Ch <= Src.LastSelStart+Src.LastSelLength-1) then
   Exit;
 Dst.Text := Copy(Dst.Text, 1, Ch) + Src.SelText +
   Copy(Dst.Text, Ch + 1, Length(Dst.Text) - Ch);
 Temp := Src.Text;
 Delete(Temp, Src.LastSelStart + 1, Src.LastSelLength);
 Src.Text := Temp;
end;


Here's another sample that allows you to drag from your Memo to an edit control.


procedure TForm1.Edit1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
 Accept := Source is TMyMemo;
end;

procedure TForm1.Edit1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
 Dst : TEdit;
 Src : TMyMemo;
 Ch  : Integer;
 Temp: String;
begin
 Dst := Sender as TEdit;
 Src := Source as TMyMemo;
 Ch := LoWord(Dst.Perform(EM_CHARFROMPOS, 0, MakeLParam(X, Y)));
 Dst.Text := Copy(Dst.Text, 1, Ch) + Src.SelText +
   Copy(Dst.Text, Ch + 1, Length(Dst.Text) - Ch);
 Temp := Src.Text;
 Delete(Temp, Src.LastSelStart + 1, Src.LastSelLength);
 Src.Text := Temp;
end;  

Delphi

All Answers


Answers by Expert:


Ask Experts

Volunteer


Randy Sill

Expertise

Turbo Pascal and Delphi developer since 1986. Strengths - UI, Windows API, Database, SQL, Internet, Threading, NT Services.

Experience

Turbo Pascal and Delphi developer since 1986.

Education/Credentials
Delphi 5 Certification, Borland

Awards and Honors
2005 Indiana IT/Software Million Dollar Award, Key Technical Contributor

©2016 About.com. All rights reserved.