May 06, 2024, 02:38:13 AM

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Multiple Lines in LISTVIEW Report

Started by Allan, September 03, 2008, 06:59:30 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Allan

Looking through ListView it seems there is no way of having multiple lines like in a TABLE in HTML.

I was hoping to display items like this:

____________________________________________________________
8.00 AM  |  Check Payment of Electricity
__________|_________________________________________________
10.00 AM | Contact Sam about the trip to England on the
                | 10th October to confirm the booking.
__________|_________________________________________________

Pardon the poor simulated graphics above.

Allan

Ionic Wind Support Team

Have you tried putting a return in there?

text = "line one\nline two"

Ionic Wind Support Team

Allan

Paul

Did try that idea but did not get the result expected.

I put it in the edit control when making an entry but it just shows up as   \n  in the list view.

Secondly tried inserting it into the text as you suggested and it just puts two rectangles in the list view.


see image attached.

LarryMc

Allan,
This might shed some light unless you're the same Allan.
It shows a multiline subitem in a listview.

http://www.codeproject.com/KB/list/aa_listview.aspx?df=100&forumid=15258&exp=0&fr=26&select=827124

Larry
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Ionic Wind Support Team

Just checked MSDN and the list view control doesn't support multiple lines per subitem using a return character, unless you draw the text yourself in an ownerdrawn control in response to WM_DRAWITEM.  Just another Windows limitation.

Actually it makes sense since a subitem with multiple lines would affect the layout and size of all other subitems in the control.  The control would need to iterate through all of the subitems to calculate the height of the row being drawn.

Paul.
Ionic Wind Support Team

Allan

Larry - not me. But have been a member there for years.

Reading through the comments at the bottom of allen's article i found a note where one person was having problem getting multiline to work and the response from another person was as follows:
QuoteI haven't got a good solution for you, but I got the same problem. After testing around I found out that the ItemWordWrap property works properly only if you work with '\r\n' or Environment.NewLine.
Thanks for the link.
The images in the article showed some items I have seen in IBPro done by sapero so I will hunt that up as it may have a part solution to multiline.

Thank you Paul I will have a try at using the OWNERDRAWN for ListView. I had seen reference to it in the API but was not sure if it was the answer to what I wanted to do.

Allan

Allan

I have made some progress on the Multiline in the ListView, however, having problem with LINE HEIGHT.

Can anyone see where I have missed the setting?  The lines do draw but spacing is incorrect...

' ListView CustomDraw Multiline
' compile Windows - Allan
' Is to make the Details column multiline....where required

'DECLARES from the Windows API we will use in our program
DECLARE IMPORT,CallWindowProcA(lpPrevWndFunc:int,hWnd:int,Msg:int,wParam:int,lParam:int),INT
DECLARE IMPORT,SetWindowLongA(hWnd:int,nIndex:int,dwNewLong:int),INT
DECLARE IMPORT,GetWindowLongA(hWnd:int,nIndex:int),INT
DECLARE IMPORT,GetDlgItem(hDlg:int,nIDDlgItem:int),INT
DECLARE IMPORT,DrawTextA(hDC:Int,lpString:String,nCount:Int,lpRect:WINRECT,uFormat:Int),INT

'Necessary constants
CONST GWL_WNDPROC=-4
CONST NM_CUSTOMDRAW = (-12)
CONST CDDS_PREPAINT = 1
CONST CDDS_ITEM = 0x10000
CONST CDDS_SUBITEM = 0x20000
CONST CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT)
CONST CDDS_SUBITEMPREPAINT = (CDDS_SUBITEM | CDDS_ITEMPREPAINT)
CONST CDRF_NOTIFYITEMDRAW = 0x20
CONST CDRF_NOTIFYSUBITEMDRAW = 0x20
CONST CDRF_DODEFAULT = 0
CONST CDRF_NEWFONT = 2
CONST CDRF_SKIPDEFAULT = 0x4
CONST DWL_MSGRESULT = 0
CONST DT_WORDBREAK = 0x10
CONST DT_CALCRECT = 0x400
CONST LVIR_BOUNDS = 0

