Что нового

[Элементы GUI] GUI таблица элементов, передать двойной клик на фокус

Zergii

Новичок
Сообщения
5
Репутация
0
Здравствуйте.
Не получается передать двойной клик на элемент с фокусом ввода.

http://imageshost.ru/photo/312973/id2566045.html

Это интерфейс редактора "Creation Kit" для игры "Scyrim". В окне "Object Window" активен первый элемент,
пытаюсь передать ему двойной клик и открыть его:
Код:
WinWait("Object Window","Filter")
If WinActive("Object Window","Filter") Then
	Else
	WinActivate("Object Window","Filter")
EndIf
$hWnd = WinWait("Object Window","Filter")

$num=ControlListView($hWnd, "", "SysListView321", "GetSelectedCount")
Msgbox(0, "Объекты", "Выделено объектов " & $num, 1)

$sControl = ControlGetFocus($hWnd)

ControlClick("Object Window", "", $sControl, "left")
ControlClick("Object Window", "", $sControl, "left")


в $num четко указывает, что выбран 1 элемент, клики ему не передает :(
при этом, если посмотреть $sControl вроде пусто :(
 
Автор
Z

Zergii

Новичок
Сообщения
5
Репутация
0
Может быть я не прав и в данном случае нельзя использовать ControlClick т.к. отсутствует кнопка(контрол) которой я пытаюсь передать клики?
Может необходимо использовать MouseClick? Но как тогда получить позицию элемента по которому я хочу произвести клик? или как переместить мышь на этот элемент?
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Zergii [?]
если посмотреть $sControl вроде пусто
Если пусто, какому же контролу вы тогда клики отправляете?

А на Enter список, случайно, не реагирует? Попробуйте
Код:
ControlSend("Object Window", "Filter", "SysListView321", "{enter}")



Добавлено:
Сообщение автоматически объединено:

Можно ещё так попробовать
Код:
#include <GuiListView.au3>

$hwnd = ControlGetHandle("Object Window", "Filter", "SysListView321")
$index = _GUICtrlListView_FindInText($hwnd, "Bridge01")
_GUICtrlListView_ClickItem($hwnd, $index, "left", False, 2)
 
Автор
Z

Zergii

Новичок
Сообщения
5
Репутация
0
Если пусто, какому же контролу вы тогда клики отправляете?
Я думаю что в данном случае контролом должна выступать сама таблица, именно ее элементу я пытаюсь передать двойной клик.
А на Enter список, случайно, не реагирует? Попробуйте
Нет, в приведенном интерфейсе почти все элементы не реагируют на Enter, т.е. там где мне надо не реагируют :(
Обычно реагируют на непосредственный клик по выделенному объекту.



Добавлено:
Сообщение автоматически объединено:

Можно ещё так попробовать
Код: AutoIt [Выделить]
#include <GuiListView.au3>

$hwnd = ControlGetHandle("Object Window", "Filter", "SysListView321")
$index = _GUICtrlListView_FindInText($hwnd, "Bridge01")
_GUICtrlListView_ClickItem($hwnd, $index, "left", False, 2)

Огромное спасибо, так сработало.
Если я правильно понял, то используя в INDEX счетчик элементов таблицы я смогу перебирать все элементы таблицы просто по списку без указания имени конкретного элемента :smile:
Код:
_GUICtrlListView_ClickItem($hwnd, INDEX, "left", False, 2)
 

InnI

AutoIT Гуру
Сообщения
4,912
Репутация
1,429
Zergii [?]
используя в INDEX счетчик элементов таблицы я смогу перебирать все элементы таблицы просто по списку
Верно. Если вы знаете индекс элемента, то просто его подставляете. Первый (верхний) элемент имеет индекс 0.
 
Автор
Z

Zergii

Новичок
Сообщения
5
Репутация
0
Вот пока что получается. Окончательный вариант будет в теме.
Код:
#include <GuiListView.au3>

;-------------------------------------------------------------------
; если хотим заменить для объектов с "Has Distant LOD"
$bHasDistantLOD = False

;-------------------------------------------------------------------
; перебор элементов основного окна "Object Window"
; копирование значения ID элемента в буфер
; заполнение фильтра в окне "Cell View"
;-------------------------------------------------------------------

WinWait("Object Window","Filter")
If WinActive("Object Window","Filter") Then
    Else
    WinActivate("Object Window","Filter")
EndIf
$hWndSpisokObj = WinWait("Object Window","Filter")

;количество объектов в "Object Window"
$num=ControlListView($hWndSpisokObj,"","SysListView321", "GetItemCount")

; указатель на окно "Object Window"
$hWnd = ControlGetHandle("Object Window", "Filter", "SysListView321")
;$index = _GUICtrlListView_FindInText($hwnd, "Bridge01FallForestDirt01")

$i = 0
;$num = 3 ; для тестов
While $i < $num  ; цикл по "Object Window"
	_GUICtrlListView_ClickItem($hwnd, $i, "left", False, 2)
	$i = $i+1
	$hWndStatic = WinActivate("Static","ID") 	;
	; проверка на флаг "Has Distant LOD"
	If ($bHasDistantLOD = False) and (1 = ControlCommand($hWndStatic,"","[CLASS:Button; INSTANCE:6]","IsChecked", "")) Then
		ControlClick($hWndStatic,"","[CLASS:Button; TEXT:Cancel]");закрыли окно
		ContinueLoop							;
	EndIf
	$NameObj = ReturnNameObj($hWndStatic)		;
	$hWndCellView = WinActivate("Cell View") 	;
	ControlSetText($hWndCellView,"","[CLASS:Edit; INSTANCE:1]",$NameObj);фильтр


WEnd ; конец цикла по "Object Window"

;-------------------------------------------------------------------
;функция ищет окно "Static" и возвращает значение поля ID этого окна
;-------------------------------------------------------------------
Func ReturnNameObj($hWndStatic)
	$sReturnName = ControlCommand($hWndStatic,"","Edit1","GetSelected", "")
	ControlClick($hWndStatic,"","[CLASS:Button; TEXT:Cancel]")
	Return $sReturnName
EndFunc
;-------------------------------------------------------------------
 
Автор
Z

Zergii

Новичок
Сообщения
5
Репутация
0
Окончательный вариант программы(v.1_005).
Это моя первая программа на autoit. Хотелось бы услышать замечания опытных людей.
Тему закрою через пару дней.
Код:
#include <GuiListView.au3>
#include <GuiStatusBar.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

HotKeySet("{F8}", "TogglePause");поставить/снять паузу
HotKeySet("{F9}", "Terminate")

;-------------------------------------------------------------------
; global variable

$Version = "v.1_005"
Global $Paused

Global $bKillRender = True		; окно Render убираем, т.к. оно тормозит
Global $bHasDistantLOD = False 	; если хотим заменить для объектов с "Has Distant LOD"
Global $bTest = False			; если делаем тестовый прогон без изменений
Global $bSetIsFullLOD = True	; установить значение(если False то снять)
Global $bIsFirst = True			; в первом прогоне нет * в названиях следо-
								; вательно объекты со * можно пропускать
								; т.к. это уже обработанные объекты
Global $bOnlySelected = True	; только выделенные в таблице

Global $iSleepUseReport = 4000
Global $iSleepReference = 30


Global $NameObj =""				; имя объекта
Global $NameObjNew = 1			; повышение стабильности

; для строки состояния
Global $hGui = ""				; окно GUI
Global $hStatus = ""			; указатель на статусбар
Global $iWorkObj = 0			; обработано объектов
Global $iAllWorkObj = 0			; всего объектов
Global $iAll = 0				; всего объектов

$WinWaitDelay = 100
$MouseClickDelay = 15
Opt("WinWaitDelay", $WinWaitDelay)
Opt("MouseClickDelay", $MouseClickDelay)

;-------------------------------------------------------------------
; создание интерфейса
;-------------------------------------------------------------------

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)


$hGui = GUICreate("IF Full LOD chenge  "&$Version, 600, 400, -1, -1, $WS_OVERLAPPEDWINDOW) ; Создаёт окно в центре экрана
$buttonRun 			= GUICtrlCreateButton("Run",520,0,80,30)
$buttonKillRender 	= GUICtrlCreateButton("Kill Render",520,31,80,30)
$StartChBox = 10
$nCh1 				= GUICtrlCreateCheckbox("Kill Render window", 10, $StartChBox, 200, 20)
GUICtrlSetState($nCh1,$GUI_CHECKED)
$nCh2 				= GUICtrlCreateCheckbox("Handle objects ""Has Distant LOD""", 10, $StartChBox+20, 200, 20)
$nCh3 				= GUICtrlCreateCheckbox("do a test run without change", 10, $StartChBox+40, 200, 20)
$nCh4 				= GUICtrlCreateCheckbox("install / remove the flag ""IS Full LOD""", 10, $StartChBox+60, 200, 20)
GUICtrlSetState($nCh4,$GUI_CHECKED)
$nCh5 				= GUICtrlCreateCheckbox("This is the first launch", 10, $StartChBox+80, 200, 20)
GUICtrlSetState($nCh5,$GUI_CHECKED)
$nCh6 				= GUICtrlCreateCheckbox("Only a selected group", 10, $StartChBox+100, 200, 20)
GUICtrlSetState($nCh6,$GUI_CHECKED)
;$test = GUICtrlRead($nCh5)

$StartDelayInput = 160
GUICtrlCreateGroup ("delay interface(ms)",5, $StartDelayInput, 200, 110)
$Inp1 = GUICtrlCreateInput($iSleepUseReport,10, $StartDelayInput+20, 60, 20)
GUICtrlCreateLabel("Use Report window",80, $StartDelayInput+20, 100, 20)
$Inp2 = GUICtrlCreateInput($iSleepReference,10, $StartDelayInput+40, 60, 20)
GUICtrlCreateLabel("Reference window",80, $StartDelayInput+40, 100, 20)
$Inp3 = GUICtrlCreateInput($WinWaitDelay,10, $StartDelayInput+60, 60, 20)
GUICtrlCreateLabel("Window Wait Delay",80, $StartDelayInput+60, 100, 20)
$Inp4 = GUICtrlCreateInput($MouseClickDelay,10, $StartDelayInput+80, 60, 20)
GUICtrlCreateLabel("Mouse Click Delay",80, $StartDelayInput+80, 100, 20)

GUICtrlCreateLabel("To interrupt the script press F9",20, 300, 200, 20)
GUICtrlCreateLabel("To pause the script press F8",20, 320, 200, 20)

GUICtrlCreateLabel("Creation kit loads cells of the world during the script runs. x86 system will fail when your Creation Kit allocates more then 2GB ROMtr. Use 64bit version. 64bit version does not exist:(",250, 100, 200, 100)
GUICtrlCreateLabel("Setup settings for delays. Lager value is more stable. I used 4000 for ""Use Report window"" for my PC config:: i5 -3570 (4.2) / 32GB (launch editor and gameres is a ramdisk)",250, 180, 200, 100)
GUICtrlCreateLabel("Use minimal RenderWin value. Also you can turn it off.",250, 250, 200, 100)



$hStatus = _GUICtrlStatusBar_Create($hGui)
_GUICtrlStatusBar_SetText($hStatus,"Processing object :")

WinSetTrans($hGui,"",220)
WinSetOnTop($hGui,"",1)
GUISetState() ; показывает созданное окно
;Sleep(2000)

;	GlobalRun()

While 1
	$msg = GUIGetMsg()
	Select
		Case $msg = $GUI_EVENT_CLOSE
			Exit
		Case $msg = $buttonRun

			If GUICtrlRead($nCh1) = 1 Then $bKillRender = True
			If GUICtrlRead($nCh1) <> 1 Then $bKillRender = False
			If GUICtrlRead($nCh2) = 1 Then $bHasDistantLOD = True
			If GUICtrlRead($nCh2) <> 1 Then $bHasDistantLOD = False
			If GUICtrlRead($nCh3) = 1 Then $bTest = True
			If GUICtrlRead($nCh3) <> 1 Then $bTest = False
			If GUICtrlRead($nCh4) = 1 Then $bSetIsFullLOD = True
			If GUICtrlRead($nCh4) <> 1 Then $bSetIsFullLOD = False
			If GUICtrlRead($nCh5) = 1 Then $bIsFirst = True
			If GUICtrlRead($nCh5) <> 1 Then $bIsFirst = False
			If GUICtrlRead($nCh6) = 1 Then $bOnlySelected = True
			If GUICtrlRead($nCh6) <> 1 Then $bOnlySelected = False

			$iSleepUseReport = GUICtrlRead($Inp1,1)
			$iSleepReference = GUICtrlRead($Inp2,1)
			$WinWaitDelay = GUICtrlRead($Inp3,1)
			$MouseClickDelay = GUICtrlRead($Inp4,1)

			GlobalRun()
			_GUICtrlStatusBar_SetText($hStatus,"Processing object : "&$iAll)
		Case $msg = $buttonKillRender
			WinRenderKill()
	EndSelect

WEnd
GUIDelete()
Exit


;-------------------------------------------------------------------
; перебор элементов основного окна "Object Window"
; копирование значения ID элемента в буфер
; заполнение фильтра в окне "Cell View"
;-------------------------------------------------------------------
Func GlobalRun()

	StableRender()
	Send("{7}")
	Send("{8}")
	Send("{U}")
	;Send("{M}")
	Send("{ALT+T}")


	WinWait("Object Window","Filter")
	If WinActive("Object Window","Filter") Then
		Else
		WinActivate("Object Window","Filter")
	EndIf
	$hWndSpisokObj = WinWait("Object Window","Filter")

	;количество объектов в "Object Window"
	$num=ControlListView($hWndSpisokObj,"","SysListView321", "GetItemCount")
	$iSelect = ControlListView($hWndSpisokObj,"","SysListView321", "GetSelected",1)

	; указатель на окно "Object Window"
	$hWnd = ControlGetHandle("Object Window", "Filter", "SysListView321")

	$i = 0
	While $i < $num  ; цикл по "Object Window"

		If ($bOnlySelected = True) and (0 = SelectedItem($i,$iSelect)) Then
			$i = $i+1
			ContinueLoop							;
		EndIf

		_GUICtrlListView_ClickItem($hwnd, $i, "left", False, 2)

		$hWndStatic = WinActivate("Static","ID") 	;
		; проверка на флаг "Has Distant LOD"
		If ($bHasDistantLOD = False) and (1 = ControlCommand($hWndStatic,"","[CLASS:Button; INSTANCE:6]","IsChecked", "")) Then
			WinClose($hWndStatic)					;закрыли окно
			$i = $i+1
			ContinueLoop							;
		ElseIf ($bHasDistantLOD = True) and (1 = ControlCommand($hWndStatic,"","[CLASS:Button; INSTANCE:6]","IsChecked", "")) Then
			ControlCommand($hWndStatic,"","[CLASS:Button; INSTANCE:6]","UnCheck", "")
			WinClose($hWndStatic)
		EndIf
		$NameObj = ReturnNameObj($hWndStatic)		;
		$hWndCellView = WinActivate("Cell View") 	;
		ControlSetText($hWndCellView,"","[CLASS:Edit; INSTANCE:1]",$NameObj);фильтр

		$iAllWorkObj = ControlListView($hwnd,"","","GetText",$i,2)
		$iWorkObj = 0
		_GUICtrlStatusBar_SetText($hStatus,"Processing object : "&$NameObj&" | all objects : "&$iAllWorkObj&"  | executed objects :")
		_GUICtrlListView_ClickItem($hwnd, $i, "right", False, 1)

		Send("{UP}")
		Send("{ENTER}") ;выбрали "Use Info" и открылось окно "Use Report:"

		ProcessingUseReport() ;перебор элементов окна "Use Report:" и т.д.

		$i = $i+1
	WEnd ; конец цикла по "Object Window"

EndFunc ;GlobalRun()

;-------------------------------------------------------------------
;функция ищет окно "Static" и возвращает значение поля ID этого окна
;-------------------------------------------------------------------
Func ReturnNameObj($hWndStatic)

	$sReturnName = ControlCommand($hWndStatic,"","Edit1","GetSelected", "")
	WinClose($hWndStatic)
	Return $sReturnName

EndFunc
;-------------------------------------------------------------------

;-------------------------------------------------------------------
;функция ищет окно "Use Report:"
;перебор элементов этого окна
;передает управление в окно "Cell View"
;-------------------------------------------------------------------
Func ProcessingUseReport()

	$hWndUseReport = WinActivate("Use Report:") 	;
	$numUseReport=ControlListView($hWndUseReport,"","[CLASS:SysListView32; INSTANCE:2]", "GetItemCount")
	$hWndUseReportHandle = ControlGetHandle("Use Report:", "", "[CLASS:SysListView32; INSTANCE:2]")

	$iUseReport = 0
	While $iUseReport < $numUseReport

		_GUICtrlListView_ClickItem($hWndUseReportHandle, $iUseReport, "left", False, 2)

		StableRender()
		Sleep($iSleepUseReport)
		WinRenderKill()

		ProcessingCellView() ; перебор элементов окна "Cell View"
		$iUseReport = $iUseReport + 1
	WEnd

	WinClose($hWndUseReport)

EndFunc ;ProcessingUseReport()

;-------------------------------------------------------------------
;функция ищет окно "Cell View"
;перебор элементов этого окна
;вызывает через свойство объекта "Edit" окно "Reference"
;
;-------------------------------------------------------------------
Func ProcessingCellView()

	$hWndCellView = WinActivate("Cell View") 	;
	$numCellView=ControlListView($hWndCellView,"","[CLASS:SysListView32; INSTANCE:1]", "GetItemCount")
	$hWndCellViewHandle = ControlGetHandle("Cell View", "", "[CLASS:SysListView32; INSTANCE:1]")

	$iCellView = 0
	While $iCellView < $numCellView

		; список объектов может включать другие объекты
		; т.е. фильтр не является "точным" и требуется проверка
		$sText = ControlListView($hWndCellViewHandle,"","","GetText",$iCellView,0)
		If StringInStr($sText," *")>0 Then

			If ($bSetIsFullLOD = True) and ($bIsFirst = True) Then
				; при первом прогоне нет * в названиях, если есть значит уже обработали
				$iCellView = $iCellView + 1
				ContinueLoop
			EndIf

			$sText = StringLeft($sText,StringLen($sText)-2)
		EndIF
		If ($NameObj <> $sText) Then
			$iCellView = $iCellView + 1
			ContinueLoop
		EndIf

		_GUICtrlListView_ClickItem($hWndCellViewHandle, $iCellView, "right", False, 1)

		Send("{DOWN}")
		Send("{DOWN}")
		Send("{ENTER}") ;выбрали "Edit" и открылось окно "Reference"

		ProcessingReference()
		$iCellView = $iCellView + 1
	WEnd

EndFunc ;ProcessingCellView()

;-------------------------------------------------------------------
;функция ищет окно "Reference"
;меняет флаг "IS Full LOD"
;-------------------------------------------------------------------
Func ProcessingReference()

	$hWndReference = WinActivate("Reference") 	;

	If ($bTest = False) Then
		If ($bSetIsFullLOD = True) and (0 = ControlCommand($hWndReference,"","[CLASS:Button; INSTANCE:12]","IsChecked", "")) Then
			ControlCommand($hWndReference,"","[CLASS:Button; INSTANCE:12]","Check", "")
		ElseIf ($bSetIsFullLOD = False) and (1 = ControlCommand($hWndReference,"","[CLASS:Button; INSTANCE:12]","IsChecked", "")) Then
			ControlCommand($hWndReference,"","[CLASS:Button; INSTANCE:12]","UnCheck", "")
		EndIF

		$iAll = $iAll + 1
		$iWorkObj = $iWorkObj + 1
		_GUICtrlStatusBar_SetText($hStatus,"Processing object : "&$NameObj&" | all objects : "&$iAllWorkObj&"  | executed objects :"&$iWorkObj)
		Sleep($iSleepReference)
		ControlClick($hWndReference,"","[CLASS:Button; INSTANCE:13]","left",1)
		Return
	EndIf
	WinClose($hWndReference)

EndFunc ;ProcessingReference()

;-------------------------------------------------------------------
;функция безусловно прерывает работу скрипта
;-------------------------------------------------------------------
Func Terminate()

    Exit

EndFunc

;-------------------------------------------------------------------
;функция убивает окно рендера когда нам надо
;но убийство не происходит т.к. это невозможно
;однако анимация окна не происходит
;-------------------------------------------------------------------
Func WinRenderKill()

	If $bKillRender = True Then
		WinWait("[Class:MonitorClass]")
		$hWndRender = WinActivate("[Class:MonitorClass]")
		WinKill($hWndRender)
	EndIf

EndFunc

;-------------------------------------------------------------------
;функция изменяет настройки окна "Render"
;-------------------------------------------------------------------
Func StableRender()

    WinWait("[Class:MonitorClass]")
	$hWndRender = WinActivate("[Class:MonitorClass]")
	Send("{T}")
	;Sleep($iSleepUseReport)

EndFunc

;-------------------------------------------------------------------
;функция ставит скрипт на паузу
;-------------------------------------------------------------------
Func TogglePause()
    $Paused = NOT $Paused
	$sS = _GUICtrlStatusBar_GetText($hStatus,0)
	_GUICtrlStatusBar_SetText($hStatus,"Pause")
    While $Paused
        sleep(1000)
    WEnd
	_GUICtrlStatusBar_SetText($hStatus,$sS)
EndFunc

;-------------------------------------------------------------------
; определает есть данный номер в стоке или нет
;-------------------------------------------------------------------
Func SelectedItem($i,$iSelect)

	$sString = $iSelect
	While StringInStr($sString,"|") <> 0
		If StringLeft($sString,(StringInStr($sString,"|")-1)) = $i Then
			Return 1
		EndIf
		$sString = StringTrimLeft($sString,(StringInStr($sString,"|")))
	WEnd
	If $sString = $i Then
		Return 1
	EndIf
	Return 0

EndFunc
 
Верх