controles gradientes ou transparentes usando canvas
12/12/2005
0
fiz uma procedure pra deixar o listbox gradiente, mas o canvas é pintado ´por cima´ dos itens e, ao selecionar um item, a cor de fundo do listbox volta ao normal.
Grato!
Vitor Rubio
Posts
12/12/2005
Ipc$
Para não voltar à cor original, defina uma WindowProc para o ListBox e coloque a rotina do Canvas neste método. Não esqueça de voltar a WindowProc original no onDestroy.
12/12/2005
Vitor Rubio
1)O que é uma windowproc e como eu faço uma?
2)se eu pintar cada um dos itens com um gradiente, vai ficar um gradiente em cada item ou um gradiente no listbox inteiro?
3) seria mais fácil eu deixá-lo transparente? a form em que ele está já tem o gradiente.
o procedure que eu usei foi essa, copiada do site delphiabout:
procedure TfrmMediaplayer.GradientControl(controle: TListBox; startcolor, endcolor: TColor); // Horizontal gradient fill of form background var startr: integer; startg: integer; startb: integer; endr: integer; endg: integer; endb: integer; curr: integer; curg: integer; curb: integer; i: integer; r: TRect; nolines: byte; curpct: integer; bitspix: longint; // bits per pixel begin // Convert TColor to RGB startr := startcolor and $000000FF; startg := (startcolor and $0000FF00) div 256; startb := (startcolor and $00FF0000) div 256 div 256; endr := endcolor and $000000FF; endg := (endcolor and $0000FF00) div 256; endb := (endcolor and $00FF0000) div 256 div 256; // Calc no of rectangles (lines) with different colors if controle.Height < 250 then nolines := controle.Height else nolines := 250; // max 250 different rectangles (no more needed) bitspix := GetDeviceCaps(controle.Canvas.Handle, BITSPIXEL); // Get bits per pixel if (bitspix = 8) and (nolines > 50) then // 256 colors nolines := 50 else if bitspix < 8 then // less than 256 colors nolines := 4; // poor guy r.Left := 0; // Left of rectangle r.Right := controle.Width; // Right of rectangle for i := 0 to nolines do // draw gradient begin curpct := (i * 100) div nolines; // ¬ change (gradient) // calc red for current rectangle if startr > endr then curr := startr - (curpct * (startr - endr) div 100) else curr := startr + (curpct * (endr - startr) div 100); // calc green for current rectangle if startg > endg then curg := startg - (curpct * (startg - endg) div 100) else curg := startg + (curpct * (endg - startg) div 100); // calc blue for current rectangle if startb > endb then curb := startb - (curpct * (startb - endb) div 100) else curb := startb + (curpct * (endb - startb) div 100); // set draw color for current rectangle controle.Canvas.Brush.Color := RGB(curr, curg, curb); // calc rectangle top/bottom r.Top := i + (i * (controle.Height div nolines)); r.Bottom := r.Top + (controle.Height div nolines) + 1; // draw rectangle on canvas controle.Canvas.FillRect(r); end; end; // GradientForm
valew!
12/12/2005
Ipc$
procedure TForm1.FormCreate(Sender: TObject); var wOri:TWndMethod; begin wOri := ListBox1.WindowProc; // aqui vc salva e no onDestroy vc restaura ListBox1.WindowProc := WP; // aqui vc diz que todas as msgs vão para WP end; procedure TForm1.WP(var Msg:TMessage); begin // aqui vc aplica o Canvas end;
2 - O FillRect preenche o espaço de TRect com a cor de Brush.Color, depois vc deve reescrever o texto dos ítens pelo TextRect ou TextOut; vc pode modificar a Font.Color também.
3 - Se puder ficar transparente, acho que daria menos trabalho.
13/12/2005
Fx|hand
eu fiz um exemplo aki utilizando esse evento e funcionou na boua...
só naum deixei gradienti pq é mto trampo... mais saca só !
Adicione um listbox no seu Form, depois mude a propriedade Style pra lbOwnerDrawVariable, depois vá ao evento OnDrawItem e adicione esse codigo:
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin if Rect.Top < HeaderControl1.Height then exit; if Rect.Top > ListBox1.Height then exit; if OdSelected in state then begin {draw background} ListBox1.Canvas.Brush.Style := bsSolid; ListBox1.Canvas.Brush.Color := clInactiveCaptionText; ListBox1.Canvas.FillRect(Rect); {draw background} {Draw Text} ListBox1.Canvas.Font.Color := clBlack; ListBox1.Canvas.TextOut(Rect.Left + 20,Rect.Top + 3,ListBox1.Items[index]); {Draw Text} end else begin {draw background} ListBox1.Canvas.Brush.Style := bsClear; ListBox1.Canvas.Brush.Color := clWhite; ListBox1.Canvas.FillRect(Rect); {draw background} {Draw Text} ListBox1.Canvas.Font.Color := clBlack; ListBox1.Canvas.TextOut(Rect.Left + 20,Rect.Top + 3,ListBox1.Items[index]); {Draw Text} end; end;
pro q eu keria funcionou legal... e eu fiz umas coisas a mais ainda, colokei uma imagem no espaço em branco antis do texto... mais ai é so vc pensar um poko q fica facil !
13/12/2005
Adriano Santos
eu fiz um exemplo aki utilizando esse evento e funcionou na boua...
só naum deixei gradienti pq é mto trampo... mais saca só !
Adicione um listbox no seu Form, depois mude a propriedade Style pra lbOwnerDrawVariable, depois vá ao evento OnDrawItem e adicione esse codigo:
procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); begin if Rect.Top < HeaderControl1.Height then exit; if Rect.Top > ListBox1.Height then exit; if OdSelected in state then begin {draw background} ListBox1.Canvas.Brush.Style := bsSolid; ListBox1.Canvas.Brush.Color := clInactiveCaptionText; ListBox1.Canvas.FillRect(Rect); {draw background} {Draw Text} ListBox1.Canvas.Font.Color := clBlack; ListBox1.Canvas.TextOut(Rect.Left + 20,Rect.Top + 3,ListBox1.Items[index]); {Draw Text} end else begin {draw background} ListBox1.Canvas.Brush.Style := bsClear; ListBox1.Canvas.Brush.Color := clWhite; ListBox1.Canvas.FillRect(Rect); {draw background} {Draw Text} ListBox1.Canvas.Font.Color := clBlack; ListBox1.Canvas.TextOut(Rect.Left + 20,Rect.Top + 3,ListBox1.Items[index]); {Draw Text} end; end;
pro q eu keria funcionou legal... e eu fiz umas coisas a mais ainda, colokei uma imagem no espaço em branco antis do texto... mais ai é so vc pensar um poko q fica facil ![/quote:24cd0c1960]
Eu fiz o teste aqui com o Gradiente e nao funcionou do jeito que o victor^_^ quer.
13/12/2005
Vitor Rubio
outra coisa, eu não entendi essa parte do código:
ListBox1.Canvas.TextOut(Rect.Left + 20,Rect.Top + 3,ListBox1.Items[index]);
porque você soma 3 no top? isso deixa meio deslocado pra baixo a seleção. Eu não somei com nada essa parte.
Valew!
Clique aqui para fazer login e interagir na Comunidade :)