[SOLVED] Add Auto-completion for non-AHK ComboBox with a AHK script ? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

[SOLVED] Add Auto-completion for non-AHK ComboBox with a AHK script ?

22 Oct 2019, 10:26

EDIT: Topic solved see selected answer and my last post for reference.

Hello,

I want to add auto-completion to a non-AHK regular win32 ComboBox control with my AHK script.

Can you listen to the other software's ComboBox text input changes within a ahk script like a Gui control gLabel would do ?

In other words, Id like to be able to listen to the 3rd party software's ComboBox text changes so that I can implement auto completion to it from within my ahk script.

Ive tried to Subclass the ComboBox but it doesnt work because its not the same process as my script.

I have also been thinking about OnMessages() but Im almost certain I cannot listen to other process's messages like that...


Please share any tip you might have.


Thanks in advance
Last edited by DRocks on 26 Oct 2019, 06:19, edited 5 times in total.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Simulate a ahk ComboBox gLabel for a non-AHK ComboBox?

22 Oct 2019, 23:16

Took this on as a bit of a challenge just for fun.

I wouldn't say that it's good, but it works on the one comboBox I tried it on (font select for notepad). So batting 100%

Code: Select all


#SingleInstance,Force
ControlGet, ComboList, List,, ComboBox1, ahk_class #32770
ComboListArray:=StrSplit(ComboList,"`n")
SetTimer,watch_it,200
return
  
watch_it:
   MatchCase:=0
   ControlGetText,currentText,Edit1,ahk_class #32770
   ControlGetFocus,focused,ahk_class #32770
   for,k,v in ComboListArray    {
      if(currentText = substr(v,1,StrLen(currentText))&&StrLen(currentText)>=3&&focused="Edit1"){
         MatchCase++,MatchingString:=k
      }
      if(MatchMade&&MatchCase=1&&focused="Edit1"){
         return
      }else if(StrLen(currentText)<=2){
         MatchMade:=0
      }
   }
   if(MatchCase=1){
      Control, Choose, %MatchingString%, ComboBox1, ahk_class #32770
      MatchMade:=1
   }
   return

*ESC::
   ExitApp


It was fun, but you will want to get something from someone that's done these sorts of things before lol.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Simulate a ahk ComboBox gLabel for a non-AHK ComboBox?

22 Oct 2019, 23:25

Hey hellbent

Thanj you very much for the help. I was just editting my post and when done you had a reply :D

Ill be off sleeping but will surely try that when i wake up.

Thanks a lot, ill get back to this thread for updates.
Have a gn
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

23 Oct 2019, 08:16

I used your SetTimer idea and i got this so far,
Theres some problems when I try to match from anywhere in the string and the CbAutoComplete() that sets the text selection.
Feel free to mess with it it needs a lot of improvement :)

Code: Select all

#SingleInstance,Force
#Persistent
ControlGet, hCB, hwnd,, ComboBox2, Enregistrements des fournisseurs
ControlGet, CBList, List,,, % "ahk_id "hCB
AutoCompleteCB := Func("AutoCompleteCB").Bind(hCB, CBList)
SetTimer,%AutoCompleteCB%,200
return

;-----------------------------------------------------------------------------------------------------------------------------------------
AutoCompleteCB(ByRef hCB, ByRef CBList) { ; ComboBox custom auto complete
;-----------------------------------------------------------------------------------------------------------------------------------------
	;-1-Initialise
	Static prevCBText
	
	;-2-Get Curr Content
	ControlGetText, CBText,, % "ahk_id "hCB
	if (!CBText or CBText=prevCBText)
		return
	
	;-3-Find in list
	if (InStr(CBList, CBText)) { ; current text matched anywhere so check it up
		;--------------------------------------------------------------------------------
		Loop, Parse, % CBList, `n
		{
			if (FoundPos := InStr(A_LoopField, CBText)){
				MatchCount++
				if (FoundPos = 1) { ; commence par contenu CBText ou Match anywhere?
					MatchCount_AtStartPos++
					; Order: "Recent" first, then "starting with"
				    MatchesAtStart := MatchesAtStart . "`n" . A_LoopField  
				} 
				else {
					; Order: "MatchAnywhere" After Best Matches
					MatchAnywhere .= "`n" . A_LoopField	   	     
				}
			}
		}
		;--------------------------------------------------------------------------------
		Matches := MatchesAtStart . MatchAnywhere ; Ordered Match list
		;ToolTip, % CBText "" Matches
		;--------------------------------------------------------------------------------
		if (MatchCount = 1) {
			FinalMatch := StrReplace(Matches, "`n") 	; match unique
			if (MatchCount_AtStartPos = 1) {
				cbAutoComplete(hCB, FinalMatch)
			} 
			else {
				Control, ChooseString, %FinalMatch%,, % "ahk_id "hCB
			}
			;ToolTip, % FinalMatch
		} 
	} 
	prevCBText := CBText ; remembered static variable
}

