Delphi5开发人员指南中有个扩展TMemo的例子: { Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira }unit ExMemo;interfaceuses Windows, Messages, Classes, StdCtrls;type TExtendedMemo = 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;procedure Register;implementationprocedure TExtendedMemo.WMHScroll(var Msg: TWMHScroll); begin inherited; HScroll; end;procedure TExtendedMemo.WMVScroll(var Msg: TWMVScroll); begin inherited; VScroll; end;procedure TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 retuns the index of the curent line. Subtracting SelStart from this value returns the column position } Result := SelStart - Perform(EM_LINEINDEX, -1, 0); end;procedure Register; begin RegisterComponents('DDG', [TExtendedMemo]); end;end.// 测试部分代码 procedure TMainForm.btnSetRowColClick(Sender: TObject); begin EMemo.Row := StrToInt(edtRow.Text); EMemo.Column := StrToInt(edtColumn.Text); EMemo.SetFocus; end;
{
Copyright ?1999 by Delphi 5 Developer's Guide - Xavier Pacheco and Steve Teixeira
}unit ExMemo;interfaceuses
Windows, Messages, Classes, StdCtrls;type TExtendedMemo = 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;procedure Register;implementationprocedure TExtendedMemo.WMHScroll(var Msg: TWMHScroll);
begin
inherited;
HScroll;
end;procedure TExtendedMemo.WMVScroll(var Msg: TWMVScroll);
begin
inherited;
VScroll;
end;procedure TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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 TExtendedMemo.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
retuns the index of the curent line. Subtracting SelStart from this
value returns the column position }
Result := SelStart - Perform(EM_LINEINDEX, -1, 0);
end;procedure Register;
begin
RegisterComponents('DDG', [TExtendedMemo]);
end;end.// 测试部分代码
procedure TMainForm.btnSetRowColClick(Sender: TObject);
begin
EMemo.Row := StrToInt(edtRow.Text);
EMemo.Column := StrToInt(edtColumn.Text);
EMemo.SetFocus;
end;