April 19, 2024, 02:20:40 PM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Searching a listview column

Started by Andy, June 18, 2018, 02:13:20 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

I know we can search a listview like this:

position = CONTROLCMD(w1,IDE_LVIEW,@LVFINDITEM,text$)

But if my listview has columns, and I want to search column 1 (last name), how do I do that?

Thanks,
Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

billhsln

Depending on what you are trying to do, LVFINDITEM would require an exact match to return a value, so any spelling error would not retrieve the results you want.  Even an extra space at the end would keep it from matching.

However, if the spelling and upper/lower case are the same, it would return a position no matter which specific column it is in.  Then you could check the value against what is in Last Name and make sure it checks.

However, since your data is stored, why not search the database for it?

Bill
When all else fails, get a bigger hammer.

LarryMc

The following info my prove helpful(maybe not)
It will allow you to create your own  LVFINDITEM  command  and change the Flags to see if you can get the desire you want.

TYPE LV_ITEM
    DEF mask as UINT
    DEF iItem as INT
    DEF iSubItem as INT
    DEF state as UINT
    DEF stateMask as UINT
    DEF pszText as POINTER
    DEF cchTextMax as INT
    DEF iImage as INT
    DEF lParam as INT
ENDTYPE

TYPE LV_COLUMN
    DEF mask as UINT
    DEF fmt as INT
    DEF cx as INT
    DEF pszText as POINTER
    DEF cchTextMax as INT
    DEF iSubItem as INT
ENDTYPE

TYPE LV_FINDINFO
    DEF flags as UINT
    DEF psz as POINTER
    DEF lParam as INT
    DEF pt as POINT
    DEF vkDirection as UINT
ENDTYPE

================================================================================================================================
SUB CONTROLCMD(win as WINDOW,id as INT,cmd as INT,OPT p1 as ANYTYPE,OPT p2 as ANYTYPE,OPT p3 as ANYTYPE,OPT p4 as ANYTYPE),INT
DEF lvf as LV_FINDINFO
CASE @LVFINDITEM
uMsg = @LVM_FINDITEMA
IF TYPEOF(p1) = @TYPESTRING
lvf.psz = ##<STRING>p1
lvf.flags = 2
n1 = -1
pointer pData = lvf
n2 = pData
ELSE
bSend = 0
ENDIF
IF bSend THEN RETURN SendMessageA(hControl,uMsg,n1,n2)

===================================================================================================
flags
Type: UINT

LVFI_PARAM 0x1
Searches for a match between this structure's lParam member and the lParam member of an item's LVITEM structure.

LVFI_PARTIAL 0x8
Checks to see if the item text begins with the string pointed to by the psz member. This value implies use of LVFI_STRING.

LVFI_STRING 0x2
Searches based on the item text. Unless additional values are specified, the item text of the matching item must exactly match the string pointed to by the psz member. However, the search is case-insensitive.

LVFI_SUBSTRING
Windows Vista and later. Equivalent to LVFI_PARTIAL.

LVFI_WRAP 0x20
Continues the search at the beginning if no match is found. If this flag is used by itself, it is assumed that a string search is wanted.

LVFI_NEARESTXY 0x40
Finds the item nearest to the position specified in the pt member, in the direction specified by the vkDirection member. This flag is supported only by large icon and small icon modes. If LVFI_NEARESTXY is specified, all other flags are ignored.



psz
Type: LPCTSTR

Address of a null-terminated string to compare with the item text. It is valid only if LVFI_STRING or LVFI_PARTIAL is set in the flags member.

lParam
Type: LPARAM

Value to compare with the lParam member of a list-view item's LVITEM structure. It is valid only if LVFI_PARAM is set in the flags member.

pt
Type: POINT

POINT structure with the initial search position. It is valid only if LVFI_NEARESTXY is set in the flags member.

vkDirection
Type: UINT

Virtual key code that specifies the direction to search. The following codes are supported:

VK_LEFT
VK_RIGHT
VK_UP
VK_DOWN
VK_HOME
VK_END
VK_PRIOR
VK_NEXT
This member is valid only if LVFI_NEARESTXY is set in the flags member.