;=======================================================================================
; https://github.com/pulover/cbautocomplete
;
; Function:      CbAutoComplete
; Description:   Auto-completes typed NewValue in a ComboBox.
;
; Author:        Pulover [Rodolfo U. Batista], D Rocks (tried improving Backspace behavior)
; Usage:         Call the function from the Combobox's gLabel.
;
; CB_GETEDITSEL = 0x0140, CB_SETEDITSEL = 0x0142
;=======================================================================================
CbAutoComplete(hCB, FinalMatch) {
	Static cbAutoCompleteBackspace
	
	hCB := "ahk_id "hCB
	SendMessage, 0x0140, 0, 0,, %hCB%
	If ((GetKeyState("Backspace", "P"))) {
		MakeShort(ErrorLevel, Start, End)
		Control, ChooseString, %FinalMatch%,, %hCB%
		if (cbAutoCompleteBackspace)  ; variable pour éviter bug double backspace quand nouveau nom (resetté après le cbAutoComplete)
			PostMessage, 0x0142, 0, MakeLong(Start,   StrLen(FinalMatch)),, %hCB%
		else 
			PostMessage, 0x0142, 0, MakeLong(Start-1, StrLen(FinalMatch)),, %hCB%
		cbAutoCompleteBackspace := False
		return
	}
	MakeShort(ErrorLevel, Start, End)
	ControlGetText, CBBtext,, %hCB%
	Control, ChooseString, %CBBtext%,, %hCB%
	If (ErrorLevel) {
		ControlSetText,, %CBBtext%, %hCB%
		PostMessage, 0x0142, 0, MakeLong(Start, End),, %hCB%
		return
	}
	ControlGetText, CBBtext,, %hCB%
	PostMessage, 0x0142, 0, MakeLong(Start, StrLen(CBBtext)),, %hCB%
}

MakeLong(LoWord, HiWord)	{
	return (HiWord << 16) | (LoWord & 0xffff)
}
MakeShort(Long, ByRef LoWord, ByRef HiWord)	{
	LoWord := Long & 0xffff
  , HiWord := Long >> 16
}
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

23 Oct 2019, 17:08

I added a gui and tweaked a bit of my auto-complete subroutine to work with the gui.

