Что нового

использование WM_NOTIFY для Input

nikita1996spb

Новичок
Сообщения
19
Репутация
0
Здравствуйте! Искал возможность изменения значения в Input в зависимости от выделенного значения Сombobox в этой теме:
http://autoit-script.ru/index.php?topic=23490
Мой вариант кода:
Код:
#include <EditConstants.au3>
#Include <Array.au3>
#Include <GuiComboBox.au3>
#include <ComboConstants.au3>
#include <GuiComboBoxEx.au3>
#Include <WindowsConstants.au3>
#Include <GUIConstantsEx.au3>
#Include <Constants.au3>
#include <GuiEdit.au3>
#include <String.au3>

$Debug_Ed = False
$Debug_CB = False

$winname = "123"
$gw = 1040
$gh = 640
$g = GUICreate($winname,$gw,$gh,-1,-1,BitOR($GUI_SS_DEFAULT_GUI,$WS_MAXIMIZEBOX,$WS_SIZEBOX ))
GUISetFont(11)

$cfgfile = "config.txt"

#CS
ОФОРМЛЕНИЕ
#CE
$prevo1 = "Нет"
;Чтение
$objects = FileRead($cfgfile)
$objects = StringReplace($objects,@CRLF," ")
$objects = StringSplit($objects," ")
$oblist="Нет|"
For $i=2 To $objects[0] Step 2
   $oblist &= $objects[$i] & "|"
Next
$oblist &= "Другое"

;Параметры
$obj1 = _GUICtrlComboBoxEx_Create($g,$oblist,600,158,150,25*($objects[0]/2+1),$CBS_DROPDOWNLIST)
$obj1c = GUICtrlCreateInput("",800,158,120,25)

#CS
Начальные параметры
#CE
_GUICtrlComboBoxEx_SetCurSel($obj1,0)

#CS
ПРОГРАММНАЯ ЧАСТЬ
#CE
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUIRegisterMsg($WM_COMMAND,'WM_COMMAND')

Func IsFamily($s)
    If (StringRight($s,2)=="вна") Or (StringRight($s,3)=="вич") Or ($s=="") Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc

Func checkparams()
    Local $c=0
    If (Not IsFamily(GUICtrlRead($obj1c))) And (_GUICtrlComboBoxEx_GetCurSel($obj1)>0) Then
        $c=1
        GUICtrlSetBkColor($obj1c,0xFF0000)
    Else
        If _GUICtrlComboBoxEx_GetCurSel($obj1)==(_GUICtrlComboBoxEx_GetCount($obj1)-1) Then
            GUICtrlSetBkColor($obj1c,0xFFFFFF)
        Else
            If (_GUICtrlComboBoxEx_GetCurSel($obj1)>0) And (Not (GUICtrlRead($obj1c)==$objects[(_GUICtrlComboBoxEx_GetCurSel($obj1)*2-1)])) Then
                GUICtrlSetBkColor($obj1c,0xFFFF00)
            Else
                GUICtrlSetBkColor($obj1c,0xD4D0C8)
            EndIf
        EndIf
    EndIf  
    Return $c
EndFunc

;WM и вспомогательные
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $tInfo
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
    Case $obj1
        Switch $iCode
        Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW
            $tInfo = DllStructCreate($tagNMCOMBOBOXEX, $ilParam)
            Local $params=_GUICtrlComboBoxEx_GetItem ($obj1, DllStructGetData($tInfo, "Item"))
            If Not ($prevo1==$params[0]) Then
                Local $ocsi=_GUICtrlComboBoxEx_FindStringExact($obj1,$params[0])
                If ($ocsi>0) And ($ocsi<=$objects[0]/2) Then
                    GUICtrlSetStyle($obj1c,$ES_READONLY)
                    GUICtrlSetData($obj1c,$objects[($ocsi*2-1)])
                ElseIf $ocsi<=0 Then
                    GUICtrlSetStyle($obj1c,$ES_READONLY)
                    GUICtrlSetData($obj1c,"")
                Else
                    GUICtrlSetStyle($obj1c,$ES_LEFT)
                    GUICtrlSetData($obj1c,"")                    
                EndIf
                $prevo1=$params[0]
            EndIf
        EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
 EndFunc
 
