Solved

Tiled background image in listbox

Posted on 2002-06-17
11
856 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
 
LVL 33

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 33

Expert Comment

by:Slick812
ID: 7090688
don't forget to free the LbBmp in your form's OnDestroy
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

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 33

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 33

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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

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…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

705 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now