Что нового

[Элементы GUI] Передча Hex-чисел в Slider

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Есть GUI с input и slider. Хочется что бы они работали с данными Hex (утилита для работы с цветом :smile:), получилось реализовать только передачу данных от slider в input, и то простым конвертированием, а вот как заставить input обрабатывать 16-тиричные числа ума не приложу :-\. Вот пример.
Код:
#include <EditConstants.au3>
#include <SliderConstants.au3>
#include <UpdownConstants.au3>
#include <WindowsConstants.au3>

$hGUI = GUICreate("Hex slider", 200, 400)

GUIRegisterMsg($WM_VSCROLL, "WM_HVSCROLL")

$in = GUICtrlCreateInput("0", 20, 10, 48, 21)
GUICtrlSetLimit($in, 3)
$upd = GUICtrlCreateUpdown($in, $UDS_ARROWKEYS)
GUICtrlSetLimit($upd, 255, 0)
$sl = GUICtrlCreateSlider(20, 31, 48, 350, $TBS_BOTH+$TBS_VERT)
GUICtrlSetLimit($sl, 255)

$hSlider = GUICtrlGetHandle($sl)

GUISetState()

While 1
	Switch GUIGetMsg()
		Case -3
			Exit
		Case $in
			$count = GUICtrlRead($in)
			If $count = "" Then
				$count = 0
				GUICtrlSetData($in, $count)
			ElseIf $count > 255 Then
				$count = 255
				GUICtrlSetData($in, $count)
			EndIf
				GUICtrlSetData($sl, $count)
		Case $sl
			$count = GUICtrlRead($sl)
			GUICtrlSetData($in, Hex($count, 2))
	EndSwitch
WEnd

Func WM_HVSCROLL($hWndGUI, $MsgID, $WParam, $LParam)
	Switch $LParam
		Case $hSlider
			$count = GUICtrlRead($sl)
			GUICtrlSetData($in, Hex($count, 2))
	EndSwitch
EndFunc


PS. И еще вопросик, как заставить slider реагировать на каждый символ, введенный в input? Т.е. я ввел первую цифру - ползунок slidera сдвинулся, ввел очередную цифру - еще сдвинулся.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Redline [?]
...а вот как заставить input обрабатывать 16-тиричные числа ума не приложу...
Так же простым конвертированием.

Код:
$Str = 'FF'
$Num = Number('0x' & $Str)
ConsoleWrite($Num & @CR)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 242
Репутация
2 344
Redline [?]
как заставить input обрабатывать 16-тиричные числа
Не очень понятно, зачем Input'у обрабатывать эти числа? или нужно просто при изменений значения (элемент Up/Down) заменять на Hex?

Тогда примерно так:
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
#include <SliderConstants.au3>
#include <UpdownConstants.au3>
#include <WindowsConstants.au3>

$hGUI = GUICreate("Hex slider", 200, 400)

$Input = GUICtrlCreateInput("0", 20, 10, 48, 21)
GUICtrlSetLimit($Input, 3)

$UpDown = GUICtrlCreateUpdown($Input, $UDS_ARROWKEYS)
GUICtrlSetLimit($UpDown, 255, 0)

$Slider = GUICtrlCreateSlider(20, 31, 48, 350, $TBS_BOTH+$TBS_VERT)
GUICtrlSetLimit($Slider, 255)

GUIRegisterMsg($WM_VSCROLL, "WM_HVSCROLL")
GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func WM_COMMAND($hWnd, $nMsg, $wParam, $lParam)
    Local $nNotifyCode = BitShift($wParam, 16)
    Local $nID = BitAND($wParam, 0xFFFF)
    Local $hCtrl = $lParam
    
    Switch $nID
        Case $Input
            Switch $nNotifyCode
				Case $EN_UPDATE
					GUIRegisterMsg($WM_COMMAND, "")
					GUIRegisterMsg($WM_VSCROLL, "")
					
                    Local $iCount = GUICtrlRead($Slider)
                    Local $iTmp = Number("0x" & GUICtrlRead($Input))
                    
					If $iTmp >= $iCount Then
						$iCount += 1
					ElseIf $iTmp <= $iCount Then
						$iCount -= 1
					EndIf
					
                    If $iCount = "" Then
                        $iCount = 0
                    ElseIf $iCount > 255 Then
                        $iCount = 255
                    EndIf
                    
                    GUICtrlSetData($Input, Hex($iCount, 2))
                    GUICtrlSetData($Slider, $iCount)
					
					GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
					GUIRegisterMsg($WM_VSCROLL, "WM_HVSCROLL")
            EndSwitch
    EndSwitch
    
    Return $GUI_RUNDEFMSG