I tested it on 4 different ComboBox controls (don't have too many to use) in two different apps (used notepad font window and my GDIP function tool) and it worked 100% of the time as expected. (with this exception: Need to find a way to know which editNN is connected to the comboBox. as is, typing in any field can trigger the auto-complete )

Feel free to replace my auto-complete subroutine with yours ( I never tried yours because I don't have "Enregistrements des fournisseurs", and mine worked fine).

To use:

1: Run this script.

2: Select the window that has the comboBox controls using the "Set Window" button.

3: Select the comboBox control you want to use from the list (selecting the control from the list will populate the DDL with all the options so you know which is which).

4: Toggle the checkbox.

5: Try typing in your comboBox.

Code: Select all

#SingleInstance,Force
SetBatchLines,-1
Gui,1:+AlwaysOnTop -Theme
Gui,1:Color,222222,333333
Gui,1:Font,cWhite s10,Segoe UI
Gui,1:Add,GroupBox,x10 y+10 w480 h110 Section,Window Info
Gui,1:Add,Text,xs+10 ys+30 w80,WinTitle:
Gui,1:Add,Edit,x+10 yp w240 r1 Center ReadOnly  vWinTitle,null
Gui,1:Add,Text,xs+10 y+20 w80,WinHwnd:
Gui,1:Add,Edit,x+10 yp w240 r1 Center ReadOnly  vWinHandle,null
Gui,1:Font,s8
Gui,1:Add,ListBox,xm y+30 w235 r5 section vComboBoxList gUpdateComboContentsList,
Gui,1:Add,Button,xm y+20 w200 h30 gSetWindow,Set Window
Gui,1:Add,CheckBox,x+20 yp vActivateAUTOCB gToggleACB,Activate Auto-Complete
Gui,1:Add,DDL,xs+245 ys w235 r20 vComboContentsList,
Gui,1:Font,s10
Gui,1:Show,,ComboBox Auto-Complete
return
GuiClose:
;~ GuiContextMenu:
;~ *ESC::
   ExitApp
  
SetWindow:
   While(!GetKeyState("ctrl"))
      ToolTip,Select the window and press "ctrl"
   ToolTip,
   WinGet,WinHandle,Id,A
   WinGetTitle,WinTitle,ahk_Id %WinHandle%
   GuiControl,1:,WinHandle,% WinHandle
   GuiControl,1:,WinTitle,% WinTitle
   GuiControl,1:,ComboBoxList,|
   WinGet,ControlList,ControlList,ahk_Id %WinHandle%
   Loop, Parse, ControlList, `n
      if(instr(A_LoopField,"ComboBox"))
         GuiControl,1:,ComboBoxList,% A_LoopField "|"
   GuiControl,1:Choose,ComboBoxList,1
UpdateComboContentsList:   ;jump point
   ComboListArray:="",ComboListArray:=[],Index:=1,ComboContentsList:=""
   GuiControlGet,SelectedControl,1:,ComboBoxList
   ControlGet, ComboList, List,,%SelectedControl%, ahk_Id %WinHandle%
   Loop,Parse,ComboList,`n
      if(A_LoopField)
         ComboListArray[Index++]:=A_LoopField,ComboContentsList.=A_LoopField "|"
   GuiControl,1:,ComboContentsList,% "|" ComboContentsList
   GuiControl,1:Choose,ComboContentsList,1
   Gui,1:Submit,NoHide
   CCon:="",MatchMade:=""
   return

ToggleACB:
   Gui,1:Submit,NoHide
   CCon:="",MatchMade:=""
   SetTimer,Auto_Combo,% ActivateAUTOCB ? 200 : "Off"
   return

Auto_Combo:
   MatchCase:=0
   ControlGetFocus,focused,ahk_Id %WinHandle%
    if(MatchMade&&CCon!=focused&&CCon)
      return
   ControlGetText,currentText,%focused%,ahk_Id %WinHandle%
   for,k,v in ComboListArray    {
      if(currentText = substr(v,1,StrLen(currentText))&&StrLen(currentText)>=3)
         MatchCase++,MatchingString:=v
      if(MatchMade&&MatchCase=1&&CCon=focused)
         return
      else if(StrLen(currentText)<=2&&CCon=focused&&MatchMade=1)
         MatchMade:=0,CCon:=""
   }
   if(MatchCase=1){
      Control, ChooseString, %MatchingString%, %ComboBoxList%,ahk_Id %WinHandle%
      MatchMade:=1,prevMatch:=MatchingString,CCon:=focused
   }
   return

Good luck with your project.
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

24 Oct 2019, 07:42

Nice Gui selector Hellbent!
I think it works well too. I'll keep messing around though because the hardest part for me is that all cb list entries in the software start with 4 digits and problem is I can't remember them all by heart.
I'll need to add matching from anywhere in the string so i'll be adding this.

Thanks so much, let's consider this as solved since I didn't know how to connect to the third party and now its possible :D
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

24 Oct 2019, 17:40

I didn't see that you wanted to match anywhere in the string until your last post.
That being the case, I think this is a better solution to your problem than Auto-Complete.



Give this a try as-is.

I think that you should have no problem understanding it, but if you have questions feel free to ask. Adding comments just isn't my bag.

Code: Select all

#SingleInstance,Force
SetBatchLines,-1
;===============================================================================================================
;===================================== For The Demo Only =======================================================
;===============================================================================================================
PipeList:="UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)|BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")|StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster="")|SetStretchBltMode(hdc, iStretchMode=4)|SetImage(hwnd, hBitmap)|SetSysColorToControl(hwnd, SysColor=15)|Gdip_BitmapFromScreen(Screen=0, Raster="")|Gdip_BitmapFromHWND(hwnd)|CreateRectF(ByRef RectF, x, y, w, h)|CreateRect(ByRef Rect, x, y, w, h)|CreateSizeF(ByRef SizeF, w, h)|CreatePointF(ByRef PointF, x, y)|CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)|PrintWindow(hwnd, hdc, Flags=0)|DestroyIcon(hIcon)|PaintDesktop(hdc)|CreateCompatibleBitmap(hdc, w, h)|CreateCompatibleDC(hdc=0)|SelectObject(hdc, hgdiobj)|DeleteObject(hObject)|GetDC(hwnd=0)|GetDCEx(hwnd, flags=0, hrgnClip=0)|ReleaseDC(hdc, hwnd=0)|DeleteDC(hdc)|Gdip_LibraryVersion()|Gdip_LibrarySubVersion()|Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)|Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)|Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)|Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)|Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)|Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)|Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)|Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)|Gdip_DrawLines(pGraphics, pPen, Points)|Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)|Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)|Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode=0)|Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)|Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)|Gdip_FillRegion(pGraphics, pBrush, Region)|Gdip_FillPath(pGraphics, pBrush, Path)|Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx="", sy="", sw="", sh="", Matrix=1)|Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)|Gdip_SetImageAttributesColorMatrix(Matrix)|Gdip_GraphicsFromImage(pBitmap)|Gdip_GraphicsFromHDC(hdc)|Gdip_GetDC(pGraphics)|Gdip_ReleaseDC(pGraphics, hdc)|Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff)|Gdip_BlurBitmap(pBitmap, Blur)|Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)|Gdip_GetPixel(pBitmap, x, y)|Gdip_SetPixel(pBitmap, x, y, ARGB)|Gdip_GetImageWidth(pBitmap)|Gdip_GetImageHeight(pBitmap)|Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)|Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)|Gdip_GetImagePixelFormat(pBitmap)|Gdip_GetDpiX(pGraphics)|Gdip_GetDpiY(pGraphics)|Gdip_GetImageHorizontalResolution(pBitmap)|Gdip_GetImageVerticalResolution(pBitmap)|Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)|Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")|Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)|Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)|Gdip_CreateBitmapFromHICON(hIcon)|Gdip_CreateHICONFromBitmap(pBitmap)|Gdip_CreateBitmap(Width, Height, Format=0x26200A)|Gdip_CreateBitmapFromClipboard()|Gdip_SetBitmapToClipboard(pBitmap)|Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)|Gdip_CreatePen(ARGB, w)|Gdip_CreatePenFromBrush(pBrush, w)|Gdip_BrushCreateSolid(ARGB=0xff000000)|Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)|Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")|Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)|Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)|Gdip_CloneBrush(pBrush)|Gdip_DeletePen(pPen)|Gdip_DeleteBrush(pBrush)|Gdip_DisposeImage(pBitmap)|Gdip_DeleteGraphics(pGraphics)|Gdip_DisposeImageAttributes(ImageAttr)|Gdip_DeleteFont(hFont)|Gdip_DeleteStringFormat(hFormat)|Gdip_DeleteFontFamily(hFamily)|Gdip_DeleteMatrix(Matrix)|Gdip_TextToGraphics(pGraphics, Text, Options, Font="", Width="", Height="", Measure=0)|Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)|Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)|Gdip_SetStringFormatAlign(hFormat, Align)|Gdip_StringFormatCreate(Format=0, Lang=0)|Gdip_FontCreate(hFamily, Size, Style=0)|Gdip_FontFamilyCreate(Font)|Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)|Gdip_CreateMatrix()|Gdip_CreatePath(BrushMode=0)|Gdip_AddPathEllipse(Path, x, y, w, h)|Gdip_AddPathPolygon(Path, Points)|Gdip_DeletePath(Path)|Gdip_SetTextRenderingHint(pGraphics, RenderingHint)|Gdip_SetInterpolationMode(pGraphics, InterpolationMode)|Gdip_SetSmoothingMode(pGraphics, SmoothingMode)|Gdip_SetCompositingMode(pGraphics, CompositingMode=0)|Gdip_Startup()|Gdip_Shutdown(pToken)|Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder=0)|Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)|Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)|Gdip_ResetWorldTransform(pGraphics)|Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)|Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)|Gdip_ImageRotateFlip(pBitmap, RotateFlipType=1)|Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)|Gdip_SetClipPath(pGraphics, Path, CombineMode=0)|Gdip_ResetClip(pGraphics)|Gdip_GetClipRegion(pGraphics)|Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)|Gdip_CreateRegion()|Gdip_DeleteRegion(Region)|Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)|Gdip_UnlockBits(pBitmap, ByRef BitmapData)|Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)|Gdip_GetLockBitPixel(Scan0, x, y, Stride)|Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)|Gdip_ToARGB(A, R, G, B)|Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)|Gdip_AFromARGB(ARGB)|Gdip_RFromARGB(ARGB)|Gdip_GFromARGB(ARGB)|Gdip_BFromARGB(ARGB)|StrGetB(Address, Length=-1, Encoding=0)|"
Gui,1:+AlwaysOnTop -Theme +HwndGui1Hwnd
Gui,1:Color,222222,333333
Gui,1:Font,s10,Segoe UI
Gui,2:+Parent1 -Caption
Gui,2:Color,004444
Gui,2:Font,csilver s12 Bold,Segoe UI
Gui,2:Add,Text,x0 y0 w380 h40 Center 0x200,This Is The Target Window For The Demo
Gui,2:Show,x10 y10 w380 h40
Gui,1:Add,ComboBox,x50 y70 w300 r20,% PipeList
Gui,3:+Parent1 -Caption
Gui,3:Color,004444
Gui,3:Font,cYellow s10 Bold,Segoe UI
Gui,3:Add,Text,x0 y0 w380 h40 Center 0x200,***Press Numpad1 To Bring Up The Sorting Tool***
Gui,3:Show,x10 y120 w380 h40
Gui,1:Show,x200 y100 w400 h170,Demo
return
GuiClose:
GuiContextMenu:
*ESC::
	ExitApp
	

