Listbox help

New to FreeBASIC? Post your questions here.
ejc.cryptography
Posts: 268
Joined: Dec 16, 2006 20:52
Contact:

Listbox help

Postby ejc.cryptography » Feb 28, 2007 18:57

Can someone possibly do a demo for me as I cannot get it to work:

Basically, I need a listbox with various values in it, and when one is selected, a particular Sub is run. I can get a listbox, but I cannot figure out how to make something happen when the selection of the box is changed (the actual function for getting the value of the selected item is already sorted).

I know there is something like LBN_SELCHANGE, but I can't implement it and would very much like some guidance on this issue, if possible in the form of a working example.

Thanks.
1000101
Posts: 2556
Joined: Jun 13, 2005 23:14
Location: SK, Canada

Postby 1000101 » Feb 28, 2007 19:36

It might help if we knew what you had so far. If you're using WinApi then how one might do it is vastly different from a home-grown GUI.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Mar 01, 2007 1:07

Quick and dirty.

Code: Select all

'=========================================================================
'' *** Build as console app so print will work ***
'=========================================================================
#include "windows.bi"
'=========================================================================

#define LBADDS(h,s)SendMessage(h,LB_ADDSTRING,0,cast(LPARAM,@s))

'=========================================================================

function ListBox( byval hParent as HWND, _
             byval x as integer, _
             byval y as integer, _
             byval w as integer, _
             byval h as integer, _
             byval cid as integer, _
             byval extraStyle as integer = 0 ) as HWND

    dim style as integer = WS_CHILD or _
                           WS_VISIBLE or _
                           WS_TABSTOP or _
                           WS_BORDER or _
                           WS_VSCROLL or _
                           LBS_HASSTRINGS or _
                           LBS_NOINTEGRALHEIGHT or _
                           LBS_DISABLENOSCROLL or _
                           extraStyle

    return CreateWindowEx( WS_EX_CLIENTEDGE, _
                           "LISTBOX", _
                           0, _
                           style, _
                           x, y, w, h, _
                           hParent, _
                           cast( HMENU, cid ), _
                           GetModuleHandle( null ), _
                           null )
end function

'=========================================================================

function WindowProc( byval hWnd as HWND,_
                     byval uMsg as uint,_
                     byval wParam as WPARAM,_
                     byval lParam as LPARAM ) as LRESULT

    static as HWND hList
    dim as integer curSel

    select case uMsg

      case WM_CREATE

        hList = ListBox( hWnd, 10, 10, 290, 180, 100, LBS_NOTIFY )

        LBADDS( hList, "string 0" )
        LBADDS( hList, "string 1" )
        LBADDS( hList, "string 2" )
        LBADDS( hList, "string 3" )
        LBADDS( hList, "string 4" )
        LBADDS( hList, "string 5" )
        LBADDS( hList, "string 6" )
        LBADDS( hList, "string 7" )
        LBADDS( hList, "string 8" )
        LBADDS( hList, "string 9" )

        SetFocus(hList)
        SendMessage( hList, LB_SETCURSEL, 0, 0 )

      case WM_COMMAND

        if lParam = hList then
          if hiword(wParam) = LBN_SELCHANGE then
            curSel = SendMessage( hList, LB_GETCURSEL, 0, 0 )
            print curSel
          end if
        end if

      case WM_CLOSE

        PostQuitMessage( null )

      case else

        return DefWindowProc( hWnd, uMsg, wParam, lParam )

    end select

    return 0

end function

'=========================================================================
'' Start of implicit main.
'=========================================================================

dim hWnd as HWND
dim wMsg as MSG
dim as integer wx, wy, nWidth, nHeight
dim wcx as WNDCLASSEX
dim className as string = "listbox_test_class"

with wcx
  .cbSize = sizeof( WNDCLASSEX )
  .style = CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
  .lpfnWndProc = cast( WNDPROC, @WindowProc )
  .cbClsExtra = null
  .cbWndExtra = null
  .hInstance = GetModuleHandle( null )
  .hbrBackground = cast( HBRUSH,COLOR_WINDOW + 1 )
  .lpszMenuName = null
  .lpszClassName = strptr( className )
  .hIcon = LoadIcon( null, IDI_APPLICATION )
  .hCursor = LoadCursor ( null, IDC_ARROW )
  .hIconSm = 0
