views:

347

answers:

1

hi guys,

I have a listview which displays (eventually) an album cover of an itunes play list with the album name under it. the problem I am having is that I cannot get the album art (currently a blank square) ABOVE the album name. It always is on the side... how do I do it? I've tried adding column headers and alsorts...

code to set up the listview

    Dim myImageList As ImageList

    albumList.View = View.Tile
    albumList.TileSize = New Size(120, 150)

    ' Initialize the item icons. 
    myImageList = New ImageList()

    myImageList.Images.Add(Image.FromFile("c:/test.jpg"))
    myImageList.ImageSize = New Size(80, 80)
    albumList.LargeImageList = myImageList

I then do a loop to display each album name which uses

        Dim item0 As New ListViewItem(New String() _
                {Albums(i).Name}, 0)

        albumList.Items.Add(item0)

the output is http://i111.photobucket.com/albums/n122/mfacer/Screenshot2010-05-02at164815.png

but as i said, I want the album name under the orange box....

any ideas?? Thanks for any info!

+4  A: 

That is the baked-in arrangement for tile view. If you want the labels underneath the images then you have to set View = LargeIcon. If that produces an undesirable spacing of images then you can P/Invoke SendMessage() to send the LVM_SETICONSPACING message. This worked well:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

class TileView : ListView {
  public TileView() {
    mSpacing = new Size(48, 48);
  }
  private Size mSpacing;
  public Size IconSpacing {
    get { return mSpacing; }
    set {
      mSpacing = value;
      updateSpacing();
    }
  }
  protected override void OnHandleCreated(EventArgs e) {
    base.OnHandleCreated(e);
    updateSpacing();
  }
  private void updateSpacing() {
    if (this.IsHandleCreated) {
      SendMessage(this.Handle, 0x1000 + 53, IntPtr.Zero, (IntPtr)((mSpacing.Height << 16) | mSpacing.Width));
    }
  }
  [DllImport("user32.dll")]
  private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
}

Change the new IconSpacing property in the designer to work well with the size of the images in your ImageList. You'll see the effect immediately.


Public Class TileView
  Inherits ListView

  Public Sub New()
    mSpacing = New Size(48, 48)
  End Sub

  Private mSpacing As Size

  Public Property IconSpacing As Size
    Get
      Return mSpacing
    End Get
    Set(ByVal value As Size)
      mSpacing = value
      updateSpacing()
    End Set
  End Property

  Protected Overrides Sub OnHandleCreated(ByVal e As System.EventArgs)
    MyBase.OnHandleCreated(e)
    updateSpacing()
  End Sub

  Private Sub updateSpacing()
    If Me.IsHandleCreated Then
      SendMessageW(Me.Handle, &H1000 + 53, IntPtr.Zero, CType((mSpacing.Height << 16) Or mSpacing.Width, IntPtr))
    End If
  End Sub

  Private Declare Function SendMessageW Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wp As IntPtr, ByVal lp As IntPtr) As IntPtr
End Class
Hans Passant
thanks for the reply. Where do I add this code? I tried adding a new class file to my project, but this doesn't seem right.... this is a new project and so far I've only used defaults... so I have only form1.vb (design and code),... thanks again, it's much appreciated :)
Matt Facer
Yes, add a new class to your project. After you compile, you'll get the new control in the top of the toolbox. Shucks, didn't see the VB.NET requirement.
Hans Passant
hmm... I added the class, but it doesn't like the code! Is this just normal VB? (noticing your VB.net comment!)
Matt Facer
@Matt: VB.NET code added to post, below the line.
Hans Passant
works a TREAT, thank you!!!
Matt Facer
@Matt: sounds like this was an answer. Do you need anything else?
Hans Passant
i cant seem to add another line under the orange square... does the code you posted only show one? I tried adding tileView.Columns.AddRange(New ColumnHeader() {New ColumnHeader, New ColumnHeader}) but it only shows one line??
Matt Facer
@Matt: standard behavior for ListView is to show at most two lines when an item doesn't have the focus, 3 lines when it does. Extra characters are elided with "...". You surely have seen this before, the Windows desktop behaves the same way. If you need more lines then you should switch back to View = Tile, it arranges text to the right to give a lot more space for text.
Hans Passant
PS: ColumnHeaders are only ever used when View = Details. No columns With Tile or LargeIcon view, the items have to fit a grid. By necessity, that doesn't leave unlimited space for text.
Hans Passant
yes I understand.. I have one normal listview which works nicely (with the text to the right)... but for the one your code uses, I am basically trying to replicate the album view screen in itunes. (here's what I've got done so far.. http://i111.photobucket.com/albums/n122/mfacer/Screenshot2010-05-02at224828.png) I just want to put the album name and artist on two lines. I could do it in tile view (as the playlist you see), but I really want the names under the icon... I've thought about using images with labels on a grid... but it seems easier with listview!
Matt Facer
Do you actually believe that Apple programmers used a control that was pre-programmed by Microsoft programmers? You can be an apple too, it take humming "I'll do it My Way". It isn't actually that hard after you read Petzold.
Hans Passant
haha... it's literally the style (album cover then title and artist under that) which I'm trying to replicate. I've done a fair bit of iphone coding so finding it fun(?!) to keep switching between the two! Thanks for your help btw... I'm sure I will figure it out!
Matt Facer