CONST LVM_FIRST = 0x1000
CONST LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54)
CONST LVS_EX_FULLROWSELECT = 0x20
CONST LVS_EX_GRIDLINES = 1
CONST LVS_EX_FLATSB = 0x100
CONST LVS_EX_LABELTIP = 0x4000
CONST LVM_GETITEMRECT = (LVM_FIRST + 14)
CONST LVM_GETSUBITEMRECT = (LVM_FIRST + 56)
CONST LVM_GETTOPINDEX = (LVM_FIRST + 39)
'CONST WM_PAINT = 0xF

'standard NMLISTVIEW UDT
'Windows sends a variable of this type in @LPARAM
'during a notification message.
TYPE NMLISTVIEW
def hwndFrom:UINT
def idFrom:INT
def code:INT
    def iItem:INT
    def iSubItem:INT
    def uNewState:UINT
    def uOldState:UINT
    def uChanged:UINT
    def ptActionx:INT
def ptActiony:INT
    def lParam:INT
ENDTYPE

'type for handling custom drawing of the header control
TYPE NMCUSTOMDRAWINFO
NMHDR hdr
UINT dwDrawStage
UINT hdc
WINRECT rc
UINT dwItemSpec
UINT uItemState
UINT lItemlParam
ENDTYPE
'type for handling custom drawing of the list view control
TYPE NMLVCUSTOMDRAW
    NMCUSTOMDRAWINFO nmcd
    UINT clrText
    UINT clrTextBk
'if internet explore version >= 4.0
    int iSubItem
ENDTYPE

CONST STATIC_1 = 1
CONST EDIT_2 = 2
CONST STATIC_3 = 3
CONST EDIT_4 = 4
CONST LV_DISP = 5
CONST BTN_ADD = 6

UINT lvHandle

DIALOG d1
CREATEDIALOG d1,0,0,365,256,0x80C80080,0,"ListView Custom Draw",&d1_handler
CONTROL d1,@STATIC,"Time",23,12,28,15,0x5000010B,STATIC_1
CONTROL d1,@EDIT,"",64,10,70,20,0x50810080,EDIT_2
CONTROL d1,@STATIC,"Details",23,45,35,14,0x5000010B,STATIC_3
CONTROL d1,@EDIT,"",62,42,276,39,0x50810044,EDIT_4
CONTROL d1,@LISTVIEW,"",19,92,325,148,0x50000001,LV_DISP
CONTROL d1,@BUTTON,"Add",264,11,70,20,0x50010000,BTN_ADD

' Show the Dialog and Wait For it To close
DOMODAL d1
' End program
END

SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
      CONTROLCMD d1,LV_DISP,@LVINSERTCOLUMN,0,"Time"
      CONTROLCMD d1,LV_DISP,@LVINSERTCOLUMN,1,"Details"
    CONTROLCMD d1,LV_DISP,@LVSETCOLWIDTH,0,60
    CONTROLCMD d1,LV_DISP,@LVSETCOLWIDTH,1,260

'the first row item and sub items
CONTROLCMD d1,LV_DISP,@LVINSERTITEM,0,"10.00 AM"
CONTROLCMD d1,LV_DISP,@LVSETTEXT,0,1,"Ring Head Office regards promotional campaign"
'the second row item and sub items
CONTROLCMD d1,LV_DISP,@LVINSERTITEM,0,"11.30 AM"
CONTROLCMD d1,LV_DISP,@LVSETTEXT,0,1,"Appointment with Sales Team"
'the third row item and sub items
CONTROLCMD d1,LV_DISP,@LVINSERTITEM,0,"1.30 PM"
CONTROLCMD d1,LV_DISP,@LVSETTEXT,0,1,"Meet Adrian from Calcat at Airport and hand over the Overseas Portfolio for next Seasons Promotional Campaign"
'the fourth row item and sub items
CONTROLCMD d1,LV_DISP,@LVINSERTITEM,0,"3.30 PM"
CONTROLCMD d1,LV_DISP,@LVSETTEXT,0,1,"Advise Head Office on todays events"

