Page 2 of 3

Re: Combobox dropdown style - search

PostPosted: Tue Feb 17, 2009 12:04 pm
by demont frank
Otto wrote:Hello Frank,

As I can’t get working incremental search in combobox I would like to test your solution with xBrowse.
Would you be so kind to send me following functions:
MAKE2DIM
NM_ALFA
MAKEGETBOX

Thanks in advance
Otto


Ok , it was send

Frank

Re: Combobox dropdown style - search

PostPosted: Tue Feb 17, 2009 10:46 pm
by Antonio Linares
Dear Otto,

First, you have to remove CBS_SORT from the RC or the order in the aItems array is not the same as the displayed in the combobox.

Second, besides James suggestion to set oCbx:lIncSearch := .T., you have to set this line:
Code: Select all  Expand view

   REDEFINE COMBOBOX oCbx VAR cItem ITEMS aItems ;
      ID 110 OF oDlg          ;
      ON CHANGE ( oSayItem:cTitle := oCbx:GetText() ) ;
      VALID ( MsgBeep(), .t. )
 
   oCbx:lIncSearch := .T.
   oCbx:oGet:bKeyChar = { | nKey | oCbx:KeyChar( nKey ) }  // this one!
 

As you are using a CBS_DROPDOWN (that uses a GET) instead of a CBS_DROPDOWNLIST (that does not uses a GET).

With these changes, your example is working fine here :-)

Re: Combobox dropdown style - search

PostPosted: Tue Feb 17, 2009 11:20 pm
by Otto
Antonio,

I changed the code but it does not work.
The changes you suggest make a DROPDOWNLIST behavior out of the DROPDOWN box.

You can’t insert a new text.
I need the dropdown behavior this means you can select an item or you can insert a new one.

Thanks in advance
Otto

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 12:26 am
by Antonio Linares
Otto,

Ok, I see what you want. Please make this change in Class TComboBox Method KeyChar:
Code: Select all  Expand view
...
      if Empty( uItem )
         if nNewAt == 0
            nNewAt = AScan( ::aItems, {|x| Upper(x) = Upper( ::cSearchKey ) } )
            // if nNewAt > 0 .and. Len( ::aItems ) <= nNewAt
            //   uItem = ::aItems[ nNewAt ]
            // endif
            uItem = If( nNewAt > 0, ::aItems[ nNewAt ], ::cSearchKey )
         else
            uItem = ::aItems[ Max( nNewAt, 1) ]
         endif  
      endif
      ::Set( If( ValType( Eval( ::bSetGet ) ) == "N", AScan( ::aItems, uItem ), uItem ) )
      ::oGet:SetPos( Len( ::cSearchKey ) + 1 )
   endif  
...
 

Please keep this line:
oCbx:oGet:bKeyChar = { | nKey | oCbx:KeyChar( nKey ) }
We may need a new DATA to select this new behavior.

Please download the EXE from here to test it:
http://www.mediafire.com/?sharekey=f67b ... 6e282a0ee8
Type "antonio" and see how it behaves. Then delete char by char :-)

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 9:49 am
by Antonio Linares
> We may need a new DATA to select this new behavior.

We can avoid it if we check if oCbx:oGet is != nil

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 10:07 am
by Antonio Linares
Otto,

This modified Class TComboBox Method KeyChar() seems to work fine, respecting spaces and evaluating ON CHANGE :-)
Code: Select all  Expand view
METHOD KeyChar( nKey, nFlags ) CLASS TComboBox

   local nNewAT := 0, nOldAT := ::nAT, uItem

   if Len( ::aItems ) == 0
      return 0
   endif

   if ::lIncSearch
      do case
         case nKey = 32   // VK_DELETE do not work!
              if ::oGet == nil
                 ::cSearchKey = ""
                 nNewAt = 1
                 uItem  = ::aItems[ nNewAt ]
              else    
                 ::cSearchKey += " "
              endif  
           
         case nKey = VK_BACK
              ::cSearchKey = Left( ::cSearchKey, Len( ::cSearchKey ) - 1 )
           
         case nKey = 190
              nKey = 0
              ::cSearchKey += "."
           
         otherwise
              ::cSearchKey += Chr( nKey )
      endcase
   
      if Empty( uItem )
         if nNewAt == 0
            nNewAt = AScan( ::aItems, {|x| x = ::cSearchKey } )
            if ::oGet == nil
               uItem = ::aItems[ If( nNewAt > 0, nNewAt, Max( ::nAT, 1 ) ) ]
            else  
               uItem = If( nNewAt > 0, ::aItems[ nNewAt ], ::cSearchKey )
            endif  
         else
            uItem = ::aItems[ Max( nNewAt, 1) ]
         endif  
      endif
      ::Set( If( ValType( Eval( ::bSetGet ) ) == "N", AScan( ::aItems, uItem ), uItem ) )
      if ::oGet != nil
         ::oGet:SetPos( Len( ::cSearchKey ) + 1 )
      endif  
   endif  

   if ::bChange != nil
      if ::oGet != nil .or. ( nNewAT != nOldAt .and. nNewAt != 0 )
         Eval( ::bChange, Self, ::VarGet() )
      endif  
   endif

   if nKey == VK_RETURN
      return ::oWnd:GoNextCtrl( ::hWnd )
   endif
   
return If( ::lIncSearch, 0, nil )
 

Here you have the EXE to test it:
http://www.mediafire.com/?sharekey=414c ... 0a1ae8665a

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 11:14 am
by Antonio Linares
To avoid case sensitive make this change in the proposed Method KeyChar():
Code: Select all  Expand view

nNewAt = AScan( ::aItems, {|x| Upper( x ) = Upper( ::cSearchKey ) } )
 

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 4:21 pm
by James Bott
Antonio,

May I suggest also modifying TCombobox so that incremental searching works when the style is DROPDOWN (and lIncSearch=.t.). According to Otto, this is not working.

Regards,
James

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 5:23 pm
by Antonio Linares
James,

Thats is what we are doing. It only works when lIncSearch is .T. and the style is dropdown.

According to Otto tests, we are close to get it fully functional. Still there are some behaviors to solve.

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 7:42 pm
by Antonio Linares
Otto,

This is a modified Method KeyChar() that provides support for VK_TAB. Here it is working fine.

I appreciate your feedback, thanks :-)
Code: Select all  Expand view
METHOD KeyChar( nKey, nFlags ) CLASS TComboBox

   local nNewAT := 0, nOldAT := ::nAT, uItem

   if Len( ::aItems ) == 0
      return 0
   endif

   if ::lIncSearch
      do case
         case nKey = 32   // VK_DELETE (DO NOT WORK!)
              if ::oGet == nil
                 ::cSearchKey = ""
                 nNewAt = 1
                 uItem  = ::aItems[ nNewAt ]
              else    
                 ::cSearchKey += " "
              endif  
           
         case nKey = VK_BACK
              ::cSearchKey = Left( ::cSearchKey, Len( ::cSearchKey ) - 1 )
           
         case nKey = 190
              nKey = 0
              ::cSearchKey += "."
             
         case ::oGet != nil .and. nKey = VK_TAB
              if ! GetKeyState( VK_SHIFT )
                 ::oWnd:GoNextCtrl( ::hWnd )
              else  
                 ::oWnd:GoPrevCtrl( ::hWnd )
              endif
              return 0  
           
         otherwise
              ::cSearchKey += Chr( nKey )
      endcase
   
      if Empty( uItem )
         if nNewAt == 0
            nNewAt = AScan( ::aItems, {|x| x = ::cSearchKey } )
            if ::oGet == nil
               uItem = ::aItems[ If( nNewAt > 0, nNewAt, Max( ::nAT, 1 ) ) ]
            else  
               uItem = If( nNewAt > 0, ::aItems[ nNewAt ], ::cSearchKey )
            endif  
         else
            uItem = ::aItems[ Max( nNewAt, 1) ]
         endif  
      endif
      ::Set( If( ValType( Eval( ::bSetGet ) ) == "N", AScan( ::aItems, uItem ), uItem ) )
      if ::oGet != nil
         ::oGet:SetPos( Len( ::cSearchKey ) + 1 )
      endif  
   endif  

   if ::bChange != nil
      if ::oGet != nil .or. ( nNewAT != nOldAt .and. nNewAt != 0 )
         Eval( ::bChange, Self, ::VarGet() )
      endif  
   endif

   if nKey == VK_RETURN
      return ::oWnd:GoNextCtrl( ::hWnd )
   endif
   
return If( ::lIncSearch, 0, nil )
 

Re: Combobox dropdown style - search

PostPosted: Wed Feb 18, 2009 9:48 pm
by Otto
Hello Antonio,

VK_TAB is working now.
Thanks again,
Otto

Re: Combobox dropdown style - search

PostPosted: Thu Feb 19, 2009 4:11 pm
by Otto
Hello Antonio,

in your last change of the method you didn't include the change
//nNewAt = AScan( ::aItems, {|x| x = ::cSearchKey } )
nNewAt = AScan( ::aItems, {|x| Upper( x ) = Upper( ::cSearchKey ) } )

Best regards,
Otto

Re: Combobox dropdown style - search

PostPosted: Thu Feb 19, 2009 5:58 pm
by Otto
Antonio,

http://www.atzwanger.info/kartei2/kartei2.htm

Please help me with this problem. I want to edit the field "briefanrede". But the changes go away.
Thanks in advance
Otto

Re: Combobox dropdown style - search

PostPosted: Wed Mar 04, 2009 9:11 pm
by Otto
Hello Antonio,

As a workaround for I changed the KeyChar method in TGet.

I inserted a
return Super:KeyChar( nKey, nFlags )
at the beginning of the method.

Now search in combobox is working.
I take the original combobox without the suggested changes. The changes I made only in TGet.

As I don’t be aware what other disadvantages the change has I copied Tget and call from combobox the copy with the changes.

Best regards,
Otto



METHOD KeyChar( nKey, nFlags ) CLASS TGet

local nHi, nLo
local lAccept
local bKeyAction := SetKey( nKey )
local nDefButton

return Super:KeyChar( nKey, nFlags )

Re: Combobox dropdown style - search

PostPosted: Tue Mar 10, 2009 12:27 am
by Otto
Hello Antonio,

Why do we need a TGet with CBS_Dropdown? Is this only for the TAB order?

If I commend out the following lines searching works but the Tab order is false.

Regards,
Otto

Code: Select all  Expand view
if lAnd( ::nStyle, CBS_DROPDOWN )
      #ifdef __XPP__
         #undef New
      #endif
      ::oGet := TGet():ReDefine( nil,    ;  // ID not used
                              ::bSetGet, ;  // bSETGET(uVar)
                              Self,      ;  // oDlg
                              ::nHelpID, ;  // Help Context ID
                              cPict,     ;  // Picture
                              nil,       ;  // Valid is handled by the CBx
                              ::nClrText,;
                              ::nClrPane,;
                              ::oFont,   ;  // <oFont>
                              nil,       ;  // <oCursor>
                              cMsg,      ;  // cMsg
                              nil,       ;  // <.update.>
                              nil,       ;  // <{uWhen}>
                              bEChange,  ;  // {|nKey,nFlags,Self| <uEChange>}
                              .F.        )  // <.readonly.> )
      ::oGet:bKeyChar = { | nKey | If( ( nKey == VK_TAB .and. ! GetKeyState( VK_SHIFT ) ) .or. ;
                                         nKey == VK_RETURN,;
                                       ( ::oWnd:GoNextCtrl( ::hWnd ), 0 ),;
                                       If( nKey == VK_TAB .and. GetKeyState( VK_SHIFT ),;
                                       ( ::oWnd:GoPrevCtrl( ::hWnd ), 0 ),) ) }
   endif