Что нового

[Элементы GUI] Изменение Input в зависимости от выделенного значения Сombobox

nikita1996spb

Новичок
Сообщения
19
Репутация
0
Здравствуйте! Ищу возможность изменения значения в Input в зависимости от выделенного значения Сombobox(то есть, когда разворачивается список и я по нему пробегаю мышкой, значение в Input должно налету меняться). Также при изменении сходу выполняются некоторые проверки. Параметры попарно находятся в файле(также есть "Нет", при котором Input становится readonly, и "Другое", при котором становится редактируемым), вот то, чего я смог добиться, и файл с данными для примера:
Код:
#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

Проблемы следующие:
1) Можно считать, что не работает при запуске x64
2) При большом количестве параметров лагает: не снимается выделение в списке, перескакивает на другие значения в input(лично у меня при количестве в примере уже очень заметно)
Есть ли другие способы реализовать подобное?
 

Вложения

A

Alofa

Гость
"GUICtrlSetData()" для "$obj1c", в функции "WM_NOTIFY()", тоже вызывает уведомление "$EN_CHANGE" в "WM_COMMAND", вот и получается "винегрет" :smile:
WM Сообщения требуют довольно основательной фильтрации событий и это все лежит на ваших плечах.
Код:
#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
 
Автор
N

nikita1996spb

Новичок
Сообщения
19
Репутация
0
Alofa
Большое спасибо! Насколько я понял, Вы убрали WM_COMMAND, перекинув checkparams() в WM_NOTIFY, и переписали checkparams(): убрали повторение _GUICtrlComboBoxEx_GetCurSel в локальную переменную и сделали замену фонового цвета только при необходимости. Возник вопрос: почему лаги отражались на combobox, если "переизбыток событий" падал на изменение Input? Кстати, Ваша программа тоже не работает под x64: фон меняется, а значение и возможность редактирования Input - нет. Решение этой проблемы не особо нужно, но тоже хотелось бы знать, почему такая проблема возникает, и возможно ли решить и её.
 

joiner

Модератор
Локальный модератор
Сообщения
3 345
Репутация
576
редактирование невозможно из-за
Код:
GUICtrlSetStyle($obj1c, $ES_READONLY);установлен стиль "только чтение"
 
Автор
N

nikita1996spb

Новичок
Сообщения
19
Репутация
0
joiner
WM_NOTIFY при выборе последнего элемента Combobox выполняет
Код:
GUICtrlSetStyle($obj1c, $ES_LEFT)

в x86 работает, и поле становится редактируемым, а в x64 - нет.
 
Верх