end with

RegisterClassEx( @wcx )

nWidth = 320
nHeight = 240
wx = (GetSystemMetrics( SM_CXSCREEN ) / 2) - nWidth / 2
wy = (GetSystemMetrics( SM_CYSCREEN ) / 2) - nHeight / 2

hWnd = CreateWindowEx( WS_EX_OVERLAPPEDWINDOW,_
                       strptr( className ),_
                       "Test",_
                       WS_OVERLAPPEDWINDOW,_
                       wx, wy, nWidth, nHeight,_
                       null, null,_
                       GetModuleHandle( null ), null )

ShowWindow( hWnd, SW_SHOWNORMAL )
'UpdateWindow( hWnd )

do until( GetMessage( @wMsg, null, 0, 0 ) = 0 )
  TranslateMessage( @wMsg )
  DispatchMessage( @wMsg )
loop
ejc.cryptography
Posts: 268
Joined: Dec 16, 2006 20:52
Contact:

Postby ejc.cryptography » Mar 05, 2007 19:56

@ Michael W (or anyone else actually)

- Thanks for your help, I've now got another problem that I wonder if you would know how to do with listboxes.

I ideally need to create a list box with various headers at the top (i.e like in Windows Explorer when you click View \ Details - there are headers for name, size, type etc.) which will contain extra information about the items in the listbox - can this be acheived in FB?
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Mar 05, 2007 21:23

I think you are describing a List-View control using the Report view window style. If so, yes, it can be done, with some difficulty.

MSDN: List-View Controls Overview.
ejc.cryptography
Posts: 268
Joined: Dec 16, 2006 20:52
Contact:

Postby ejc.cryptography » Mar 06, 2007 17:00

Looks a bit like that - I meant more like this http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/header/header.asp

(Inside a list box) or something.

I reckon it might be to tricky for me to do!
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Mar 06, 2007 18:26

Take a look at the ListView thread in the Windows forum. Jerry Fielden posted an example that creates a List-View control that uses the Report view (LVS_REPORT) style.
ejc.cryptography
Posts: 268
Joined: Dec 16, 2006 20:52
Contact:

Listbox with icon

Postby ejc.cryptography » Apr 02, 2007 18:43

Can anyone show me how you'd make a list box (as shown in previous posts above), but one that has a small icon next to each item to the left inside the listbox? - just like many applications have.

I think it might have something to do woth OWNER_DRAW?

Thanks for all help.
MichaelW
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Postby MichaelW » Apr 03, 2007 11:47

This is not quite finished, but I'm out of time to play with it.

Resource definition, assumes fblogo.ico in current directory.

Code: Select all

1000 ICON "fblogo.ico"

Code: Select all

'=========================================================================
#include "windows.bi"
'=========================================================================

sub AddItem( byval hWndList as HWND, _
             byval pItemStr as zstring ptr, _
             byval hIcon as HICON )

  dim as integer nItem

  nItem = SendMessage( hWndList, LB_ADDSTRING, 0, cast(LPARAM,pItemStr) )
  SendMessage( hWndList, LB_SETITEMDATA, nItem, cast(LPARAM,hIcon) )

end sub

'=========================================================================

function PushButton( byref caption as string, _
                     byval hParent as HWND, _
                     byval x as integer, _
                     byval y as integer, _
                     byval w as integer, _
                     byval h as integer, _
                     byval cid as integer, _
                     byval extraStyle as integer = 0 ) as HWND

    dim style as integer = WS_CHILD or _
                           WS_VISIBLE or _
                           WS_TABSTOP or _
                           BS_PUSHBUTTON or _
                           extraStyle

    return CreateWindowEx( 0, _
                           "BUTTON", _
                           caption, _
                           style, _
                           x, y, w, h, _
                           hParent, _
                           cast( HMENU, cid ), _
                           GetModuleHandle( null ), _
                           null )