Func WM_COMMAND($hWnd,$imsg,$iwParam,$ilParam)
    Local $nNotifyCode,$nID,$sText
    $nNotifyCode = BitShift($iwParam,16)
    $nID = BitAND($iwParam,0xFFFF)
    Switch $hWnd
    Case $g
        Switch $nID
        Case $obj1c
            If $nNotifyCode == $EN_CHANGE Then
                checkparams()
            EndIf
        EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc

Func _GetComboBoxEx($ilParam)
    $tInfo = DllStructCreate($tagNMCOMBOBOXEX, $ilParam)
    Local $aItem = _GUICtrlComboBoxEx_GetItem ($obj1, DllStructGetData($tInfo, "Item"))
    Return @lf & "--> hwndfrom:" & @tab & DllStructGetData($tInfo, "hWndFrom") & @LF & _
            "-->IDFrom:" & @tab & DllStructGetData($tInfo, "IDFrom") & @LF & _
            "-->Code:" & @tab & DllStructGetData($tInfo, "Code") & @LF & _
            "-->Mask:" & @tab & DllStructGetData($tInfo, "Mask") & @LF & _
            "-->Item:" & @tab & DllStructGetData($tInfo, "Item") & @LF & _
            "-->Text:" & @TAB & $aItem[0] & @LF & _
            "-->TextMax:" & @TAB & $aItem[1] & @LF & _
            "-->Indent:" & @TAB & $aItem[2] & @LF & _
            "-->Image:" & @TAB & $aItem[3] & @LF & _
            "-->SelectedImage:" & @TAB & $aItem[4] & @LF & _
            "-->OverlayImage:" & @TAB & $aItem[5] & @LF & _
            "-->Param:" & @TAB & $aItem[5]
EndFunc      

GUISetState(@SW_SHOW)
checkparams()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_MINIMIZE
            GUISetState(@SW_MINIMIZE,$g)
        Case $GUI_EVENT_RESTORE
            GUISetState(@SW_RESTORE,$g)
        Case $GUI_EVENT_MAXIMIZE
            GUISetState(@SW_MAXIMIZE,$g)
    EndSwitch
WEnd
Решение, предложенное Alofa:
Код:
#include <EditConstants.au3>
#include <Array.au3>
#include <GuiComboBox.au3>
#include <ComboConstants.au3>
#include <GuiComboBoxEx.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
#include <Constants.au3>
#include <GuiEdit.au3>
#include <String.au3>

$Debug_Ed = False
$Debug_CB = False

$winname = "123"
$gw = 1040
$gh = 640
$g = GUICreate($winname, $gw, $gh, -1, -1, BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX))
GUISetFont(11)

$cfgfile = "config.txt"

#CS
    ОФОРМЛЕНИЕ
#CE
$prevo1 = "Нет"
;Чтение
$objects = FileRead($cfgfile)
$objects = StringReplace($objects, @CRLF, " ")
$objects = StringSplit($objects, " ")
$oblist = "Нет|"
For $i = 2 To $objects[0] Step 2
    $oblist &= $objects[$i] & "|"
Next
$oblist &= "Другое"

;Параметры
$obj1 = _GUICtrlComboBoxEx_Create($g, $oblist, 600, 158, 150, 25 * ($objects[0] / 2 + 1), $CBS_DROPDOWNLIST)
$obj1c = GUICtrlCreateInput("", 800, 158, 120, 25)

#CS
    Начальные параметры
#CE
_GUICtrlComboBoxEx_SetCurSel($obj1, 0)

#CS
    ПРОГРАММНАЯ ЧАСТЬ
#CE

Global $k = 0

GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")