EndFunc

Func WM_HVSCROLL($hWndGUI, $MsgID, $WParam, $LParam)
	GUIRegisterMsg($WM_COMMAND, "")
	GUIRegisterMsg($WM_VSCROLL, "")
	
	Local $iCount = GUICtrlRead($Slider)
	GUICtrlSetData($Input, Hex($iCount, 2))
	
	GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")
	GUIRegisterMsg($WM_VSCROLL, "WM_HVSCROLL")
EndFunc
 
Автор
Redline

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
CreatoR сказал(а):
Не очень понятно, зачем Input'у обрабатывать эти числа? или нужно просто при изменений значения (элемент Up/Down) заменять на Hex?

Тогда примерно так:
Нужно чтобы была возможность ввести в input 16-ричнное число, и slider смог на это адекватно среагировать. Похоже надо делать по наводке Yashied. За up/down отдельное спасибо.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Redline [?]
Нужно чтобы была возможность ввести в input 16-ричнное число...
Числа не бывают 16-ричные, число это мера чего-либо. "16-ричное" - это только способ представления числа, а в каком "-ричном" виде его представить не имеет особого значения. Здесь все зависит от поставленной задачи (как удобнее). В твоем случае нужно просто конвертировать туда-сюда и все. Дабы не усложнять основной цикл, лучше все это организовать через сообщение WM_COMMAND (как предложил CreatoR). Единственное, что я бы не стал делать, это постоянно регистрировать сообщения - GUIRegisterMsg(). IMHO не хорошо это. Лучше ввести глобальный запирающий флаг и проверять его в начале функции.

OffTopic:
16-ричное представление числа очень удобно только потому, что любые две цифры определяют ровно один байт.
 
Автор
Redline

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Yashied сказал(а):
Числа не бывают 16-ричные, число это мера чего-либо. "16-ричное" - это только способ представления числа, а в каком "-ричном" виде его представить не имеет особого значения. Здесь все зависит от поставленной задачи (как удобнее). В твоем случае нужно просто конвертировать туда-сюда и все. Дабы не усложнять основной цикл, лучше все это организовать через сообщение WM_COMMAND (как предложил CreatoR). Единственное, что я бы не стал делать, это постоянно регистрировать сообщения - GUIRegisterMsg(). IMHO не хорошо это. Лучше ввести глобальный запирающий флаг и проверять его в начале функции.

OffTopic:
16-ричное представление числа очень удобно только потому, что любые две цифры определяют ровно один байт.
Покопаюсь-поковыряюсь в ваших скриптах и выложу результат, что бы тема была решена. С GUIRegisterMsg мне сложновато работать :wacko:, выдираю куски из ваших скриптов для своих нужд, их работа понятна только частично, где бы взять по ним информацию на русском?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Redline [?]
Покопаюсь-поковыряюсь в ваших скриптах и выложу результат, что бы тема была решена. С GUIRegisterMsg мне сложновато работать , выдираю куски из ваших скриптов для своих нужд, их работа понятна только частично, где бы взять по ним информацию на русском?
Каких именно скриптов?
 
Автор
Redline

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Yashied сказал(а):
Каких именно скриптов?
Ну например вот этот - чтобы в off topic не уйти :smile:
http://autoit-script.ru/index.php?topic=404.msg2689#msg2689