end function

'=========================================================================

function ListBox( byval hParent as HWND, _
             byval x as integer, _
             byval y as integer, _
             byval w as integer, _
             byval h as integer, _
             byval cid as integer, _
             byval extraStyle as integer = 0 ) as HWND

    dim style as integer = WS_CHILD or _
                           WS_VISIBLE or _
                           WS_TABSTOP or _
                           WS_BORDER or _
                           WS_VSCROLL or _
                           LBS_HASSTRINGS or _
                           LBS_NOINTEGRALHEIGHT or _
                           LBS_DISABLENOSCROLL or _
                           extraStyle

    return CreateWindowEx( WS_EX_CLIENTEDGE, _
                           "LISTBOX", _
                           0, _
                           style, _
                           x, y, w, h, _
                           hParent, _
                           cast( HMENU, cid ), _
                           GetModuleHandle( null ), _
                           null )
end function

'=========================================================================

function WindowProc( byval hWnd as HWND,_
                     byval uMsg as uint,_
                     byval wParam as WPARAM,_
                     byval lParam as LPARAM ) as LRESULT

    static as HWND hListBox
    static as COLORREF crSelText
    static as COLORREF crSelBkgnd
    dim as COLORREF crText
    dim as COLORREF crBkgnd
    dim as HICON hIcon
    dim as TEXTMETRIC tm
    dim as LPDRAWITEMSTRUCT lpdis
    dim as integer y, fSelected
    dim as zstring * 20 tBuffer

    select case uMsg

      case WM_CREATE

        hListBox = ListBox( hWnd, 15, 10, 110, 130, 101, _
                            LBS_OWNERDRAWFIXED or LBS_HASSTRINGS )

        PushButton( "Close", hWnd, 145, 10, 70, 30, IDCANCEL )

        hIcon = LoadIcon( GetModuleHandle( null ), MAKEINTRESOURCE(1000) )

        AddItem( hListBox, @"Item 1", hIcon )
        AddItem( hListBox, @"Item 2", hIcon )
        AddItem( hListBox, @"Item 3", hIcon )
        AddItem( hListBox, @"Item 4", hIcon )
        AddItem( hListBox, @"Item 5", hIcon )
        AddItem( hListBox, @"Item 6", hIcon )
        AddItem( hListBox, @"Item 7", hIcon )
        AddItem( hListBox, @"Item 8", hIcon )

        '' Get the system highlight colors.
        ''
        crSelText = GetSysColor( COLOR_HIGHLIGHTTEXT )
        crSelBkgnd = GetSysColor( COLOR_HIGHLIGHT )

        return true

      case WM_MEASUREITEM

        cast(LPMEASUREITEMSTRUCT,lParam)->itemHeight = 24

        return true

      case WM_DRAWITEM

        lpdis = cast(LPDRAWITEMSTRUCT,lParam)

        '' Skip this message if there are no listbox items.
        ''
        if lpdis->itemID = -1 then exit select

        select case lpdis->itemAction

          case ODA_SELECT, ODA_DRAWENTIRE

            ''-----------------------------------------
            '' Draw the icon associated with the item.
            ''-----------------------------------------

            hIcon = cast(HICON,SendMessage( lpdis->hwndItem, _
                                            LB_GETITEMDATA, _
                                            lpdis->itemID, 0 ))

            '' Use DrawIconEx so we can compress the icons.
            ''
            DrawIconEx( lpdis->hDC, _
                        lpdis->rcItem.left + 5, _
                        lpdis->rcItem.top + 4, _
                        hIcon, _
                        18, _
                        18, _
                        0, _
                        0, _
                        DI_NORMAL )

            ''-----------------------------------------
            '' Draw the text associated with the item.
            ''-----------------------------------------

            '' If the item is selected, use the system
            '' highlight colors to draw the text.
            ''
            if lpdis->itemState and ODS_SELECTED then
              crText = SetTextColor( lpdis->hDC, crSelText )
              crBkgnd = SetBkColor( lpdis->hDC, crSelBkgnd )
              fSelected = true
            end if

            SendMessage( lpdis->hwndItem, LB_GETTEXT, _
                         lpdis->itemID, cast(LPARAM,@tBuffer) )

            '' Calc the y coordinate necessary to align
            '' the text vertically with the icon.
            ''
            GetTextMetrics( lpdis->hDC, @tm )
            y = (lpdis->rcItem.bottom + lpdis->rcItem.top - _
                  tm.tmHeight) / 2

            '' For security, this *should* use the safe
            '' string function StringCchLength.
            ''
            TextOut( lpdis->hDC, 30, y, @tBuffer, len(tBuffer) )

            '' If the colors were changed, restore the
            '' normal non-selected colors.
            ''
            if fSelected then
              SetTextColor( lpdis->hDC, crText )
              SetBkColor( lpdis->hDC, crBkgnd )
            end if

          case ODA_FOCUS

            '' Draw the focus rectangle, in this case around
            '' the text only.

            '' Todo: adjust focus rectangle coordinates in a way
            '' that accounts for the actual length of the text.
            ''
            lpdis->rcItem.left += 28
            lpdis->rcItem.right -= 8

            '' The ODA_FOCUS message is sent when the focus changes,
            '' so it will be sent once for the item that is loosing
            '' the focus, and once for the item that is receiving
            '' the focus. DrawFocusRect is an XOR function, so it
            '' will remove the focus rectangle from the item that
            '' is loosing the focus, and add a focus rectangle to
            '' the item that is receiving the focus.
            ''
            DrawFocusRect( lpdis->hDC, @lpdis->rcItem )

        end select

        return true

      case WM_COMMAND

        if hiword(wParam) = BN_CLICKED then
          if loword(wParam) = IDCANCEL then
            DestroyWindow(hWnd)
          end if
        end if

      case WM_DESTROY

        PostQuitMessage( null )

      case else

        return DefWindowProc( hWnd, uMsg, wParam, lParam )

    end select

    return 0

