Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to put check box in List

Status
Not open for further replies.

alisaif

ISP
Apr 6, 2013
418
AE
Hi,

Is it possible to show check box in listbox like we change in grid in place of text box.

Thanks

Saif
 
I am still interested in check box and the list should be read only.
I open one field (inv c(8)) in delivery order table and value is replaced with invoice no. once the invoice is generated.
So, I want to put the syntax something like this.

Code:
This.Parent.ContList.List1.RowSource = 'DoView'
This.Parent.ContList.List1.RowSourceType = 2
This.Parent.ContList.List1.Picture = Iif(! Empty(inv),'\GRAPHICS\ICONS\CHECKBOX_CHECKED.BMP','\GRAPHICS\ICONS\UnCHECKBOX_CHECKED.BMP')

Thanks

Saif
 
Picture is not a Dynamic property you can fill with an IIF, you have to go through all items and set that in Picture[n]. It was already mentioned it's an array property with an element per Item.

Bye, Olaf.
 
Saif,

That won't work. What you'll get is the same iamge in every item.

To make it work, you need to treat the items in the list like an array. You can then indivually address each item according to the contents of the corresponding record. Something like this:

Code:
SELECT DoView
lnRow = 1
this.Parent.ContList.List1.RowSourceType = 0
SCAN
  this.Parent.ContList.List1.AddItem(Order_ID)    && or whatever character field you want to display
  this.Parent.ContList.List1.Picture(lnRow) = ;
     IIF(! EMPTY(inv),'\GRAPHICS\ICONS\CHECKBOX_CHECKED.BMP','\GRAPHICS\ICONS\UnCHECKBOX_CHECKED.BMP')
  lnRow = lnRow + 1
ENDSCAN


Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
How many records are you putting into the listbox?
Of course this takes more time compared to setting a rowsourcetpye alias and a table or cursor as rowsource, because you need to really create all the items.
The grid is the better choice in that case.

Bye, Olaf.
 
A listbox is not a good object for handling many items.
If your table has no more than 500 records, you can try RowSourceType=5 amd SELECT ... INTO ARRAY instead of SCAN... ENDSCAN (but I didn't noticed a gain in speed)
If you have 501 items, then Picture[1] is ignored.
If you have 502 items, then Picture[1] and Picture[2] is ignored, and so on.

For the solution proposed by Mr. Mike Lewis, with RowSourceType=0, I tried a cursor with 20000 records and I didn't noticed this problem.

Code:
PUBLIC ofrm
DO GenPict
ofrm=CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS MyForm as Form
	DIMENSION MyArray(1)
	ADD OBJECT lst1 as Listbox WITH width=200,columncount=2,columnwidths='75,125'
	
	PROCEDURE load
		CREATE CURSOR Invoices (inv c(8),cust C(20))
		LOCAL lni
		FOR lni=1 TO 500
			IF m.lni%7=0
				APPEND BLANK
			ELSE
				INSERT INTO Invoices VALUES ('Inv '+TRANSFORM(m.lni),'Cust '+TRANSFORM(m.lni%5+1))
			ENDIF
		NEXT
	ENDPROC
	PROCEDURE Init
		LOCAL lni
		SELECT * FROM Invoices INTO ARRAY ThisForm.MyArray
		This.lst1.RowSourceType=5
		This.lst1.RowSource='ThisForm.MyArray'
		FOR lni=1 TO This.lst1.ListCount
			This.lst1.Picture[m.lni]=IIF(EMPTY(This.lst1.List[m.lni,1]),"uncheck.bmp","check.bmp")
		NEXT
	ENDPROC
	PROCEDURE lst1.destroy
		LOCAL lni
		FOR lni=1 TO This.ListCount
			IF FILE(This.Picture[m.lni])
				ERASE (This.Picture[m.lni])
			ENDIF
		NEXT
	ENDPROC
ENDDEFINE


PROCEDURE GenPict
		LOCAL lcFile,oImage,oGr,oFillColor,oLineColor,oPen,oFontFam,oFont,oStringFormat,oBounds,oBrush,nHeight,nBkColor,nForeColor
		nBkColor=RGB(255,255,255)
		nForeColor=0
		nHeight=14
		
		lcFile="uncheck.bmp"
		oImage = Newobject('Gpbitmap',Home(1)+'ffc/_gdiplus.vcx')
		oImage.Create(m.nHeight,m.nHeight)
		oGr = Newobject('GpGraphics',Home(1)+'ffc/_gdiplus.vcx')
		oGr.CreateFromImage(oImage)
		oFillColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)) ) 
		oFillColor.set(nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)))
		oGr.Clear(oFillColor)
		oLineColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nForeColor,FLOOR(nForeColor%(256*256)/(256)),FLOOR(nForeColor/(256*256)) )
		oPen = Newobject('GpPen', Home(1)+'ffc/_gdiplus.vcx' )
		oPen.Create( m.oLineColor, 1 )
		oGr.DrawRectangle(oPen, 2,2, m.nHeight-5,m.nHeight-5)
		oImage.Savetofile( lcFile, "image/bmp")
		
		lcFile="check.bmp"
		oGr.DrawLine(oPen, 2,2, m.nHeight-4,m.nHeight-4)
		oGr.DrawLine(oPen, m.nHeight-3,2,2,m.nHeight-3)
		oImage.Savetofile( lcFile, "image/bmp")
		
		RETURN lcFile
