|
DDE / OLE
GroupFile and additems to Group
Ole Automation on Delphi16
OLE Server
DDE- passing text
How to add a group to the program manager
Getting DDE to talk to Program Manger under Win95
GroupFile and additems to Group
Question
How to create groups in program manager?
Answer
A:
Here is the code for creating a group file and add an item file to the
group. To use the procedure, specify the DDE clientconv App as ProgMan.
******************************************************
procedure TMainForm.CreateWinGroup(Sender: TObject);
var
Name: string;
Name1: string;
Macro: string;
Macro1: string;
Cmd, Cmd1: array[0..255] of Char;
begin
{destDir is the dos directory to hold the YourFile.Ext'}
Name := 'GroupName';
Name1 := destDir + 'YourFile.Ext, FileName_in_Group ';
Macro := Format('[CreateGroup(%s)]', [Name]) + #13#10;
Macro1 :=Format('[Additem(%s)]',[Name1]) +#13#10;
StrPCopy (Cmd, Macro);
StrPCopy (cmd1, Macro1);
DDEClient.OpenLink;
if not DDEClient.ExecuteMacro(Cmd, False) then
MessageDlg('Unable to create group '+Name,mtInformation, [mbOK], 0)
else
begin
DDEClient.ExecuteMacro(Cmd1, False);
end;
DDEClient.CloseLink;
end;
Ole Automation on Delphi16
Question
Can Delphi16 do Ole Automation?
Answer
A:
Delphi 16 can do OLE Automation, and just about anything else. But
there are no nifty pre-built components nor objects to make the job as
easy as it is to do most other things in Delphi. Delphi32 should have a
all of the OLE features managed in someway (at least I hope so).
So if you are going to do any OLE server types of actions then you have
to use all of the mean and nasty Windows SDK routines for it. However
there may be a component that will manage the stuff for you. If so it is
not from Borland.
OLE Server
Question
I want to make an OLE-server with Delphi. In OLE you pass 'Interfaces'
around, which are basically structures with function pointers. I need
to be able to generate these structures and to call functions defined
by those structures. The problem is that the functions use the 'c'
calling convention, which Delphi supports (sort of) with the 'cdecl'
keyword. I say 'sort of' because the following wont compile:
...
interface
function OLEfunction(x, y, z: integer): integer; cdecl; export;
implementation
function OLEfunction(x, y, z: integer): integer;
begin
end;
procedure buildOLEstructure;
var
F: function (x, y, z: integer): integer; { need 'cdecl' here }
begin
F := OLEfunction; { Type mismatch here... }
end;
This will not compile, because of a type mismatch caused by the 'cdecl'
on the function (which I really need) and the missing 'cdecl' on the
definition of the variable 'F'. In this example I could live with a
simple pointer-definition for F, because I don't need to call the
function myself, but OLE sometimes gives me a pointer to a 'cdecl'
function, which I need to call myself. As I see it, there is no way
that this is possible. Am I right in this assumption?
Answer
A:
The following code compiled OK. It's not so clean but it may help you:
unit Unit1;
interface
function OLEfunction(x, y, z: integer): integer; cdecl; export;
implementation
function OLEfunction(x, y, z: integer): integer;
begin
end;
procedure buildOLEstructure;
var
F: pointer;
begin
F := @OLEfunction; { Compiles OK ... }
end;
end.
A:
Use the approach that follows. You have to declare one calling function for
each combination of parameters that you are going to pass. Then you call the
calling function passing as a pointer the function you want to call.
library Pcdecl;
function olefunction(a1 : pchar; a2 : longint; x : integer ) : integer;
cdecl; export;
begin
end;
function callolefunction(func : pointer; a1 : pchar; a2 : longint; x :
integer) : integer;
assembler;
asm
push x { push parameters in reverse order }
push word ptr a2 + 2 { if a 32 bit value push it in two steps, starting
with the high part }
push word ptr a2
push word ptr a1 + 2
push word ptr a1
call func
add sp, 10 { restore stack by adding back the bytes pushed. Note that
func is not pushed }
end;
procedure buildolefunction;
var
f : pointer;
reslt : integer;
begin
f := @olefunction;
{ --- }
reslt := callolefunction(f, 'hello world', 1000000, 25);
{ --- }
end;
begin
{ --- }
end.
This compiled perfectly well in my computer. It should do the job.
Warning. Methods should be treated slightly different than functions.
DDE- passing text
Question
I just want to pass a text value from a ddeclient to a ddeserver using
pokedata.
I have , however, found it strangely difficult. I've put all relevant
values as watches to see what was happening and found that the ddeItem
property was a nil string!! It should be something like ddeServerItem1.
The following is some example code. See if you can spot any deliberate
mistakes.
procedure TForm2.Button2Click(Sender: TObject);
Var
DDeCli : TDdeClientConv;
SPtr : array[0..200] of char;
begin
{DdeClientItem1.DdeItem := 'DdeServerItem1'; what it should be?}
DdeCli := DdeClientItem1.DdeConv;
if DdeCli <> nil then
DdeCli.PokeData(DdeClientItem1.DdeItem, StrPCopy(SPtr, Edit1.Text));
end;
As you can see when button2 is hit it should poke the data from an
editbox upto the ddeServer. It doesn't work. {even when i included the
bracketed code}
What am i missing. I bet it's pretty obvious.
Answer
A:
This works for me when poking to Excel:
DDEClientConv1.SetLink('Excel','Sheet1');
try
DDEClientConv1.OpenLink;
DDEClientItem1.DDEItem:= 'R1C1';
DDEClientConv1.PokeData(DDEClientItem1.DDEItem,
StrPCopy(P, SomeString)));
finally
DDEClientConv1.CloseLink;
end;
As you see the DDEItem property is determined by the server. If your
server is a Delphi application, the DDEItem is the name of the
DDEServerItem. I wouldn't trust debugging DDE programs too much, if I
were you. There is a lot of synchronization involved, that goes either
right or wrong when debugging.
How to add a group to the program manager
Question
I am writing an installation utility , but i don't know how to add a group
and icon to the program manager.
Answer
A:
interface
procedure CreateGroup;
implementation
procedure TSetupForm.CreateGroup;
{ Uses the TProgMan component to install Program Manager group }
var
ItemList: TStringList;
GroupName: String;
ItemName: String;
i: word;
begin
{ Get the GroupName string from the INI file }
GroupName := IniFile.ReadString('General', 'PMGroup', '');
{ If there is one, then install group }
if GroupName <> '' then begin
ItemList := TStringList.Create;
try
{ read items to be installed }
IniFile.ReadSectionValues('PMGroup', ItemList);
with TProgMan.Create(Self) do
try
CreateGroup(GroupName);
for i := 0 to ItemList.Count - 1 do begin
{ get file name }
ItemName := Copy(ItemList.Strings[i], 1, Pos('=',
ItemList.Strings[i]) - 1);
{ append file name to path and add the item }
AddItem(GetTarget(ItemList.Values[ItemName][1]) + ItemName, ItemName);
end;
finally
Free;
end;
finally
ItemList.Free;
end;
end;
end;
Getting DDE to talk to Program Manger under Win95
Question
Is there a special trick to getting DDE to establish a link with
program Manger using DDE, when uisng Win95 (V1.0 of delphi)?
Answer
A:
I've been using the following unit to manage program groups using dde to
progman. It's an adaption of Steve Texeira's(sp) code in Dephi Developers Guide.
have had success in 3.1 and '95.
unit Pm;
interface
uses
SysUtils, Classes, DdeMan;
type
EProgManError = class(Exception);
TProgMan = class(TComponent)
private
FDdeClientConv: TDdeClientConv;
procedure InitDDEConversation;
function ExecMacroString(Macro: String): Boolean;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
Procedure CreateGroup(GroupName: String; ShowGroup:Boolean);
procedure DeleteGroup(GroupName: String);
procedure DeleteItem(ItemName: String);
procedure AddItem(CmdLine, ItemName: String);
end;
implementation
uses Utils;
const
{ Program Manager DDE macro strings }
SDDECreateGroup = '[CreateGroup(%s)]';
SDDEShowGroup = '[ShowGroup(%s, 1)]';
SDDEDeleteGroup = '[DeleteGroup(%s)]';
SDDEDeleteItem = '[DeleteItem(%s)]';
SDDEAddItem = '[AddItem(%s, "%s", %s)]';
constructor TProgMan.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
InitDDEConversation;
end;
destructor TProgMan.Destroy;
begin
if Assigned(FDDEClientConv) then
FDdeClientConv.CloseLink;
inherited Destroy;
end;
function TProgMan.ExecMacroString(Macro: String): Boolean;
Begin
StringAsPchar(Macro);
Result := FDdeClientConv.ExecuteMacro(@Macro[1], False);
End;
Procedure TProgMan.InitDDEConversation;
begin
FDdeClientConv := TDdeClientConv.Create(Self);
If NOT FDdeClientConv.SetLink('PROGMAN', 'PROGMAN') then
raise EProgManError.Create('Failed to establish DDE Link');
end;
Procedure TProgMan.CreateGroup(GroupName: String; ShowGroup:Boolean);
Begin
{ Delete the group if it exists }
ExecMacroString(Format(SDDEDeleteGroup, [GroupName]));
If NOT ExecMacroString(Format(SDDECreateGroup, [GroupName])) then
raise EProgManError.Create('Could not create group ' + GroupName);
If ShowGroup then
If not ExecMacroString(Format(SDDEShowGroup, [GroupName])) then
raise EProgManError.Create('Could not show group ' + GroupName);
End;
Procedure TProgMan.DeleteGroup(GroupName: String);
Begin
if NOT ExecMacroString(Format(SDDEDeleteGroup, [GroupName])) then
raise EProgManError.Create('Could not delete group ' + GroupName);
End;
Procedure TProgMan.DeleteItem(ItemName: String);
Begin
if NOT ExecMacroString(Format(SDDEDeleteGroup, [ItemName])) then
raise EProgManError.Create('Could not delete item ' + ItemName);
End;
Procedure TProgMan.AddItem(CmdLine, ItemName: String);
Var
P: PChar;
PSize: Word;
Begin
PSize := StrLen(SDDEAddItem) + (Length(CmdLine) *2) + Length(ItemName) + 1;
GetMem(P, PSize);
try
StrFmt(P, SDDEAddItem, [CmdLine, ItemName, CmdLine]);
if NOT FDdeClientConv.ExecuteMacro(P, False) then
raise EProgManError.Create('Could not add item ' + ItemName);
finally
FreeMem(P, PSize);
end;
End;
end.
|