А вот другой пример работы с GUIRegisterMsg (взят с форума озона 2007 года :D) - здесь просто темный лес, что-то куда то пишется/читается, а откуда Creator (это его функция) узнал что и где храниться? Вобщем нужен мастер-класс по работе с GUIRegisterMsg или документация.
[box title=off topic]
Код:
GUIRegisterMsg($WM_GETMINMAXINFO, "_WM_GETMINMAXINFO")
; Функция для ограничения (минимального) размера окна гуи
Func MY_WM_GETMINMAXINFO($hWnd, $Msg, $wParam, $lParam)
    Local $MINMAXINFO = DllStructCreate("int;int;int;int;int;int;int;int;int;int",$lParam)
    Local $MINGuiX = 508, $MINGuiY = 368
    DllStructSetData($MINMAXINFO, 7, $MINGuiX)
    DllStructSetData($MINMAXINFO, 8, $MINGuiY)
    Return 0
EndFunc
[/box]
 
Автор
Redline

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Долго тестировал пример скрипта от Creatora - возникли вопросы:
- в Input невозможно ввести что-либо
- UpDown некорректно работает - конвертирование из Dec в Hex и обратно не всегда производится правильно(?) Что бы понять о чем я - поставьте ползунок Slidera например на позицию "CC", а дальше кликните на UpDown - вверх или вниз - не имеет значения - ползунок будет ползти только вверх :wacko:.

To Yashied поясни пожалуйста про "глобальный запирающий флаг" - я так понял это альтернатива постоянному обнулению GUIRegisterMsg внутри функций?

Похоже нужно вводить несколько GUIRegisterMsg для скролла($WM_VSCROLL) UpDown и Slider, для изменений($WM_COMMAND >> $EN_UPDATE) в Input, а для клика по UpDown не знаю какой :-\.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
На самом деле все не так уж и сложно. Нужно просто разобраться кикие и в каком порядке следуют сообщения... Я максимально упростил следующий код, надеюсь ты в нем разберешься. Up/Down сделаешь сам, если конечно нужно.

Код:
#Include <EditConstants.au3>
#Include <GUIConstantsEx.au3>
#Include <GUIEdit.au3>
#Include <SliderConstants.au3>
#Include <WindowsConstants.au3>

Opt('MustDeclareVars', 1) 

Global $hForm, $Msg, $Input, $Label, $Dummy, $Slider, $hSlider
Global $Value = 0xEA

$hForm = GUICreate('MyGUI', 140, 350)
$Input = GUICtrlCreateInput(Hex($Value, 2), 25, 20, 30, 19, BitOR($ES_AUTOHSCROLL, $ES_CENTER, $ES_MULTILINE))
$Slider = GUICtrlCreateSlider(20, 50, 40, 280, BitOR($TBS_BOTH, $TBS_VERT, $WS_TABSTOP))
$hSlider = GUICtrlGetHandle(-1)
GUICtrlSetLimit(-1, 0xFF, 0)
GUICtrlSetData(-1, 255 - $Value)
$Dummy = GUICtrlCreateDummy()
$Label = GUICtrlCreateLabel('', 80, 282, 40, 40)
GUICtrlSetBkColor(-1, BitShift($Value, -16))
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
GUIRegisterMsg($WM_VSCROLL, 'WM_VSCROLL')
GUISetState()