GUISetState(@SW_SHOW)
checkparams()
While 1
    $msg = GUIGetMsg()
    Switch $msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $GUI_EVENT_MINIMIZE
            GUISetState(@SW_MINIMIZE, $g)
        Case $GUI_EVENT_RESTORE
            GUISetState(@SW_RESTORE, $g)
        Case $GUI_EVENT_MAXIMIZE
            GUISetState(@SW_MAXIMIZE, $g)
    EndSwitch
WEnd

; ======= Ф У Н К Ц И И ========================================================================

;WM и вспомогательные
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iCode, $tNMHDR, $tInfo
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
    $iCode = DllStructGetData($tNMHDR, "Code")
    Switch $hWndFrom
        Case $obj1
            Switch $iCode
                Case $CBEN_GETDISPINFOA, $CBEN_GETDISPINFOW
                    $tInfo = DllStructCreate($tagNMCOMBOBOXEX, $ilParam)
                    Local $params = _GUICtrlComboBoxEx_GetItem($obj1, DllStructGetData($tInfo, "Item"))
                    If Not ($prevo1 == $params[0]) Then
                        Local $ocsi = _GUICtrlComboBoxEx_FindStringExact($obj1, $params[0])
                        If ($ocsi > 0) And ($ocsi <= $objects[0] / 2) Then
                            GUICtrlSetStyle($obj1c, $ES_READONLY)
                            GUICtrlSetData($obj1c, $objects[($ocsi * 2 - 1)])
                        ElseIf $ocsi <= 0 Then
                            GUICtrlSetStyle($obj1c, $ES_READONLY)
                            GUICtrlSetData($obj1c, "")
                        Else
                            GUICtrlSetStyle($obj1c, $ES_LEFT)
                            GUICtrlSetData($obj1c, "")
                        EndIf
                        $prevo1 = $params[0]
                    EndIf
                    checkparams()
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_NOTIFY

Func checkparams()
    Local $c = 0, $iColor, $iGetCurSel = _GUICtrlComboBoxEx_GetCurSel($obj1), $sInputRead = GUICtrlRead($obj1c)
    ; Не надо вызывать 100 раз одну и ту же функцию, чтобы узнать одно и то же значение
    Local Static $iColorPrev
    
    If (Not IsFamily($sInputRead)) And ($iGetCurSel > 0) Then
        $c = 1
        $iColor = 0xFF0000
    Else
        If $iGetCurSel = (_GUICtrlComboBoxEx_GetCount($obj1) - 1) Then
            $iColor = 0xFFFFFF
        Else
            If ($iGetCurSel > 0) And (Not ($sInputRead == $objects[($iGetCurSel * 2 - 1)])) Then
                $iColor = 0xFFFF00
            Else
                $iColor = 0xD4D0C8
            EndIf
        EndIf
    EndIf
    
    If $iColor <> $iColorPrev Then
        GUICtrlSetBkColor($obj1c, $iColor)
        $iColorPrev = $iColor
    EndIf
    Return $c
EndFunc   ;==>checkparams

Func IsFamily($s)
    If (StringRight($s, 2) == "вна") Or (StringRight($s, 3) == "вич") Or ($s == "") Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc   ;==>IsFamily

Ещё раз опишу задачу:
есть файл с парными данными, разделенными пробелом. Данные из 2 столбца добавляются в Listview, в который на первом месте находится вариант "Нет", а на последнем "Другое". Если выбирается вариант "Нет", то Input становится пустым и нередактируемым и меняет фоновый цвет на "нормальный". Если выбран один из вариантов из файла, то Input также становится нередактиремым, но в нем появляется соответствующая "пара", которая проходит проверку IsFamily(): если успешно - фоновый цвет становится "нормальным", если нет - красным. Если выбрано "Другое", Input становится редактиремым, фон меняется на белый в случае успешного прохождения проверки или красным в случае неудачи(это делается "налету").
В моем варианте список сильно лагает при раскрывании, а в варианте Alofa не происходит проверки Input. Насколько я понял, это из-за отсутствия взаимодействия WM_NOTIFY и Input. Собственно вопрос: как реализовать и то, и другое без лагов?
 

Вложения

  • config.txt
    424 байт · Просмотры: 1
Верх