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
[SOLVED] Add Auto-completion for non-AHK ComboBox with a AHK script ? Topic is solved
[SOLVED] Add Auto-completion for non-AHK ComboBox with a AHK script ?
Last edited by DRocks on 26 Oct 2019, 06:19, edited 5 times in total.
Re: Simulate a ahk ComboBox gLabel for a non-AHK ComboBox?
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%
It was fun, but you will want to get something from someone that's done these sorts of things before lol.
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.
Re: Simulate a ahk ComboBox gLabel for a non-AHK ComboBox?
Hey hellbent
Thanj you very much for the help. I was just editting my post and when done you had a reply
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
Thanj you very much for the help. I was just editting my post and when done you had a reply
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
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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
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
}
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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.
Good luck with your project.
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
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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
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
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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.
Start with typing something like "date" in the tool.
***Edit***
Added:
To InjectSelection: and 4GuiClose:
The two can also be connected via goto or gosub
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 ==================================
;=====================================================================================
***Edit***
Added:
Code: Select all
ComboListArray:="",ComboContentsList:="",SortedList:="",Choice:="",ComboSorter:="",InputValue:="",ComboList:=""
The two can also be connected via goto or gosub
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
@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
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 !
*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
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
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 !
*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.
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
Sure sorry I typed with a bit of hype
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
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)
the important bit is this:
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
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
}
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
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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.
Thanks again for the idea
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.
Thanks again for the idea
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ? Topic is solved
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].
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.
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 ==================================
;=====================================================================================
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
Damn nice, I like it.
Re: Add Auto-completion for non-AHK ComboBox with a AHK script ?
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.
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
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")
}
}
Spoiler
Who is online
Users browsing this forum: CoffeeChaton, peter_ahk and 120 guests