Added support for typing the filename in the listview control and

having the control select it.
This commit is contained in:
Jason Mawdsley 2000-06-03 21:04:33 +00:00 committed by Alexandre Julliard
parent eac0e1837c
commit 84c494bd34
2 changed files with 255 additions and 1 deletions

View file

@ -3,6 +3,7 @@
*
* Copyright 1998, 1999 Eric Kohl
* Copyright 1999 Luc Tourangeau
* Copyright 2000 Jason Mawdsley
*
* NOTES
* Listview control implementation.
@ -39,14 +40,16 @@
* LISTVIEW_Update : not completed
*/
#include <ctype.h>
#include <string.h>
#include "winbase.h"
#include "heap.h"
#include "commctrl.h"
#include "listview.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(listview)
DEFAULT_DEBUG_CHANNEL(listview);
/*
* constants
@ -139,6 +142,247 @@ static BOOL LISTVIEW_EndEditLabel(HWND hwnd, LPSTR pszText, DWORD nItem);
static LRESULT LISTVIEW_Command(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT LISTVIEW_SortItems(HWND hwnd, WPARAM wParam, LPARAM lParam);
static LRESULT LISTVIEW_GetStringWidthA(HWND hwnd, LPCSTR lpszText);
static INT LISTVIEW_ProcessLetterKeys( HWND hwnd, WPARAM charCode, LPARAM keyData );
static BOOL LISTVIEW_KeySelection(HWND hwnd, INT nItem);
/******** Defines that LISTVIEW_ProcessLetterKeys uses ****************/
#define KEY_DELAY 900
#define LISTVIEW_InitLvItemStruct(item,idx,TEXT) \
ZeroMemory(&(item), sizeof(LVITEMA)); \
(item).mask = LVIF_TEXT; \
(item).iItem = (idx); \
(item).iSubItem = 0; \
(item).pszText = (TEXT); \
(item).cchTextMax = MAX_PATH
/*************************************************************************
* DESCRIPTION:
* Processes keyboard messages generated by pressing the letter keys on the keyboard.
* Assumes the list is sorted alphabetically, without regard to case.
*
* PARAMETERS:
* [I] HWND: handle to the window
* [I] WPARAM: the character code, the actual character
* [I] LPARAM: key data
*
*
* RETURN:
* Zero.
*
* TODO:
*
*
*/
static INT LISTVIEW_ProcessLetterKeys( HWND hwnd, WPARAM charCode, LPARAM keyData )
{
LISTVIEW_INFO *infoPtr = NULL;
INT nItem = -1;
BOOL bRedraw;
INT nSize = 0;
INT idx = 0;
BOOL bFoundMatchingFiles = FALSE;
LVITEMA item;
CHAR TEXT[ MAX_PATH ];
CHAR szCharCode[ 2 ];
DWORD timeSinceLastKeyPress = 0;
szCharCode[0] = charCode;
szCharCode[1] = 0;
/* simple parameter checking */
if ( !hwnd || !charCode || !keyData )
return 0;
infoPtr = (LISTVIEW_INFO *)GetWindowLongA(hwnd, 0);
if ( !infoPtr )
return 0;
/* only allow the valid WM_CHARs through */
if ( isalnum( charCode ) || charCode == '.' || charCode == '`' || charCode == '!'
|| charCode == '@' || charCode == '#' || charCode == '$' || charCode == '%'
|| charCode == '^' || charCode == '&' || charCode == '*' || charCode == '('
|| charCode == ')' || charCode == '-' || charCode == '_' || charCode == '+'
|| charCode == '=' || charCode == '\\'|| charCode == ']' || charCode == '}'
|| charCode == '[' || charCode == '{' || charCode == '/' || charCode == '?'
|| charCode == '>' || charCode == '<' || charCode == ',' || charCode == '~')
{
timeSinceLastKeyPress = GetTickCount();
nSize = GETITEMCOUNT( infoPtr );
/* if there are 0 items, there is no where to go */
if ( nSize == 0 )
return 0;
/*
* If the last charCode equals the current charCode then look
* to the next element in list to see if it matches the previous
* charCode.
*/
if ( infoPtr->charCode == charCode )
{
if ( timeSinceLastKeyPress - infoPtr->timeSinceLastKeyPress < KEY_DELAY )
{ /* append new character to search string */
strcat( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength++;
/* loop from start of list view */
for( idx = infoPtr->nFocusedItem; idx < nSize; idx++ )
{ /* get item */
LISTVIEW_InitLvItemStruct( item, idx, TEXT );
ListView_GetItemA( hwnd, &item );
/* compare items */
if ( strncasecmp( item.pszText, infoPtr->szSearchParam,
infoPtr->nSearchParamLength ) == 0 )
{
nItem = idx;
break;
}
}
}
else if ( infoPtr->timeSinceLastKeyPress > timeSinceLastKeyPress )
{ /* The DWORD went over it's boundery?? Ergo assuming too slow??. */
for ( idx = 0; idx < nSize; idx++ )
{
LISTVIEW_InitLvItemStruct( item, idx, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
{
nItem = idx;
break;
}
}
strcpy( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength = 1;
}
else
{ /* Save szCharCode for use in later searches */
strcpy( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength = 1;
LISTVIEW_InitLvItemStruct( item, infoPtr->nFocusedItem + 1, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
nItem = infoPtr->nFocusedItem + 1;
else
{ /*
* Ok so there are no more folders that match
* now we look for files.
*/
for ( idx = infoPtr->nFocusedItem + 1; idx < nSize; idx ++ )
{
LISTVIEW_InitLvItemStruct( item, idx, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
{
nItem = idx;
bFoundMatchingFiles = TRUE;
break;
}
}
if ( !bFoundMatchingFiles )
{ /* go back to first instance */
for ( idx = 0; idx < nSize; idx ++ )
{
LISTVIEW_InitLvItemStruct( item,idx, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
{
nItem = idx;
break;
}
}
}
}
}
} /*END: if ( infoPtr->charCode == charCode )*/
else /* different keypressed */
{
/* could be that they are spelling the file/directory for us */
if ( timeSinceLastKeyPress - infoPtr->timeSinceLastKeyPress > KEY_DELAY )
{ /*
* Too slow, move to the first instance of the
* charCode.
*/
for ( idx = 0; idx < nSize; idx++ )
{
LISTVIEW_InitLvItemStruct( item,idx, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
{
nItem = idx;
break;
}
}
strcpy( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength = 1;
}
else if ( infoPtr->timeSinceLastKeyPress > timeSinceLastKeyPress )
{ /* The DWORD went over it's boundery?? Ergo assuming too slow??. */
for ( idx = 0; idx < nSize; idx++ )
{
LISTVIEW_InitLvItemStruct( item,idx, TEXT );
ListView_GetItemA( hwnd, &item );
if ( strncasecmp( &( item.pszText[ 0 ] ), szCharCode, 1 ) == 0 )
{
nItem = idx;
break;
}
}
strcpy( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength = 1;
}
else /* Search for the string the user is typing */
{
/* append new character to search string */
strcat( infoPtr->szSearchParam, szCharCode );
infoPtr->nSearchParamLength++;
/* loop from start of list view */
for( idx = 0; idx < nSize; idx++ )
{ /* get item */
LISTVIEW_InitLvItemStruct( item, idx, TEXT );
ListView_GetItemA( hwnd, &item );
/* compare items */
if ( strncasecmp( item.pszText, infoPtr->szSearchParam,
infoPtr->nSearchParamLength ) == 0 )
{
nItem = idx;
break;
}
}
}
}/*END: else */
}
else
return 0;
bRedraw = LISTVIEW_KeySelection(hwnd, nItem );
if (bRedraw != FALSE)
{
/* refresh client area */
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
/* Store the WM_CHAR for next time */
infoPtr->charCode = charCode;
/* Store time */
infoPtr->timeSinceLastKeyPress = timeSinceLastKeyPress;
return 0;
}
/*************************************************************************
* LISTVIEW_UpdateHeaderSize [Internal]
@ -7581,6 +7825,9 @@ static LRESULT WINAPI LISTVIEW_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
return LISTVIEW_Update(hwnd, (INT)wParam);
/* case WM_CHAR: */
case WM_CHAR:
return LISTVIEW_ProcessLetterKeys( hwnd, wParam, lParam );
case WM_COMMAND:
return LISTVIEW_Command(hwnd, wParam, lParam);

View file

@ -74,6 +74,13 @@ typedef struct tagLISTVIEW_INFO
BOOL bDoEditLabel;
EDITLABEL_ITEM *pedititem;
DWORD dwHoverTime;
WPARAM charCode; /* Added */
CHAR szSearchParam[ MAX_PATH ]; /* Added */
DWORD timeSinceLastKeyPress; /* Added */
INT nSearchParamLength; /* Added */
} LISTVIEW_INFO;