Improve company productivity with a Business Account.Sign Up

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 899
  • Last Modified:

Tiled background image in listbox

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
sazehra
Asked:
sazehra
  • 5
  • 4
  • 2
1 Solution
 
alx512Commented:
Heh, very difficult task.
The simple way is to use the TListView component.
0
 
sazehraAuthor Commented:
hmmm... ok, then how do i do it using TListView?
0
 
alx512Commented:
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
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

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.

 
Slick812Commented:
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
 
Slick812Commented:
don't forget to free the LbBmp in your form's OnDestroy
0
 
sazehraAuthor Commented:
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
 
sazehraAuthor Commented:
actually i don't want to change the control if possible...
0
 
Slick812Commented:
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
 
sazehraAuthor Commented:
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
 
Slick812Commented:
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
 
sazehraAuthor Commented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 5
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now