Что нового

[Элементы GUI] При работе скрипта мерцает курсор

Sampler

Новичок
Сообщения
5
Репутация
0
Прошу помочь с непонятным поведением курсора при отрисовке GUI.

Скрипит постоянно нажимает {CTRL}+{INS} и {DOWN}, копируя столбец таблицы и записывая их в файл.

Если использовать «Send ("^{INS}", 0)», то не возможно нажать кнопку «Стоп». Из-за нажатий {DOWN} смещается фокус.
Если же использовать «ControlSend($title, "", "", "{DOWN}")»,то курсор при наведении на GUI-форму скрипта постоянно мигает часиками.
Такое поведение курсора замечено только, если GUI-форма скрипта расположена поверх таблицы Excel. Если же сделать так чтобы GUI-форма скрипта и окно с таблицей не пересекались все вроде нормально.

Ps: я не использую <Excel.au3> т.к. Еxcel эмулирует Java интерфейс программы из которой я получаю данные. Поведение курсора, что на Java окне, что на Excel одинаковое.
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

#Region Interface
$frm_main = GUICreate("Еxample", 149, 50, 250, 218, -1, BitOR($WS_EX_TOPMOST,$WS_EX_WINDOWEDGE))
$btn_start = GUICtrlCreateButton("Старт", 0, 0, 49, 25)
$btn_stop = GUICtrlCreateButton("Стоп", 75, 0, 73, 25)
GUISetState(@SW_SHOW)
#EndRegion

Opt("GUIOnEventMode", 1)
Opt("SendKeyDelay", 10)
Opt("SendKeyDownDelay", 10)

GUISetOnEvent($GUI_EVENT_CLOSE, "Close_click")
GUICtrlSetOnEvent($btn_start, "Start_click")
GUICtrlSetOnEvent($btn_stop, "Stop_click")

Global $stop_flag = 1 ; флаг останова
Global $cur_step = 0 ; текущий шаг
Global $stroki = 1000 ; число строк в столбеце excel для копирования
; просто большое число, чтобы успеть нажать stop
Global $flag_onTop = 262144
Global $title =  "Microsoft Excel"

While 1
	if $stop_flag= 0 Then Initial() ;проверяем начальниые условия

While ($stop_flag = 0)
	$file = FileOpen("Test.txt", 2)   ; открыть файл для чтения и для записи. удалить прежнее содержимое
	$cur_step =0
	While (($stop_flag = 0) And ($cur_step <= $stroki))
		; не могу нажать кнопку стоп. смещается фокус из-за постоянных нажатий стрелки "вниз"
		;Send ( "^{INS}", 0 )
		;Send ( "{DOWN}", 0 )
		;при полноэкранном excel курсор часто мигает часами
		ControlSend($title, "", "", "^{INS}")
		ControlSend($title, "", "", "{DOWN}")
		$tmp = ClipGet()  & @CRLF
		FileWrite ( $file, $tmp)
		$cur_step += 1
	WEnd
	FileClose($file)
	$stop_flag = 1
WEnd
Sleep(1000)  ; Idle around
WEnd

Func Close_click()
	$stop_flag=1
	Sleep(100)  ;даю время доработать циклу и закрыть файл
	Exit
EndFunc

Func Start_click()
	$stop_flag=0
EndFunc

Func Stop_click()
	$stop_flag = 1
EndFunc

Func Initial()
If WinWait($title,"",1) = 0 Then
	$stop_flag = 1
	MsgBox($flag_onTop,"Ошибка", "Запустите excel и  выделите 1-ю ячейку")
Else
	WinActivate ( $title )
EndIf
EndFunc
 

Futurebear

Знающий
Сообщения
29
Репутация
6
У меня появлялась схожая проблема, попробуйте вместо While использовать http://autoit-script.ru/autoit3_docs/functions/AdlibRegister.htm

Не гарантирую что вашем случае поможет, но у меня проблема исчезала.

У меня ваш скрипт работает, курсор меняет вид только на документе Excel, эт из-за того что идет обработка данных.
При выполнении скрипта окно GUI не октивно, для проверки активируй его мышью.
Как вариант попробуйте прописать курсор
Код:
GUISetCursor (2)
 
Автор
S

Sampler

Новичок
Сообщения
5
Репутация
0
При выполнении скрипта окно GUI не октивно, для проверки активируй его мышью.
:ok:Спасибо за подсказку с активацией окна.

Механизм мерцания я понял следующим образом. Есть три объекта:
1. активное окно Excel
2. окно GUI TOPMOST
3. курсор мыши, который тоже должен быть поверх всех окон.

Если с окнами все понятно, то курсор периодически проваливается под форму GUI на активное окно (возможно, как-то связано с ControlSend). В этот же момент еще и происходит копирование работа, поэтому появляются часики.
Потом курсор опять возвращается на GUI TOPMOST и так мельтешит до окончания работы скрипта.

