Fórum Usar propriedade de outra classe em componente. #295450
14/09/2005
0
[url=http://www.clubedelphi.net/Novo/Colunistas/AdrianoSantos/01.asp]Download com Progresso[/url]
Bom, criei uma classe para acessar a interface IBindStatusCallback que será usada para atualizar a barra de progresso. E na classe principal do componente crie uma propriedade ProgressBar (TProgressBar) e uma LabelInfo (TLabel). Essas propriedades, quando configuradas, vão ser atualizadas pelo componente, mas não consigo acessá-las pelo evento onProgress da Interface, juro que tô viajando na maionese aki. Segue alguns trechos do fonte abaixo:
...
type
TOpcoesDown = (odCriarDestino, odAvisarSobrepor, odAvisarFinalizacao);
TOpcoes = Set of TOpcoesDown;
type
TMeuObjetoInterface = class(TInterfacedObject, IBindStatusCallback)
public
function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall;
function GetPriority(out nPriority): HResult; stdcall;
function OnLowResource(reserved: DWORD): HResult; stdcall;
function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
szStatusText: LPCWSTR): HResult; stdcall;
function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult;
stdcall;
function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult;
stdcall;
function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc:
PFormatEtc;
stgmed: PStgMedium): HResult; stdcall;
function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult;
stdcall;
end;
type
TDcDownProgress = class(TComponent)
private
{ Private declarations }
FProgress: TProgressBar;
FDestino: String;
FOrigem: String;
FOpcoes: TOpcoes;
FLabelInfo: TLabel;
function GetDestino: String;
function GetOrigem: String;
procedure SetDestino(const Value: String);
procedure SetOrigem(const Value: String);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy;override;
function Execute : Boolean;
published
{ Published declarations }
property Origem : String read GetOrigem write SetOrigem;
property Destino : String read GetDestino write SetDestino;
property ProgressBar : TProgressBar read FProgress write FProgress;
property Opcoes : TOpcoes read FOpcoes write FOpcoes default [odCriarDestino];
property LabelInfo: TLabel read FLabelInfo write FLabelInfo;
end;
...
function TDcDownProgress.Execute: Boolean;
var
MeuEstatus: TMeuObjetoInterface;
begin
if Trim(FDestino) = ´´ then
begin
MessageDlg(´O destino do download não foi especificado.´, mtError, [mbOk], 0);
Exit;
end;
if (not DirectoryExists(FDestino)) and (odCriarDestino in Opcoes) then
ForceDirectories(FDestino)
else
begin
MessageDlg(´O diretório destino não existe.´, mtError, [mbOk], 0);
Exit;
end;
{Aqui inicia o Download}
MeuEstatus := TMeuObjetoInterface.Create;
{Testa se foi configurado um ProgressBar e um Label}
if (not (FProgress = Nil)) and (not (FLabelInfo = Nil)) then
UrlDownloadToFile(nil, PChar(FOrigem), PChar(FDestino), 0, MeuEstatus)
else
UrlDownloadToFile(nil, PChar(FOrigem), PChar(FDestino), 0, nil);
{testa se precisa dar mensagem final}
if odAvisarFinalizacao in Opcoes then
Messagedlg(´Download concluído´, mtInformation, [mbOk],0);
end;
...
function TMeuObjetoInterface.OnProgress(ulProgress, ulProgressMax,
ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult;
begin
//aqui vai atualizar a propriedade ProgressBar e Label.
end;
...
end.
Adriano Santos
Curtir tópico
+ 0Posts
14/09/2005
Massuda
Gostei + 0
14/09/2005
Adriano Santos
[b:7fa66375da]Massuda[/b:7fa66375da], eu entendi o que quis dizer, mas confesso que nunca fiz e não sei fazer...vou tentar aki, qualquer coisa eu grito.
valeu
Gostei + 0
14/09/2005
Massuda
Gostei + 0
14/09/2005
Adriano Santos
Criei um tipo enumerado e estou tentando usá-lo, mas fica sempre vazio...acho que to esquecendo de fazer alguma coisa...valeu
type TOpcoesDown = (odCriarDestino, odAvisarSobrepor, odAvisarFinalizacao); TOpcoes = Set of TOpcoesDown; ... private FOpcoes: TOpcoes; ... procedure SetOpcoes(const Value: TOpcoes); ... property Opcoes : TOpcoes read FOpcoes write SetOpcoes default [odCriarDestino]; ... ... ... constructor TDcDownProgress.Create(AOwner: TComponent); begin inherited Create(AOwner); end; ... procedure TDcDownProgress.SetOpcoes(const Value: TOpcoes); begin FOpcoes := Value; end;
Gostei + 0
14/09/2005
Massuda
Se esse for o problema, inicie a propriedade no construtor do componente...
constructor TDcDownProgress.Create(AOwner: TComponent); begin inherited Create(AOwner); FOpcoes := [odCriarDestino]; end;
A palavra reservada [b:557c3de263]default[/b:557c3de263] tem um pegadinha... na verdade ela é uma dica do programador para a IDE/Object Inspector avisando que o programador vai iniciar sempre a propriedade com o valor informado. Assim, quando a IDE vai gravar o componente no DFM, quando ela vê que o valor de uma propriedade é o default, ela não grava o valor.
Gostei + 0
14/09/2005
Adriano Santos
Se esse for o problema, inicie a propriedade no construtor do componente...
constructor TDcDownProgress.Create(AOwner: TComponent); begin inherited Create(AOwner); FOpcoes := [odCriarDestino]; end;
A palavra reservada [b:67b5976be7]default[/b:67b5976be7] tem um pegadinha... na verdade ela é uma dica do programador para a IDE/Object Inspector avisando que o programador vai iniciar sempre a propriedade com o valor informado. Assim, quando a IDE vai gravar o componente no DFM, quando ela vê que o valor de uma propriedade é o default, ela não grava o valor.[/quote:67b5976be7]
Não é isso nao, quando vou fazer o teste ela tah vazia, olha o trecho:
if (not DirectoryExists(ExtractFilePath(FDestino))) then begin if (odCriarDestino in FOpcoes) then ForceDirectories(ExtractFilePath(FDestino)) else begin MessageDlg(´O diretório destino não existe.´, mtError, [mbOk], 0); Exit; end; end;
[color=red:67b5976be7]Pra ser mais exato, se eu mudo a propriedade em tempo de projeto, parece que ela não é alterada, ou seja, sou obrigado a alterar em tempo de execução, tipo aqui[/color:67b5976be7]
with DcDownProgress1 do begin Opcoes := [odCriarDestino];//mudando Origem := Edit1.Text; Destino := Edit2.Text; Execute; end;
Gostei + 0
14/09/2005
Massuda
Gostei + 0
14/09/2005
Adriano Santos
Entao Massuda, se eu fizer isso funciona...já tinha feito. O problema é quando eu mudo algo em tempo de projeto no componente. Por exemplo:
Coloco o componente no form e configuro todos os tipos para True na propriedade. Em runtime, o componente ´não sabe´ que coloquei todas como true, fica somente a que eu coloquei no constructor como verdadeira...entende?
Eu quero que funcinoe tipo a propriedade Options do DBGrid. Você vai lá desativa dgTabs e dgEdit e em runtime o componente sabe que ta desativado e não faz determinada ação....é isso...
valeu
Gostei + 0
14/09/2005
Massuda
Isso é feito através do método protegido DefineProperties (dê uma olhada na Ajuda do Delphi para ver um exemplo completo) combinado com um par de métodos para ler/gravar sua propriedade...
type TDcDownProgress = class(TComponent) private ... procedure LerOpcoes(Reader: TReader); procedure GravarOpcoes(Writer: TWriter); protected procedure DefineProperties(Filer: TFiler); override; ...
Gostei + 0
14/09/2005
Adriano Santos
type TDcDownProgress = class(TComponent) private ... procedure LerOpcoes(Reader: TReader); procedure GravarOpcoes(Writer: TWriter); protected procedure DefineProperties(Filer: TFiler); override; ...
Nossa Massuda, mas nunca vi isso...jurava de pe junto que ele fazia sozinho. Como o DBGrid faz? Não vi nada no fonte Grids.pas da VCL.l
Gostei + 0
14/09/2005
Massuda
Relendo o tópico percebi que você tem uma procedure TDcDownProgress.SetOptions... será que dava para você postar o código dela aqui?
Gostei + 0
15/09/2005
Adriano Santos
Relendo o tópico percebi que você tem uma procedure TDcDownProgress.SetOptions... será que dava para você postar o código dela aqui?[/quote:e095dd9793]
Sim dá, vou colocar o fonte inteiro. Mas já mudei trocentas vezes o SetOptions.
unit DcDownProgress;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, UrlMon, ShellApi, ActiveX, ComCtrls;
type
TOpcoesDown = (odCriarDestino, odAvisarSobrepor, odAvisarFinalizacao);
TOpcoes = Set of TOpcoesDown;
type
TMeuObjetoInterface = class(TInterfacedObject, IBindStatusCallback)
private
FProgress: TProgressBar;
FLabelInfo: TLabel;
public
function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall;
function GetPriority(out nPriority): HResult; stdcall;
function OnLowResource(reserved: DWORD): HResult; stdcall;
function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
szStatusText: LPCWSTR): HResult; stdcall;
function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult;
stdcall;
function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult;
stdcall;
function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc:
PFormatEtc;
stgmed: PStgMedium): HResult; stdcall;
function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult;
stdcall;
end;
type
TDcDownProgress = class(TComponent)
private
{ Private declarations }
FProgress: TProgressBar;
FDestino: String;
FOrigem: String;
FOpcoes: TOpcoes;
FLabelInfo: TLabel;
function GetDestino: String;
function GetOrigem: String;
procedure SetDestino(const Value: String);
procedure SetOrigem(const Value: String);
procedure SetOpcoes(const Value: TOpcoes);
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy;override;
function Execute : Boolean;
published
{ Published declarations }
property Origem : String read GetOrigem write SetOrigem;
property Destino : String read GetDestino write SetDestino;
property ProgressBar : TProgressBar read FProgress write FProgress;
property Opcoes : TOpcoes read FOpcoes write SetOpcoes default [odCriarDestino];
property LabelInfo: TLabel read FLabelInfo write FLabelInfo;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents(´Doiscliques ADD´, [TDcDownProgress]);
end;
{ TDcDownProgress }
constructor TDcDownProgress.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TDcDownProgress.Destroy;
begin
inherited;
end;
function TDcDownProgress.Execute: Boolean;
var
MeuEstatus: TMeuObjetoInterface;
begin
if Trim(FDestino) = ´´ then
begin
MessageDlg(´O destino do download não foi especificado.´, mtError, [mbOk], 0);
Exit;
end;
if (not DirectoryExists(ExtractFilePath(FDestino))) then
begin
if (odCriarDestino in FOpcoes) then
ForceDirectories(ExtractFilePath(FDestino))
else
begin
MessageDlg(´O diretório destino não existe.´, mtError, [mbOk], 0);
Exit;
end;
end;
{Aqui inicia o Download}
MeuEstatus := TMeuObjetoInterface.Create;
if FProgress = nil then
begin
MessageDlg(´Especifique um componente ProgressBar na propriedade de mesmo nome.´,mtWarning,[mbOK],0);
Exit;
end;
if FLabelInfo = nil then
begin
MessageDlg(´Especifique um componente Label na propriedade de mesmo nome.´,mtWarning,[mbOK],0);
Exit;
end;
MeuEstatus.FProgress := FProgress;
MeuEstatus.FLabelInfo := FLabelInfo;
{Testa se foi configurado um ProgressBar e um Label}
if (not (FProgress = Nil)) and (not (FLabelInfo = Nil)) then
UrlDownloadToFile(nil, PChar(FOrigem), PChar(FDestino), 0, MeuEstatus)
else
UrlDownloadToFile(nil, PChar(FOrigem), PChar(FDestino), 0, nil);
{testa se precisa dar mensagem final}
if odAvisarFinalizacao in Opcoes then
Messagedlg(´Download concluído´, mtInformation, [mbOk],0);
end;
function TDcDownProgress.GetDestino: String;
begin
Result := FDestino;
end;
function TDcDownProgress.GetOrigem: String;
begin
Result := FOrigem;
end;
procedure TDcDownProgress.SetDestino(const Value: String);
begin
FDestino := Value;
end;
procedure TDcDownProgress.SetOpcoes(const Value: TOpcoes);
begin
FOpcoes := Value;
end;
procedure TDcDownProgress.SetOrigem(const Value: String);
begin
FOrigem := Value;
end;
{ TMeuObjetoInterface }
function TMeuObjetoInterface.GetBindInfo(out grfBINDF: DWORD;
var bindinfo: TBindInfo): HResult;
begin
end;
function TMeuObjetoInterface.GetPriority(out nPriority): HResult;
begin
end;
function TMeuObjetoInterface.OnDataAvailable(grfBSCF, dwSize: DWORD;
formatetc: PFormatEtc; stgmed: PStgMedium): HResult;
begin
end;
function TMeuObjetoInterface.OnLowResource(reserved: DWORD): HResult;
begin
end;
function TMeuObjetoInterface.OnObjectAvailable(const iid: TGUID;
punk: IInterface): HResult;
begin
end;
function TMeuObjetoInterface.OnProgress(ulProgress, ulProgressMax,
ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult;
begin
Application.ProcessMessages;
if FLabelInfo <> nil then
FLabelInfo.Caption := ´Baixando: ´ + FormatFloat(´#.,´, ulProgress)
+ ´ de ´ + FormatFloat(´.,´, ulProgressMax) + ´ total de bytes´;
if FProgress <> nil then
begin
FProgress.Max := ulProgressMax;
FProgress.Position := FProgress.Position + (ulProgress div 1024);
end;
end;
function TMeuObjetoInterface.OnStartBinding(dwReserved: DWORD;
pib: IBinding): HResult;
begin
end;
function TMeuObjetoInterface.OnStopBinding(hresult: HResult;
szError: LPCWSTR): HResult;
begin
end;
end.
Gostei + 0
15/09/2005
Massuda
O fato de você por...
property Opcoes : TOpcoes read FOpcoes write SetOpcoes default [odCriarDestino];
Gostei + 0
15/09/2005
Adriano Santos
property Opcoes : TOpcoes read FOpcoes write SetOpcoes default [odCriarDestino];
O default na verdade Massuda, nem precisa, coloquei por colocar. A unica coisa que quero é que o usuario do meu componente possa setar o componente em tempo de projeto e ele fazer as devidas verificações. Só isso....rs...valeu pela força.
Gostei + 0
15/09/2005
Massuda
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)