15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


'Virtual' list-box

Ellis Brover -- brover@siemens.com.au
Tuesday, November 14, 1995


Hi,

I am trying to create a "virtual" list-box deriving from CListCtrl
(i.e. using the Windows95 list-view control). It needs to handle
scrolling completely, so that only the items visible on the screen
are actually in the list at any given time. This is necesary so that
I can dynamically read in just a few items from a huge database
cursor query.

I have looked at the VLIST sample on MSDN, but it doesn't really
work the same for the list-view control. For example, the list-view
tries to set the scroll position/range on every WM_PAINT, so I need
to intercept WM_PAINT and reset my own scroll position. This creates
flickering and all sorts of recursion problems with WM_SIZE being called
repeatedly. The only way I can find to tell Windows to leave scrolling
alone is the LVS_NOSCROLL style, but this has an unexpected side-effect:
under NT 3.51 it also turns off the column headers!

Any help would be appreciated! Also if anybody has written a
virtual tree-view control that would be even more appreciated!

Thanks,
Ellis Brover

Ellis.Brover@siemens.com.au  



jerry_albro@tcpgate.ibi.com
Thursday, November 16, 1995

Maybe a proper database grid contol would be more useful. I've used the Kansmen
table tool  control, and it allows exactly what you need. You tell it how many
records you have, and it will request data when the user scrolls, with a
selectable amount of buffering so you dont bang on the database more than you
want to. I'm sure other database grid controls can also do this. It surely will
be a lot easier than force-fitting a listbox into your scheme...

Jerry Albro

_________________________Reply Header_________________________
Author: mfc-l@netcom.com
Subject: "Virtual" list-box
11-14-95 08:23 PM


Hi,

I am trying to create a "virtual" list-box deriving from CListCtrl
(i.e. using the Windows95 list-view control). It needs to handle
scrolling completely, so that only the items visible on the screen
are actually in the list at any given time. This is necesary so that
I can dynamically read in just a few items from a huge database
cursor query.

I have looked at the VLIST sample on MSDN, but it doesn't really
work the same for the list-view control. For example, the list-view
tries to set the scroll position/range on every WM_PAINT, so I need
to intercept WM_PAINT and reset my own scroll position. This creates
flickering and all sorts of recursion problems with WM_SIZE being called
repeatedly. The only way I can find to tell Windows to leave scrolling
alone is the LVS_NOSCROLL style, but this has an unexpected side-effect:
under NT 3.51 it also turns off the column headers!

Any help would be appreciated! Also if anybody has written a
virtual tree-view control that would be even more appreciated!

Thanks,
Ellis Brover

Ellis.Brover@siemens.com.au  




Mike Blaszczak -- mikeblas@interserv.com
Friday, November 17, 1995

On Tue, 14 Nov 95, Ellis Brover  wrote:

>I am trying to create a "virtual" list-box deriving from CListCtrl
>(i.e. using the Windows95 list-view control). It needs to handle
>scrolling completely, so that only the items visible on the screen
>are actually in the list at any given time. This is necesary so that
>I can dynamically read in just a few items from a huge database
>cursor query.

You don't need to worry about doing any virtualization yourself if you're 
using a Windows list view common control.  Just implement a handler for the 
get disp info notification message from the list (in MFC, it would be 
OnGetDispInfo() in the owner window) and tell the list control that all of 
your strings are LPSTR_TEXTCALLBACK.

You can find information on how this works starting with this section in the 
Win32 SDK documentation:

Win32
   Overviews
      Window Controls
         Common Controls
            List View Controls
               About List View COntrols
                  Callback Items and the Callback Mask

.B ekiM
--
#ifdef JOHNELS_SAID_I_COULD_STEAL_HIS_SIG
//REVIEW: JohnEls changed his and now it's cooler than the one I stole
TCHAR szDisc[] = _T("These words are my own; I do not speak for Microsoft.");
#endif




Colin Oatley -- ColinOatley@msn.com
Sunday, January 28, 1996

