Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Tiled background image in listbox

Posted on 2002-06-17
11
871 Views
Last Modified: 2007-11-27
Hi,

I want to create watermarks in instances of TListBox and TLMDListBox.

That is, i want to place one faint background image on the listbox and have it tiled all over the listbox. Even in case i resize my form (the listbox will also be resized), the image should get tiled smoothly, leaving no white space behind on the listbox.  

Does anyone have a clue as to how can it be done?

Thanks a lot in advance...
0
Comment
Question by:sazehra
  • 5
  • 4
  • 2
11 Comments
 
LVL 1

Expert Comment

by:alx512
ID: 7086488
Heh, very difficult task.
The simple way is to use the TListView component.
0
 

Author Comment

by:sazehra
ID: 7086741
hmmm... ok, then how do i do it using TListView?
0
 
LVL 1

Expert Comment

by:alx512
ID: 7087636
Sorry. It was a mistake. I think what TListView has a BackGroundImage property.
May be easy to create a new Component whith own draw code.
It must look like this:

On WM_ERASEBKGND :

  r := ClientRect;
  rgn := CreateRectRgnIndirect(r);
  SelectClipRgn(Canvas.Handle, rgn);
  Canvas.StretchDraw(r, FPicture.Bitmap);
  SelectClipRgn(Sender.Canvas.Handle, 0);
  DeleteObject(rgn);


On WM_DRAWITEM:

    Flags := DrawTextBiDiModeFlags(DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX);
    SetBkMode(Canvas.Handle, TRANSPARENT);
    DrawText(Canvas.Handle, PChar(Text), Length(Text), Rect, Flags);
0
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 
LVL 34

Accepted Solution

by:
Slick812 earned 30 total points
ID: 7090679
hello sazehra, you can set the TListBox Style to lbOwnerDrawFixed. The ItemHeight is set in your FormCreate. Now go to the ListBox1 Object Inspector and get the events, and double click OnDrawItem.

private
    { Private declarations }
    LbBmp: TBitmap;

procedure TForm1.FormCreate(Sender: TObject);
var
TempBmp: TBitmap;
X,Y: Integer;
begin
TempBmp := TBitmap.Create;
{I draw the tiled Bmp (TempBmp) but you should load it from Resource}
{TempBmp.LoadFromResourceName(hInstance, 'LBBACK');}
TempBmp.Canvas.Brush.Color := $00D8E8F8;
TempBmp.Height := 42;
TempBmp.Width := 42;
TempBmp.Canvas.Brush.Color := $00CFE9F0;
TempBmp.Canvas.Pen.Color := $00B0CEDF;
TempBmp.Canvas.Ellipse(4,5,34,32);
LbBmp := TBitmap.Create;
LbBmp.Height := TempBmp.Height * 2;
{all you need is twice the TempBmp height no matter
how tall the Listbox is}
LbBmp.Width := ListBox1.Width * 2;
{set the LbBmp width to the maximum that the List box can get to
maybe LbBmp.Width := Screen.Width}
Y := 0;
{this while loop tile's the TempBmp on the LbBmp}
while Y < LbBmp.Height do
  begin
  X := 0;
  while X < LbBmp.Width do
    begin
    LbBmp.Canvas.Draw(X, Y, TempBmp);
    Inc(X, TempBmp.Width);
    end;
  Inc(Y, TempBmp.Height);
  end;
TempBmp.Canvas.Font := ListBox1.Font;
ListBox1.ItemHeight := TempBmp.Canvas.TextHeight('W')+1;
ListBox1.ClientHeight := ListBox1.ClientHeight - (ListBox1.ClientHeight mod ListBox1.ItemHeight);
{It is Important to adjust the Client Height to keep blank spots off the bottom of the Listbox}
FreeAndNil(TempBmp);
end;


procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;
  ARect: TRect; State: TOwnerDrawState);