While 1
	$Msg = GUIGetMsg()
	Switch $Msg
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Dummy
			GUICtrlSetBkColor($Label, BitShift($Value, -16))
	EndSwitch
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)

	Local $CtrlID = BitAND($wParam, 0xFFFF), $ID = BitShift($wParam, 16)
	Local $Data, $Pos, $Left, $Right, $Num, $Hex, $Str

	Switch $hWnd
		Case $hForm
			Switch $ID
				Case $EN_UPDATE
					Switch $CtrlID
						Case $Input
							$Data = GUICtrlRead($CtrlID)
							$Pos = _GUICtrlEdit_GetSel($CtrlID)
							$Left = StringLeft($Data, $Pos[1])
							$Right = StringTrimLeft($Data, $Pos[1])
							$Hex = StringRegExpReplace($Left, '[^[:xdigit:]]', '')
							$Pos = $Pos[1] - (StringLen($Left) - StringLen($Hex))
							$Str = StringLeft(StringUpper($Hex) & StringTrimLeft($Right, (StringLen($Right) > 1)  * StringLen($Hex)), 2)
							$Num = Number('0x' & $Str)
							If $Num <> $Value Then
								$Value = $Num
								GUICtrlSetData($Slider, 255 - $Value)
								GUICtrlSendToDummy($Dummy)
							EndIf
							If StringCompare($Data, $Str, 1) Then
								GUICtrlSetData($CtrlID, $Str)
								_GUICtrlEdit_SetSel($CtrlID, $Pos, $Pos)
							EndIf
					EndSwitch
				Case $EN_KILLFOCUS
					Switch $CtrlID
						Case $Input
							$Data = GUICtrlRead($CtrlID)
							$Str = Hex($Value, 2)
							If StringCompare($Data, $Str, 1) Then
								GUICtrlSetData($CtrlID, $Str)
							EndIf
					EndSwitch
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_COMMAND

Func WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)
	Switch $hWnd
		Case $hForm
			Switch $iMsg
				Case $WM_VSCROLL
					Switch $lParam
						Case $hSlider
							$Value = 255 - GUICtrlRead($Slider)
							GUICtrlSetData($Input, Hex($Value, 2))
							GUICtrlSendToDummy($Dummy)
					EndSwitch
			EndSwitch
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_VSCROLL
 
Автор
Redline

Redline

AutoIT Гуру
Сообщения
506
Репутация
369
Yashied [?]
На самом деле все не так уж и сложно. Нужно просто разобраться кикие и в каком порядке следуют сообщения... Я максимально упростил следующий код, надеюсь ты в нем разберешься. Up/Down сделаешь сам, если конечно нужно.
Спасибо - очень помогло! Убрал GUICtrlCreateDummy() - установку GUICtrlSetBkColor сделал внутри самих функций. А для чего сделана реакция на $EN_KILLFOCUS в Input?

Попытался сделать GUIRegisterMsg($WM_VSCROLL, 'WM_VSCROLL'), но работает не всегда правильно, за то можно спокойно вводить значения в Input :smile:.
Код:
Func WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam)
    Switch $hWnd
        Case $hForm
            Switch $iMsg
                Case $WM_VSCROLL
                    Switch $lParam
                        Case $hSlider
                            $Value = 255 - GUICtrlRead($Slider)
                            GUICtrlSetData($Input, Hex($Value, 2))
							GUICtrlSetBkColor($Label, BitShift($Value, -16))
						Case $hUpDown
							Local $iSl = 255 - GUICtrlRead($Slider)
							Local $iIn = Number('0x' & GUICtrlRead($Input))

							ConsoleWrite(' READ: Slider - ' & $iSl & '|Input - ' & $iIn & @CRLF) ; если держать UpDown нажатым или пользоваться колесиком мыши в нем, то видно как $iIn может "вырасти" выше 255
							If $iSl > $iIn Then
								$iSl -= 1
							ElseIf $iSl < $iIn Then
								$iSl += 1
							EndIf

							If $iSl < 0 Then
								$iSl = 0
							ElseIf $iSl > 255 Then
								$iSl = 255
							EndIf
							ConsoleWrite('WRITE: Slider - ' & $iSl & '|Input - ' & Hex($iSl, 2) & @CRLF)
							GUICtrlSetData($Input, Hex($iSl, 2))
							GUICtrlSetData($Slider, 255 - $iSl)
							GUICtrlSetBkColor($Label, BitShift($iSl, -16))
					EndSwitch
            EndSwitch
    EndSwitch
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_VSCROLL


Что-то не так опять сделал? :-\
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 711
Redline [?]
А для чего сделана реакция на $EN_KILLFOCUS в Input?
Форматирует значение в Input (две цифры). Например A -> 0A и т.д. Так приятнее и нагляднее.
 
Верх