Fórum Desenhando componentes em delphi: Como se faz isso? #264875
11/01/2005
0
Jah que ultimamente esse site tem falado bastante sobre componentes, entao eu acho q a minha duvida é a de muitas outras pessoas!
Como se desenha um componente?
Por exemplo, se eu quiser desenhar um outro botao! Um botao com a aparencia de um botao do Mac antigo, ou do KDE, ou do Windows XP! Ou um outro que ninguem nunca tenha visto igual! Onde que eu faco o desenho? Como funciona?
Posso fazer herança? Se naum puder, como responder aos cliques do windows? E etc, etc, etc... :D
Tah ae uma boa dica pra quem quer postar um bom artigo pro UpLoader Master!
Valeuz :D
_chiappone_
Curtir tópico
+ 0Posts
11/01/2005
Bruno_fantin
TWinControl - Para componentes que vão receber focus...
TGraphicControl - Para componentes que não vão receber focus...
Uma vez feito isso basta você sobreescrever o metodo paint... E nesse metodo fazer os desenhos usando Canvas...
Em exemplo simples...
unit Botao;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TBotao = class(TGraphicControl) // Herdei de TGraphicControl... Esse componente não pode receber o focus
private
{ Private declarations }
protected
procedure Paint; override; // Metodo Paint reescrito
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; // Mensagem que pega quando o botão esquerdo do mouse é clicado
public
constructor Create(AOwner: TComponent); override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents(´Teste´, [TBotao]);
end;
{ TBotao }
constructor TBotao.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Self.Height := 25;
Self.Width := 75;
Invalidate; // Chamando o metodo paint manualmente... Sempre chama ele pelo Invalidade...
end;
procedure TBotao.Paint;
begin
// Aqui que eu desenho tudo o que eu quero...
// O ideal aqui é usar doublebuffering
Canvas.Rectangle(0,0,75,25);
Canvas.TextOut(22,6, ´Botão´);
inherited;
end;
procedure TBotao.WMLButtonDown(var Message: TWMLButtonDown);
begin
showmessage(´Clicou´);
end;
end.
Gostei + 0
11/01/2005
_chiappone_
Mas, algumas perguntas :D
A Message WMLButtonDown seria usada na verdade para ´afundar o botao´, ok? E eu teria algo como ´WMLButtonUp´ para voltar ele ao normal, correto?
Outra coisa... O que é DoubleBuffering?
Vlwz! :D
Gostei + 0
11/01/2005
Bruno_fantin
Para você saber todas as mensagem que pode usar abre a unit Controls e veja a declaração da TControl...
DoubleBuffering???
Canvas é um buffer... DoubleBuffering é usar dois Canvas em vez de um...
O primeiro é o do proprio componente que será usado para desenhar o resultado final...
O segundo é um canvas criando em run-time aonde será feito cada um dos passos do desenho...
Por exemplo...
Você tem varios processos de desenho...
* Desenhar a Bordar...
* Desenhar o Glyphs...
* Desenhar o Texto....
* Desenhar a Sobra...
Ai você faz cada um deles na segunda canvas... No final a segunda canvas vai estar com o desenho que era visto pelo usuario... Ai nessa hora você copia ela para a primeira canvas...
Pra que tudo isso??? Para evitar aquelas piscadas na tela...
Gostei + 0
11/01/2005
_chiappone_
O Canvas que voce exemplificou no Paint eh o proprio Canvas do componente, ok?
Eu criaria uma variavel do tipo TCanvas e faria o processo lah...
Mas...
eu colocaria o Canvas novo no private desse componente e faria qualquer alteracao lah dentro, usando esse Canvas?
Canvas2.metodo
Canvas2.metodo
isso?
E pra aplicar as alteracoes no segundo Canvas? jogo no primeiro?
Como?
Voce, ou alguem mais aqui, tem algum componente que exemplifique o DoubleBuffering?
Valewz!!! :D
PS: Como voces podem ver, eu nunca mexi com canvas :D
Gostei + 0
11/01/2005
Bruno_fantin
unit Botao;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
TBotao = class(TGraphicControl) // Herdei de TGraphicControl... Esse componente não pode receber o focus
private
OffScreen: TBitmap; // O segundo canvas aqui chamado de OffScreen...
protected
procedure Paint; override; // Metodo Paint reescrito
procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; // Mensagem que pega quando o botão esquerdo do mouse é clicado
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents(´Teste´, [TBotao]);
end;
{ TBotao }
constructor TBotao.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
OffScreen := TBitmap.Create; // Crie o OffScreen...
OffScreen.Height:= 25; //Defini o tamanho do OffScreen...
OffScreen.Width := 75;
Self.Height := 25;
Self.Width := 75;
Invalidate; // Chamando o metodo paint manualmente... Sempre chama ele pelo Invalidade...
end;
destructor TBotao.Destroy;
begin
OffScreen.Free; // Matei o OffScreen...
inherited Destroy;
end;
procedure TBotao.Paint;
begin
// Aqui que eu desenho tudo o que eu quero...
// O ideal aqui é usar doublebuffering
OffScreen.Canvas.FillRect(Rect( 0, 0, 75, 25)); // Limpei o OffScreen...
OffScreen.Canvas.Rectangle(0,0,75,25);
OffScreen.Canvas.TextOut(22,6, ´Botão´);
Canvas.Draw(0, 0, OffScreen); //Copiei tudo do OffScreen para o canvas...
inherited;
end;
procedure TBotao.WMLButtonDown(var Message: TWMLButtonDown);
begin
showmessage(´Clicou´);
end;
end.
Gostei + 0
11/01/2005
Massuda
Se o seu componente precisar ter foco de entrada, você pode partir de um TWinControl... nesse caso, o double buffering está embutido no TWinControl, você não precisa implementar nada.
Gostei + 0
11/01/2005
_chiappone_
Colei esse codigo em um componente novo, e funcionou.
Soh que ae eu tentei implementar ele, usando a message WM_LBUTTONUP;
fiz assim:
procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUp;
logo abaixo do WMLButtonDown
e alterei mais isso:
procedure TBotao.WMLButtonDown(var Message: TWMLButtonDown); begin OffScreen.Canvas.Brush.Color := clRed; Invalidate; end; procedure TBotao.WMLButtonUp(var Message: TWMLButtonUp); begin OffScreen.Canvas.Brush.Color := clWhite; Invalidate; end;
Funcionou também. Quando voce clica, ele de branco passa a ser vermelho, e quando solta, ele fica branco.
Soh que, a partir do momento em que eu der clique duplo nele, ele passa a alterar a cor em qualquer lugar do form que eu clicar!
Sem contar que ele naum deixa eu fechar o form, pq, ao invez de dexecutar qualquer outra coisa, ele pinta o botao.
Porque?
Valeuz denovo :D
Gostei + 0
11/01/2005
_chiappone_
Se o seu componente precisar ter foco de entrada, você pode partir de um TWinControl... nesse caso, o double buffering está embutido no TWinControl, você não precisa implementar nada.[/quote:92e7bf5488]
e como funcionaria?
Ele espera eu chamar o Draw para aplicar as alteracoes?
Gostei + 0
11/01/2005
Bruno_fantin
Faz assim... Declara...
procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message WM_LBUTTONDBLCLK;
E no codigo só faz assim...
procedure TBotao.WMLButtonDblClk(var Message: TWMLButtonDblClk);
begin
end;
Gostei + 0
11/01/2005
_chiappone_
Eh, nao eh tao simples assim... agora eu preciso tratar o Drag and Drop...
pq qndo eu clico, e solto o mouse fora do botao, ele nao volta a cor pra branco....
Mas agora acho q dah pra mim seguir adiante....
Valeu mesmo rapaziada!!! Quando tiver pronto o que eu quero, eu posto aqui denovo!
Outra coisa... eu tava mostrando pro pessoal aqui, e eles deram a ideia:
[b:3bd3260c6c]´Pq vcs do forum naum criam uma paleta de componentes?´[/b:3bd3260c6c]
Tipo... uma ´Jedi Lib´ feita por brasileiros!
Nos temos fama de criativos (e realmente somos, sem duvida)... dah pra fazer umas coisas mto feras, e aprender muito!
Fica a ideia ae... qq vcs acham?
Gostei + 0
12/01/2005
Massuda
e como funcionaria? Ele espera eu chamar o Draw para aplicar as alteracoes?[/quote:f9c4a57960]
Num componente derivado de TWinControl, você controla o uso de double buffering através da propriedade DoubleBuffered.
Quando DoubleBuffered é True, o processo de desenho do componente (a procedure Paint) é redirecionado (pela VCL) para um canvas que na verdade é um bitmap, não a tela. Assim, você não precisa fazer nada de especial para ´aplicar as alterações´.
O default é ter TWinControl.DoubleBuffered = False.
Gostei + 0
12/01/2005
Bruno_fantin
No meu caso falta de tempo...
Mas se alguém começar a fazer alguma pode contrar com a minha ajuda..
Gostei + 0
12/01/2005
_chiappone_
Nos temos alguns componentes prontos jah... estamos esperando terminar o ultimo, e dpois eu posto um outro topico... ms quem quizer fazer isso antes, e jah bolar um lugar pra deixar os componentes :D
Flw!
Gostei + 0
04/02/2005
Rcoltrane
Estive lendo os tópicos acima sobre criação de componentes e talvez vcs. possam me ajudar. É o seguinte: eu tenho uma TreeView e coloquei uma imagem em seu background para que a mesma ficasse com um visual mais bacana. Contudo, os canvas dos itens da Treeview ficam brancos (ou de qq. cor que vc. quiser) mas eu preciso que os canvas fiquem transparentes, para que eu possa ver na integra a imagem do background. Vcs sabem como fazer isto? Ou tenho que desenvolver uma nova treeview com as propriedades de transparencia?
Obrigado.
RC.
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)