end function

'=========================================================================
'' Start of implicit main.
'=========================================================================

dim hWnd as HWND
dim wMsg as MSG
dim as integer wx, wy, nWidth, nHeight
dim wcx as WNDCLASSEX
dim className as string = "listbox_test_class"

with wcx
  .cbSize = sizeof( WNDCLASSEX )
  .style = CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
  .lpfnWndProc = cast( WNDPROC, @WindowProc )
  .cbClsExtra = null
  .cbWndExtra = null
  .hInstance = GetModuleHandle( null )
  .hbrBackground = cast( HBRUSH,COLOR_WINDOW + 1 )
  .lpszMenuName = null
  .lpszClassName = strptr( className )
  .hIcon = LoadIcon( null, IDI_APPLICATION )
  .hCursor = LoadCursor ( null, IDC_ARROW )
  .hIconSm = 0
end with

RegisterClassEx( @wcx )

nWidth = 240
nHeight = 180
wx = (GetSystemMetrics( SM_CXSCREEN ) / 2) - nWidth / 2
wy = (GetSystemMetrics( SM_CYSCREEN ) / 2) - nHeight / 2

hWnd = CreateWindowEx( 0,_
                       strptr( className ),_
                       "Test",_
                       WS_OVERLAPPED or WS_SYSMENU,_
                       wx, wy, nWidth, nHeight,_
                       null, null,_
                       GetModuleHandle( null ), null )

ShowWindow( hWnd, SW_SHOWNORMAL )
UpdateWindow( hWnd )

'' Use IsDialogMessage as easy method of adding dialog-style
'' keyboard navigation and selection, and in combination with
'' IDCANCEL provide an easy way to close with the Escape key.
''
do until( GetMessage( @wMsg, null, 0, 0 ) = 0 )
  if IsDialogMessage( hWnd, @wMsg ) = 0 then
    TranslateMessage( @wMsg )
    DispatchMessage( @wMsg )
  end if
loop

Return to “Beginners”

Who is online

Users browsing this forum: No registered users and 0 guests