;=====================================================================================
;=========================== Main Functionality ======================================
;=====================================================================================



;~ #IfWinActive, You know what to do here

*Numpad1::
	Gui,4:New,+AlwaysOnTop -Theme
	Gui,4:Color,333333,444444
	Gui,4:Font,cWhite s10,Segoe UI
	Gui,4:Add,Edit,x10 y10 w280 r1 vInputValue gReviseList, 
	Gui,4:Add,ListBox,x10 y+10 w280 r10 vComboSorter,
	Gui,4:Add,Button,x+10 y10 gInjectSelection,Set Target
	Gui,4:Add,Button,xp y+10 gStartOver,Start Over
	gosub,GetListFromTarget
	Gui,4:Show,,Sorter
	return

;~ #If


4GuiClose:
	Gui,4:Destroy
	ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
	return

ReviseList:
	GuiControlGet,InputValue
	if(!InputValue){
		GuiControl,4:,ComboSorter,% "|" ComboContentsList
		return
	}
	SortedList:=""
	Loop,% ComboListArray.Length()	
		if(InStr(ComboListArray[A_Index],InPutValue))
			SortedList.=ComboListArray[A_Index] "|"
	if(SortedList)
		GuiControl,4:,ComboSorter,% "|" SortedList
	return


GetListFromTarget:
	ComboListArray:="",ComboListArray:=[],ComboContentsList:="",Index:=1
	ControlGet, ComboList, List,,ComboBox1,ahk_Id %Gui1Hwnd%
	Loop,Parse,ComboList,`n
      if(A_LoopField)
         ComboListArray[Index++]:=A_LoopField,ComboContentsList.=A_LoopField "|"
	GuiControl,4:,ComboSorter,% "|" ComboContentsList
	return


StartOver:
	GuiControl,4:,ComboSorter,% "|" ComboContentsList	
	GuiControl,4:,InputValue,
	return
	
InjectSelection:
	GuiControlGet,Choice,4:,ComboSorter
	Control,ChooseString,%Choice%,ComboBox1,ahk_Id %Gui1Hwnd%
	Gui,4:Destroy
	ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
	return
	
;=====================================================================================
;=========================== Main Functionality End ==================================
;=====================================================================================	
Start with typing something like "date" in the tool.


***Edit***
Added:

Code: Select all

ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
To InjectSelection: and 4GuiClose:
The two can also be connected via goto or gosub
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

25 Oct 2019, 07:44

@Hellbent Ahhhh it took me a few seconds to understand what was the link between the two windows but I think i got it.

The target window is a simulation of any third party software's window which has the combobox.
then you have the 2nd Gui that allows you to type and filter through the list of possibilities in the combobox.

This is great and can be better that's true. In fact, before I read your post I had already come up with something very similar.

The only thing I miss from a "typical autocomplete" is the fact that it auto selects it in the real box and sets the text selection correctly so that you can continue typing. (I am not able to do that yet btw)

To your code I have added two very small add-ons that are useful to me.

1. when the sorted combobox updates itself, I make it choose its own 1st entry.
2. I just added the word Default to the options of the InjecSelection Button so you can press enter and use the 1st entry
So you can do like : type "date" and press enter then you automatically get the only remaining choice inserted :D

Thank you very much

Note: related to the "typical auto complete" I mentionned, there is a working example in the function called CBAutoComplete() by pulover in my previously posted code. It works well for text starting with typed input.
But my challenge for today or the week-end is to make it work also for when there a unique match like "date" in "update". I need to make it set the text selection so that you can smoothly continue typing what you were typing before the autocompletion happened.

Even with that feature, I'd keep the second Gui feature because its really nice to have a filtered list show you the matching options you got ! :bravo: :bravo:

*Edit: I am thinking to do something with the Sorter Gui: I'd place it on top of the original window's combobox so that it completely fakes belonging to the original window. So you'd have all the features of the AHK implementation but the looks of staying in the original softwares frame
**Edit2: and Up Down arrow could navigate through the remaining options in the Sorted ListBox
Last edited by DRocks on 25 Oct 2019, 07:51, edited 1 time in total.
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

25 Oct 2019, 07:50

DRocks wrote:
25 Oct 2019, 07:44
I need to make it set the text selection so that you can smoothly continue typing what you were typing before the autocompletion happened.
Can you give me a bit of clarification?
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

25 Oct 2019, 07:57

Sure sorry I typed with a bit of hype :P

This is the result of CBAutoComplete() by pulover that I call when the sorted list matchCount = 1 and matchesAtStartPos = 1. In other words, because this function is able to set the combobox selection and the typed input text selection correctly for choices that starts with the user input, I call it only when this situation happens.
But I'd need to add another scenario where theres only 1 match but it does not start with this typed input. It has to do with the SendMessage part fo the function, where it defines what should be the text selection. Hope I'm able to explain myself a bit more lol :)
Image
In this picture I input "5700" and the sorted list had only 1 match for this input so I called CBAutoComplete() and it selected that unique match in the combobox. Then it set the text selection to everything AFTER what I had started typing so that I could continue to type without erasing everything. (when there a ComboBox selection made, the text automatically gets all selected so if you type one more time by mistake it would erase all)

Code: Select all

;=======================================================================================
; https://github.com/pulover/cbautocomplete
;
; Function:      CbAutoComplete
; Description:   Auto-completes typed NewValue in a ComboBox.
;
; Author:        Pulover [Rodolfo U. Batista], D Rocks (tried improving Backspace behavior)
; Usage:         Call the function from the Combobox's gLabel.
;
; CB_GETEDITSEL = 0x0140, CB_SETEDITSEL = 0x0142
;=======================================================================================
CbAutoComplete(hCB, CBUniqueMatch) {
	
	SendMessage, 0x0140, 0, 0,,  % "ahk_id "hCB
	If ((GetKeyState("Backspace", "P"))) {
		MakeShort(ErrorLevel, Start, End)
		Control, ChooseString, %CBUniqueMatch%,,  % "ahk_id "hCB
		PostMessage, 0x0142, 0, MakeLong(Start-1, StrLen(CBUniqueMatch)),,  % "ahk_id "hCB
		return
	}
	MakeShort(ErrorLevel, Start, End)
	ControlGetText, CBBtext,,  % "ahk_id "hCB
	Control, ChooseString, %CBBtext%,,  % "ahk_id "hCB
	If (ErrorLevel) {
		ControlSetText,, %CBBtext%,  % "ahk_id "hCB
		PostMessage, 0x0142, 0, MakeLong(Start, End),,  % "ahk_id "hCB
		return
	}
	ControlGetText, CBBtext,,  % "ahk_id "hCB
	PostMessage, 0x0142, 0, MakeLong(Start, StrLen(CBBtext)),,  % "ahk_id "hCB
}
MakeLong(LoWord, HiWord)	{
	return (HiWord << 16) | (LoWord & 0xffff)
}
MakeShort(Long, ByRef LoWord, ByRef HiWord)	{
	LoWord := Long & 0xffff
	  , HiWord := Long >> 16
}
the important bit is this:

Code: Select all

	MakeShort(ErrorLevel, Start, End)
	ControlGetText, CBBtext,,  % "ahk_id "hCB
	Control, ChooseString, %CBBtext%,,  % "ahk_id "hCB
	If (ErrorLevel) {
		ControlSetText,, %CBBtext%,  % "ahk_id "hCB
		PostMessage, 0x0142, 0, MakeLong(Start, End),,  % "ahk_id "hCB
		return
	}
	ControlGetText, CBBtext,,  % "ahk_id "hCB
	PostMessage, 0x0142, 0, MakeLong(Start, StrLen(CBBtext)),,  % "ahk_id "hCB
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

25 Oct 2019, 08:09

try this:

Code: Select all

Send, {Right} 
or this:

Code: Select all

ControlFocus,
Send,{Right}
DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

25 Oct 2019, 08:27

I don't know why but with this I previously experimented unreliability. I'd have to test again but to be honest I really want to dig into this post message logic and make use of it since it acts more precisely on the text selection.

Btw you can't tell that this is your idea of Sorter GUI that is placed on top of the original software window.
I'm gonna go with this, it's going to help a lot. 1st you can use a bigger font to taste, then you can do auto completion and filter out the unmatching list choices.
Image
Thanks again for the idea :D
User avatar
Hellbent
Posts: 2109
Joined: 23 Sep 2017, 13:34

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?  Topic is solved

25 Oct 2019, 08:49

I made a few small tweaks to this (I marked the *changes). If you like them, incorporate them into what you have if you haven't already added this.

On a side note.
I'm not sure, but it might be better to use contains rather than inStr(). inStr() works well, but if you were to type something like datbbbbb it doesn't clear the list like you might expect it to. It doesn't cause a failure, but it should show that no matches are being made.
Derp. Not a instr() issue lol

Anyway, this now automatically injects the item if it's the only one left in the list and sends right so you don't have to worry about clearing your selection. [ blockinput might also be a idea. Just have it block your keys for a sec or 2 after it injects].

Code: Select all

#SingleInstance,Force
SetBatchLines,-1
;===============================================================================================================
;===================================== For The Demo Only =======================================================
;===============================================================================================================
 

PipeList:="UpdateLayeredWindow(hwnd, hdc, x="", y="", w="", h="", Alpha=255)|BitBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, Raster="")|StretchBlt(ddc, dx, dy, dw, dh, sdc, sx, sy, sw, sh, Raster="")|SetStretchBltMode(hdc, iStretchMode=4)|SetImage(hwnd, hBitmap)|SetSysColorToControl(hwnd, SysColor=15)|Gdip_BitmapFromScreen(Screen=0, Raster="")|Gdip_BitmapFromHWND(hwnd)|CreateRectF(ByRef RectF, x, y, w, h)|CreateRect(ByRef Rect, x, y, w, h)|CreateSizeF(ByRef SizeF, w, h)|CreatePointF(ByRef PointF, x, y)|CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)|PrintWindow(hwnd, hdc, Flags=0)|DestroyIcon(hIcon)|PaintDesktop(hdc)|CreateCompatibleBitmap(hdc, w, h)|CreateCompatibleDC(hdc=0)|SelectObject(hdc, hgdiobj)|DeleteObject(hObject)|GetDC(hwnd=0)|GetDCEx(hwnd, flags=0, hrgnClip=0)|ReleaseDC(hdc, hwnd=0)|DeleteDC(hdc)|Gdip_LibraryVersion()|Gdip_LibrarySubVersion()|Gdip_BitmapFromBRA(ByRef BRAFromMemIn, File, Alternate=0)|Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)|Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)|Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)|Gdip_DrawBezier(pGraphics, pPen, x1, y1, x2, y2, x3, y3, x4, y4)|Gdip_DrawArc(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)|Gdip_DrawPie(pGraphics, pPen, x, y, w, h, StartAngle, SweepAngle)|Gdip_DrawLine(pGraphics, pPen, x1, y1, x2, y2)|Gdip_DrawLines(pGraphics, pPen, Points)|Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)|Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)|Gdip_FillPolygon(pGraphics, pBrush, Points, FillMode=0)|Gdip_FillPie(pGraphics, pBrush, x, y, w, h, StartAngle, SweepAngle)|Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)|Gdip_FillRegion(pGraphics, pBrush, Region)|Gdip_FillPath(pGraphics, pBrush, Path)|Gdip_DrawImagePointsRect(pGraphics, pBitmap, Points, sx="", sy="", sw="", sh="", Matrix=1)|Gdip_DrawImage(pGraphics, pBitmap, dx="", dy="", dw="", dh="", sx="", sy="", sw="", sh="", Matrix=1)|Gdip_SetImageAttributesColorMatrix(Matrix)|Gdip_GraphicsFromImage(pBitmap)|Gdip_GraphicsFromHDC(hdc)|Gdip_GetDC(pGraphics)|Gdip_ReleaseDC(pGraphics, hdc)|Gdip_GraphicsClear(pGraphics, ARGB=0x00ffffff)|Gdip_BlurBitmap(pBitmap, Blur)|Gdip_SaveBitmapToFile(pBitmap, sOutput, Quality=75)|Gdip_GetPixel(pBitmap, x, y)|Gdip_SetPixel(pBitmap, x, y, ARGB)|Gdip_GetImageWidth(pBitmap)|Gdip_GetImageHeight(pBitmap)|Gdip_GetImageDimensions(pBitmap, ByRef Width, ByRef Height)|Gdip_GetDimensions(pBitmap, ByRef Width, ByRef Height)|Gdip_GetImagePixelFormat(pBitmap)|Gdip_GetDpiX(pGraphics)|Gdip_GetDpiY(pGraphics)|Gdip_GetImageHorizontalResolution(pBitmap)|Gdip_GetImageVerticalResolution(pBitmap)|Gdip_BitmapSetResolution(pBitmap, dpix, dpiy)|Gdip_CreateBitmapFromFile(sFile, IconNumber=1, IconSize="")|Gdip_CreateBitmapFromHBITMAP(hBitmap, Palette=0)|Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)|Gdip_CreateBitmapFromHICON(hIcon)|Gdip_CreateHICONFromBitmap(pBitmap)|Gdip_CreateBitmap(Width, Height, Format=0x26200A)|Gdip_CreateBitmapFromClipboard()|Gdip_SetBitmapToClipboard(pBitmap)|Gdip_CloneBitmapArea(pBitmap, x, y, w, h, Format=0x26200A)|Gdip_CreatePen(ARGB, w)|Gdip_CreatePenFromBrush(pBrush, w)|Gdip_BrushCreateSolid(ARGB=0xff000000)|Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)|Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")|Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)|Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)|Gdip_CloneBrush(pBrush)|Gdip_DeletePen(pPen)|Gdip_DeleteBrush(pBrush)|Gdip_DisposeImage(pBitmap)|Gdip_DeleteGraphics(pGraphics)|Gdip_DisposeImageAttributes(ImageAttr)|Gdip_DeleteFont(hFont)|Gdip_DeleteStringFormat(hFormat)|Gdip_DeleteFontFamily(hFamily)|Gdip_DeleteMatrix(Matrix)|Gdip_TextToGraphics(pGraphics, Text, Options, Font="", Width="", Height="", Measure=0)|Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)|Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)|Gdip_SetStringFormatAlign(hFormat, Align)|Gdip_StringFormatCreate(Format=0, Lang=0)|Gdip_FontCreate(hFamily, Size, Style=0)|Gdip_FontFamilyCreate(Font)|Gdip_CreateAffineMatrix(m11, m12, m21, m22, x, y)|Gdip_CreateMatrix()|Gdip_CreatePath(BrushMode=0)|Gdip_AddPathEllipse(Path, x, y, w, h)|Gdip_AddPathPolygon(Path, Points)|Gdip_DeletePath(Path)|Gdip_SetTextRenderingHint(pGraphics, RenderingHint)|Gdip_SetInterpolationMode(pGraphics, InterpolationMode)|Gdip_SetSmoothingMode(pGraphics, SmoothingMode)|Gdip_SetCompositingMode(pGraphics, CompositingMode=0)|Gdip_Startup()|Gdip_Shutdown(pToken)|Gdip_RotateWorldTransform(pGraphics, Angle, MatrixOrder=0)|Gdip_ScaleWorldTransform(pGraphics, x, y, MatrixOrder=0)|Gdip_TranslateWorldTransform(pGraphics, x, y, MatrixOrder=0)|Gdip_ResetWorldTransform(pGraphics)|Gdip_GetRotatedTranslation(Width, Height, Angle, ByRef xTranslation, ByRef yTranslation)|Gdip_GetRotatedDimensions(Width, Height, Angle, ByRef RWidth, ByRef RHeight)|Gdip_ImageRotateFlip(pBitmap, RotateFlipType=1)|Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)|Gdip_SetClipPath(pGraphics, Path, CombineMode=0)|Gdip_ResetClip(pGraphics)|Gdip_GetClipRegion(pGraphics)|Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)|Gdip_CreateRegion()|Gdip_DeleteRegion(Region)|Gdip_LockBits(pBitmap, x, y, w, h, ByRef Stride, ByRef Scan0, ByRef BitmapData, LockMode = 3, PixelFormat = 0x26200a)|Gdip_UnlockBits(pBitmap, ByRef BitmapData)|Gdip_SetLockBitPixel(ARGB, Scan0, x, y, Stride)|Gdip_GetLockBitPixel(Scan0, x, y, Stride)|Gdip_PixelateBitmap(pBitmap, ByRef pBitmapOut, BlockSize)|Gdip_ToARGB(A, R, G, B)|Gdip_FromARGB(ARGB, ByRef A, ByRef R, ByRef G, ByRef B)|Gdip_AFromARGB(ARGB)|Gdip_RFromARGB(ARGB)|Gdip_GFromARGB(ARGB)|Gdip_BFromARGB(ARGB)|StrGetB(Address, Length=-1, Encoding=0)|"
;~ ToolTip,% A_ScreenDPI / 96
Gui,1:+AlwaysOnTop -Theme +HwndGui1Hwnd
Gui,1:Color,222222,333333
Gui,1:Font,s10,Segoe UI
Gui,2:+Parent1 -Caption
Gui,2:Color,004444
Gui,2:Font,csilver s12 Bold,Segoe UI
Gui,2:Add,Text,x0 y0 w380 h40 Center 0x200,This Is The Target Window For The Demo
Gui,2:Show,x10 y10 w380 h40
Gui,1:Add,ComboBox,x50 y70 w300 r20,% PipeList
Gui,3:+Parent1 -Caption
Gui,3:Color,004444
Gui,3:Font,cYellow s10 Bold,Segoe UI
Gui,3:Add,Text,x0 y0 w380 h40 Center 0x200,***Press Numpad1 To Bring Up The Sorting Tool***
Gui,3:Show,% "x10 y" 120*(A_ScreenDPI / 96) " w380 h40"
Gui,1:Show,x200 y100 w400 h170,Demo
return
GuiClose:
GuiContextMenu:
*ESC::
	ExitApp
;=====================================================================================
;=========================== Main Functionality ======================================
;=====================================================================================

;~ #IfWinActive, You know what to do here

*Numpad1::
	Gui,4:New,+AlwaysOnTop -Theme
	Gui,4:Color,333333,444444
	Gui,4:Font,cWhite s10,Segoe UI
	Gui,4:Add,Edit,x10 y10 w280 r1 vInputValue gReviseList, 
	Gui,4:Add,ListBox,x10 y+10 w280 r10 vComboSorter,
	Gui,4:Add,Button,x+10 y10 gInjectSelection,Set Target
	Gui,4:Add,Button,xp y+10 gStartOver,Start Over
	gosub,GetListFromTarget
	Gui,4:Show,,Sorter
	return

;~ #If


4GuiClose:
	Gui,4:Destroy
	ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
	return

ReviseList:
	GuiControlGet,InputValue
	if(!InputValue){
		GuiControl,4:,ComboSorter,% "|" ComboContentsList
		return
	}
	;================================================
	;================================================
	SortedList:="",Count:=0,last:=""
	Loop,% ComboListArray.Length()	
		if(InStr(ComboListArray[A_Index],InPutValue)){
			SortedList.=ComboListArray[A_Index] "|"
			Count++,last:=ComboListArray[A_Index]
		}
	;if(SortedList)  ;<------- The Derp!!!
		GuiControl,4:,ComboSorter,% "|" SortedList
	if(Count=1){
		GuiControl,4:Choose,ComboSorter,% last
		goto,InjectSelection
	}
	;================================================
	;================================================
	return

GetListFromTarget:
	ComboListArray:="",ComboListArray:=[],ComboContentsList:="",Index:=1
	ControlGet, ComboList, List,,ComboBox1,ahk_Id %Gui1Hwnd%
	Loop,Parse,ComboList,`n
      if(A_LoopField)
         ComboListArray[Index++]:=A_LoopField,ComboContentsList.=A_LoopField "|"
	GuiControl,4:,ComboSorter,% "|" ComboContentsList
	return

