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

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


virtual CListView

Gene Sewell -- genes@fast.net
Monday, May 13, 1996

Hi,

I was asked to provide code for a comment I made a bit ago about virtual
CListView.  I chopped the following out of my code - tried to narrow it down
to the essentials.  Hope it's of some help to someone!
------------------------------------------------------------------------

I made a new class CDBListView based on CListView.  As most folks will have to 
do, I am using style: LVS_REPORT | LVS_OWNERDRAWFIXED.  I'm only going to
comment on the virtual listbox function here, though.

The important functions are:
	void CDBListView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
	void   CDBListView::VirtualVScroll(long lStart)

------------------------------------------------------------------------

VirtualVScroll is the main function - it's passed the starting record to
display.

// this function sets up listbox and handle's all the virtual functions
void   CDBListView::VirtualVScroll(long lStart)
{
	
	if (mx_ListUnderConstruction)
		return;							// should never happen....

	// turn on flag to keep size guy from going crazy....
	mx_ListUnderConstruction = TRUE;			// keep everyone else quiet....

	// we always start from scratch each time...
	m_ctlList.DeleteAllItems();

	m_TopRec = lStart;

	// Prepare a LV_COLUMN structure for GetColumn()
	char itemTxt[16];
	LV_COLUMN lvColumn;
	lvColumn.pszText = itemTxt;
	lvColumn.cchTextMax = sizeof( itemTxt );
	lvColumn.mask = LVCF_TEXT;

	m_CurrentScrollPos = (long)((double)NumRec*lStart);

	iMax = min(m_ItemsVisible, m_ProfileDoc->mx_Fmt.recs - m_CurrentScrollPos);	
	for( i = 0; i <= iMax; ++i )
	{

		// I'm deleting how I got the data - just that I'm getting it from
		// somewhere....
		for(curColumn = 0; curColumn < m_NumColumns; curColumn++ )
		{
			// I made a function, but this is easy...
			AddItem( i,
					 curColumn,
					 f4str( hField[ curColumn ] ),
					 i % NUM_STATE_IMAGES,		
					 recno );
		}
	}
	// turn off flag to keep size guy quiet...
	mx_ListUnderConstruction = FALSE;			// keep everyone else quiet....
}

------------------------------------------------------------------------

This variable changes when the window is resized....
		m_ItemsVisible = m_ctlList.GetCountPerPage( );

I generated a user defined message which is mapped to a function to update
the thumb position.  

	#define WM_UPDATESCROLL_INFO	WM_USER +11

It's mapped into the message map as:

	ON_MESSAGE(WM_UPDATESCROLL_INFO, UpdateScrollValues)

I invoke this function using the following define:

	#define UPDATE_SCROLL_POSITION(pos)	  PostMessage(WM_UPDATESCROLL_INFO,
(pos), 0)

------------------------------------------------------------------------


Here is where the scroll function is handled:

afx_msg LRESULT CDBListView::UpdateScrollValues(WPARAM wParam, LPARAM lParam)
{
	if (!mx_ListUnderConstruction)
	{
		// In my case, mx_Fmt.recs is the number of items I want to display
		if (m_ProfileDoc->mx_Fmt.recs > m_ItemsVisible)
		{
			m_ctlList.ShowScrollBar(SB_VERT,TRUE);
			SCROLLINFO ScrollInfo;
		
			// I had tons of problems with this function
			// I sort of loop trying to stabilize the window until
			// the scroll bars are stable
			BOOL bR = m_ctlList.GetScrollInfo( SB_VERT, &ScrollInfo, SIF_ALL );	//
SIF_POS
			if (bR)		// often not working....
			{
				mx_ScrollAttempts = 0;						//  reset # times around the barn
				ScrollInfo.nMin = 1;
				ScrollInfo.nMax = m_ProfileDoc->mx_Fmt.recs;
				ScrollInfo.nPage = m_ItemsVisible - 1;
				ScrollInfo.nPos = wParam;
				bR = SetScrollInfo(SB_VERT, &ScrollInfo, 1);
			}
			else
			{
				if (mx_ScrollAttempts < MAX_ATTEMPTS)
				{
					mx_ScrollAttempts++;						 // yikes - this sucks
					m_ctlList.UpdateWindow();
		  			// resubmit request for scroll info - deferred post
					UPDATE_SCROLL_POSITION(wParam);		// this will update scroll bar pos
				}
			}
		}
		else
			 m_ctlList.ShowScrollBar(SB_VERT,FALSE);	// default ...
	}
	return (LRESULT)1;
}