ENDPROC


Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
It is very very slow.

It will only be slow if the listbox has many items. As others have said, a listbox is not the ideal tool if there are a large number of items in the list - somewhere between 25 and 50 items should be the maximum. If you keep below that figure, the method I suggested will not be particularly slow - unless there are other factors in play that we don't know about.

This isn't just a performance issue. If your aim is to let the user make a selection from the listbox, then you make it harder for them to do that if you have more than a couple of dozen items to choose from. In that case, you wil need some sort of search or filter to narrow down the choices. That applies equally to a grid. But at least a grid will load much faster if you realy must have a large number of items.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
It is around 18900+ records [purpleface]

I think I must switch to Grid Option without any further delay.

Saif
 
It is around 18900+ records

Believe me, that is far too many for a listbox - even without the images.

Even for a grid, that is a large number of records to show at one time. The grid will handle it easily, but I would question the user interface issues involved with displaying such a large amount of information in a single control.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Considering the delivery status you could skip all data that is completely delivered for at least a month. That's of no interest anymore.
If you show this for orderitems you should consider seperating that into a listbox or grid for orders and one to show the details of one order only, the currently selected order in the first list.
Also filter for any order, which is already completed for a long enough time for the user to also see just currently finished orders for their confirmation, perhaps.

If you really have such an amount of current orders partly delivered, than congrats.

Bye, Olaf.
 
Actually delivery order is just an example, same way I want to display the Sales Invoice records throughout the year. It is because I kept the date (from-to) open and user can enter any date in order to track the customer record.

Please suggest which is the best option in this circumstance?

Saif

 
You can always limit the amount of data you display with TOP clause.

Anyway the suggestion to accumulate a major list and show just one order, one invoice,one xyz completely can always be applied.

Bye, Olaf.
 
Saif,

I suggest you start by showing all the data - in a grid - but then give the user various options for filtering it. For example, you might let them filter by date of order (this month's orders, last month's orders, year-to-date, specific dates, etc); or by product, or value, or whatever makes sense in your application. And combine the filters so that they can use them in any combination.

Also, let them specify which column the grid is to be sorted on. It would be nice to let them click on a column header to sort on that column, but other mechanisms are also possible. And, once they have the grid in a given order, let them do an incremental search on the column in question.

Alternatively, take a completely different approach: Start by having them search for the orders (or whatever) they are interested in; then use the grid to display the records that match the search criteria.

These are just suggestions. You now your application - and your users - better than we do, so do whatever you think would work best.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks for the valuable suggestion

