Code:
unit ExtMemo;
interface
uses
Windows, Messages, Classes, StdCtrls;
type
TddgExtendedMemo = class(TMemo)
private
FRow: Longint;FColumn: Longint;
FOnHScroll: TNotifyEvent;
FOnVScroll: TNotifyEvent;
procedure WMHScroll(var Msg: TWMHScroll); message WM_HSCROLL;
procedure WMVScroll(var Msg: TWMVScroll); message WM_VSCROLL;
procedure SetRow(Value: Longint);
procedure SetColumn(Value: Longint);
function GetRow: Longint;
function GetColumn: Longint;
protected
// Event dispatching methods
procedure HScroll; dynamic;
procedure VScroll; dynamic;
public
property Row: Longint read GetRow write SetRow;
property Column: Longint read GetColumn write SetColumn;
published
property OnHScroll: TNotifyEvent read FOnHScroll write FOnHScroll;
property OnVScroll: TNotifyEvent read FOnVScroll write FOnVScroll;
end;
implementation
procedure TddgExtendedMemo.WMHScroll(var Msg: TWMHScroll);
begin
inherited;
HScroll;
end;
procedure TddgExtendedMemo.WMVScroll(var Msg: TWMVScroll);
begin
inherited;
VScroll;
end;
procedure TddgExtendedMemo.HScroll;
{ This is the OnHScroll event dispatch method. It checks to see
if OnHScroll points to an event handler and calls it if it does. }
begin
if Assigned(FOnHScroll) then
FOnHScroll(self);
end;
procedure TddgExtendedMemo.VScroll;
{ This is the OnVScroll event dispatch method. It checks to see
if OnVScroll points to an event handler and calls it if it does. }
begin
{ if Assigned(FOnVScroll) then }
{ FOnVScroll(self); }
end;
procedure TddgExtendedMemo.SetRow(Value: Longint);
{
{ The EM_LINEINDEX returns the character position of the first }
{ character in the line specified by wParam. The Value is used for }
{ wParam in this instance. Setting SelStart to this return value }
{ positions the caret on the line specified by Value. }
}
begin
SelStart := Perform(EM_LINEINDEX, Value, 0);
FRow := SelStart;
end;
function TddgExtendedMemo.GetRow: Longint;
{ The EM_LINEFROMCHAR returns the line in which the character specified
by wParam sits. If -1 is passed as wParam, the line number at which
the caret sits is returned. }
begin
Result := Perform(EM_LINEFROMCHAR, -1, 0);
end;
procedure TddgExtendedMemo.SetColumn(Value: Longint);
begin
{ Get the length of the current line using the EM_LINELENGTH
message. This message takes a character position as WParam.
The length of the line in which that character sits is returned. }
FColumn := Perform(EM_LINELENGTH, Perform(EM_LINEINDEX, GetRow, 0), 0);
{ If the FColumn is greater than the value passed in, then set
FColumn to the value passed in }
if FColumn > Value then
FColumn := Value;
// Now set SelStart to the newly specified position
SelStart := Perform(EM_LINEINDEX, GetRow, 0) + FColumn;
end;
function TddgExtendedMemo.GetColumn: Longint;
begin
{ The EM_LINEINDEX message returns the line index of a specified
character passed in as wParam. When wParam is -1 then it
returns the index of the current line. Subtracting SelStart from this
value returns the column position }
Result := SelStart - Perform(EM_LINEINDEX, -1, 0);
end;
end.
I am using Embarcadero Delphi 10 community edition.
I wanted some code that would add an OnScroll event to a TMemo, and the code I posted here works well. It is not my code. It is from "Borland Delphi 6 Developer's Guide".
However, the TddgExtendedMemo.GetColumn method,and the TddgExtendedMemo.GetRow method do not work. And I would like to know if the code was wrong even in the Dephi 6 era, or if the definition of EM_LINEFROMCHAR, and the definition of EM_LINEINDEX, has changed since Delphi 6.
Comments and/or observations welcomed.