var
CopyRect: TRect;
Y: Integer;
begin
{don't draw anything if out of sight}
if (ARect.Top < -3) or (ARect.Top > ListBox1.Height+2) then
Exit;
CopyRect := ARect;
if Index > 0 then
  begin
  {adjust the CopyRect to the Item Index}
  CopyRect.Top := Index * (ARect.Bottom- ARect.Top);
  if CopyRect.Top > LbBmp.Height div 2 then
  CopyRect.Top := CopyRect.Top mod (LbBmp.Height div 2);
  CopyRect.Bottom := CopyRect.Top +(ARect.Bottom- ARect.Top);
  end;

(Control as TListBox).Canvas.Font := ListBox1.Font;
Y := (ListBox1.Items.Count) * ListBox1.ItemHeight;

if Y < ListBox1.Height then
  begin
  {you need to fill out the canvas below the last item if Y is less than height}
  (Control as TListBox).Canvas.CopyRect(Rect(0,Y,ARect.Right,Y+LbBmp.Height-(Y mod (LbBmp.Height div 2))),
                  LbBmp.Canvas,Rect(0,(Y mod (LbBmp.Height div 2)),ARect.Right,LbBmp.Height));
  Y:= Y+LbBmp.Height-(Y mod (LbBmp.Height div 2));
  while Y < ListBox1.Height do
    begin
    (Control as TListBox).Canvas.Draw(0, Y, LbBmp);
    Inc(Y, LbBmp.Height);
    end;
  end;

if odSelected in State then
  begin
  {change the colors for selected}
  (Control as TListBox).Canvas.Brush.Color := clHighLight;
  (Control as TListBox).Canvas.FillRect(ARect);
  (Control as TListBox).Canvas.Font.Color := clHighLightText;
  end else
(Control as TListBox).Canvas.CopyRect(ARect,LbBmp.Canvas,CopyRect);

(Control as TListBox).Canvas.Brush.Style := bsClear;
if (odDisabled in State) or (odGrayed in State) then
(Control as TListBox).Canvas.Font.Color := clGrayText;
{change text color for disabled}
(Control as TListBox).Canvas.TextOut(ARect.Left+2,ARect.Top,ListBox1.Items[Index]);
end;


procedure TForm1.sbut_DisListBClick(Sender: TObject);
begin
ListBox1.Enabled := not ListBox1.Enabled;
end;

procedure TForm1.sbut_AddListBClick(Sender: TObject);
begin
ListBox1.Clear;
ListBox1.Items.Add('First Line');
ListBox1.Items.Add('Second Line');
ListBox1.Items.Add('Third Line');
ListBox1.Items.Add('Fourth Line');
end;


- - - - - - - - - - - - - - - - - - - - - - - - - - - -

ask questions if it is unclear.
0
 
LVL 34

Expert Comment

by:Slick812
ID: 7090688
don't forget to free the LbBmp in your form's OnDestroy
0
 

Author Comment

by:sazehra
ID: 7098389
Hello Slick812,

Thanks a lot... Your works wonderfully with TListBox.

However, there is a little problem when i use it with TLMDListBox. I have 4 columns in it. Using your code, all the items appear in 1 column with semi-colon seperated list. I'll try to depict it...

This is what i should get:

Col1     Col2     Col3     Col4
----     ----     ----     ----

Itm11    Itm12    Itm13    Itm14
Itm21    Itm22    Itm23    Itm24
Itm31    Itm32    Itm33    Itm34
.....    .....    .....    .....



and this is what i m getting:

Col1     Col2     Col3     Col4
----     ----     ----     ----

Itm11;Itm12;Itm13;Itm14
Itm21;Itm22;Itm23;Itm24
Itm31;Itm32;Itm33;Itm34
.......................

the resizing of columns do not have any effect on the items in the LMDlistbox.

i'll be very grateful if u could help in this as well.

Thanks again!

0
 

Author Comment

by:sazehra
ID: 7098400
actually i don't want to change the control if possible...
0
 
LVL 34

Expert Comment

by:Slick812
ID: 7099561
I'm not familar with the TLMDListBox component, is it a standard delphi component or an add On. You may look at the properties of the Columns, like width and when there is a single ";" in the items text then move the text draw over to the next column width to place the text at the right spot, deleting the ; so it will not show.
0
 

Author Comment

by:sazehra
ID: 7099973
No TLMDListBox isn't a standard component.

ok, i'll try what u have suggested but the columns are resizeable so i m not sure if that'll b the best way to do it. Thanks anyway...
0
 
LVL 34

Expert Comment

by:Slick812
ID: 7099991
there should be a column width property somewhere, since the columns are resizable then it may be associated with the header, which I guess is a sub component?
0
 

Author Comment

by:sazehra
ID: 7118191
Hello, Slick812,

I didn't succeed with TLMDListBox so decided to change the component. But your code works beatifully with TListBox. Thank you very much.

Regards.
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

860 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question