'change some of the listview extended styles
SENDMESSAGE d1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FLATSB|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES|LVS_EX_LABELTIP,LV_DISP
' handle to list view control
lvHandle   = GetDlgItem(d1.hwnd, LV_DISP)
CASE @IDCLOSEWINDOW
CLOSEDIALOG d1,@IDOK
CASE @IDCONTROL
SELECT @CONTROLID
CASE EDIT_2
/* respond to edit notifications here */
CASE EDIT_4
/* respond to edit notifications here */
CASE LV_DISP
/* respond to control notifications here */
SELECT @NOTIFYCODE
CASE NM_CUSTOMDRAW
SetWindowLongA(d1.hwnd,DWL_MSGRESULT,ColorListView(d1.hwnd,@LPARAM))
RETURN TRUE
ENDSELECT
CASE BTN_ADD
IF @NOTIFYCODE = 0
/*button clicked*/
ENDIF
ENDSELECT
ENDSELECT
RETURN
ENDSUB

' LISTVIEW colors text and background
SUB ColorListView(hwnd as UINT,lParam as UINT),UINT
DEF rv:UINT
DEF iCol,iRow,hgt,hdc:INT
DEF str1:STRING
DEF rc,lvrc:WINRECT

SELECT *<NMLVCUSTOMDRAW>lParam.nmcd.dwDrawStage
CASE CDDS_PREPAINT
rv = CDRF_NOTIFYITEMDRAW
CASE CDDS_ITEMPREPAINT
'*<NMLVCUSTOMDRAW>lParam.nmcd.dwItemSpec is the zero based item the control is drawing
'but we want to color each column item (subitem) individually
rv =CDRF_NOTIFYSUBITEMDRAW
CASE CDDS_SUBITEMPREPAINT
'*<NMLVCUSTOMDRAW>lParam.iSubItem contains the zero based sub item number
'on system with IE 4.0 or greater installed.
iCol = *<NMLVCUSTOMDRAW>lParam.iSubItem
iRow = *<NMLVCUSTOMDRAW>lParam.nmcd.dwItemSpec
CONTROLCMD(d1,LV_DISP,@LVGETTEXT,iRow,iCol,str1)
hdc = *<NMLVCUSTOMDRAW>lParam.nmcd.hdc
lvrc = *<NMLVCUSTOMDRAW>lParam.nmcd.rc
hgt = 0
SELECT iCol
CASE 0:'  the Time color
*<NMLVCUSTOMDRAW>lParam.clrText = RGB(0,0,0)
*<NMLVCUSTOMDRAW>lParam.clrTextBk = RGB(255,0,0)
rv = CDRF_NEWFONT
CASE 1:' the Details
*<NMLVCUSTOMDRAW>lParam.clrText = RGB(0,0,0)
*<NMLVCUSTOMDRAW>lParam.clrTextBk = RGB(0,255,0)
' Set up rc for GetSubItemRect
rc.left = LVIR_BOUNDS     :'icon and label
rc.top  = iCol            :'SubItem
SendMessage(lvHandle, LVM_GETSUBITEMRECT, iRow, &rc)
rc.right-=1
' Calculate the height of the text
hgt = DrawTextA(hdc,str1,LEN(str1),rc,DT_WORDBREAK|DT_CALCRECT)
*<NMLVCUSTOMDRAW>lParam.nmcd.rc.bottom = *<NMLVCUSTOMDRAW>lParam.nmcd.rc.top + hgt
' Draw the text
DrawTextA(hdc,str1,LEN(str1),rc,DT_WORDBREAK)
rv = CDRF_SKIPDEFAULT
DEFAULT: 'the color of the rest of the line
*<NMLVCUSTOMDRAW>lParam.clrText = RGB(0,0,0)
*<NMLVCUSTOMDRAW>lParam.clrTextBk = RGB(255,0,255)
rv = CDRF_NEWFONT
ENDSELECT
' rv = CDRF_NEWFONT
DEFAULT
rv = CDRF_DODEFAULT
ENDSELECT
RETURN rv
ENDSUB



Thanks for any help  ...

Allan


sapero

September 13, 2008, 04:32:12 AM #7 Last Edit: September 13, 2008, 07:10:07 AM by sapero
Allan, listview does not support variable in height items. Listbox does, and I've already coded a bit.
There is a small bug in the first line, DrawText returns height of two lines instead one.
Bug fixed - missing SelectObject(font) after GetDC() in MeasureListItem handler.

Added gridlines and a separate function to initialize the listbox.
Removed LB_SETITEMDATA from InsertListItem, because LB_ADDSTRING did that already.

Do you need a header over the list? Or additional notifications from this control?

Allan

Sapero,

