Code : Tout sélectionner
#include <GuiEdit.au3>
#include <Misc.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <ListBoxConstants.au3>
#include <Array.au3>
#include <WinAPI.au3>
#include <GUIListBox.au3>
#include <Constants.au3>
Opt("MustDeclareVars", 1)
;
; ça va remplir le "edit" pour tester la complétion :o)
;
Global $aaa
For $i = 0 To 1000
$aaa &= "test" & Random(100000, 999999, 1) & " "
Next
;~ ClipPut($aaa)
Global Const $NULL = ""
; constante servant à définir ce qui sépare les mots
Global Const $SEPARATEUR_DE_MOTS[5] = [ _
@CRLF, _
@CR, _
@LF, _
@TAB, _
" "]
Global $completion = GUICreate("Complétion", 500, 500)
Global $edit = GUICtrlCreateEdit("", 0, 0, 500, 500)
Global $hEdit = GUICtrlGetHandle($edit)
Global $guiListeCompletion, $listeCompletion, $hListeCompletion
Global $listeCompletionAffichee = False
Global $debutMot
;
; met le texte dans le "edit" pour tester la complétion
;
GUICtrlSetData($edit, $aaa)
creeListeCompletion()
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
; http://msdn.microsoft.com/en-us/library/ms633570(VS.85).aspx
Global $hWndproc_Edit = DllCallbackRegister('wndproc_Edit', 'lparam', 'hwnd;uint;wparam;lparam')
If $hWndproc_Edit = 0 Then Exit
Global $hAncienWNDPROC_edit = _WinAPI_GetWindowLong(GUICtrlGetHandle($edit), $GWL_WNDPROC)
_WinAPI_SetWindowLong(GUICtrlGetHandle($edit), $GWL_WNDPROC, DllCallbackGetPtr($hWndproc_Edit))
GUISetState(@SW_SHOW, $completion)
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
DllCallbackFree($hWndproc_Edit)
GUIDelete()
Func completion($txt, $emplacement_curseur, $separateur)
Local $i, $index, $temp, $t, $retCompletionMots, $debutDoc_mot
If Not $txt Then Return SetError(1, "", "")
; récupère le texte du début du document jusqu'au mot à compléter
$debutDoc_mot = StringLeft($txt, $emplacement_curseur)
; recherche le début du mot
For $i = 1 To StringLen($txt)
$temp = StringMid($debutDoc_mot, StringLen($debutDoc_mot) - $i + 1, 1)
$index = _ArraySearch($separateur, $temp)
If $index <> -1 Then
$debutMot = StringRight($debutDoc_mot, $i - 1)
ExitLoop
EndIf
Next
If Not $debutMot Then $debutMot = $txt
; remplace les caractères spéciaux
$debutMot = StringRegExpReplace($debutMot, _
'(?x)([\$ \\ \( \) \| \. \[ \]])', _
"\\\1")
; recherche le mot dans le texte
;~ $t = TimerInit()
If $debutMot Then $retCompletionMots = StringRegExp($txt, _
'(?ixs)' & _
'(?>' & _
' (?<=\A|\s) (' & $debutMot & '[^\s]+)' & _
')' & _
'(?!' & _
' .*? (?:\A|\s) \1 (?:\s|\z)' & _
')', _
3)
;~ MsgBox(0, "", TimerDiff($t))
; si le mot est trouvé
If UBound($retCompletionMots) Then
Return $retCompletionMots
Else
Return SetError(1, "", "")
EndIf
EndFunc ;==>completion
Func creeListeCompletion()
$guiListeCompletion = GUICreate("", _
200, 150, 0, 0, _
$WS_POPUP, _
$WS_EX_WINDOWEDGE, _
$completion)
$listeCompletion = GUICtrlCreateList("", 0, 0, 200, 150)
$hListeCompletion = GUICtrlGetHandle($listeCompletion)
EndFunc ;==>creeListeCompletion
Func afficheListeCompletion()
Local $ret, $tRect
Local $x_edit, $y_edit, $x_curseur, $y_curseur
; récupère les coordonnées du contrôle "edit"
$tRect = _WinAPI_GetWindowRect($hEdit)
$x_edit = DllStructGetData($tRect, "Left")
$y_edit = DllStructGetData($tRect, "Top")
; récupère les coordonnées de l'emplacement du curseur
$ret = _GUICtrlEdit_GetSel($hEdit)
$ret = _GUICtrlEdit_PosFromChar($hEdit, $ret[0] - 1)
$x_curseur = $ret[0]
$y_curseur = $ret[1]
; déplace la liste sous le curseur
WinMove($guiListeCompletion, "", $x_edit + $x_curseur, $y_edit + $y_curseur + 20)
; sélectionne le premier élément
_GUICtrlListBox_SetCurSel($hListeCompletion, 0)
GUISetState(@SW_SHOWNOACTIVATE, $guiListeCompletion)
$listeCompletionAffichee = True
EndFunc ;==>afficheListeCompletion
Func cacheListeCompletion()
GUISetState(@SW_HIDE, $guiListeCompletion)
$listeCompletionAffichee = False
EndFunc ;==>cacheListeCompletion
Func metDonneesListeCompletion($donnees)
effaceListeCompletion()
GUICtrlSetData($listeCompletion, $donnees)
EndFunc ;==>metDonneesListeCompletion
Func effaceListeCompletion()
_GUICtrlListBox_ResetContent($hListeCompletion)
EndFunc ;==>effaceListeCompletion
Func WM_COMMAND($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam, $ilParam
Local $posDansEdit, $retCompletionMots
Switch $ilParam
Case $hEdit
Switch _WinAPI_HiWord($iwParam)
Case $EN_CHANGE
; affichage de la liste de complétion
$posDansEdit = _GUICtrlEdit_GetSel($edit)
$retCompletionMots = completion(GUICtrlRead($edit), $posDansEdit[0], $SEPARATEUR_DE_MOTS)
If UBound($retCompletionMots) Then
$retCompletionMots = _ArrayToString($retCompletionMots, "|")
metDonneesListeCompletion($retCompletionMots)
afficheListeCompletion()
Else
If $listeCompletionAffichee Then
effaceListeCompletion()
cacheListeCompletion()
EndIf
EndIf
EndSwitch
EndSwitch
EndFunc ;==>WM_COMMAND
Func wndproc_Edit($hWnd, $iMsg, $iwParam, $ilParam)
#forceref $hWnd, $iMsg, $iwParam, $ilParam
Local $ret, $posDansListe, $posDansEdit, $texteElement, $nbElements, $finMotCompletion
; si la liste de complétion n'est affichée alors on ne fait rien
If $listeCompletionAffichee = False Then
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $iwParam, $ilParam)
If Not @error Then Return $ret
EndIf
Switch $iMsg
Case $WM_CHAR
Switch $iwParam
Case 13 ; entrée
$posDansListe = _GUICtrlListBox_GetCurSel($hListeCompletion)
; on récupère le mot dans la liste
$texteElement = _GUICtrlListBox_GetText($hListeCompletion, $posDansListe)
; on récupère la fin du mot qui reste à compléter
$finMotCompletion = StringTrimLeft($texteElement, StringLen($debutMot))
; on ajoute la complétion au mot
$posDansEdit = _GUICtrlEdit_GetSel($edit)
_GUICtrlEdit_InsertText($edit, $finMotCompletion, $posDansEdit[0])
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
EndSwitch
Case $WM_KEYDOWN
Switch $iwParam
Case 33 ; page haut
$posDansListe = _GUICtrlListBox_GetCurSel($hListeCompletion)
If $posDansListe - 5 < $nbElements Then
_GUICtrlListBox_SetCurSel($hListeCompletion, 0)
Else
_GUICtrlListBox_SetCurSel($hListeCompletion, $posDansListe - 5)
EndIf
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
Case 34 ; page bas
$nbElements = _GUICtrlListBox_GetCount($hListeCompletion) - 1
$posDansListe = _GUICtrlListBox_GetCurSel($hListeCompletion)
If $posDansListe + 5 > $nbElements Then
_GUICtrlListBox_SetCurSel($hListeCompletion, $nbElements)
Else
_GUICtrlListBox_SetCurSel($hListeCompletion, $posDansListe + 5)
EndIf
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
Case 35 ; fin
$nbElements = _GUICtrlListBox_GetCount($hListeCompletion) - 1
_GUICtrlListBox_SetCurSel($hListeCompletion, $nbElements)
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
Case 36 ; début
_GUICtrlListBox_SetCurSel($hListeCompletion, 0)
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
Case 37 ; gauche
cacheListeCompletion()
Case 38 ; haut
$posDansListe = _GUICtrlListBox_GetCurSel($hListeCompletion)
If $posDansListe = 0 Then
; si on est déjà en haut de la liste alors on sélectionne le dernier
_GUICtrlListBox_SetCurSel($hListeCompletion, _
_GUICtrlListBox_GetCount($hListeCompletion) - 1)
Else
; sinon on sélectionne l'élément suivant
_GUICtrlListBox_SetCurSel($hListeCompletion, _
$posDansListe - 1)
EndIf
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
Case 39 ; droite
cacheListeCompletion()
Case 40 ; bas
$posDansListe = _GUICtrlListBox_GetCurSel($hListeCompletion)
If $posDansListe = _GUICtrlListBox_GetCount($hListeCompletion) - 1 Then
; si on est déjà en bas de la liste alors on sélectionne le premier
_GUICtrlListBox_SetCurSel($hListeCompletion, 0)
Else
; sinon on sélectionne l'élément suivant
_GUICtrlListBox_SetCurSel($hListeCompletion, _
$posDansListe + 1)
EndIf
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $NULL, $ilParam)
If Not @error Then Return $ret
EndSwitch
EndSwitch
$ret = _WinAPI_CallWindowProc($hAncienWNDPROC_edit, $hWnd, $iMsg, $iwParam, $ilParam)
If Not @error Then Return $ret
EndFunc ;==>wndproc_Edit