I suggest you start by showing all the data - in a grid - but then give the user various options for filtering it. For example, you might let them filter by date of order (this month's orders, last month's orders, year-to-date, specific dates, etc); or by product, or value, or whatever makes sense in your application. And combine the filters so that they can use them in any combination.

I will do the same and doing the same even for the list, now I have to change the list to grid.

Thanks

Saif
 
you can speed up the whole process by first assigning the picture image for the most frequent values.
In the following demo the empty() is six time less frequent.

Code:
PUBLIC ofrm
DO genpict
ofrm=CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS MyForm as Form
	ADD OBJECT lst2 as Listbox WITH width=200,columncount=2,columnwidths='75,100'
	PROCEDURE load
		LOCAL lni
		CREATE cursor cTmp (inv c(9),cust C(20))
		FOR lni=1 TO 20000
			IF lni%7<>0
				INSERT INTO cTmp (inv,cust ) VALUES ('Inv '+TRANSFORM(m.lni),'Cust '+TRANSFORM(m.lni%5))
			ELSE
				APPEND BLANK
			ENDIF
		NEXT
		GO TOP
	PROCEDURE Init
		LOCAL lni
		This.lst2.Picture="check.bmp" && First I set the most frequent picture
		SELECT cTmp
		lni=0
		SCAN
			lni=m.lni+1
			This.lst2.AddItem(inv)
			This.lst2.LIST(This.lst2.NewIndex,2)=cust
			If Empty(inv) && here I set only the less frequent picture
				This.lst2.Picture[m.lni]="uncheck.bmp"
			ENDIF
		ENDSCAN
	ENDPROC
	
	PROCEDURE lst2.destroy
*!*			LOCAL lni
*!*			FOR lni=1 TO This.ListCount
*!*				IF FILE(This.Picture[m.lni])
*!*					ERASE (This.Picture[m.lni])
*!*				ENDIF
*!*			NEXT
		IF FILE("check.bmp")
			ERASE check.bmp
		ENDIF
		IF FILE("uncheck.bmp")
			ERASE uncheck.bmp
		ENDIF
	ENDPROC
ENDDEFINE

PROCEDURE GenPict
	LOCAL lcFile,oImage,oGr,oFillColor,oLineColor,oPen,nHeight,nBkColor,nForeColor
	nBkColor=RGB(255,255,255)
	nForeColor=0
	nHeight=14
		
	lcFile="uncheck.bmp"
	oImage = Newobject('Gpbitmap',Home(1)+'ffc/_gdiplus.vcx')
	oImage.Create(m.nHeight,m.nHeight)
	oGr = Newobject('GpGraphics',Home(1)+'ffc/_gdiplus.vcx')
	oGr.CreateFromImage(oImage)
	oFillColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)) ) 
	oFillColor.set(nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)))
	oGr.Clear(oFillColor)
	oLineColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nForeColor,FLOOR(nForeColor%(256*256)/(256)),FLOOR(nForeColor/(256*256)) )
	oPen = Newobject('GpPen', Home(1)+'ffc/_gdiplus.vcx' )
	oPen.Create( m.oLineColor, 1 )
	oGr.DrawRectangle(oPen, 2,2, m.nHeight-5,m.nHeight-5)
	oImage.Savetofile( lcFile, "image/bmp")
		
	lcFile="check.bmp"
	oGr.DrawLine(oPen, 2,2, m.nHeight-4,m.nHeight-4)
	oGr.DrawLine(oPen, m.nHeight-3,2,2,m.nHeight-3)
	oImage.Savetofile( lcFile, "image/bmp")
ENDPROC

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Thanks again for the nice example, but I switched to grid which now consist of several forms like Sales Order, Despatch Order, Delivery Challans, Sales Invoice, Sales Return and FOC. This is a good example for future use.

Thanks

Saif
 