Have been searching net for answers to CustomDraw and it does not appear to be available except some coders at Code Project have done it somehow. I could not find an overall HEIGHT setting either.

Dave Calkins in his article Multi-Line List Control has a working example and source code but its a bit heavy for my reading.

Anyway what you have done looks really hot using a LISTBOX.

Thank you for the code and effort you put into this resolution.

At the moment I have used Horizontal scrollbar to allow the ListView to extend if there is more text that is not viewable in a row. That is ok but not really top work.

I have an image of the real app attached.

In the app I have actually (4) FOUR Columns - two are hidden and hold ID and MASTID UINT for use in ACCESS Database.

A Single Click on a ROW allows the buttons to change to DELETE enabled.
A Double click on a ROW will put the text into the EDIT Controls for Editing and enable the EDIT button.
A single click on a Row will also cancel any EDIT in place.

Other than the two ID columns (hidden) there is nothing else really done in the ListBox.

The ListBox Rows are interfaced to a MS ACCESS database.

Just a question on your include "commctrl.inc" - is it the same as the one used in EBasic "Comctrl32.inc"?

Allan

sapero

These two includes are the same you would find in any complete c/c++ environment for Windows platform, just converted to EB. I always hated pasting winapi defines in every source code, so long time ago started with porting all the headers. You'll find links in my signature.

I have no Comctrl32.inc, and didn't hear about it.
The guy from Codeproject created multiline listview, but it's a joke - all lines have same height. You can do this by applying big enough image as imagelist for your listview, and use custom drawn items. You can also set big font (WM_SETFONT), and manually draw text with default, small font.

Allan

Sapero I downloaded the includes you mentioned. Thanks for them.

I have already done the ICON set to defined size as that fellow did at CodeProject.
It is not 100% as the Vertical Scroll bar does not kick in until the LV is scrolled. I still have a few things to do to get it working better. You can use PageUp etc in the LV of course.

I dont mind it so much this way as it reflects the layout of Lotus Notes which I was hoping to do originally.

Comctrl32.inc is in the EBasic Helpfiles.

After reading your code more and doing a bit of research I can understand it more now. I see you have an OWNERDRAWN LISTBOX which is quite interesting in that I was thinking earlier on what control I could build something like what you have done. The ListBox is ideal as if I remember correctly it has an ItemData which is not displayed and could contain the Database Table ID I need.

Just curious though about why you did it the way you did in that you used the original LV to get position and measurements and then HIDE it and used the Created Owner Drawn List Box.

Could you have simply created the Owner Drawn ListBox from the start and bypassed all that other thingey with the original ListView.??

Allan


sapero

Yes, you can skip the initial creation of LV_DISP, but must apply some modifications:
CONTROL d1,@BUTTON,"Add",264,11,70,20,0x50010000,BTN_ADD
'CONTROL d1,@LISTBOX,"",19,92,325,148,0,LV_DISP /* not required */

[cut]

SUB d1_handler
HWND hwndList
SELECT @MESSAGE
CASE @IDINITDIALOG

hwndList = CreateListWindow(d1.hwnd, LV_DISP, 60, 19,92,325,148, WS_EX_CLIENTEDGE)

'the first row item and sub items
InsertListItem(hwndList,"10.00 AM", "Ring Head Office regards promotional campaign")
[cut]

sub CreateListWindow(HWND hwndParent, int listID, int ColumnWidth, int left, int top, int width, int height, int exstyle),HWND
HWND hwndList

' subclass the dialog, because we need WM_DRAWITEM
' note: this must be emergence window or dialog
' note: do not use g_OldDlgProc for window AND dialog, if used once for a dialog, do not use it for window
g_OldDlgProc = SetWindowLong(hwndParent, GWL_WNDPROC, &ForwardDrawItemProc)

' create new listbox
hwndList = CreateWindowEx(exstyle, WC_LISTBOX, NULL, LBS_MULTILINE, _
left, top, width, height, _
hwndParent, listID, _hinstance, 0)

' save first column width
SetProp(hwndList, "colw", ColumnWidth)
' restore font
SendMessage(hwndList, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), 0)

return hwndList
endsub

Allan

Thanks Sapero

This looks good and the way to go for my program. I use a Window as main window where this is to be used because I need  @HIDDEN in the Window flags.

Allan