autohotkey

The class name of the control is different in different PC


I want to jump to the corresponding input box by the class name of the control, and then enter the data in the CSV. This code works on my PC, but I found that the class name of the control is different in different PC, some are r8, some are r7, and some are r6. What should I do?

; 载入CSV数据到内存
material_map := {}
FileRead, csvdata, mapping.csv
Loop, parse, csvdata, `n, `r
{
    if (A_Index = 1) ; 跳过标题行
        continue
    fields := StrSplit(A_LoopField, ",")
    if (fields.Length() >= 4) ; 只处理四个字段
    {
        no := Trim(fields[1])
        material_map[no] := material_map[no] ? material_map[no] . "|" . fields[2] . "," . fields[3] . "," . fields[4] : fields[2] . "," . fields[3] . "," . fields[4]
    }
}


^q::
    SetTimer, on_top, 50  ; Set a timer to apply always on top
    InputBox, userInput, 输入料号, 请手动输入料号或复制料号至此, , 220, 120  ; Launch inputbox
    SetTimer, on_top, Off  ; Stop on_top timer when done
    if (ErrorLevel)  ; Check if the user canceled the input
        return
    userInput := Trim(userInput)

    if !material_map.HasKey(userInput)
    {
        MsgBox, 未找到料号:%userInput%,请确认输入是否正确。
        return
    }

    options := StrSplit(material_map[userInput], "|")
    if (options.Length() = 1)
    {
        selected := options[1]
    }
    else
    {
        ; 创建选择框供用户选择
        choice := ""
        Loop, % options.Length()
        {
            choice .= A_Index . ": " . options[A_Index] . "`n"
        }
        choice .= "请选择一个选项:"
        InputBox, userChoice, 选择品名, %choice%, , 300, 200
        if (ErrorLevel || userChoice < 1 || userChoice > options.Length())
            return
        selected := options[userChoice]
    }

    selectedFields := StrSplit(selected, ",")

    MsgBox, % "系统即将自动填写以下数据:`n`n"
        . "输入的料号:" userInput "`n"
        . "品名:" selectedFields[1] "`n"
        . "原材料编号:" selectedFields[2] "`n"
        . "原材料UL认证档案号:" selectedFields[3]

    ;WinActivate, ahk_class WindowsForms10.Window.8.app.0.13965fa_r8_ad1
    
    WinActivate, TCL瑞智二维码打印软件 

    sleep, 200

    ; 填写料号
    controlfocus, WindowsForms10.EDIT.app.0.13965fa_r8_ad110, A
    controlsettext, WindowsForms10.EDIT.app.0.13965fa_r8_ad110, % userInput, A
    sleep, 200

    ; 填写品名
    controlfocus, WindowsForms10.EDIT.app.0.13965fa_r8_ad116, A
    controlsettext, WindowsForms10.EDIT.app.0.13965fa_r8_ad116, % selectedFields[1], A
    sleep, 200

    ; 填写原材料编号
    controlfocus, WindowsForms10.EDIT.app.0.13965fa_r8_ad111, A
    controlsettext, WindowsForms10.EDIT.app.0.13965fa_r8_ad111, % selectedFields[2], A
    sleep, 200

    ; 填写原材料ul认证档案号
    controlfocus, WindowsForms10.EDIT.app.0.13965fa_r8_ad12, A
    controlsettext, WindowsForms10.EDIT.app.0.13965fa_r8_ad12, % selectedFields[3], A
    sleep, 200

on_top:  ; 
    ib_ahk := "ahk_class #32770"  ; The class for the inputbox
    if WinExist(ib_ahk)  ; When it exists
        WinSet, AlwaysOnTop, On, ahk_class #32770  ; Apply always on top attribute
return

I've tried using regular expressions, maybe I have something wrong with the syntax.

    SetTitleMatchMode, RegEx
    sleep, 200

    controlfocus, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad110, A
    controlsettext, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad110, % userInput, A
    sleep, 200

    controlfocus, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad116, A
    controlsettext, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad116, % selectedFields[1], A
    sleep, 200

    controlfocus, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad111, A
    controlsettext, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad111, % selectedFields[2], A
    sleep, 200

    controlfocus, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad12, A
    controlsettext, WindowsForms10\.EDIT\.app\.0\.13965fa_r\d_ad12, % selectedFields[3], A
    sleep, 200

Solution

  • Try to to get a list of those controls, in the auto-execute section, and, within the parsing loop, assign a variable's name to each control you want to use:

    WinGet, ControlList, ControlList, TCL瑞智二维码打印软件 
    Loop, Parse, ControlList, `n
    {
        If !InStr(A_LoopField, "WindowsForms10.EDIT.app.0.13965fa_")
            continue
        If SubStr(A_LoopField, -5) = "_ad110"
            Control_1 := A_LoopField
        If SubStr(A_LoopField, -5) = "_ad116"
            Control_2 := A_LoopField
        If SubStr(A_LoopField, -4) = "_ad12"
            Control_3 := A_LoopField
    }
    

    Then you can use the variable's name in ControlFocus and ControlSetText instead of the control's name:

    controlfocus, % Control_1, A
    controlsettext, % Control_1, % userInput, A