Another advantage of the grids dynamicproperties: Even if you couldn't embed a checkbox, you could embed two image controls in a column and use dynamiccurrentcontrol to switch between pictures, as Mike suggested right after I suggested dynamicbackcolor. The trick with the Picture property setting the whole array and then only reset the few pictures, that are different, is still taking much more time than that.

Bye, Olaf.
 
I've found a way to use different pictures when Rowsource=2 (alias), but the limit of 500 rows remains.
The same limit I found for RowSource=5 (array).

The trick is to place the setting picture in the paint method.
To avoid unnecessary calling of the FirstPaint method, I added a new form property, named lFirstPaint.

Code:
PUBLIC ofrm
DO GenPict
ofrm=CREATEOBJECT("MyForm")
ofrm.show()

DEFINE CLASS MyForm as Form
	ADD OBJECT lst1 as Listbox WITH width=200,columncount=2,columnwidths='75,125',RowSourceType=2,RowSource="Invoices"

************ The new property and procedures
	lFirstPaint=.F.
	PROCEDURE paint
		IF !This.lFirstPaint
			This.FirstPaint
			This.lFirstPaint=.T.
		ENDIF
	ENDPROC
	PROCEDURE FirstPaint
		SELECT Invoices
		SCAN
			This.lst1.Picture[RECNO("Invoices")]=IIF(EMPTY(invoices.inv),"uncheck.bmp","check.bmp")
		ENDSCAN
		GO TOP
	ENDPROC
*************
	
	PROCEDURE load
		CREATE CURSOR Invoices (inv c(8),cust C(20))
		LOCAL lni
		FOR lni=1 TO 500 && for 501 the first row show no picture, for 502 the first two rows and so on
			IF m.lni%7=0
				APPEND BLANK
			ELSE
				INSERT INTO Invoices VALUES ('Inv '+TRANSFORM(m.lni),'Cust '+TRANSFORM(m.lni%5+1))
			ENDIF
		NEXT
	ENDPROC

	PROCEDURE lst1.destroy
		LOCAL lni
		FOR lni=1 TO This.ListCount
			IF FILE(This.Picture[m.lni])
				ERASE (This.Picture[m.lni])
			ENDIF
		NEXT
	ENDPROC
ENDDEFINE


PROCEDURE GenPict
		LOCAL lcFile,oImage,oGr,oFillColor,oLineColor,oPen,oFontFam,oFont,oStringFormat,oBounds,oBrush,nHeight,nBkColor,nForeColor
		nBkColor=RGB(255,255,255)
		nForeColor=0
		nHeight=14
		
		lcFile="uncheck.bmp"
		oImage = Newobject('Gpbitmap',Home(1)+'ffc/_gdiplus.vcx')
		oImage.Create(m.nHeight,m.nHeight)
		oGr = Newobject('GpGraphics',Home(1)+'ffc/_gdiplus.vcx')
		oGr.CreateFromImage(oImage)
		oFillColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)) ) 
		oFillColor.set(nBkColor%256,FLOOR(nBkColor%(256*256)/(256)),FLOOR(nBkColor/(256*256)))
		oGr.Clear(oFillColor)
		oLineColor = Newobject( 'GpColor',Home(1)+'ffc/_gdiplus.vcx','', nForeColor,FLOOR(nForeColor%(256*256)/(256)),FLOOR(nForeColor/(256*256)) )
		oPen = Newobject('GpPen', Home(1)+'ffc/_gdiplus.vcx' )
		oPen.Create( m.oLineColor, 1 )
		oGr.DrawRectangle(oPen, 2,2, m.nHeight-5,m.nHeight-5)
		oImage.Savetofile( lcFile, "image/bmp")
		
		lcFile="check.bmp"
		oGr.DrawLine(oPen, 2,2, m.nHeight-4,m.nHeight-4)
		oGr.DrawLine(oPen, m.nHeight-3,2,2,m.nHeight-3)
		oImage.Savetofile( lcFile, "image/bmp")
		
		RETURN lcFile
ENDPROC



Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top