Wishes
Sadeq N.
sad...@yahoo.com
Hi,
You can't do that with TMemo. I guess you should use
TRichEdit or find a third-party editor. Seems, you'll
have problems with standard TRichEdit component,
since it has no support of the links and bitmaps inserting
(or any ole object). But it's only a wrapper under windows
control, and windows control has such abilityes, so you
should add them using Win Api capabilityes. Actually you
can turn on links autodetection and insert pictures in
the your form's events, but since this newsgroup is
component building related, I'll tell how to write a
TRichEdit descendant.
As regards links, you can add them manually or force
richedit to detect them automatically. To do it you need
to send EM_AUTOURLDETECT to the control.
Also you'll need to set ENM_LINK flag in the events mask,
and you'll get notification messages when user clicks or,
moves mouse under your links.
Here's example:
SendMessage(RichEdit.Handle, EM_SETEVENTMASK, 0, ENM_LINK);
SendMessage(RichEdit.Handle, EM_AUTOURLDETECT, longint(true), 0);
Notifications can be received through WM_NOTIFY message
in the form or CN_NOTIFY in the edit control.
To add pictures would be a bit complex, since you'll need
to get IRichEditOle interface from the control and use its
methods.
Check example, listed below. It's a rich edit control,
which can automatically identify links and open them
in the IE. Also it has a InsertFromFile method. You
can use it to insert pictures to the any place of the
control.
Best regards, Serge Gubenko.
____________________________________________________
unit MyRichEd;
interface
uses
Windows, Messages, Controls, Graphics, StdCtrls,
Classes, ExtCtrls, CommCtrl, SysUtils, ComCtrls,
ActiveX, RichEdit, ShellApi, OleCtnrs, ComObj, oledlg;
type
PENLink = ^TENLink;
_ReObject = record
cbStruct: DWORD;
cp: ULONG;
clsid: TCLSID;
poleobj: IOleObject;
pstg: IStorage;
polesite: IOleClientSite;
sizel: TSize;
dvAspect: Longint;
dwFlags: DWORD;
dwUser: DWORD;
end;
TReObject = _ReObject;
IRichEditOle = interface(IUnknown)
['{00020d00-0000-0000-c000-000000000046}']
function GetClientSite(out clientSite: IOleClientSite): HResult; stdcall;
function GetObjectCount: HResult; stdcall;
function GetLinkCount: HResult; stdcall;
function GetObject(iob: Longint; out reobject: TReObject;
dwFlags: DWORD): HResult; stdcall;
function InsertObject(var reobject: TReObject): HResult; stdcall;
function ConvertObject(iob: Longint; rclsidNew: TIID;
lpstrUserTypeNew: LPCSTR): HResult; stdcall;
function ActivateAs(rclsid: TIID; rclsidAs: TIID): HResult; stdcall;
function SetHostNames(lpstrContainerApp: LPCSTR;
lpstrContainerObj: LPCSTR): HResult; stdcall;
function SetLinkAvailable(iob: Longint; fAvailable: BOOL): HResult; stdcall;
function SetDvaspect(iob: Longint; dvaspect: DWORD): HResult; stdcall;
function HandsOffStorage(iob: Longint): HResult; stdcall;
function SaveCompleted(iob: Longint; const stg: IStorage): HResult; stdcall;
function InPlaceDeactivate: HResult; stdcall;
function ContextSensitiveHelp(fEnterMode: BOOL): HResult; stdcall;
function GetClipboardData(var chrg: TCharRange; reco: DWORD;
out dataobj: IDataObject): HResult; stdcall;
function ImportDataObject(dataobj: IDataObject; cf: TClipFormat;
hMetaPict: HGLOBAL): HResult; stdcall;
end;
TMyRichEdit = class(TRichEdit)
protected
FLeftIndent: integer;
FLinkDetect: boolean;
FRichEditOle: IUnknown;
procedure WMNCHitTest(var Message: TWMNCHitTest); message WM_NCHITTEST;
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
procedure CreateWnd; override;
procedure DestroyWnd; override;
procedure SetEditRect;
procedure SetLeftIndent(AValue: integer);
procedure SetLinkDetect(AValue: boolean);
public
constructor Create(AOwner: TComponent); override;
procedure InsertFromFile(AIndex: integer; const AFileName: WideString);
published
property LeftIndent: integer read FLeftIndent write SetLeftIndent;
property LinkDetect: boolean read FLinkDetect write SetLinkDetect;
end;
procedure Register;
{===============================================}
implementation
procedure Register;
begin
RegisterComponents('My Components', [TMyRichEdit]);
end;
{===============================================}
constructor TMyRichEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLeftIndent:=0;
FLinkDetect:=false;
end;
procedure TMyRichEdit.CreateWnd;
begin
inherited CreateWnd;
SendMessage(Handle, EM_SETEVENTMASK, 0, ENM_LINK);
SendMessage(Handle, EM_AUTOURLDETECT, longint(FLinkDetect), 0);
SendMessage(Handle, EM_GETOLEINTERFACE, 0, Longint(@FRichEditOle))
end;
procedure TMyRichEdit.DestroyWnd;
begin
FRichEditOle:=nil;
inherited DestroyWnd;
end;
procedure TMyRichEdit.CNNotify(var Message: TWMNotify);
var
XLinkText: string;
begin
inherited;
with Message do
case NMHdr^.code of
EN_LINK: with PENLink(NMHdr)^ do begin
case Msg of
WM_LBUTTONDOWN: begin
if (chrg.cpMin=0) and (chrg.cpMax<0)
then XLinkText:=Text
else XLinkText:=copy(Text, chrg.cpMin+1, chrg.cpMax-chrg.cpMin);
ShellApi.ShellExecute(0, 'Open', PChar(XLinkText),
nil, nil, SW_SHOW);
end;
end;
end;
end;
end;
procedure TMyRichEdit.WMNCHitTest(var Message: TWMNCHitTest);
begin
inherited;
if (Message.Result=HTBORDER)
then Message.Result:=HTCLIENT;
end;
procedure TMyRichEdit.SetEditRect;
var
XRect: TRect;
begin
SendMessage(Handle, EM_GETRECT, 0, integer(@XRect));
XRect.Left:=FLeftIndent;
SendMessage(Handle, EM_SETRECT, 0, integer(@XRect));
end;
procedure TMyRichEdit.InsertFromFile(AIndex: integer; const AFileName: WideString);
var
XRichOLE: IRichEditOle;
XOleClientSite: IOleClientSite;
XReObject: TReObject;
XOLEObject: IOLEObject;
XStorage: IStorage;
procedure xxCreateStorage(var AStorage: IStorage);
var
XLockBytes: ILockBytes;
begin
OleCheck(CreateILockBytesOnHGlobal(0, true, XLockBytes));
try
OleCheck(StgCreateDocfileOnILockBytes(XLockBytes,
STGM_READWRITE or STGM_SHARE_EXCLUSIVE or STGM_CREATE,
0, AStorage));
finally
XLockBytes:=nil;
end;
end;
begin
SendMessage(Handle, EM_GETOLEINTERFACE, 0, integer(@XRichOLE));
if Assigned(XRichOLE) then begin
try
FillChar(XReObject, sizeOf(TReObject), 0);
IRichEditOle(FRichEditOle).GetClientSite(XOleClientSite);
xxCreateStorage(XStorage);
OleCheck(OleCreateFromFile(GUID_NULL, PWideChar(AFileName),
IOleObject, OLERENDER_DRAW, nil,
XOleClientSite, XStorage, XOleObject));
XReObject.cbStruct:=SizeOf(TReObject);
XReObject.cp:=AIndex;
XOleObject.GetUserClassID(XReObject.clsid);
XReObject.poleobj:=XOleObject;
XReObject.pstg:=XStorage;
XReObject.polesite:=XOleClientSite;
XReObject.dwFlags:=1;
XReObject.dvAspect:=DVASPECT_CONTENT;
XRichOLE.InsertObject(XReObject);
finally
XStorage:=nil;
XRichOLE:=nil;
XOleClientSite:=nil;
end;
end;
end;
procedure TMyRichEdit.SetLeftIndent(AValue: integer);
begin
if FLeftIndent<>AValue then begin
FLeftIndent:=AValue;
SetEditRect;
end;
end;
procedure TMyRichEdit.SetLinkDetect(AValue: boolean);
begin
if FLinkDetect<>AValue then begin
FLinkDetect:=AValue;
RecreateWnd;
end;
end;
end.