I am trying to follow up on the suggestions that were given in the message, 
"Re 'Virtual' list-box," dated 11/17/95. You will recall that a "Virtual" list 
box is a CListCtrl that contains the visible subset of a database cursor 
query; as the user scrolls through the CListCtrl, the virtual list box would 
insert the newly visible items and delete the newly invisible items from the 
control. If a cursor contains only a few rows, one can afford to insert all of 
them into the control. But if a cursor contains thousands or millions of rows, 
it's impractical to insert them all at once.

I've studied the suggested solution and the MFC & SDK manuals, I've run some 
tests, and I don't see how inserting rows as callback items helps to achieve 
the virtual list box. It appears that the LVN_GETDISPINFO notification message 
only applies to items that I have already inserted into the control; it 
doesn't tell me when I need to insert or remove items from the control. Am I 
missing something?

At present, the only way I can think of to implement a virtual list box is to 
insert, say, 100 items into the CListCtrl and intercept the scrolling 
messages, adding/deleting items to/from the control as the user scrolls.

Does this sound reasonable? Does anyone know of a better way?


>From:  owner-mfc-l@netcom.com on behalf of mikeblas@interserv.com
>Sent:  Friday, November 17, 1995 2:43 PM
>To:  mfc-l@netcom.com
>Subject:  Re: "Virtual" list-box
>
>On Tue, 14 Nov 95, Ellis Brover  wrote:
>
>>I am trying to create a "virtual" list-box deriving from CListCtrl
>>(i.e. using the Windows95 list-view control). It needs to handle
>>scrolling completely, so that only the items visible on the screen
>>are actually in the list at any given time. This is necesary so that
>>I can dynamically read in just a few items from a huge database
>>cursor query.
>
>You don't need to worry about doing any virtualization yourself if you're
>using a Windows list view common control.  Just implement a handler for the
>get disp info notification message from the list (in MFC, it would be
>OnGetDispInfo() in the owner window) and tell the list control that all of
>your strings are LPSTR_TEXTCALLBACK.

>You can find information on how this works starting with this section in the
>Win32 SDK documentation:
>
>Win32
>   Overviews
>      Window Controls
>         Common Controls
>            List View Controls
>               About List View COntrols
>                  Callback Items and the Callback Mask
>
>.B ekiM
>--
>#ifdef JOHNELS_SAID_I_COULD_STEAL_HIS_SIG
>//REVIEW: JohnEls changed his and now it's cooler than the one I stole
>TCHAR szDisc[] = _T("These words are my own; I do not speak for Microsoft.");
>#endif




Tim Philip -- philip@cs.usask.ca
Monday, January 29, 1996

[Mini-digest: 2 responses]

Colin Oatley writes:
> 
> I am trying to follow up on the suggestions that were given in the message, 
> "Re 'Virtual' list-box," dated 11/17/95. You will recall that a "Virtual" list 
> box is a CListCtrl that contains the visible subset of a database cursor 
> query; as the user scrolls through the CListCtrl, the virtual list box would 
> insert the newly visible items and delete the newly invisible items from the 
> control. If a cursor contains only a few rows, one can afford to insert all of 
> them into the control. But if a cursor contains thousands or millions of rows, 
> it's impractical to insert them all at once.
> 
> I've studied the suggested solution and the MFC & SDK manuals, I've run some 
> tests, and I don't see how inserting rows as callback items helps to achieve 
> the virtual list box. It appears that the LVN_GETDISPINFO notification message 
> only applies to items that I have already inserted into the control; it 
> doesn't tell me when I need to insert or remove items from the control. Am I 
> missing something?
> 
> At present, the only way I can think of to implement a virtual list box is to 
> insert, say, 100 items into the CListCtrl and intercept the scrolling 
> messages, adding/deleting items to/from the control as the user scrolls.
> 
> Does this sound reasonable? Does anyone know of a better way?
> 

I've never tried this ... but this is what I would look into:

Set up a very simple CVirtualListCtrl which acts just like a CListCtrl
except that it accepts a posted message to insert a new element.

Then create a threaded class that will read extra elements from the
database and send messages to the CVirtualListCtrl to add more items.
Hook this class into OnIdle() so that it doesn't suck up too much
CPU time (effectively stopping the user from scrolling through the
list).

