Added support for typing the filename in the listview control and
having the control select it.
This commit is contained in:
parent
eac0e1837c
commit
84c494bd34
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue