StringGadget et AutoComplétion

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Avatar de l’utilisateur
wood51
Messages : 122
Inscription : ven. 05/juin/2009 13:04
Localisation : orléans

StringGadget et AutoComplétion

Message par wood51 »

Bonjour,

Dans mon projet,j'avais besoin d'un StringGadget avec auto-complétion comme dans l'éditeur PureBasic . Après avoir trouvé sur le forum un code avec un ComboBox, je l'ai adapté a mes besoins .
Le code est pleinement fonctionnel avec PB4.61 Vista et Seven . Il a quelques défauts que je comblerais au fur et à mesure

AC_StringGadget.pbi :

Code : Tout sélectionner

;/////////////////////////////////////////////////////////////////////
;/  AC_String_Gadget
;/
;/  StringGadget avec autocomplétion 
;/
;/  Date : 28/06/2012
;/
;/  Auteurs : Ebs,LSI,Nico,Wood51
;/
;/  Bricolage : Wood51
;/  Procedure d'autocomplétion : Ebs réadapter par LSI
;/  Astuce pour les callbacks : Nico
;/  
;////////////////////////////////////////////////////////////////////

;- TODO
;{
; Gestion des touches ---- OK
; Gestion click dans le ListView ---- OK
; Cacher Afficher ListView ---- OK
; Timer pour affichage de la listbox
; Reverifier variable pour activé EnableExplicite ---- OK
; Déclaration des procedures ---- OK
; Commenter le code
; Faire Fichier PBI ---- OK
;
; PROBLEMES
; Selection text string lors du déplacement avec les flèches
; Redonner le focus au stringgadget après click sur listview
;}

EnableExplicit

;- Structure
;{
Structure Lst
  Text.s
  Affiche.i
EndStructure

Structure ACStringInfo
  ID_Edit.i
  ID_List.i
  ListHeight.i
EndStructure
;}

;- Variables
;{
Global NewList Liste.Lst()
Global ACS.ACStringInfo
Global Keep_EN_CHANGE = 0
Global oldEditProc.i,oldListProc.i
;}

;- Declaration des procedures
;{
Declare LoWord(value)
Declare HiWord(value)

Declare AddToList(String.s)
Declare UpdateListView()
Declare SearchInList()

Declare ListProc(hWnd.i, uMsg.i, wParam.i, lParam.i)
Declare EditProc(hWnd.i, uMsg.i, wParam.i, lParam.i)
Declare AC_StringGadgetProc(hWnd.i,uMsg.i,wParam.i,lParam.i)

Declare AC_StringGadget(Gadget,x,y,w,h,lh)

;}

;- Procedure
;{

Procedure LoWord(value)
  ProcedureReturn value & $FFFF
EndProcedure

Procedure HiWord(value)
  ProcedureReturn value >> 16 & $FFFF
EndProcedure

Procedure AddToList(String.s)
  Protected Result.i
  If ACS\ID_List
    Result=AddElement(Liste())
    If Result
      Liste()\Text = String
      Liste()\Affiche = 1
      SortStructuredList(Liste(), #PB_Sort_Ascending, OffsetOf(Lst\Text), #PB_Sort_String)
    EndIf
  EndIf
  
  UpdateListView()
EndProcedure

Procedure UpdateListView()
  ClearGadgetItems(ACS\ID_List)
  ResetList(Liste())
  
  While NextElement(Liste())
    If Liste()\Affiche = 1
      AddGadgetItem(ACS\ID_List,-1,Liste()\Text)
    EndIf
  Wend
  
EndProcedure

Procedure SearchInList()
  Protected.s TextTyped,ItemText
  Protected.i LenTextSave,LenTextTyped,ItemCount,Item
  Protected.i Selection_Start,Selection_End
  
  Keep_EN_CHANGE = 1 ; pour éviter l'auto apel avec le message #EN_CHANGE
  ;Texte tapé et sa longueur
  TextTyped = GetGadgetText(ACS\ID_Edit)
  LenTextTyped = Len(TextTyped)
  
  ;Maj Liste chainée
  ResetList(Liste())
  While NextElement(Liste())
    If UCase(Left(TextTyped,LenTextTyped)) = UCase(Left(Liste()\Text,LenTextTyped))
      Liste()\Affiche = 1
    Else
      Liste()\Affiche = 0
    EndIf
  Wend
  
  ;Maj du ListView
  ClearGadgetItems(ACS\ID_List)
  
  
  ResetList(Liste())
  
  While NextElement(Liste())
    If Liste()\Affiche = 1
      AddGadgetItem(ACS\ID_List,-1,Liste()\Text)
    EndIf
  Wend
  
  LenTextSave = GetGadgetData(ACS\ID_Edit)
  If LenTextTyped <= LenTextSave
    SetGadgetData(ACS\ID_Edit, LenTextTyped)
  Else
    ;Selection dans le ListView
    ItemCount = CountGadgetItems(ACS\ID_List)
    
    For Item = 0 To ItemCount - 1
      ItemText.s = GetGadgetItemText(ACS\ID_List,Item)
      If  UCase(TextTyped) = UCase(Left(ItemText,LenTextTyped))
        SetGadgetState(ACS\ID_List,Item)
        Selection_Start = LenTextTyped
        Selection_End = Len(ItemText)
        
        
        SetGadgetText(ACS\ID_Edit,ItemText)
        SendMessage_(GadgetID(ACS\ID_Edit), #EM_SETSEL, Selection_Start, Selection_End)
        
        SetGadgetData(ACS\ID_Edit, LenTextTyped)
        Break
      EndIf
    Next
  EndIf
  Keep_EN_CHANGE = 0
  
EndProcedure

;- Event Loop (List)
Procedure ListProc(hWnd.i, uMsg.i, wParam.i, lParam.i)
  Protected OriginProc.i
  Protected Item.i
  
  OriginProc = GetProp_(hWnd, "OriginProc")
  
  Select uMsg   
    Case #WM_LBUTTONUP
      ;Debug "Click"
      Keep_EN_CHANGE = 1
      SetActiveGadget(ACS\ID_List)
      Item=GetGadgetState(ACS\ID_List)
      SetGadgetText(ACS\ID_Edit,GetGadgetItemText(ACS\ID_List,Item))
      HideGadget(ACS\ID_List,1)
      Keep_EN_CHANGE = 0
      
    Case #WM_NCDESTROY
      SetWindowLong_(Hwnd, #GWL_WNDPROC, OriginProc)
      RemoveProp_(Hwnd, "OriginProc")
  EndSelect
  
  ProcedureReturn CallWindowProc_(OriginProc, Hwnd, uMsg, wParam, lParam)
EndProcedure

;- Event Loop (Edit)
Procedure EditProc(hWnd.i, uMsg.i, wParam.i, lParam.i)
  Protected OriginProc.i
  Protected ItemText.s
  Static Item.i = 0

  
  OriginProc = GetProp_(hWnd, "OriginProc")
  
  Select uMsg
    Case #WM_KEYDOWN
      Select wParam
        Case #VK_DOWN
          If Item < CountGadgetItems(ACS\ID_List)-1
            Item = Item + 1
            ;Debug Item
          EndIf
          SetGadgetState(ACS\ID_List,Item)
          If CountGadgetItems(ACS\ID_List) = 0
            HideGadget(ACS\ID_List,1)
          Else
            HideGadget(ACS\ID_List,0)
          EndIf
          
          Keep_EN_CHANGE = 1
          ItemText.s=GetGadgetItemText(ACS\ID_List,Item)
          SetGadgetText(ACS\ID_Edit,ItemText)
          Keep_EN_CHANGE = 0
          
          
        Case #VK_UP
          If Item > 0
            Item = Item - 1
            ;Debug Item
          EndIf
          SetGadgetState(ACS\ID_List,Item)
          HideGadget(ACS\ID_List,0)
          Keep_EN_CHANGE = 1
          ItemText.s=GetGadgetItemText(ACS\ID_List,Item)
          SetGadgetText(ACS\ID_Edit,ItemText)
          Keep_EN_CHANGE = 0
          
        Case #VK_RETURN
          SetGadgetText(ACS\ID_Edit,GetGadgetText(ACS\ID_List))
          HideGadget(ACS\ID_List,1)
          
        Case #VK_ESCAPE
          SetGadgetText(ACS\ID_Edit,"")
          SetGadgetState(ACS\ID_List,0)
          HideGadget(ACS\ID_List,1)
          
      EndSelect
      
    Case #WM_KEYDOWN
      ProcedureReturn CallWindowProc_(OriginProc, hWnd, uMsg, wParam, lParam)
      
    Case #WM_NCDESTROY
      SetWindowLong_(hWnd, #GWL_WNDPROC, OriginProc)
      RemoveProp_(hWnd, "OriginProc")
  EndSelect
  
  ProcedureReturn CallWindowProc_(OriginProc, hWnd, uMsg, wParam, lParam)
EndProcedure

;- Event Loop (AC_StringGadget)
Procedure AC_StringGadgetProc(hWnd,uMsg,wParam,lParam)
  Protected result.i
  result = #PB_ProcessPureBasicEvents
  Select uMsg
    Case #WM_COMMAND
      If (HiWord(wParam) = #EN_CHANGE) And (lParam = GadgetID(ACS\ID_Edit))
        ;Debug "#EN_CHANGE"
        If Keep_EN_CHANGE = 0
          HideGadget(ACS\ID_List,0)
          SearchInList()
          If CountGadgetItems(ACS\ID_List) = 0
            HideGadget(ACS\ID_List,1)
          EndIf
          
        EndIf
      EndIf   
  EndSelect
  
  ProcedureReturn result
EndProcedure

Procedure AC_StringGadget(Gadget,x,y,w,h,lh)
  ACS\ID_Edit=Gadget
  If StringGadget(Gadget,x,y,w,h,"")
    
    ACS\ID_List=ListViewGadget(#PB_Any,x,y+GadgetHeight(Gadget),w,lh,#LBS_NOTIFY)
    If ACS\ID_List
      
      SetActiveGadget(ACS\ID_Edit)
      SetGadgetState(ACS\ID_List,0)
      
      HideGadget(ACS\ID_List,1)
      
      oldEditProc=SetWindowLong_(GadgetID(ACS\ID_Edit),#GWL_WNDPROC,@EditProc())
      SetProp_(GadgetID(ACS\ID_Edit), "OriginProc", oldEditProc)
      
      oldListProc=SetWindowLong_(GadgetID(ACS\ID_List),#GWL_WNDPROC,@ListProc())
      SetProp_(GadgetID(ACS\ID_List), "OriginProc", oldListProc)
      
      SetWindowCallback(@AC_StringGadgetProc())
      
    EndIf
    
  EndIf
  
  
EndProcedure
;}

DisableExplicit
Et le programme pour le tester :

Code : Tout sélectionner

XIncludeFile "AC_StringGadget.pbi"

If OpenWindow(0,0,0,300,150,"StringGadgetEx",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  AC_StringGadget(1,50,10,200,20,100)
EndIf

AddToList("AS250M150V3")
AddToList("AS250L250V2")
AddToList("AS250/100V2")
AddToList("AS250M130-16V4")
AddToList("AS250M160")
AddToList("AB100V2")
AddToList("AC100")
AddToList("AS280L240-28V6")
AddToList("AS280L240-28V5")
AddToList("AS280L240-28V8")
AddToList("AB100V3")
AddToList("AS180L170")

Repeat
  Event = WaitWindowEvent()
  
  Select Event
    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = 0
        CloseWindow(0)
        Break
      EndIf
  EndSelect
ForEver
Utilisation :

Code : Tout sélectionner

AC_StringGadget(x,y,width,height,hauteur_listview) // Création du gadget
AddToList(texte) // Ajout à la liste pour l'auto-complétion
Voilà si ça peut être utile ...
@+ David
Dernière modification par wood51 le mar. 03/juil./2012 18:19, modifié 3 fois.
Compétences : Bricoleur PureBasic du dimanche
Crâmage de cerveau en cours 100% :D
Projet en cours : http://purepicbasic.frenchboard.com/
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: StringGadget et AutoComplétion

Message par falsam »

J'adopte. Merci pour ce partage wood51:)
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Avatar de l’utilisateur
Kwai chang caine
Messages : 6989
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: StringGadget et AutoComplétion

Message par Kwai chang caine »

Merci pour le partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: StringGadget et AutoComplétion

Message par dayvid »

Sa marche pas :(
J'ai un accès mémoire invalide !
Ligne 189 !
Une erreur d'écriture !
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Avatar de l’utilisateur
wood51
Messages : 122
Inscription : ven. 05/juin/2009 13:04
Localisation : orléans

Re: StringGadget et AutoComplétion

Message par wood51 »

Salut,
Merci pour les encouragement
Sa marche pas :(
J'ai un accès mémoire invalide !
Ligne 189 !
Une erreur d'écriture !
C'est dans ListProc c'est çà ? Avec quel OS tu teste ? Je l'ai pas tester sous XP
Vraiment désolé :oops:
Compétences : Bricoleur PureBasic du dimanche
Crâmage de cerveau en cours 100% :D
Projet en cours : http://purepicbasic.frenchboard.com/
Avatar de l’utilisateur
falsam
Messages : 7324
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: StringGadget et AutoComplétion

Message par falsam »

En attendant que dayvid poste sa réponse, j'ai testé sous Wndow XP SP2 et je n'ai pas eu cette erreur. J'espére que dayvid expliquera dans quel cas il obtient cette erreur.
Configuration : Windows 11 Famille 64-bit - PB 6.20 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: StringGadget et AutoComplétion

Message par dayvid »

Salut :)

Oui, je suis sous Sevent PB-4.60 64 Bits :)
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Avatar de l’utilisateur
wood51
Messages : 122
Inscription : ven. 05/juin/2009 13:04
Localisation : orléans

StringGadget et AutoComplétion

Message par wood51 »

Salut,
Je viens d'essayer . Compilé en 32Bit Pas de Problèmes . Par contre compilé en 64bit ca ne marche pas . Je suis vraiment désolé , je recherche un solution .

@+ David
Compétences : Bricoleur PureBasic du dimanche
Crâmage de cerveau en cours 100% :D
Projet en cours : http://purepicbasic.frenchboard.com/
dayvid
Messages : 1242
Inscription : mer. 11/nov./2009 18:17
Localisation : Poitiers (Vienne)

Re: StringGadget et AutoComplétion

Message par dayvid »

Effectivement tu as raison, ça marche pas en 64 Bits, bizarre :?
Sinon superbe travail, ça va me servir :D
Hum...

Une petite idée pour améliorer, si le texte entrée ne correspond à aucun élément de la liste
Tu fais disparaitre le ListViewGadget :)

Merci, salut !
La vie, C'est comme, Une boitte, De startis, On en voie, De toutes, Les couleurs !

Mon forum http://purebasic.forumphp3.com/index.php
Avatar de l’utilisateur
wood51
Messages : 122
Inscription : ven. 05/juin/2009 13:04
Localisation : orléans

Re: StringGadget et AutoComplétion

Message par wood51 »

Salut ,
J'ai trouvé la soluce : bannir les Long et remplacer tous par des Integer.
Je m'occupe de la petite soluce dès demain , j'éditerai mon post .... (c'est fait !!!)
Bonne soirée a tous
Compétences : Bricoleur PureBasic du dimanche
Crâmage de cerveau en cours 100% :D
Projet en cours : http://purepicbasic.frenchboard.com/
Répondre