가상 목록 뷰 컨트롤을 사용하는 방법
이 항목에서는 가상 목록 뷰 컨트롤을 사용하는 방법을 보여 줍니다. 함께 제공되는 C++ 코드 예제에서는 가상 목록 뷰 컨트롤 알림 메시지를 처리하는 방법, 캐시를 최적화하는 방법 및 캐시에서 항목을 검색하는 방법을 보여 줍니다.
참고
이 섹션의 예제 코드에서는 캐시가 애플리케이션 정의 구조의 동적으로 할당된 배열이라고 가정합니다. 이 구조체는 다음 C++ 코드 예제에서 정의됩니다.
struct RndItem
{
int iIcon; // Bitmap assigned to this item.
UINT state; // Item state value.
TCHAR Title[BUFFER_SIZE]; // BUFFER_SIZE is a user-defined macro value.
TCHAR SubText1[BUFFER_SIZE]; // Text for the label of the first sub-item.
TCHAR SubText2[BUFFER_SIZE]; // Text for the label of the second item.
};
알아야 하는 작업
기술
필수 구성 요소
- C/C++
- Windows 사용자 인터페이스 프로그래밍
지침
가상 목록 뷰 컨트롤 알림 코드 처리
다른 목록 뷰 컨트롤에서 보낸 알림 코드 외에도 가상 목록 뷰 컨트롤은 LVN_ODCACHEHINT 및 LVN_ODFINDITEM 알림 코드도 보낼 수 있습니다.
이 애플리케이션 정의 함수는 가상 목록 뷰 컨트롤에서 일반적으로 전송되는 알림 메시지를 처리합니다.
LRESULT OnNotify(HWND hwnd, NMHDR* pnmhdr)
{
HRESULT hr;
LRESULT lrt = FALSE;
switch (pnmhdr->code)
{
case LVN_GETDISPINFO:
{
RndItem rndItem;
NMLVDISPINFO* plvdi = (NMLVDISPINFO*) pnmhdr;
if (-1 == plvdi->item.iItem)
{
OutputDebugString(TEXT("LVOWNER: Request for -1 item?\n"));
DebugBreak();
}
// Retrieve information for item at index iItem.
RetrieveItem( &rndItem, plvdi->item.iItem );
if(plvdi->item.mask & LVIF_STATE)
{
// Fill in the state information.
plvdi->item.state |= rndItem.state;
}
if(plvdi->item.mask & LVIF_IMAGE)
{
// Fill in the image information.
plvdi->item.iImage = rndItem.iIcon;
}
if(plvdi->item.mask & LVIF_TEXT)
{
// Fill in the text information.
switch (plvdi->item.iSubItem)
{
case 0:
// Copy the main item text.
hr = StringCchCopy(plvdi->item.pszText, MAX_COUNT, rndItem.Title);
if(FAILED(hr))
{
// Insert error handling code here. MAX_COUNT
// is a user-defined value. You must not enter
// more characters than specified by MAX_COUNT or
// the text will be truncated.
}
break;
case 1:
// Copy SubItem1 text.
hr = StringCchCopy( plvdi->item.pszText, MAX_COUNT, rndItem.SubText1);
if(FAILED(hr))
{
// Insert error handling code here. MAX_COUNT
// is a user-defined value. You must not enter
// more characters than specified by MAX_COUNT or
// the text will be truncated..
}
break;
case 2:
// Copy SubItem2 text.
hr = StringCchCopy(plvdi->item.pszText, MAX_COUNT, rndItem.SubText2);
if(FAILED(hr))
{
// Insert error handling code here. MAX_COUNT
// is a user-defined value. You must not enter
// more characters than specified by MAX_COUNT or
// the text will be truncated..
}
break;
default:
break;
}
}
lrt = FALSE;
break;
}
case LVN_ODCACHEHINT:
{
NMLVCACHEHINT* pcachehint = (NMLVCACHEHINT*) pnmhdr;
// Load the cache with the recommended range.
PrepCache( pcachehint->iFrom, pcachehint->iTo );
break;
}
case LVN_ODFINDITEM:
{
LPNMLVFINDITEM pnmfi = NULL;
pnmfi = (LPNMLVFINDITEM)pnmhdr;
// Call a user-defined function that finds the index according to
// LVFINDINFO (which is embedded in the LPNMLVFINDITEM structure).
// If nothing is found, then set the return value to -1.
break;
}
default:
break;
} // End Switch block.
return(lrt);
}
캐시 최적화
가상 목록 뷰 컨트롤은 표시 영역의 콘텐츠가 변경되면 LVN_ODCACHEHINT 알림 메시지를 보냅니다. 메시지에는 캐시할 항목 범위에 대한 정보가 포함됩니다. 알림 메시지를 받으면 애플리케이션은 요청된 범위에 대한 항목 정보와 함께 캐시를 로드할 준비가 되어 있어야 LVN_GETDISPINFO 알림 메시지가 전송될 때 정보를 쉽게 사용할 수 있습니다.
다음 C++ 코드 예제에서 애플리케이션 정의 함수는 가상 목록 뷰 컨트롤에서 보낸 캐시에 대한 항목 범위를 허용합니다. 확인을 수행하여 요청된 항목 범위가 아직 캐시되지 않았는지 확인한 다음, 필요한 전역 메모리를 할당하고 필요한 경우 캐시를 채웁니다.
void PrepCache(int iFrom, int iTo)
{
/* Global Variables
* g_priCache[ ]: the main cache.
* g_iCache: the index of the first item in the main cache.
* g_cCache: the count of items in the main cache.
*
* g_priEndCache[ ]: the cache of items at the end of the list.
* g_iEndCache: the index of the first item in the end cache.
* g_cEndCache: the count of items in the end cache.
*/
// Local Variables
int i;
BOOL fOLFrom = FALSE;
BOOL fOLTo = FALSE;
// Check to see if this is the end cache.
if ((iTo == g_cCache - 1) && ((iTo - iFrom) < 30)) // 30 entries wide.
{
// Check to see if this is a portion of the current end cache.
if ((g_cCache) && (iFrom >= g_iEndCache) && (iFrom < g_iEndCache+g_cEndCache))
return;
// If it is a part of current end cache, no loading is necessary.
// This is a new end cache. Free the old memory.
if ( g_priEndCache )
GlobalFree( g_priEndCache );
// Set the index and count values for the new end cache,
// and then retrieve the memory.
g_iEndCache = iFrom;
g_cEndCache = (iTo - iFrom + 1);
g_priEndCache = (RndItem *)GlobalAlloc(GPTR, sizeof(RndItem) * g_cEndCache);
if (! g_priEndCache)
{
// TODO: Out of memory. Perform error handling.
}
// Loop to fill the cache with the recommended items.
for (i=0; i<g_cEndCache; i++)
{
// TODO: Call a function that accesses item information and
// fills a cache element.
}
}
else
{
// It is not a member of the current end cache.
// Try the primary cache instead.
// Check to see if iFrom is within the primary cache.
if ((g_cCache) && (iFrom >= g_iCache) && (iFrom < g_iCache+g_cCache))
fOLFrom = TRUE;
// Check to see if iTo is within the primary cache.
if ((g_cCache) && (iTo >= g_iCache) && (iTo <= g_iCache+g_cCache))
fOLTo = TRUE;
// do nothing if both iFrom and iTo are within the current cache.
if (fOLFrom && fOLTo)
return;
// Enlarge the cache size rather than make it specific to this hint.
if (fOLFrom)
iFrom = g_iCache;
else if (fOLTo)
iTo = g_iCache + g_cCache;
// A new primary cache is needed. Free the old primary cache.
if ( g_priCache )
GlobalFree( g_priCache );
// Set the index and count values for the new primary cache,
// and then retrieve the memory.
g_iCache = iFrom;
g_cCache = (iTo - iFrom + 1);
g_priCache = (RndItem *)GlobalAlloc( GPTR, sizeof( RndItem ) * g_cCache );
if (!g_priCache)
{
// TODO: Out of memory. Do error handling.
}
// Loop to fill the cache with the recommended items.
for (i=0; i<g_cCache; i++)
{
// TODO: Call a function that accesses item information
// and fills a cache element.
}
}
}
캐시에서 항목 검색
이 예제 함수는 두 매개 변수, 즉 애플리케이션 정의 구조체의 주소와 목록에 있는 항목의 인덱스를 나타내는 정수 값을 허용합니다. 인덱스 값을 확인하여 원하는 항목이 캐시되었는지 검색합니다. 캐시되었으면 함수에 전달된 포인터가 캐시의 위치로 설정됩니다. 항목이 주 캐시 또는 끝 캐시에 없는 경우 항목 정보를 수동으로 찾아야 합니다.
void RetrieveItem( RndItem * prndItem, int index )
{
// Global Variables
// g_priCache[ ]: the main cache.
// g_iCache: the index of the first item in the main cache.
// c_cCache: the count of items in the main cache.
//
// g_priEndCache[ ]: the cache of items at the end of the list.
// g_iEndCache: the index of the first item in the end cache.
// g_cEndCache: the count of items in the end cache.
//
// Check to see if the item is in the main cache.
if ((index >= g_iCache) && (index < g_iCache + g_cCache))
*prndItem = g_priCache[index-g_iCache];
// If it is not in the main cache, then check to see if
// the item is in the end area cache.
else if ((index >= g_iEndCache) && (index < g_iEndCache + g_cEndCache))
*prndItem = g_priEndCache[index-g_iEndCache];
else
{
// The item is not in either cache.
// Therefore, retrieve the item information manually.
}
}
설명
목록 뷰 컨트롤에서 처리되는 창 메시지 목록은 기본 목록 뷰 메시지 처리를 참조하세요.
전체 예제
관련 항목