StartOver:
	GuiControl,4:,ComboSorter,% "|" ComboContentsList	
	GuiControl,4:,InputValue,
	return
	
InjectSelection:
	GuiControlGet,Choice,4:,ComboSorter
	Control,ChooseString,%Choice%,ComboBox1,ahk_Id %Gui1Hwnd%
	Gui,4:Destroy
	;================================================
	;================================================
	send,{Right}
	;================================================
	;================================================
	ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
	return
	
;=====================================================================================
;=========================== Main Functionality End ==================================
;=====================================================================================	

DRocks
Posts: 565
Joined: 08 May 2018, 10:20

Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?

26 Oct 2019, 06:04

At the end, I used your idea of a AHK GUI that becomes the ComboBox's list sorter/filter. It was in fact, better than autocompletion.

So I made a AHK GUI that will be automatically created on top of the software's window when I press Tab from the name control to switch to the ComboBox page.
This Gui will be populated with the real combobox content and with it, I am basically doing the same process as in your code, but I just rewrote my own so I could better understand what I'm doing (and mostly make it fit to my specific context).

What it does:
-When I type in the edit field, the ListBox is filtered and only matching results remain.
-When I press up or down when edit field is focused, it selects up and down in the listbox without loosing focus with the edit ctrl.
-When I press Tab, Enter or NumpadEnter, it will inject the listbox selected choice to the software's original combobox and automatically switch to the software's next page.

