home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 April
/
Chip_1997-04_cd.bin
/
prezent
/
cb
/
data.z
/
DDEMAN.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1997-01-16
|
46KB
|
1,793 lines
{*******************************************************}
{ }
{ Delphi Visual Component Library }
{ }
{ Copyright (c) 1995,96 Borland International }
{ }
{*******************************************************}
unit DdeMan;
{$R-}
interface
uses
Windows, Classes, Graphics, Forms, Controls, DDEML, StdCtrls;
type
TDataMode = (ddeAutomatic, ddeManual);
TDdeServerConv = class;
TMacroEvent = procedure(Sender: TObject; Msg: TStrings) of object;
TDdeClientItem = class;
{ TDdeClientConv }
TDdeClientConv = class(TComponent)
private
FDdeService: string;
FDdeTopic: string;
FConv: HConv;
FCnvInfo: TConvInfo;
FItems: TList;
FHszApp: HSZ;
FHszTopic: HSZ;
FDdeFmt: Integer;
FOnClose: TNotifyEvent;
FOnOpen: TNotifyEvent;
FAppName: string;
FDataMode: TDataMode;
FConnectMode: TDataMode;
FWaitStat: Boolean;
FFormatChars: Boolean;
procedure SetDdeService(const Value: string);
procedure SetDdeTopic(const Value: string);
procedure SetService(const Value: string);
procedure SetTopic(const Value: string);
procedure SetConnectMode(NewMode: TDataMode);
procedure SetFormatChars(NewFmt: Boolean);
procedure XactComplete;
procedure SrvrDisconnect;
procedure DataChange(DdeDat: HDDEData; hszIt: HSZ);
protected
function CreateDdeConv(FHszApp: HSZ; FHszTopic: HSZ): Boolean;
function GetCliItemByName(const ItemName: string): TPersistent;
function GetCliItemByCtrl(ACtrl: TDdeClientItem): TPersistent;
procedure Loaded; override;
procedure DefineProperties(Filer: TFiler); override;
procedure ReadLinkInfo(Reader: TReader);
procedure WriteLinkInfo(Writer: TWriter);
function OnSetItem(aCtrl: TDdeClientItem; const S: string): Boolean;
procedure OnAttach(aCtrl: TDdeClientItem);
procedure OnDetach(aCtrl: TDdeClientItem);
procedure Close; dynamic;
procedure Open; dynamic;
function ChangeLink(const App, Topic, Item: string): Boolean;
procedure ClearItems;
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function PasteLink: Boolean;
function OpenLink: Boolean;
function SetLink(const Service, Topic: string): Boolean;
procedure CloseLink;
function StartAdvise: Boolean;
function PokeDataLines(const Item: string; Data: TStrings): Boolean;
function PokeData(const Item: string; Data: PChar): Boolean;
function ExecuteMacroLines(Cmd: TStrings; waitFlg: Boolean): Boolean;
function ExecuteMacro(Cmd: PChar; waitFlg: Boolean): Boolean;
function RequestData(const Item: string): PChar;
property DdeFmt: Integer read FDdeFmt;
property WaitStat: Boolean read FWaitStat;
property Conv: HConv read FConv;
property DataMode: TDataMode read FDataMode write FDataMode;
published
property ServiceApplication: string read FAppName write FAppName;
property DdeService: string read FDdeService write SetDdeService;
property DdeTopic: string read FDdeTopic write SetDdeTopic;
property ConnectMode: TDataMode read FConnectMode write SetConnectMode default ddeAutomatic;
property FormatChars: Boolean read FFormatChars write SetFormatChars default False;
property OnClose: TNotifyEvent read FOnClose write FOnClose;
property OnOpen: TNotifyEvent read FOnOpen write FOnOpen;
end;
{ TDdeClientItem }
TDdeClientItem = class(TComponent)
private
FLines: TStrings;
FDdeClientConv: TDdeClientConv;
FDdeClientItem: string;
FOnChange: TNotifyEvent;
function GetText: string;
procedure SetDdeClientItem(const Val: string);
procedure SetDdeClientConv(Val: TDdeClientConv);
procedure SetText(const S: string);
procedure SetLines(L: TStrings);
procedure OnAdvise;
protected
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
property Text: string read GetText write SetText;
property Lines: TStrings read FLines write SetLines;
property DdeConv: TDdeClientConv read FDdeClientConv write SetDdeClientConv;
property DdeItem: string read FDdeClientItem write SetDdeClientItem;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;
{ TDdeServerConv }
TDdeServerConv = class(TComponent)
private
FOnOpen: TNotifyEvent;
FOnClose: TNotifyEvent;
FOnExecuteMacro: TMacroEvent;
protected
procedure Connect; dynamic;
procedure Disconnect; dynamic;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function ExecuteMacro(Data: HDdeData): LongInt;
published
property OnOpen: TNotifyEvent read FOnOpen write FOnOpen;
property OnClose: TNotifyEvent read FOnClose write FOnClose;
property OnExecuteMacro: TMacroEvent read FOnExecuteMacro write FOnExecuteMacro;
end;
{ TDdeServerItem }
TDdeServerItem = class(TComponent)
private
FLines: TStrings;
FServerConv: TDdeServerConv;
FOnChange: TNotifyEvent;
FOnPokeData: TNotifyEvent;
FFmt: Integer;
procedure ValueChanged;
protected
function GetText: string;
procedure SetText(const Item: string);
procedure SetLines(Value: TStrings);
procedure SetServerConv(SConv: TDdeServerConv);
procedure Notification(AComponent: TComponent;
Operation: TOperation); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function PokeData(Data: HDdeData): LongInt;
procedure CopyToClipboard;
procedure Change; dynamic;
property Fmt: Integer read FFmt;
published
property ServerConv: TDdeServerConv read FServerConv write SetServerConv;
property Text: string read GetText write SetText;
property Lines: TStrings read FLines write SetLines;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnPokeData: TNotifyEvent read FOnPokeData write FOnPokeData;
end;
{ TDdeMgr }
TDdeMgr = class(TComponent)
private
FAppName: string;
FHszApp: HSZ;
FConvs: TList;
FCliConvs: TList;
FConvCtrls: TList;
FDdeInstId: Longint;
FLinkClipFmt: Word;
procedure Disconnect(DdeSrvrConv: TComponent);
function GetSrvrConv(const Topic: string ): TComponent;
function AllowConnect(hszApp: HSZ; hszTopic: HSZ): Boolean;
function AllowWildConnect(hszApp: HSZ; hszTopic: HSZ): HDdeData;
function Connect(Conv: HConv; hszTopic: HSZ; SameInst: Boolean): Boolean;
procedure PostDataChange(const Topic: string; Item: string);
procedure SetAppName(const Name: string);
procedure ResetAppName;
function GetServerConv(const Topic: string): TDdeServerConv;
procedure InsertServerConv(SConv: TDdeServerConv);
procedure RemoveServerConv(SConv: TDdeServerConv);
procedure DoError;
function GetForm(const Topic: string): TForm;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function GetExeName: string; // obsolete
property DdeInstId: LongInt read FDdeInstId write FDdeInstId;
property AppName: string read FAppName write SetAppName;
property LinkClipFmt: Word read FLinkClipFmt;
end;
function GetPasteLinkInfo(var Service: string; var Topic: string;
var Item: string): Boolean;
var
ddeMgr: TDdeMgr;
implementation
uses SysUtils, Dialogs, Consts, Clipbrd;
type
EDdeError = class(Exception);
TDdeSrvrConv = class;
{ TDdeSrvrItem }
TDdeSrvrItem = class(TComponent)
private
FConv: TDdeSrvrConv;
FItem: string;
FHszItem: HSZ;
FSrvr: TDdeServerItem;
protected
procedure SetItem(const Value: string);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function RequestData(Fmt: Word): HDdeData;
procedure PostDataChange;
property Conv: TDdeSrvrConv read FConv write FConv;
property Item: string read FItem write SetItem;
property Srvr: TDdeServerItem read FSrvr write FSrvr;
property HszItem: HSZ read FHszItem;
end;
{ TDdeSrvrConv }
TDdeSrvrConv = class(TComponent)
private
FTopic: string;
FHszTopic: HSZ;
FForm: TForm;
FSConv: TDdeServerConv;
FConv: HConv;
FCnvInfo: TConvInfo;
FDdeFmt: Integer;
FItems: TList;
protected
function GetControl(WinCtrl: TWinControl; DdeConv: TDdeServerConv; const ItemName: string): TDdeServerItem;
function GetSrvrItem(hszItem: HSZ): TDdeSrvrItem;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function RequestData(Conv: HConv; hszTopic: HSZ; hszItem: HSZ;
Fmt: Word): HDdeData;
function AdvStart(Conv: HConv; hszTopic: HSZ; hszItem: HSZ;
Fmt: Word): Boolean;
procedure AdvStop(Conv: HConv; hszTopic: HSZ; hszItem: HSZ);
function PokeData(Conv: HConv; hszTopic: HSZ; hszItem: HSZ; Data: HDdeData;
Fmt: Integer): LongInt;
function ExecuteMacro(Conv: HConv; hszTopic: HSZ; Data: HDdeData): Integer;
function GetItem(const ItemName: string): TDdeSrvrItem;
property Conv: HConv read FConv;
property Form: TForm read FForm;
property SConv: TDdeServerConv read FSConv;
property Topic: string read FTopic write FTopic;
property HszTopic: HSZ read FHszTopic;
end;
{ TDdeCliItem }
TDdeCliItem = class(TPersistent)
protected
FItem: string;
FHszItem: HSZ;
FCliConv: TDdeClientConv;
FCtrl: TDdeClientItem;
function StartAdvise: Boolean;
function StopAdvise: Boolean;
procedure StoreData(DdeDat: HDDEData);
procedure DataChange;
function AccessData(DdeDat: HDDEData; pDataLen: PDWORD): Pointer;
procedure ReleaseData(DdeDat: HDDEData);
public
constructor Create(ADS: TDdeClientConv);
destructor Destroy; override;
function RefreshData: Boolean;
function SetItem(const S: string): Boolean;
procedure SrvrDisconnect;
property HszItem: HSZ read FHszItem;
property Control: TDdeClientItem read FCtrl write FCtrl;
published
property Item: string read FItem;
end;
procedure DDECheck(Success: Boolean);
var
err: Integer;
ErrStr: string;
begin
if Success then Exit;
err := DdeGetLastError(DDEMgr.DdeInstId);
case err of
DMLERR_LOW_MEMORY, DMLERR_MEMORY_ERROR:
ErrStr := FmtLoadStr(SDdeMemErr, [err]);
DMLERR_NO_CONV_ESTABLISHED:
ErrStr := FmtLoadStr(SDdeConvErr, [err]);
else
ErrStr := FmtLoadStr(SDdeErr, [err]);
end;
raise EDdeError.Create(ErrStr);
end;
function DdeMgrCallBack(CallType, Fmt : UINT; Conv: HConv; hsz1, hsz2: HSZ;
Data: HDDEData; Data1, Data2: DWORD): HDDEData; stdcall;
var
ci: TConvInfo;
ddeCli: TComponent;
ddeSrv: TDdeSrvrConv;
ddeObj: TComponent;
xID: Integer;
begin
Result := 0;
case CallType of
XTYP_CONNECT:
Result := HDdeData(ddeMgr.AllowConnect(hsz2, hsz1));
XTYP_WILDCONNECT:
Result := ddeMgr.AllowWildConnect(hsz2, hsz1);
XTYP_CONNECT_CONFIRM:
ddeMgr.Connect(Conv, hsz1, Boolean(Data2));
end;
if Conv <> 0 then
begin
ci.cb := sizeof(TConvInfo);
if CallType = XTYP_XACT_COMPLETE then
xID := Data1
else
xID := QID_SYNC;
if DdeQueryConvInfo(Conv, xID, @ci) = 0 then Exit;
case CallType of
XTYP_ADVREQ:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
Result := ddeSrv.RequestData(Conv, hsz1, hsz2, Fmt);
end;
XTYP_REQUEST:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
Result := ddeSrv.RequestData(Conv, hsz1, hsz2, Fmt);
end;
XTYP_ADVSTOP:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
ddeSrv.AdvStop(Conv, hsz1, hsz2);
end;
XTYP_ADVSTART:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
Result := HDdeData(ddeSrv.AdvStart(Conv, hsz1, hsz2, Fmt));
end;
XTYP_POKE:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
Result := HDdeData(ddeSrv.PokeData(Conv, hsz1, hsz2, Data, Fmt));
end;
XTYP_EXECUTE:
begin
ddeSrv := TDdeSrvrConv(ci.hUser);
Result := HDdeData(ddeSrv.ExecuteMacro(Conv, hsz1, Data));
end;
XTYP_XACT_COMPLETE:
begin
ddeCli := TComponent(ci.hUser);
if ddeCli <> nil then TDdeClientConv(ddeCli).XactComplete
end;
XTYP_ADVDATA:
begin
ddeCli := TComponent(ci.hUser);
TDdeClientConv(ddeCli).DataChange(Data, hsz2);
end;
XTYP_DISCONNECT:
begin
ddeObj := TComponent(ci.hUser);
if ddeObj <> nil then
begin
if ddeObj is TDdeClientConv then
TDdeClientConv(ddeObj).SrvrDisconnect
else
ddeMgr.Disconnect(ddeObj);
end;
end;
end;
end;
end;
function GetPasteLinkInfo(var Service, Topic, Item: string): Boolean;
var
hData: THandle;
pData: Pointer;
P: PChar;
begin
Result := False;
Clipboard.Open;
hData := Clipboard.GetAsHandle(ddeMgr.LinkClipFmt);
if hData <> 0 then
begin
pData := GlobalLock(hData);
try
P := PChar(pData);
Service := PChar(pData);
P := P + Length(Service) + 1;
Topic := P;
P := P + Length(Topic) + 1;
Item := P;
finally
GlobalUnlock(hData);
end;
Result := True;
end;
Clipboard.Close;
end;
{ TDdeMgr }
constructor TDdeMgr.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLinkClipFmt := RegisterClipboardFormat('Link');
FDdeInstId := 0;
DDECheck(DdeInitialize(FDdeInstId, DdeMgrCallBack, APPCLASS_STANDARD, 0) = 0);
FConvs := TList.Create;
FCliConvs := TList.Create;
FConvCtrls := TList.Create;
AppName := ParamStr(0);
end;
destructor TDdeMgr.Destroy;
var
I: Integer;
begin
if FConvs <> nil then
begin
for I := 0 to FConvs.Count - 1 do
TDdeSrvrConv(FConvs[I]).Free;
FConvs.Free;
FConvs := nil;
end;
if FCliConvs <> nil then
begin
for I := 0 to FCliConvs.Count - 1 do
TDdeSrvrConv(FCliConvs[I]).Free;
FCliConvs.Free;
FCliConvs := nil;
end;
if FConvCtrls <> nil then
begin
FConvCtrls.Free;
FConvCtrls := nil;
end;
ResetAppName;
DdeUnInitialize(FDdeInstId);
inherited Destroy;
end;
function TDdeMgr.AllowConnect(hszApp: HSZ; hszTopic: HSZ): Boolean;
var
Topic: string;
Buffer: array[0..4095] of Char;
Form: TForm;
SConv: TDdeServerConv;
begin
Result := False;
if (hszApp = 0) or (DdeCmpStringHandles(hszApp, FHszApp) = 0) then
begin
SetString(Topic, Buffer, DdeQueryString(FDdeInstId, hszTopic, Buffer,
SizeOf(Buffer), CP_WINANSI));
SConv := GetServerConv(Topic);
if SConv <> nil then
Result := True
else begin
Form := GetForm(Topic);
if Form <> nil then Result := True;
end;
end;
end;
function TDdeMgr.AllowWildConnect(hszApp: HSZ; hszTopic: HSZ): HDdeData;
var
conns: packed array[0..1] of THSZPair;
begin
Result := 0;
if hszTopic = 0 then Exit;
if AllowConnect(hszApp, hszTopic) = True then
begin
conns[0].hszSvc := FHszApp;
conns[0].hszTopic := hszTopic;
conns[1].hszSvc := 0;
conns[1].hszTopic := 0;
Result := DdeCreateDataHandle(ddeMgr.DdeInstId, @conns,
2 * sizeof(THSZPair), 0, 0, CF_TEXT, 0);
end;
end;
function TDdeMgr.Connect(Conv: HConv; hszTopic: HSZ; SameInst: Boolean): Boolean;
var
Topic: string;
Buffer: array[0..4095] of Char;
DdeConv: TDdeSrvrConv;
begin
DdeConv := TDdeSrvrConv.Create(Self);
SetString(Topic, Buffer, DdeQueryString(FDdeInstId, hszTopic, Buffer,
SizeOf(Buffer), CP_WINANSI));
DdeConv.Topic := Topic;
DdeConv.FSConv := GetServerConv(Topic);
if DdeConv.FSConv = nil then
DdeConv.FForm := GetForm(Topic);
DdeConv.FConv := Conv;
DdeSetUserHandle(Conv, QID_SYNC, LongInt(DdeConv));
FConvs.Add(DdeConv);
if DdeConv.FSConv <> nil then DdeConv.FSConv.Connect;
Result := True;
end;
procedure TDdeMgr.Disconnect(DdeSrvrConv: TComponent);
var
DdeConv: TDdeSrvrConv;
begin
DdeConv := TDdeSrvrConv(DdeSrvrConv);
if DdeConv.FSConv <> nil then DdeConv.FSConv.Disconnect;
if DdeConv.FConv <> 0 then DdeSetUserHandle(DdeConv.FConv, QID_SYNC, 0);
DdeConv.FConv := 0;
if FConvs <> nil then
begin
FConvs.Remove(DdeConv);
DdeConv.Free;
end;
end;
function TDdeMgr.GetExeName: string;
begin
Result := ParamStr(0);
end;
procedure TDdeMgr.SetAppName(const Name: string);
var
Dot: Integer;
begin
ResetAppName;
FAppName := ExtractFileName(Name);
Dot := Pos('.', FAppName);
if Dot <> 0 then
Delete(FAppName, Dot, Length(FAppName));
FHszApp := DdeCreateStringHandle(FDdeInstId, PChar(FAppName), CP_WINANSI);
DdeNameService(FDdeInstId, FHszApp, 0, DNS_REGISTER);
end;
procedure TDdeMgr.ResetAppName;
begin
if FHszApp <> 0 then
begin
DdeNameService(FDdeInstId, FHszApp, 0, DNS_UNREGISTER);
DdeFreeStringHandle(FDdeInstId, FHszApp);
end;
FHszApp := 0;
end;
function TDdeMgr.GetServerConv(const Topic: string): TDdeServerConv;
var
I: Integer;
SConv: TDdeServerConv;
begin
Result := nil;
for I := 0 to FConvCtrls.Count - 1 do
begin
SConv := TDdeServerConv(FConvCtrls[I]);
if AnsiCompareText(SConv.Name, Topic) = 0 then
begin
Result := SConv;
Exit;
end;
end;
end;
function TDdeMgr.GetForm(const Topic: string): TForm;
var
I: Integer;
Form: TForm;
begin
Result := nil;
for I := 0 to Screen.FormCount - 1 do
begin
Form := TForm(Screen.Forms[I]);
if AnsiCompareText(Form.Caption, Topic) = 0 then
begin
Result := Form;
Exit;
end;
end;
end;
function TDdeMgr.GetSrvrConv(const Topic: string ): TComponent;
var
I: Integer;
Conv: TDdeSrvrConv;
begin
Result := nil;
for I := 0 to FConvs.Count - 1 do
begin
Conv := FConvs[I];
if AnsiCompareText(Conv.Topic, Topic) = 0 then
begin
Result := Conv;
Exit;
end;
end;
end;
procedure TDdeMgr.PostDataChange(const Topic: string; Item: string);
var
Conv: TDdeSrvrConv;
Itm: TDdeSrvrItem;
begin
Conv := TDdeSrvrConv(GetSrvrConv (Topic));
If Conv <> nil then
begin
Itm := Conv.GetItem(Item);
if Itm <> nil then Itm.PostDataChange;
end;
end;
procedure TDdeMgr.InsertServerConv(SConv: TDdeServerConv);
begin
FConvCtrls.Insert(FConvCtrls.Count, SConv);
end;
procedure TDdeMgr.RemoveServerConv(SConv: TDdeServerConv);
begin
FConvCtrls.Remove(SConv);
end;
procedure TDdeMgr.DoError;
begin
DDECheck(False);
end;
constructor TDdeClientConv.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := TList.Create;
end;
destructor TDdeClientConv.Destroy;
begin
CloseLink;
FItems.Free;
FItems := nil;
inherited Destroy;
end;
procedure TDdeClientConv.DefineProperties(Filer: TFiler);
begin
inherited DefineProperties(Filer);
Filer.DefineProperty('LinkInfo', ReadLinkInfo, WriteLinkInfo,
not ((DdeService = '') and (DdeTopic = '')));
end;
procedure TDdeClientConv.Loaded;
var
Service, Topic: string;
begin
inherited Loaded;
Service := DdeService;
Topic := DdeTopic;
if (Length(Service) <> 0) and (ConnectMode <> ddeManual) then
ChangeLink(Service, Topic, '');
end;
procedure TDdeClientConv.ReadLinkInfo (Reader: TReader);
var
Value: string;
Text: string;
Temp: Integer;
begin
Reader.ReadListBegin;
while not Reader.EndOfList do
begin
Value := Reader.ReadString;
Temp := Pos(' ', Value);
Text := Copy(Value, Temp + 1, Length (Value) - Temp);
case Value[1] of
'S': SetService(Text);
'T': SetTopic(Text);
end;
end;
Reader.ReadListEnd;
end;
procedure TDdeClientConv.WriteLinkInfo (Writer: TWriter);
var
Value: string;
begin
Writer.WriteListBegin;
Value := DdeService;
Writer.WriteString(Format('Service %s', [Value]));
Value := DdeTopic;
Writer.WriteString(Format('Topic %s', [Value]));
Writer.WriteListEnd;
end;
procedure TDdeClientConv.OnAttach(aCtrl: TDdeClientItem);
var
ItemLnk: TDdeCliItem;
begin
ItemLnk := TDdeCliItem.Create(Self);
FItems.Insert(FItems.Count, ItemLnk);
ItemLnk.Control := aCtrl;
ItemLnk.SetItem('');
end;
procedure TDdeClientConv.OnDetach(aCtrl: TDdeClientItem);
var
ItemLnk: TDdeCliItem;
begin
ItemLnk := TDdeCliItem(GetCliItemByCtrl(aCtrl));
if ItemLnk <> nil then
begin
ItemLnk.SetItem('');
FItems.Remove(ItemLnk);
ItemLnk.Free;
end;
end;
function TDdeClientConv.OnSetItem(aCtrl: TDdeClientItem; const S: string): Boolean;
var
ItemLnk: TDdeCliItem;
begin
Result := True;
ItemLnk := TDdeCliItem(GetCliItemByCtrl(aCtrl));
if (ItemLnk = nil) and (Length(S) > 0) then
begin
OnAttach (aCtrl);
ItemLnk := TDdeCliItem(GetCliItemByCtrl(aCtrl));
end;
if (ItemLnk <> nil) and (Length(S) = 0) then
begin
OnDetach (aCtrl);
end
else if ItemLnk <> nil then
begin
Result := ItemLnk.SetItem(S);
if Not (Result) and Not (csLoading in ComponentState) then
OnDetach (aCtrl); {error occurred, do cleanup}
end;
end;
function TDdeClientConv.GetCliItemByCtrl(ACtrl: TDdeClientItem): TPersistent;
var
ItemLnk: TDdeCliItem;
I: word;
begin
Result := nil;
I := 0;
while I < FItems.Count do
begin
ItemLnk := FItems[I];
if ItemLnk.Control = aCtrl then
begin
Result := ItemLnk;
Exit;
end;
Inc(I);
end;
end;
function TDdeClientConv.PasteLink: Boolean;
var
Service, Topic, Item: string;
begin
if GetPasteLinkInfo(Service, Topic, Item) = True then
Result := ChangeLink(Service, Topic, Item) else
Result := False;
end;
function TDdeClientConv.ChangeLink(const App, Topic, Item: string): Boolean;
begin
CloseLink;
SetService(App);
SetTopic(Topic);
Result := OpenLink;
if Not Result then
begin
SetService('');
SetTopic('');
end;
end;
function TDdeClientConv.OpenLink: Boolean;
var
CharVal: array[0..255] of Char;
Res: Boolean;
begin
Result := False;
if FConv <> 0 then Exit;
if (Length(DdeService) = 0) and (Length(DdeTopic) = 0) then
begin
ClearItems;
Exit;
end;
if FHszApp = 0 then
begin
StrPCopy(CharVal, DdeService);
FHszApp := DdeCreateStringHandle(ddeMgr.DdeInstId, CharVal, CP_WINANSI);
end;
if FHszTopic = 0 then
begin
StrPCopy(CharVal, DdeTopic);
FHszTopic := DdeCreateStringHandle(ddeMgr.DdeInstId, CharVal, CP_WINANSI);
end;
Res := CreateDdeConv(FHszApp, FHszTopic);
if Not Res then
begin
if Not((Length(DdeService) = 0) and
(Length(ServiceApplication) = 0)) then
begin
if Length(ServiceApplication) <> 0 then
StrPCopy(CharVal, ServiceApplication)
else
StrPCopy(CharVal, DdeService + ' ' + DdeTopic);
if WinExec(CharVal, SW_SHOWMINNOACTIVE) >= 32 then
Res := CreateDdeConv(FHszApp, FHszTopic);
end;
end;
if Not Res then
begin
ClearItems;
Exit;
end;
if FCnvInfo.wFmt <> 0 then FDdeFmt := FCnvInfo.wFmt
else FDdeFmt := CF_TEXT;
if StartAdvise = False then Exit;
Open;
DataChange(0, 0);
Result := True;
end;
procedure TDdeClientConv.CloseLink;
var
OldConv: HConv;
begin
if FConv <> 0 then
begin
OldConv := FConv;
SrvrDisconnect;
FConv := 0;
DdeSetUserHandle(OldConv, QID_SYNC, 0);
DdeDisconnect(OldConv);
end;
if FHszApp <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszApp);
FHszApp := 0;
end;
if FHszTopic <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszTopic);
FHszTopic := 0;
end;
SetService('');
SetTopic('');
end;
procedure TDdeClientConv.ClearItems;
var
ItemLnk: TDdeCliItem;
i: word;
begin
if FItems.Count = 0 then Exit;
for I := 0 to FItems.Count - 1 do
begin
ItemLnk := TDdeCliItem(FItems [0]);
ItemLnk.Control.DdeItem := EmptyStr;
end;
end;
function TDdeClientConv.CreateDdeConv(FHszApp: HSZ; FHszTopic: HSZ): Boolean;
var
Context: TConvContext;
begin
FillChar(Context, SizeOf(Context), 0);
with Context do
begin
cb := SizeOf(TConvConText);
iCodePage := CP_WINANSI;
end;
FConv := DdeConnect(ddeMgr.DdeInstId, FHszApp, FHszTopic, @Context);
Result := FConv <> 0;
if Result then
begin
FCnvInfo.cb := sizeof(TConvInfo);
DdeQueryConvInfo(FConv, QID_SYNC, @FCnvInfo);
DdeSetUserHandle(FConv, QID_SYNC, LongInt(Self));
end;
end;
function TDdeClientConv.StartAdvise: Boolean;
var
ItemLnk: TDdeCliItem;
i: word;
begin
Result := False;
if FConv = 0 then Exit;
i := 0;
while i < FItems.Count do
begin
ItemLnk := TDdeCliItem(FItems [i]);
if Not ItemLnk.StartAdvise then
begin
ItemLnk.Control.DdeItem := EmptyStr;
end else
Inc(i);
if i >= FItems.Count then
break;
end;
Result := True;
end;
function TDdeClientConv.ExecuteMacroLines(Cmd: TStrings; waitFlg: Boolean): Boolean;
begin
Result := False;
if (FConv = 0) or FWaitStat then Exit;
Result := ExecuteMacro(PChar(Cmd.Text), waitFlg);
end;
function TDdeClientConv.ExecuteMacro(Cmd: PChar; waitFlg: Boolean): Boolean;
var
hszCmd: HDDEData;
hdata: HDDEData;
ddeRslt: LongInt;
begin
Result := False;
if (FConv = 0) or FWaitStat then Exit;
hszCmd := DdeCreateDataHandle(ddeMgr.DdeInstId, Cmd, StrLen(Cmd) + 1,
0, 0, FDdeFmt, 0);
if hszCmd = 0 then Exit;
if waitFlg = True then FWaitStat := True;
hdata := DdeClientTransaction(Pointer(hszCmd), -1, FConv, 0, FDdeFmt,
XTYP_EXECUTE, TIMEOUT_ASYNC, @ddeRslt);
if hdata = 0 then FWaitStat := False
else Result := True;
end;
function TDdeClientConv.PokeDataLines(const Item: string; Data: TStrings): Boolean;
begin
Result := False;
if (FConv = 0) or FWaitStat then Exit;
Result := PokeData(Item, PChar(Data.Text));
end;
function TDdeClientConv.PokeData(const Item: string; Data: PChar): Boolean;
var
hszDat: HDDEData;
hdata: HDDEData;
hszItem: HSZ;
begin
Result := False;
if (FConv = 0) or FWaitStat then Exit;
hszItem := DdeCreateStringHandle(ddeMgr.DdeInstId, PChar(Item), CP_WINANSI);
if hszItem = 0 then Exit;
hszDat := DdeCreateDataHandle (ddeMgr.DdeInstId, Data, StrLen(Data) + 1,
0, hszItem, FDdeFmt, 0);
if hszDat <> 0 then
begin
hdata := DdeClientTransaction(Pointer(hszDat), -1, FConv, hszItem,
FDdeFmt, XTYP_POKE, TIMEOUT_ASYNC, nil);
Result := hdata <> 0;
end;
DdeFreeStringHandle (ddeMgr.DdeInstId, hszItem);
end;
function TDdeClientConv.RequestData(const Item: string): PChar;
var
hData: HDDEData;
ddeRslt: LongInt;
hItem: HSZ;
pData: Pointer;
Len: Integer;
begin
Result := nil;
if (FConv = 0) or FWaitStat then Exit;
hItem := DdeCreateStringHandle(ddeMgr.DdeInstId, PChar(Item), CP_WINANSI);
if hItem <> 0 then
begin
hData := DdeClientTransaction(nil, 0, FConv, hItem, FDdeFmt,
XTYP_REQUEST, 10000, @ddeRslt);
DdeFreeStringHandle(ddeMgr.DdeInstId, hItem);
if hData <> 0 then
try
pData := DdeAccessData(hData, @Len);
if pData <> nil then
try
Result := StrAlloc(Len + 1);
StrCopy(Result, pData);
finally
DdeUnaccessData(hData);
end;
finally
DdeFreeDataHandle(hData);
end;
end;
end;
function TDdeClientConv.GetCliItemByName(const ItemName: string): TPersistent;
var
ItemLnk: TDdeCliItem;
i: word;
begin
Result := nil;
i := 0;
while i < FItems.Count do
begin
ItemLnk := TDdeCliItem(FItems[i]);
if ItemLnk.Item = ItemName then
begin
Result := ItemLnk;
Exit;
end;
Inc(i);
end;
end;
procedure TDdeClientConv.XactComplete;
begin
FWaitStat := False;
end;
procedure TDdeClientConv.SrvrDisconnect;
var
ItemLnk: TDdeCliItem;
i: word;
begin
if FConv <> 0 then Close;
FConv := 0;
i := 0;
while i < FItems.Count do
begin
ItemLnk := TDdeCliItem(FItems [i]);
ItemLnk.SrvrDisconnect;
inc(i);
end;
end;
procedure TDdeClientConv.DataChange(DdeDat: HDDEData; hszIt: HSZ);
var
ItemLnk: TDdeCliItem;
i: word;
begin
i := 0;
while i < FItems.Count do
begin
ItemLnk := TDdeCliItem(FItems [i]);
if (hszIt = 0) or (ItemLnk.HszItem = hszIt) then
begin
{ data has changed and we found a link that might be interested }
ItemLnk.StoreData(DdeDat);
end;
Inc(i);
end;
end;
function TDdeClientConv.SetLink(const Service, Topic: string): Boolean;
begin
CloseLink;
if FConnectMode = ddeAutomatic then
Result := ChangeLink(Service, Topic, '')
else begin
SetService(Service);
SetTopic(Topic);
DataChange(0,0);
Result := True;
end;
end;
procedure TDdeClientConv.SetConnectMode(NewMode: TDataMode);
begin
if FConnectMode <> NewMode then
begin
if (NewMode = ddeAutomatic) and (Length(DdeService) <> 0) and
(Length(DdeTopic) <> 0) and not OpenLink then
raise Exception.CreateRes(SDdeNoConnect);
FConnectMode := NewMode;
end;
end;
procedure TDdeClientConv.SetFormatChars(NewFmt: Boolean);
begin
if FFormatChars <> NewFmt then
begin
FFormatChars := NewFmt;
if FConv <> 0 then DataChange(0, 0);
end;
end;
procedure TDdeClientConv.SetDdeService(const Value: string);
begin
end;
procedure TDdeClientConv.SetDdeTopic(const Value: string);
begin
end;
procedure TDdeClientConv.SetService(const Value: string);
begin
FDdeService := Value;
end;
procedure TDdeClientConv.SetTopic(const Value: string);
begin
FDdeTopic := Value;
end;
procedure TDdeClientConv.Close;
begin
if Assigned(FOnClose) then FOnClose(Self);
end;
procedure TDdeClientConv.Open;
begin
if Assigned(FOnOpen) then FOnOpen(Self);
end;
procedure TDdeClientConv.Notification(AComponent: TComponent;
Operation: TOperation);
var
ItemLnk: TDdeCliItem;
i: word;
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (FItems <> nil) then
begin
i := 0;
while i < FItems.Count do
begin
ItemLnk := TDdeCliItem(FItems [i]);
if (AComponent = ItemLnk.Control) then
ItemLnk.Control.DdeItem := EmptyStr;
if i >= FItems.Count then break;
Inc(I);
end;
end;
end;
constructor TDdeClientItem.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FLines := TStringList.Create;
end;
destructor TDdeClientItem.Destroy;
begin
FLines.Free;
inherited Destroy;
end;
procedure TDdeClientItem.SetDdeClientConv(Val: TDdeClientConv);
var
OldItem: string;
begin
if Val <> FDdeClientConv then
begin
OldItem := DdeItem;
FDdeClientItem := '';
if FDdeClientConv <> nil then
FDdeClientConv.OnDetach (Self);
FDdeClientConv := Val;
if FDdeClientConv <> nil then
begin
FDdeClientConv.FreeNotification(Self);
if Length(OldItem) <> 0 then SetDdeClientItem (OldItem);
end;
end;
end;
procedure TDdeClientItem.SetDdeClientItem(const Val: string);
begin
if FDdeClientConv <> nil then
begin
FDdeClientItem := Val;
if Not FDdeClientConv.OnSetItem (Self, Val) then
begin
if Not (csLoading in ComponentState) or
not ((FDdeClientConv.FConv = 0) and
(FDdeClientConv.ConnectMode = ddeManual)) then
FDdeClientItem := '';
end;
end
else if (csLoading in ComponentState) then
FDdeClientItem := Val;
end;
procedure TDdeClientItem.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (AComponent = FDdeClientConv) then
begin
FDdeClientConv.OnDetach (Self);
FDdeClientConv := nil;
FDdeClientItem := '';
end;
end;
procedure TDdeClientItem.OnAdvise;
begin
if csDesigning in ComponentState then
begin
if Owner.InheritsFrom (TForm) and (TForm(Owner).Designer <> nil) then
TForm(Owner).Designer.Modified;
end;
if Assigned(FOnChange) then FOnChange(Self);
end;
function TDdeClientItem.GetText: string;
begin
if FLines.Count > 0 then
Result := FLines.Strings[0]
else Result := '';
end;
procedure TDdeClientItem.SetText(const S: string);
begin
end;
procedure TDdeClientItem.SetLines(L: TStrings);
begin
end;
constructor TDdeCliItem.Create(ADS: TDdeClientConv);
begin
inherited Create;
FHszItem := 0;
FCliConv := ADS;
end;
destructor TDdeCliItem.Destroy;
begin
StopAdvise;
inherited Destroy;
end;
function TDdeCliItem.SetItem(const S: string): Boolean;
var
OldItem: string;
begin
Result := False;
OldItem := Item;
if FHszItem <> 0 then StopAdvise;
FItem := S;
FCtrl.Lines.Clear;
if (Length(Item) <> 0) then
begin
if (FCliConv.Conv <> 0) then
begin
Result := StartAdvise;
if Not Result then
FItem := '';
end
else if FCliConv.ConnectMode = ddeManual then Result := True;
end;
RefreshData;
end;
procedure TDdeCliItem.StoreData(DdeDat: HDDEData);
var
Len: Longint;
Data: string;
I: Integer;
begin
if DdeDat = 0 then
begin
RefreshData;
Exit;
end;
Data := PChar(AccessData(DdeDat, @Len));
if Data <> '' then
begin
FCtrl.Lines.Text := Data;
ReleaseData(DdeDat);
if FCliConv.FormatChars = False then
begin
for I := 1 to Length(Data) do
if (Data[I] > #0) and (Data[I] < ' ') then Data[I] := ' ';
FCtrl.Lines.Text := Data;
end;
end;
DataChange;
end;
function TDdeCliItem.RefreshData: Boolean;
var
ddeRslt: LongInt;
DdeDat: HDDEData;
begin
Result := False;
if (FCliConv.Conv <> 0) and (FHszItem <> 0) then
begin
if FCliConv.WaitStat = True then Exit;
DdeDat := DdeClientTransaction(nil, -1, FCliConv.Conv, FHszItem,
FCliConv.DdeFmt, XTYP_REQUEST, 1000, @ddeRslt);
if DdeDat = 0 then Exit
else begin
StoreData(DdeDat);
DdeFreeDataHandle(DdeDat);
Result := True;
Exit;
end;
end;
DataChange;
end;
function TDdeCliItem.AccessData(DdeDat: HDDEData; pDataLen: PDWORD): Pointer;
begin
Result := DdeAccessData(DdeDat, pDataLen);
end;
procedure TDdeCliItem.ReleaseData(DdeDat: HDDEData);
begin
DdeUnaccessData(DdeDat);
end;
function TDdeCliItem.StartAdvise: Boolean;
var
ddeRslt: LongInt;
hdata: HDDEData;
begin
Result := False;
if FCliConv.Conv = 0 then Exit;
if Length(Item) = 0 then Exit;
if FHszItem = 0 then
FHszItem := DdeCreateStringHandle(ddeMgr.DdeInstId, PChar(Item), CP_WINANSI);
hdata := DdeClientTransaction(nil, -1, FCliConv.Conv, FHszItem,
FCliConv.DdeFmt, XTYP_ADVSTART or XTYPF_NODATA, 1000, @ddeRslt);
if hdata = 0 then
begin
DdeGetLastError(ddeMgr.DdeInstId);
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszItem);
FHszItem := 0;
FCtrl.Lines.Clear;
end else
Result := True;
end;
function TDdeCliItem.StopAdvise: Boolean;
var
ddeRslt: LongInt;
begin
if FCliConv.Conv <> 0 then
if FHszItem <> 0 then
DdeClientTransaction(nil, -1, FCliConv.Conv, FHszItem,
FCliConv.DdeFmt, XTYP_ADVSTOP, 1000, @ddeRslt);
SrvrDisconnect;
Result := True;
end;
procedure TDdeCliItem.SrvrDisconnect;
begin
if FHszItem <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszItem);
FHszItem := 0;
end;
end;
procedure TDdeCliItem.DataChange;
begin
FCtrl.OnAdvise;
end;
constructor TDdeServerItem.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFmt := CF_TEXT;
FLines := TStringList.Create;
end;
destructor TDdeServerItem.Destroy;
begin
FLines.Free;
inherited Destroy;
end;
procedure TDdeServerItem.SetServerConv(SConv: TDdeServerConv);
begin
FServerConv := SConv;
if SConv <> nil then SConv.FreeNotification(Self);
end;
function TDdeServerItem.GetText: string;
begin
if FLines.Count > 0 then
Result := FLines.Strings[0]
else Result := '';
end;
procedure TDdeServerItem.SetText(const Item: string);
begin
FFmt := CF_TEXT;
FLines.Clear;
FLines.Add(Item);
ValueChanged;
end;
procedure TDdeServerItem.SetLines(Value: TStrings);
begin
if CompareStr(Value.Text, FLines.Text) <> 0 then
begin
FFmt := CF_TEXT;
FLines.Assign(Value);
ValueChanged;
end;
end;
procedure TDdeServerItem.ValueChanged;
begin
if Assigned(FOnChange) then FOnChange(Self);
if FServerConv <> nil then
ddeMgr.PostDataChange(FServerConv.Name, Name)
else if (Owner <> nil) and (Owner is TForm) then
ddeMgr.PostDataChange(TForm(Owner).Caption, Name);
end;
function TDdeServerItem.PokeData(Data: HDdeData): LongInt;
var
Len: Integer;
pData: Pointer;
begin
Result := dde_FNotProcessed;
pData := DdeAccessData(Data, @Len);
if pData <> nil then
begin
Lines.Text := PChar(pData);
DdeUnaccessData(Data);
ValueChanged;
if Assigned(FOnPokeData) then FOnPokeData(Self);
Result := dde_FAck;
end;
end;
procedure TDdeServerItem.CopyToClipboard;
var
Data: THandle;
LinkData: string;
DataPtr: Pointer;
begin
if FServerConv <> nil then
LinkData := ddeMgr.AppName + #0 + FServerConv.Name + #0 + Name
else if (Owner =nil) then Exit
else if Owner is TForm then
LinkData := ddeMgr.AppName + #0 + TForm(Owner).Caption + #0 + Name;
try
Clipboard.AsText := Text;
Data := GlobalAlloc(GMEM_MOVEABLE, Length(LinkData) + 1);
try
DataPtr := GlobalLock(Data);
try
Move(PChar(LinkData)^, DataPtr^, Length(LinkData) + 1);
Clipboard.SetAsHandle(DdeMgr.LinkClipFmt, Data);
finally
GlobalUnlock(Data);
end;
except
GlobalFree(Data);
raise;
end;
finally
Clipboard.Close;
end;
end;
procedure TDdeServerItem.Change;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TDdeServerItem.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (AComponent = FServerConv) and (Operation = opRemove) then
FServerConv := nil;
end;
constructor TDdeServerConv.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ddeMgr.InsertServerConv (Self);
end;
destructor TDdeServerConv.Destroy;
begin
ddeMgr.RemoveServerConv(Self);
inherited Destroy;
end;
function TDdeServerConv.ExecuteMacro(Data: HDdeData): LongInt;
var
Len: Integer;
pData: Pointer;
MacroLines: TStringList;
begin
Result := dde_FNotProcessed;
pData := DdeAccessData(Data, @Len);
if pData <> nil then
begin
if Assigned(FOnExecuteMacro) then
begin
MacroLines := TStringList.Create;
MacroLines.Text := PChar(pData);
FOnExecuteMacro(Self, MacroLines);
MacroLines.Destroy;
end;
Result := dde_FAck;
end;
end;
procedure TDdeServerConv.Connect;
begin
if Assigned(FOnOpen) then FOnOpen(Self);
end;
procedure TDdeServerConv.Disconnect;
begin
if Assigned(FOnClose) then FOnClose(Self);
end;
constructor TDdeSrvrConv.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FItems := TList.Create;
end;
destructor TDdeSrvrConv.Destroy;
var
I: Integer;
begin
if FItems <> nil then
begin
for I := 0 to FItems.Count - 1 do
TDdeSrvrItem(FItems[I]).Free;
FItems.Free;
FItems := nil;
end;
if FConv <> 0 then DdeDisconnect(FConv);
if FHszTopic <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszTopic);
FHszTopic := 0;
end;
inherited Destroy;
end;
function TDdeSrvrConv.AdvStart(Conv: HConv; hszTopic: HSZ; hszItem: HSZ;
Fmt: Word): Boolean;
var
Srvr: TDdeServerItem;
Buffer: array[0..4095] of Char;
SrvrItem: TDdeSrvrItem;
begin
Result := False;
if Fmt <> CF_TEXT then Exit;
DdeQueryString(ddeMgr.DdeInstId, hszItem, Buffer, SizeOf(Buffer), CP_WINANSI);
Srvr := GetControl(FForm, FSConv, Buffer);
if Srvr = nil then Exit;
SrvrItem := TDdeSrvrItem.Create(Self);
SrvrItem.Srvr := Srvr;
SrvrItem.Item := Buffer;
FItems.Add(SrvrItem);
SrvrItem.FreeNotification(Self);
if FHszTopic = 0 then
FHszTopic := DdeCreateStringHandle(ddeMgr.DdeInstId, PChar(Topic), CP_WINANSI);
Result := True;
end;
procedure TDdeSrvrConv.AdvStop(Conv: HConv; hszTopic: HSZ; hszItem :HSZ);
var
SrvrItem: TDdeSrvrItem;
begin
SrvrItem := GetSrvrItem(hszItem);
if SrvrItem <> nil then
begin
FItems.Remove(SrvrItem);
SrvrItem.Free;
end;
end;
function TDdeSrvrConv.PokeData(Conv: HConv; hszTopic: HSZ; hszItem: HSZ;
Data: HDdeData; Fmt: Integer): LongInt;
var
Srvr: TDdeServerItem;
Buffer: array[0..4095] of Char;
begin
Result := dde_FNotProcessed;
if Fmt <> CF_TEXT then Exit;
DdeQueryString(ddeMgr.DdeInstId, hszItem, Buffer, SizeOf(Buffer), CP_WINANSI);
Srvr := GetControl(FForm, FSConv, Buffer);
if Srvr <> nil then Result := Srvr.PokeData(Data);
end;
function TDdeSrvrConv.ExecuteMacro(Conv: HConv; hszTopic: HSZ;
Data: HDdeData): Integer;
begin
Result := dde_FNotProcessed;
if (FSConv <> nil) then
Result := FSConv.ExecuteMacro(Data);
end;
function TDdeSrvrConv.RequestData(Conv: HConv; hszTopic: HSZ; hszItem :HSZ;
Fmt: Word): HDdeData;
var
Data: string;
Buffer: array[0..4095] of Char;
SrvrIt: TDdeSrvrItem;
Srvr: TDdeServerItem;
begin
Result := 0;
SrvrIt := GetSrvrItem(hszItem);
if SrvrIt <> nil then
Result := SrvrIt.RequestData(Fmt)
else
begin
DdeQueryString(ddeMgr.DdeInstId, hszItem, Buffer, SizeOf(Buffer), CP_WINANSI);
Srvr := GetControl(FForm, FSConv, Buffer);
if Srvr <> nil then
begin
if Fmt = CF_TEXT then
begin
Data := Srvr.Lines.Text;
Result := DdeCreateDataHandle(ddeMgr.DdeInstId, PChar(Data),
Length(Data) + 1, 0, hszItem, Fmt, 0 );
end;
end;
end;
end;
function TDdeSrvrConv.GetControl(WinCtrl: TWinControl; DdeConv: TDdeServerConv; const ItemName: string): TDdeServerItem;
var
I: Integer;
Ctrl: TComponent;
MainCtrl: TWinControl;
Srvr: TDdeServerItem;
begin
Result := nil;
MainCtrl := WinCtrl;
if MainCtrl = nil then
begin
if (DdeConv <> nil) and (DdeConv.Owner <> nil) and
(DdeConv.Owner is TForm) then
MainCtrl := TWinControl(DdeConv.Owner);
end;
if MainCtrl = nil then Exit;
for I := 0 to MainCtrl.ComponentCount - 1 do
begin
Ctrl := MainCtrl.Components[I];
if Ctrl is TDdeServerItem then
begin
if (Ctrl.Name = ItemName) and
(TDdeServerItem(Ctrl).ServerConv = DdeConv) then
begin
Result := TDdeServerItem(Ctrl);
Exit;
end;
end;
if Ctrl is TWinControl then
begin
Srvr := GetControl(TWinControl(Ctrl), DdeConv, ItemName);
if Srvr <> nil then
begin
Result := Srvr;
Exit;
end;
end;
end;
end;
function TDdeSrvrConv.GetItem(const ItemName: string): TDdeSrvrItem;
var
I: Integer;
Item: TDdeSrvrItem;
begin
Result := nil;
for I := 0 to FItems.Count - 1 do
begin
Item := FItems[I];
If Item.Item = ItemName then
begin
Result := Item;
Exit;
end;
end;
end;
function TDdeSrvrConv.GetSrvrItem(hszItem: HSZ): TDdeSrvrItem;
var
I: Integer;
Item: TDdeSrvrItem;
begin
Result := nil;
for I := 0 to FItems.Count - 1 do
begin
Item := FItems[I];
If DdeCmpStringHandles(Item.HszItem, hszItem) = 0 then
begin
Result := Item;
Exit;
end;
end;
end;
constructor TDdeSrvrItem.Create(AOwner: TComponent);
begin
FConv := TDdeSrvrConv(AOwner);
inherited Create(AOwner);
end;
destructor TDdeSrvrItem.Destroy;
begin
if FHszItem <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszItem);
FHszItem := 0;
end;
inherited Destroy;
end;
function TDdeSrvrItem.RequestData(Fmt: Word): HDdeData;
var
Data: string;
Buffer: array[0..4095] of Char;
begin
Result := 0;
SetString(FItem, Buffer, DdeQueryString(ddeMgr.DdeInstId, FHszItem, Buffer,
SizeOf(Buffer), CP_WINANSI));
if Fmt = CF_TEXT then
begin
Data := FSrvr.Lines.Text;
Result := DdeCreateDataHandle(ddeMgr.DdeInstId, PChar(Data), Length(Data) + 1,
0, FHszItem, Fmt, 0 );
end;
end;
procedure TDdeSrvrItem.PostDataChange;
begin
DdePostAdvise(ddeMgr.DdeInstId, FConv.HszTopic, FHszItem);
end;
procedure TDdeSrvrItem.SetItem(const Value: string);
begin
FItem := Value;
if FHszItem <> 0 then
begin
DdeFreeStringHandle(ddeMgr.DdeInstId, FHszItem);
FHszItem := 0;
end;
if Length(FItem) > 0 then
FHszItem := DdeCreateStringHandle(ddeMgr.DdeInstId, PChar(FItem), CP_WINANSI);
end;
begin
ddeMgr := TDdeMgr.Create(Application);
end.