Just some general comments
If I were displaying names in a listview and were wanting to search on Last name I would have the last name in column 0 and the first name in column 1 which I believe is the way you see list 9 out of 10 times.
If you insist on having the last name in column 1 and are unsuccessful in getting the search to work then a possibility might be to have an off screen shadow list with the last name in column 0 and the row number from the on screen list stored also.  So you would search the off screen list, get the row number and move to that row in the on screen list.
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Andy

Thanks Bill and Larry,

Larry, I found some code you posted a while ago where you can search even a partial word.

'Compile as a WINDOWS target

Const LVM_FIRST = 0x1000
CONST LVM_ENSUREVISIBLE = (LVM_FIRST + 19)
Const LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54)
CONST LVFI_PARTIAL = 0x8
CONST LVFI_WRAP = 0x20
CONST LVFI_STRING = 0x2

CONST LVM_FINDITEM = (LVM_FIRST + 13)
Const LVS_EX_FULLROWSELECT = 0x020
Const LVS_EX_CHECKBOXES = 0x4 

TYPE LV_FINDINFO
    DEF flags as UINT
    DEF psz as POINTER
    DEF lParam as INT
    DEF pt as POINT
    DEF vkDirection as UINT
ENDTYPE

window w1
int dir
pointer attrib
string filename
const LV=1
const BTN=2
const ED=3

openwindow w1,0,0,500,380,0x80C80080,0,"List view test",&handler
CONTROL w1,@LISTVIEW,"",30,24,460,158,@LVSREPORT|@LVSSORTASCENDING|@LVSSHOWSELALWAYS,LV
CONTROL w1,@BUTTON,"Find",30,200,70,20,0x50000000,BTN
CONTROL w1,@edit,"",120,200,150,20,0x50000000,ED
CONTROLCMD w1,LV,@LVINSERTCOLUMN,0,"Column1"
CONTROLCMD w1,LV,@LVINSERTCOLUMN,1,"Column2"
CONTROLCMD w1,LV, @LVSETCOLWIDTH, 0, 340
SENDMESSAGE(w1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_CHECKBOXES|LVS_EX_FULLROWSELECT,LV)

dir = FINDOPEN("c:\\*.*")
IF(dir)
DO
filename = FINDNEXT(dir)
CONTROLCMD w1,LV,@LVINSERTITEM,0,filename
UNTIL filename = ""
FINDCLOSE dir
endif
waituntil iswindowclosed(w1)
end

SUB handler(),int
select @MESSAGE
case @IDcreate
centerwindow w1
case @IDCONTROL
select @CONTROLID
case BTN
if @notifycode=0
string text$ = GETCONTROLTEXT (w1, ED)
LV_FINDINFO li
li.flags = LVFI_STRING|LVFI_PARTIAL|LVFI_WRAP
li.psz = text$
int pos = SendMessage(w1, LVM_FINDITEM, -1,  li,LV)
CONTROLCMD(w1,LV, @LVSETSELECTED, pos)
sendmessage w1,LVM_ENSUREVISIBLE ,pos,false,LV
endif
ENDselect
case @IDCLOSEWINDOW
closewindow w1
endselect
return 0
ENDSUB


I've used this to do the search, the problem turns out to be the last name wasn't in column 0 (as you suggested), now changed, I can search.

Thanks guys.
Andy.
:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

One problem,

Although the above code selects what you are searching for, it also keeps any other selections highlighted, so how do we remove any other selections before highlighting the new one?

Andy.
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

Andy

June 19, 2018, 04:35:06 AM #5 Last Edit: June 19, 2018, 05:58:57 AM by Andy
Found the answer!


CONTROL w1,@LISTVIEW,"",8,430,1140,172,@LVSREPORT|@BORDER|@LVSSINGLESEL|@LVSSHOWSELALWAYS|@VSCROLL,IDE_LVIEW

:)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

LarryMc

QuoteLarry, I found some code you posted a while ago where you can search even a partial word.


I don't remember writing that at all. But of course, I don't remember a lot of things any more and it is getting worse all the time. :(
LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library