A muito tempo que tive a necessidade de acessar uma propriedade de um objeto Caché no Delphi (via ActiveX) de forma dinamica e esta semana consegui com ajuda de algumas pesquisas na internet.
Os testes que realizei foram utilizando Delphi 2007 e Caché 5.0.21, porem, creio que pode funcionar em qualquer versão de Delphi e Caché.
O codigo abaixo demonstra como obter o valor de uma propriedade:
uses
ComObj, ActiveX;
procedure TForm1.Button1Click(Sender: TObject);
var
objFactory:variant;
obj:OleVariant;
nmProperty:PWideChar;
vParam:Pointer;
idDisp:integer;
vlProperty:variant;
idUserDefaultLC:integer;
begin
/// Objeto que fará a conexão com o banco de dados.
objFactory := CreateOleObject('CacheObject.Factory');
/// Aqui selecionar o namespace "SAMPLES".
objFactory.Connect(objFactory.ConnectDlg('Conexão'));
/// Abro um objeto do banco de dados.
obj := objFactory.OpenId('Sample.Person',10);
/// Esta vai ser a propriedade que vou acessar de forma dinamica (atravez do nome).
nmProperty := 'Name';
idUserDefaultLC := GetUserDefaultLCID;
IDispatch(obj).GetIDsOfNames(GUID_NULL, @nmProperty, 1, idUserDefaultLC, @idDisp);
vParam := nil;
IDispatch(Obj).Invoke(idDisp, GUID_NULL, idUserDefaultLC, DISPATCH_PROPERTYGET, vParam, @vlProperty, nil, nil);
/// Aqui mostro o valor da propriedade que foi recuperado.
ShowMessage(vlProperty);
end;
E este codigo abaixo demonstra como atribuir o valor a uma propriedade:
uses
ComObj, ActiveX;
procedure TForm1.Button2Click(Sender: TObject);
var
objFactory:variant;
obj:OleVariant;
nmProperty:PWideChar;
idDisp:integer;
idUserDefaultLC:integer;
rDispParams:TDispParams;
vlNew:OleVariant;
begin
/// Objeto que fará a conexão com o banco de dados.
objFactory := CreateOleObject('CacheObject.Factory');
/// Aqui selecionar o namespace "SAMPLES".
objFactory.Connect(objFactory.ConnectDlg('Conexão'));
/// Abro um objeto do banco de dados.
obj := objFactory.OpenId('Sample.Person',10);
/// Valor antes de alterar.
ShowMessage(obj.Name);
/// Esta vai ser a propriedade que vou acessar/alterar de forma dinamica (atravez do nome).
nmProperty := 'Name';
idUserDefaultLC := GetUserDefaultLCID;
IDispatch(obj).GetIDsOfNames(GUID_NULL, @nmProperty, 1, idUserDefaultLC, @idDisp);
/// Novo valor que vou atribuir na propriedade.
vlNew := 'alexandre';
with rDispParams do
begin
rgvarg := @vlNew;
rgdispidNamedArgs := @DispIDArgs;
cArgs := 1;
cNamedArgs := 1;
end;
IDispatch(obj).Invoke(idDisp, GUID_NULL, 0, DISPATCH_PROPERTYPUT, rDispParams, nil, nil, nil);
/// Valor depois de alterar.
ShowMessage(obj.Name);
end;
É isso ;) Agora quem gostar e for utilizar é só usar a imaginação para adicionar mais funcionalidades.
Obrigado a todos por lerem meu primeiro post, e fiquem a vontade para comentar e entrar em contato comigo para mais informações a respeito.
Muito bom o seu post. Este código também pode ser utilizado para acessar/setar propriedades de outras dll's. Fiz um teste com o código postado, porém utilizando outra dll e funcionou perfeitamente.
ResponderExcluir[]'s
Rafael Camillis
Legal Rafael! Se vc quizer fique a vontade para escrever um comentario junto com este seu exemplo.
ResponderExcluirAbraço!