Изменить форму курсора командой: GUISetCursor (2) не получится, т.к. курсор меняет вид не на GUI-форме, а уже под ней.

Имхо AdlibRegister портит карму.

Чтобы этого избежать активирую GUI форму сразу после активации листа Excel. Тогда курсор не проваливается под форму. После окончания работы скрипта для удобства возвращаю фокус Excel.
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPI.au3>

#Region Interface
$frm_main = GUICreate("Еxample", 149, 50, 250, 218, -1, BitOR($WS_EX_TOPMOST,$WS_EX_WINDOWEDGE))
$btn_start = GUICtrlCreateButton("Старт", 0, 0, 49, 25)
$btn_stop = GUICtrlCreateButton("Стоп", 75, 0, 73, 25)
GUISetState(@SW_SHOW)
#EndRegion

Opt("GUIOnEventMode", 1)
Opt("SendKeyDelay", 10)
Opt("SendKeyDownDelay", 10)

GUISetOnEvent($GUI_EVENT_CLOSE, "Close_click")
GUICtrlSetOnEvent($btn_start, "Start_click")
GUICtrlSetOnEvent($btn_stop, "Stop_click")

Global $stop_flag = 1 ; флаг останова
Global $cur_step = 0 ; текущий шаг
Global $stroki = 1000 ; число строк в столбеце excel для копирования
; просто большое число, чтобы успеть нажать stop
Global $flag_onTop = 262144
Global $title =  "Microsoft Excel"

While 1
    if $stop_flag= 0 Then Initial() ;проверяем начальниые условия

While ($stop_flag = 0)
    $file = FileOpen("Test.txt", 2)   ; открыть файл для чтения и для записи. удалить прежнее содержимое
    $cur_step =0
    While (($stop_flag = 0) And ($cur_step <= $stroki))
        ; не могу нажать кнопку стоп. смещается фокус из-за постоянных нажатий стрелки "вниз"
        ;Send ( "^{INS}", 0 )
        ;Send ( "{DOWN}", 0 )
        ;при полноэкранном excel курсор часто мигает часами
        ControlSend($title, "", "", "^{INS}")
        ControlSend($title, "", "", "{DOWN}")
        $tmp = ClipGet()  & @CRLF
        FileWrite ( $file, $tmp)
		$cur_step += 1
    WEnd
    FileClose($file)
    $stop_flag = 1
	WinActivate ( $title ); ДОБАВЛЕНО. Для удобства использования возвращаю фокус приложению.
WEnd
Sleep(1000)  ; Idle around
WEnd

Func Close_click()
    $stop_flag=1
    Sleep(100)  ;даю время доработать циклу и закрыть файл
    Exit
EndFunc

Func Start_click()
    $stop_flag=0
EndFunc

Func Stop_click()
    $stop_flag = 1
EndFunc

Func Initial()
If WinWait($title,"",1) = 0 Then
    $stop_flag = 1
    MsgBox($flag_onTop,"Ошибка", "Запустите excel и  выделите 1-ю ячейку")
Else
    WinActivate ( $title )
	WinActivate ( "Еxample" ) ; ДОБАВЛЕНО. Антимерцание курсора
EndIf
EndFunc


Info: Из-за плотности потока нажатий трудно достучатся до Windows окон. Но т.к. кнопка "Стоп" работает, то это не сильно мешает.

Ps: Завтра перепроверю на java интерфейсе и помечу тему решенной.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,323
Sampler
Попробуйте добавить в Ваш код:
Код:
;...
#include <WinAPIEx.au3>
;...
Global $hCursor
;Yashied
$hCursor = _WinAPI_CopyCursor(_WinAPI_LoadCursor(0, 32650))
_WinAPI_SetSystemCursor(_WinAPI_LoadCursor(0, 32512), 32650, 1)

OnAutoItExitRegister('_OnExit')

#cs
	Ваш код
#ce

Func _OnExit()
	If $hCursor Then
		_WinAPI_SetSystemCursor($hCursor, 32650)
	EndIf
EndFunc   ;==>_OnExit
 
Автор
S

Sampler

Новичок
Сообщения
5
Репутация
0
madmasles не работает.

Мой способ оказался тоже не рабочим. По какой-то причине данные при смене фокуса (активации gui мышкой или через WinActivate) перестают копироваться. Т.е. Excel-лист вниз ползет (кнопка {DOWN}), а {CTRL}+{INS} Excel либо не получает, либо не отрабатывает.

Т.о. придется в процедуре первичной инициализации растаскивать окна источника данных и GUI скрипта. Ну или смирится с мерцающим курсором.

Пичалька ((((.
 
Верх