The end result should be a listbox that slowly grows  (ie. growing
faster the less the user does, so if the user gets to the end of the
list and pauses it should quickly fill in extra entries).

As I said, I've never done this and I'm not even sure that it is do-able.
But it sure sounds good, eh!

:)

-------
Tim Philip, B.Sc.           Randco Software Corporation
Consultant                  2530 Hanover Avenue   
                            Saskatoon, SK          Phone: +1-306-343-3380
philip@cs.usask.ca          Canada   S7J 1G1         Fax: +1-306-343-3341
-----From: kitk@mudshark.sunquest.com (Kit Kauffmann)

>"Re 'Virtual' list-box," dated 11/17/95. You will recall that a "Virtual" list 
>box is a CListCtrl that contains the visible subset of a database cursor 
>query; as the user scrolls through the CListCtrl, the virtual list box would 
>

FYI, "virtual listbox" usually refers to a freebie from MS called VLIST, 
which is a simple virtual listbox that makes it possible to have a 
standard-looking listbox which can handle a huge (2^31) number of items (by 
using a regular listbox control which actually only contains the # of 
visible items: it then calls you to ask for the next or previous record, and 
so forth)

If anyone cares, I provide both an updated version of that (rather 
bug-ridden) VLIST control which is in commercial use in a number of programs 
(worldwide!), and an MFC wrapper class which is also in use by most of those 
programs (not in programs I wrote: I've only used it in a few myself, so it 
may not be perfect but lots of people are using it.

(Shameless self-promotion for some free software: you can get it and other 
items at mudshark.sunquest.com in the pub/kitk directory -there is an index 
which briefly describes the VLIST stuff and some other useful stuff for MFC 
and Windows programmers)

K




Stephen Keeler -- keelers@igs.net
Tuesday, January 30, 1996

> I am trying to follow up on the suggestions that were given in the
> message, "Re 'Virtual' list-box," dated 11/17/95. You will recall
> that a "Virtual" list box is a CListCtrl that contains the visible
> subset of a database cursor query; as the user scrolls through the
> CListCtrl, the virtual list box would insert the newly visible items
> and delete the newly invisible items from the control. If a cursor
> contains only a few rows, one can afford to insert all of them into
> the control. But if a cursor contains thousands or millions of rows,
> it's impractical to insert them all at once.
> 
> I've studied the suggested solution and the MFC & SDK manuals, I've
> run some tests, and I don't see how inserting rows as callback items
> helps to achieve the virtual list box. It appears that the
> LVN_GETDISPINFO notification message only applies to items that I
> have already inserted into the control; it doesn't tell me when I
> need to insert or remove items from the control. Am I missing
> something?
> 
> At present, the only way I can think of to implement a virtual list
> box is to insert, say, 100 items into the CListCtrl and intercept
> the scrolling messages, adding/deleting items to/from the control as
> the user scrolls.
> 
> Does this sound reasonable? Does anyone know of a better way?
> 

This is the approach that I took 3 years ago, using Windows 3.1 and a 
subclassed LISTBOX control.  You set up a row buffer that is somewhat 
larger than the max number of displayed rows in the control, then 
intercept user movement requests.

While it certainly is possible to go after data on a one-by-one basis 
-- the callback mentioned above for CListCtrl and also the approach 
used in the VLIST sample -- it is terribly inefficient for certain 
types of data sources.  In our case, we're going after data in SQL 
Server databases.

This is definitely a non-trivial task.  In order to justify the 
amount of work required to provide this type of functionality, we 
implemented our original solution as a VBX so that it could be easily 
reused.

Regards,
Stephen Keeler
On-Line Systems Inc.



Balaji S -- balaji@hiso.honeywell.soft.net
Friday, February 02, 1996


Hello,

	I am using the VLIST and a class based implementation of the same.

	I want the Drag'n Drop feature also to be added to the VLIST box. I 
am using MSVC 1.52 and Windows v3.11. The application should be able to 
send me messages when some item is clicked and dragged. I don't want drag'n 
drop within the same VLIST, but I should be able to Drop it to another 
normal listbox.

	For this normal listbox, I am processing the OnLButtonDown, 
OnMouseMove and OnLButtonUp messages. It is inherited from CListbox ( MFC 
class ). Should I do the same way for VLIST also by processing all the 
above mouse messages ?

	Moreover is it possible to have  multiple selection in the VLIST 
box ? Are there any freeware implementations available or any style bit can 
be set for this purpose ?

	Any pointers will be appreciated.

TIA

WM_CHEERS | WM_REGARDS
Balaji
                   ____________________________
                  |   Balaji Subramaniam       |
                /)| balaji@honeywell.soft.net  |(\
               / )| Balaji.S@CORP.honeywell.com|( \
            __(  (|____________________________|)  )__
           ((( \  \ >  /_)              ( \  < /  / )))
           (\\\ \  \_/  /                \  \_/  / ///)
            \          /                  \          /
              \      _/                     \_      /
               /    /                         \     \
              /    /                            \    \

*********************************************************************
           fu cn rd ths, u cn gt a gd jb n cmptr prgrmmng
*********************************************************************
02/01/96   10:00:28 IST




Kit Kauffmann -- kitk@mudshark.sunquest.com
Thursday, February 01, 1996

>> I am trying to follow up on the suggestions that were given in the
>> message, "Re 'Virtual' list-box," dated 11/17/95. You will recall
>> that a "Virtual" list box is a CListCtrl that contains the visible
>> subset of a database cursor query; as the user scrolls through the
>> CListCtrl, the virtual list box would insert the newly visible items
>> and delete the newly invisible items from the control. If a cursor
>> contains only a few rows, one can afford to insert all of them into
>> the control. But if a cursor contains thousands or millions of rows,
>> it's impractical to insert them all at once.
>> 
>> I've studied the suggested solution and the MFC & SDK manuals, I've
>> run some tests, and I don't see how inserting rows as callback items
>> helps to achieve the virtual list box. It appears that the
>> LVN_GETDISPINFO notification message only applies to items that I
>> have already inserted into the control; it doesn't tell me when I
>> need to insert or remove items from the control. Am I missing
>> something?
>> 
>> At present, the only way I can think of to implement a virtual list
>> box is to insert, say, 100 items into the CListCtrl and intercept
>> the scrolling messages, adding/deleting items to/from the control as
>> the user scrolls.
>> 
>> Does this sound reasonable? Does anyone know of a better way?
>> 
>
>This is the approach that I took 3 years ago, using Windows 3.1 and a 
>subclassed LISTBOX control.  You set up a row buffer that is somewhat 
>larger than the max number of displayed rows in the control, then 
>intercept user movement requests.
>
>While it certainly is possible to go after data on a one-by-one basis 
>-- the callback mentioned above for CListCtrl and also the approach 
>used in the VLIST sample -- it is terribly inefficient for certain 
>types of data sources.  In our case, we're going after data in SQL 
>Server databases.
>
>This is definitely a non-trivial task.  In order to justify the 
>amount of work required to provide this type of functionality, we 
>implemented our original solution as a VBX so that it could be easily 
>reused.
>
>Regards,
>Stephen Keeler
>On-Line Systems Inc.
>

You could save yourself some work and use Microsoft's VLIST - here is my 
standard posting on the subject:

MS provides (MSDN, ftp, or Compu$erve) VLIST.DLL, a single-selection listbox 
(capable of owner-draw and/or LBS_USETABSTOPS, either of which can provide 
columnar-style output).  It has two modes, one of which can handle 2^32-1 
items; the other can handle any number of rows, but the UI is broken (the 
thumb will not function correctly).  See the VLIST docs for more details on 
this.

BTW, it does this by sending the listbox owner messages like "get the next 
record", "get the previous record", and so forth.

I provide an MFC-compatible wrapper for this DLL at:

mudshark.sunquest.com  pub/kitk/vl.zip

This wrapper considerably simplifies (IMHO) the mechanics of dealing with 
VLIST.  Also, akin to the "self-draw" semantics of CListBox, CComboBox, and 
CButton (replacing the less OO owner-draw semantics), the wrapper returns the 
responsibility of record-fetching to the listbox, making a more object- 
oriented style of listbox (and derivation) possible. (self-fetching 
listboxes? :-)
In 3.1, the limits are:

32K item data, and 64K of string data.  This gives you a max of 8160 items, 
with an owner draw box without the LBS_HASSTRINGS style.

If you are exceeding this limit, you may wish to look at the VLIST custom 
control provided by MS at ftp site, on MSDN, or on CIS in the WINSDK forum.

If you are an MFC user, you might be interested in my MFC-based wrapper class 
for VLIST:

mudshark.sunquest.com pub/kitk/vl.zip

(Also available in the MSMFC Doc/View/UI forum library on CIS)




Tim Philip -- philip@cs.usask.ca
Monday, February 05, 1996

Balaji Subramaniam writes:
> 
> 	I want the Drag'n Drop feature also to be added to the VLIST box. I 
> am using MSVC 1.52 and Windows v3.11. The application should be able to 
> send me messages when some item is clicked and dragged. I don't want drag'n 
> drop within the same VLIST, but I should be able to Drop it to another 
> normal listbox.
> 

I'm trying to do something along a similar line.  I'm using MSVC 1.52 and
I want to implement drag and drop between a couple listboxes.  Everything
in the documentation associated OLE with drag and drop so I started looking
at OLE containers and drag'n'drop.  However, I do not want any interaction
with other applications so I'm not quite sure that OLE is appropriate.

What is the correct "MFC-way" to implement drag'n'drop?  Is OLE the 
right way to do it or is it possible to implement it without OLE?!

Any hints/tips/pointers would be greatly appreciated.

Thanks!

-------
Tim Philip, B.Sc.           Randco Software Corporation
Consultant                  2530 Hanover Avenue   
                            Saskatoon, SK          Phone: +1-306-343-3380
philip@cs.usask.ca          Canada   S7J 1G1         Fax: +1-306-343-3341



Kit Kauffmann -- kitk@mudshark.sunquest.com
Tuesday, February 06, 1996

>Balaji Subramaniam writes:
>> 
>> 	I want the Drag'n Drop feature also to be added to the VLIST box. I 
>> am using MSVC 1.52 and Windows v3.11. The application should be able to 
>> send me messages when some item is clicked and dragged. I don't want drag'n 
>> drop within the same VLIST, but I should be able to Drop it to another 
>> normal listbox.
>> 
>
>I'm trying to do something along a similar line.  I'm using MSVC 1.52 and
>I want to implement drag and drop between a couple listboxes.  Everything
>in the documentation associated OLE with drag and drop so I started looking
>at OLE containers and drag'n'drop.  However, I do not want any interaction
>with other applications so I'm not quite sure that OLE is appropriate.
>
>What is the correct "MFC-way" to implement drag'n'drop?  Is OLE the 
>right way to do it or is it possible to implement it without OLE?!
>
>Any hints/tips/pointers would be greatly appreciated.
>
>Thanks!
>
>-------
>Tim Philip, B.Sc.           Randco Software Corporation
>Consultant                  2530 Hanover Avenue   
>                            Saskatoon, SK          Phone: +1-306-343-3380
>philip@cs.usask.ca          Canada   S7J 1G1         Fax: +1-306-343-3341
>

Certainly you can do this with OLE - but that is quite a lot of overhead if 
all you want is some simple listbox drag'n'drop: if you are interested in 
doing it by hand, I provide some sample code adapted for MFC (from some C 
code provided by the famous John Grant) by ftp at:

mudshark.sunquest.com pub/kitk/dragdrop.zip

It has absolutely no documentation (I'm getting lazier every day).  All you do 
to use it is create an object of type CDragDropListBox in your dialog class, 
and use the Subclass method to connect it to the resource-based listbox, as in:

CDragDropListBox m_ListBox;            // declared in dialog class

YourDialog::OnInitDialog()
{
...
m_ListBox.Subclass( ID_LISTBOX, this );
...
}

Note that using LBS_SORT with this would probably not yield the expected 
results :-)

The code allows you to use drag and drop to resort the elements of a listbox 
(I've also adapted it for drag'n'drop between two LB's - all pretty 
straightforward).

HTH!





| Вернуться в корень Архива |