Here's the code, but there are things specific to the scenario I'm working with so the code might be wierd for you in some parts.

Code: Select all

#If WinActive(WinTitles["EnregFournisseurs"])
Tab::

;...context specific stuff

ControlGet, hCB, hwnd,, %comboBoxComptes%
if (!WinExist("ahk_id "hCBMatchesGui)) {
	CreateCBMatchingGUI(hCB, WinTitles.EnregFournisseurs)
}

;--------------------------------------------------------------------------------
CreateCBMatchingGUI(hCB, parentWindowTitle) {
;--------------------------------------------------------------------------------
	Global CBMatchingGUI := {}
	
	Gui CBMatchingGUI:New, -Caption -SysMenu -Resize +ToolWindow +AlwaysOnTop
	Gui, +HWNDhCBMatchesGui +Delimiter`n
	Gui, Margin, 0, 0
	Gui, Font, s14 q5
	
	; get Parent ComboBox info
	WinGetPos, cX, cY, cW, cH, % "ahk_id "hCB
	ControlGet, CBList, List,,, % "ahk_id "hCB
	ControlGet, CBChoice, Choice,,, % "ahk_id "hCB
	
	; set Gui controls with Parent ComboBox info
	Gui, Add, Edit, % "+HWNDhEdit x0 y0 w"cW+200 " R1"
	GuiControl,, %hEdit%, %CBChoice%
	Gui, Add, ListBox, % "+HWNDhLB xp y+0 wp" " R20", % CBList
	GuiControl, ChooseString, %hLB%, %CBChoice%
	
	CBMatchingGUI.hwnd := hCBMatchesGui
	CBMatchingGUI.hEdit := hEdit
	CBMatchingGUI.hLB := hLB
	CBMatchingGUI.hParentCB := hCB
	CBMatchingGUI.parentCBList := CBList
	CBMatchingGUI.parentWindowTitle := parentWindowTitle
	
	gFunction := Func("CBMatching").Bind(CBMatchingGUI)
	GuiControl, +g, %hEdit%, %gFunction%
	
	Gui, Show, % "x"cX-5 " y"cY-5 " ", % "CBMatchingGUI"
	SetTimer, DestroyCBMatchingGUI, 80
}

;--------------------------------------------------------------------------------
CBMatching(ByRef CBMatchingGUI) { ; ByRef object generated at the GUI creation
;--------------------------------------------------------------------------------
	GuiControlGet, userInput,, % CBMatchingGUI.hEdit
	
	;--Find in list
	choicesList := CBMatchingGUI.parentCBList
	if (InStr(choicesList, userInput)) {
		Loop, Parse, choicesList, "`n"
		{
			if (FoundPos := InStr(A_LoopField, userInput)) {
				if (FoundPos = 1)
					MatchesAtStart .= "`n"A_LoopField
				else
					MatchesAnywhere .= "`n"A_LoopField 	   	     
				MatchCount++
			} 
		}
		Matches := MatchesAtStart . MatchesAnywhere ; Ordered Match list
		GuiControl,, % CBMatchingGUI.hLB, %Matches%
		if (MatchCount = 1) {
			UniqueMatch := Matches
			GuiControl, ChooseString, % CBMatchingGUI.hLB, %UniqueMatch%
		} 
		else
			GuiControl, Choose, % CBMatchingGUI.hLB, 1
	} 
	else
		GuiControl,, % CBMatchingGUI.hLB, `n<! Aucune correspondance !>
}

;--------------------------------------------------------------------------------
DestroyCBMatchingGUI() {
;--------------------------------------------------------------------------------
	Global CBMatchingGUI ; global object created with the CBMatchingGUI
	
	if (!WinActive("Ahk_id "CBMatchingGUI.hwnd) and WinExist("ahk_id "CBMatchingGUI.hwnd)) {
		Gui, % CBMatchingGUI.hwnd ":Destroy"
		SetTimer, DestroyCBMatchingGUI, Delete
	}
}

;================================================================================
;#[3.3.2.1 CBMatchingGUI]
#IfWinActive, CBMatchingGUI
;================================================================================
F2::
Enter::
NumpadEnter::
Tab::setCBMatchingGUILBChoice(CBMatchingGUI) ; pass GUI object reference
		
Up::
Down::ControlSend,, % A_ThisHotkey = "Up" ? "{Up}" : "{Down}", % "ahk_id "CBMatchingGUI.hLB
		
;--------------------------------------------------------------------------------
setCBMatchingGUILBChoice(CBMatchingGUI) {
;--------------------------------------------------------------------------------
	; get ListBox choice
	GuiControlGet, LBMatchesSelectedChoice,, % CBMatchingGUI.hLB 
			
	; set choice in sage ComboBox
	Control, ChooseString, %LBMatchesSelectedChoice%,,% "ahk_id "CBMatchingGUI.hParentCB
			
	; execute next Tab_EnregFournisseursClients() step
	ControlFocus,, % "ahk_id "CBMatchingGUI.hParentCB
	parentWinTitle := CBMatchingGUI.parentWindowTitle
	if (InStr(parentWinTitle, WinTitles.EnregFournisseurs)) {
		Tab_EnregFournisseursClients("Fournisseurs")
	} 
	else if (InStr(parentWinTitle, WinTitles.EnregClients)) {
		Tab_EnregFournisseursClients("Clients")
	}
}
So a big thanks @Hellbent this is a great feature that will help be everyday and save my eyes from the size8 original combobox list that didn't support filtering :)
Spoiler

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: haomingchen1998 and 250 guests