------------------------------------------------------------------------
Here's how I handle the scroll bars

void CDBListView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	long CurPos;
	// make it so on paging, the item at the bottom becomes the item at the top
	// and vice versa...
	int page = m_ItemsVisible - 1;


	switch (nSBCode)
	{
		case SB_BOTTOM:
			CurPos = NumRec;
			VirtualVScroll(CurPos);
			break;
		case SB_ENDSCROLL:
			CurPos = -1;
			break;
		case SB_LINEDOWN:
			if (NumRec > (CurPos + (page - BLANK_AT_END)))
			{
				VirtualVScroll(++CurPos);
			}
			break;
		case SB_LINEUP:
			if (CurPos > 0)
			{
				VirtualVScroll(--CurPos);
			}
			break;
		case SB_PAGEDOWN:
			if (NumRec > CurPos)
			{
				CurPos = min(NumRec - (CurPos + page) + BLANK_AT_END, page );
				VirtualVScroll(CurPos);
			}
			break;
		case SB_PAGEUP:
			if (CurPos > 0)
			{
				CurPos = min(CurPos, page );
				VirtualVScroll(CurPos);
			}
			break;
		case SB_THUMBPOSITION:
			apos = (double)(max(0, nPos - 1)) / (double)(max(NumRec, 1));
			CurPos = (long)((double)NumRec*apos);		// it's not precise, add buffer
			VirtualVScroll(CurPos);
			break;
 		case SB_THUMBTRACK:
			// this would be too much overhead....
			CurPos = -1;
			break;
		case SB_TOP:
			VirtualVScroll(CurPos = 0);
			break;
		default:
			CurPos = -1;
			break;
	}
	if (CurPos >= 0)
	{
		UPDATE_SCROLL_POSITION(CurPos);			// this will do it all
	}
}

note: I allow some blank lines at the bottom to show there's no more...
#define BLANK_AT_END  2

------------------------------------------------------------------------


Guess that covers most of it.  I had to delete a bunch of special code,
so I don't know that this will run, but it should....

I'll be happy to explain anything - just ask!


Gene
----
Friend - One who knows all about you and likes you just the same.




Frederic Steppe -- FredericS@msn.com
Tuesday, May 14, 1996

>I was asked to provide code for a comment I made a bit ago about virtual
>CListView.  I chopped the following out of my code - tried to narrow it down
>to the essentials.  Hope it's of some help to someone!

Thanks, sure it will help.

Do you think it could be possible to modify a little bit this ?
   - It would be great to work entirely at the CListCtrl level (subclassed).
   - It may be interesting to avoid filling the entire list every time you 
scroll (only in the case of a line-scroll)

I didn't implement your sample right now, but I'll work on this asap.

Frederic Steppe (frederics@msn.com)



Gene Sewell -- genes@fast.net
Thursday, May 16, 1996

Hi Frederic,

>>I was asked to provide code for a comment I made a bit ago about virtual
>>CListView.  I chopped the following out of my code - tried to narrow it down
>>to the essentials.  Hope it's of some help to someone!
>
>Thanks, sure it will help.

Good.

>Do you think it could be possible to modify a little bit this ?
>   - It would be great to work entirely at the CListCtrl level (subclassed).

Go for it!

>   - It may be interesting to avoid filling the entire list every time you 
>scroll (only in the case of a line-scroll)

Actually, in my case, I'm displaying a multi-user database, and it's a good
thing to constantly refresh the screen from the shared database so that the
display is up to date.  In every other case, you are right - I think for one
line scrolling, you could just add one new line.

>I didn't implement your sample right now, but I'll work on this asap.

Hope it helps.

Gene
----
This is the gender that invented the polio vacine?
	-- Snow Crash





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