Войти

Показать полную графическую версию : [архив - Часть 2] AutoIt скрипты


Страниц : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [31] 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50

amel27
15-10-2007, 04:46
Creat0R
чтобы отображалась граница растягиваемого окна (только граница, без содержимого окна) »ИМХО от WM_SETREDRAW толку мало - оно не отличается от @SW_LOCK, тебе же нужна рамка... Может для установки размера использовать специальное полупрозрачное окно?
чтобы не сфокусированный элемент возвращала, а тот над которым проводим мышкой? (типа _ControlGetHovered()) »попробуй так:Func _ControlGetHovered()
Local $ret = DllCall("user32.dll", "int", "WindowFromPoint", _
"long", MouseGetPos(0), _
"long", MouseGetPos(1) )
Return $ret[0]
EndFunc

Maza Faka
15-10-2007, 11:16
Oldschool
я хочу прочитать эту линию
Ну так и считывай её: ;)

$text = ControlListView("Drop_Gui", "", "SysListView321", "GetText", 10) ;число 10 означает индекс элемента, счёт идёт с нуля
MsgBox(0, "GetList", $text)

Creat0R
15-10-2007, 21:26
amel27,
ИМХО от WM_SETREDRAW толку мало - оно не отличается от @SW_LOCK
То же самое мне на оф. форуме сказали :)
Может для установки размера использовать специальное полупрозрачное окно?
На своё же удивление, я написал функцию (http://www.autoitscript.com/forum/index.php?s=&showtopic=55024&view=findpost&p=417711) для отката состояния “Отображать содержимое окна при перетаскивании”, это всего лишь для демонстрации того, что именно мне требуется сделать (видимо мой Английский ещё сыроват, ну или до кое кого медленно доходит ;) )...

И вот на основе этого примера (полагаю), мне подкинули идею (а точнее готовый пример с решением), ведь на момент растягивания/смещения окна, можно отключать режим “Отображать содержимое окна при перетаскивании”, а потом восстанавливать старое состояние (как я только сам до этого не додумался)...

#include <GUIConstants.au3>

Global Const $WM_EXITSIZEMOVE = 0x232
Global Const $WM_SYSCOMMAND = 0x0112
Global Const $SC_MOVE = 0xF010
Global Const $SC_SIZE = 0xF000

Global $Old_Param

$Gui = GUICreate("GUI", 200, 400, -1, -1, $WS_SIZEBOX)
GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE")
GUIRegisterMsg($WM_SYSCOMMAND, "WM_SYSCOMMAND")

$Button = GUICtrlCreateButton("Button", 50, 100, 100, 21)

GUISetState(@SW_SHOW)

While 1
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd

Func WM_SYSCOMMAND($hWnd, $Msg, $wParam, $lParam)
Switch BitAND($wParam, 0xFFF0)
Case $SC_MOVE, $SC_SIZE
;Local Const $SPI_SETDRAGFULLWINDOWS = 37
;Local Const $SPI_GETDRAGFULLWINDOWS = 38
;Local Const $SPIF_SENDWININICHANGE = 2
Local $tBool = DllStructCreate("int")
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 38, "int", 0, "ptr", DllStructGetPtr($tBool), "int", 0)
$Old_Param = DllStructGetData($tBool, 1)
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", 0, "ptr", 0, "int", 2)
EndSwitch
EndFunc

Func WM_EXITSIZEMOVE()
DllCall("user32.dll", "int", "SystemParametersInfo", "int", 37, "int", $Old_Param, "ptr", 0, "int", 2)
EndFunc

попробуй так:
То что нужно! Спасибо!
Я так понял тут возвращается идентификатор контроля? мне просто нужно сравнивать с элементами моего ГУИ, а там как известно обычная нумерация элементов, я конечно использовал GuiCtrlGetHandle, а на возвращённое значение от функции _ControlGetHovered() использовал Hwnd, но вот хотелось бы узнать, возможно ли конвертировать этот самый идентификатор в то же число, как и возвращает элемент GUI? (чтобы можно было просто использовать стандартные функци для чтения данных от GUI, типа GuiCtrlRead()).

-AAA-
15-10-2007, 23:15
Всем привет. У меня такая задача. Нужно в одной папке просмотреть все вложенные подпапки (количество подкаталогов, количество уровней вложенности и иена подкаталогов заранее неизвестны). Как с помощью AutoIT получить список подкаталогов данного каталога?

Creat0R
16-10-2007, 00:01
-AAA-,
Как с помощью AutoIT получить список подкаталогов данного каталога?
Ранее приводилась функция (http://forum.oszone.net/archive/index.php/t-60616-p-21.html) (_DirListToArray() - в самом конце).

amel27
16-10-2007, 03:39
Creat0R
возможно ли конвертировать этот самый идентификатор в то же число, как и возвращает элемент GUI? »Func _ControlIDGetHovered()
Local $ret = DllCall("user32.dll", "int", "WindowFromPoint", _
"long", MouseGetPos(0), _
"long", MouseGetPos(1) )
$ret = DllCall("user32.dll", "int", "GetDlgCtrlID", "hwnd", $ret[0])
Return $ret[0]
EndFunc

Maza Faka
16-10-2007, 12:15
Интересная штука WinAPI :)
Поначалу абсолютно не понимал, что к чему, но благодаря amel27, вроде начал понимать.
Примеры того, что смог сделать сам:

Создание файла (текстового):

Global Const $lCreate_RW = 0x00000000

Func FileCreate()
DllCall("kernel32.dll", "int", "_lcreat", "str", @ScriptDir & "\test.txt", "int", $lCreate_RW)
If Not @error Then MsgBox(64, "Success", "File test.txt created in " & @ScriptDir)
EndFunc


Активирование окон:

#include <GUIConstants.au3>

$gui = GuiCreate("Test", 200, 100)
$button = GUICtrlCreateButton("Child", 10, 70, 50, 25)
$child = GUICreate("Dummy", 300, 200)
$ChildButton = GUICtrlCreateButton("Parent", 10, 70, 50, 25)

GUISetState(@SW_HIDE, $child)
GUISetState(@SW_SHOW, $gui)

While 1
$msg = GUIGetMsg(1)

Select
Case $msg[0] = $GUI_EVENT_CLOSE And $msg[1] = $gui
ExitLoop
Case $msg[0] = $GUI_EVENT_CLOSE And $msg[1] = $child
GUISetState(@SW_HIDE, $child)
Case $msg[0] = $button
If Not GetWinState() Then
GUISetState(@SW_SHOW, $child)
Else
SetActive($child)
EndIf
Case $msg[0] = $ChildButton
SetActive($gui)
EndSelect
WEnd

Func SetActive($hwnd)
DllCall("user32.dll", "hwnd", "SetActiveWindow", "hwnd", $hwnd)
EndFunc

Func GetWinState()
Return BitAND(WinGetState($child), 2)
EndFunc

Maza Faka
16-10-2007, 16:05
-AAA-
Нужно в одной папке просмотреть все вложенные подпапки
Можно так:


#include <File.au3>
#include <Array.au3>

Global $DirArray[1]
Dim $sPath = "c:\windows"

$GetDirs = DirList($sPath)
_ArrayDisplay($DirArray)

Func DirList($path)
Local $sRet = ""
Local $sDir = _FileListToArray($path, "*", 2)

If IsArray($sDir) And $sDir[0] > 0 Then
For $i = 1 To UBound($sDir) - 1
_ArrayAdd($DirArray, $sDir[$i])
$sRet = DirList($sPath &"\"& $sDir[$i])
Next
EndIf
EndFunc

amel27
17-10-2007, 11:12
Можно так: »
идея понятна, но ты очевидно поторопился ;), итак:

- у тебя очепятка ($path vs $sPath);
- имя каталога заносится в массив без пути;
- проверка локального массива через IsArray() необязательна (особенность For);
- проверка глобального массива IsArray() желательна (особенность _ArrayAdd())
- зачем $sRet ?
- наконец, повторюсь: чтобы избежать путаницы при повторном использовании функций с глобальными переменными их нужно объявлять в параметрах через ByRef.
#include <File.au3>
#include <Array.au3>

Global $DirArray[1]
_ArrayDirListAdd($DirArray, "c:\windows")
_ArrayDisplay($DirArray,'')

Func _ArrayDirListAdd (ByRef $aGDir, $sPath = @ScriptDir)
Local $aLDir = _FileListToArray($sPath, "*", 2)
For $i = 1 To UBound($aLDir) - 1
If IsArray($aGDir) Then _ArrayAdd($aGDir, $sPath &"\"& $aLDir[$i])
_ArrayDirListAdd ($aGDir, $sPath &"\"& $aLDir[$i])
Next
EndFunc

Maza Faka
17-10-2007, 14:06
amel27
- у тебя очепятка ($path vs $sPath);
Вообще-то сделано специально, теперь вижу, что без смысла.

- имя каталога заносится в массив без пути;
Поторопился :)

- проверка локального массива через IsArray() необязательна (особенность For);
Учту на будущее.

- проверка глобального массива IsArray() желательна (особенность _ArrayAdd())
А зачем постоянно проверять массив $aGDir ведь он уже обьявлен массивом?

- зачем $sRet ?
Помнишь пример который ты постил для меня:

MsgBox(64, "Done", _FindFile("icqlite.exe", @ProgramFilesDir))

Func _FindFile($sFile, $sPath)
Local $sRetPath='', $sFullPath
Local $hSearch = FileFindFirstFile($sPath & "\*.*"), $sName = FileFindNextFile($hSearch)
While @error=0 And $sRetPath = ''
$sFullPath = $sPath &'\'& $sName
If $sName = $sFile Then $sRetPath = $sPath
If StringInStr(FileGetAttrib($sFullPath), "D") Then $sRetPath = _FindFile($sFile, $sFullPath)
$sName = FileFindNextFile($hSearch)
WEnd
FileClose($hSearch)
Return $sRetPath
EndFunc


Теперь к вопросу о возвращаемом значении… Во-первых, функция не является рекурсивной, так как нарушено одно из правил рекурсии: возвращаемое функцией значение должно передаваться по всей цепочке рекурсивных вызовов, у тебя же значение, возвращаемое WritePathToReg() вообще игнорируется… из этого имеем два следствия:
- дальше первого уровня подкаталогов функция и не пытается заглянуть, если бы файл лежал глубже чем на один уровень функция бы его не нашла;
- функция, осуществившая рекурсивный вызов не знает о результате этого вызова… поэтому даже если файл найден (как в твоем случае) на возвращаемое значение это никак не повлияет и результат будет зависеть только от содержимого текущего каталога ($path).

один из возможных вариантов,
ключевой переменной, передаваемой между рекурсивными вызовами является $sRetPath

- наконец, повторюсь: чтобы избежать путаницы при повторном использовании функций с глобальными переменными их нужно объявлять в параметрах через ByRef.
А зачем постоянно передавать глобальный массив по ссылке?

Creat0R
17-10-2007, 19:51
amel27,
Спасибо.

По поводу рекурсии...
Всё это хорошо, но на склько известно, есть ограничение на количество вызовов подфункции? можно как то его обойти?

Creat0R
17-10-2007, 20:26
Попутный вопрос: Как можно получить число не больше указанного, если как второе число передаёся большее число, но при этом, если всё же передаётся меньшее число, нужно вернуть именно его...

Я это делаю так (надеялся может есть какой-то быстрый метод, используя всякие BitShift/And/Or и т.п.):

Func BitNumber($Nmber, $Value)
If $Value >= $Nmber Then Return $Nmber
Return $Value
EndFunc

Diamond
18-10-2007, 11:50
Maza Faka,
А зачем постоянно передавать глобальный массив по ссылке? »
...имхо ByRef - более универсальный подход.
Если массив глобальный то ByRef по большому счёту не нужен. Ну а если например нужно передать локальный массив из другой функции...? Т.е тебе каждый раз придётся корректировать эту функцию в зависимости от потребности... ;)

amel27
18-10-2007, 12:08
Maza Faka
Помнишь пример который ты постил для меня »помню, там не было глобальных данных, поэтому рукурсивная функция возвращала результат ($ret) который передавался "по цепочке" вызовов. В твоем случае в этом нет необходимости.

зачем постоянно передавать глобальный массив по ссылке? »к примеру если кто другой будет использовать функцию в своей программе со своим именем массива... что проще: поменять имя по всему тексту функции (об этом еще нужно вспомнить!) или указать свое имя в параметре?

Creat0R
есть ограничение на количество вызовов подфункции? можно как то его обойти? »в общем случае нет... в данном случае это некритично - не встречал каталога на глубине 384 уровня ;) ... особенно если учесть, что весь путь к файлу обычно не больше 255 символов :)

может есть какой-то быстрый метод »
это и есть самый быстрый, можно сделать короче (одной строчкой) но считаться будет дольше "IF"

используя всякие BitShift/And/Or и т.п
только если $Nmber есть степень двойки, т.е. в двоичном виде есть последовательность "единичек"

Creat0R
18-10-2007, 12:12
Может кому пригодится (или может кто мне покажет более правильное/простое решение), вот функция для получения числа разделённого запятыми (когда то на батнике пробовал решить, получилось - но кривовато, а тут совсем другое дело :) )...


$MyNumber = 212347525 ;> 212,347,525

MsgBox(64, "Внимание", "Конвертировали обычное число: " & @LF & @LF & _
$MyNumber & @LF & @LF & _
"В строку (числовую) разделённую запятыми: " & @LF & @LF & GetComasNumber($MyNumber))

Func GetComasNumber($iNumber)
$iNumber = Number($iNumber)
If $iNumber <= 1000 Then Return $iNumber

Local $iLength = StringLen($iNumber)
Local $RetStr = '', $iN

For $i = 1 To $iLength
$iN = StringMid($iNumber, $i, 1)
If IsInt(($iLength - $i) / 3) And ($iLength - $i) / 3 > 0 Then
$RetStr &= $iN & ','
Else
$RetStr &= $iN
EndIf
Next
Return $RetStr
EndFunc

amel27,
в общем случае нет
А жаль :( - Я как раз написал собственный редактор реестра, он правда медленно работает, но полагаю что даже если у кого то и хватит терпения дождаться окончания считывания всех строчек с реестра (у меня не хватает :biggrin: ), то он увидит не полный список, или скрипт выпадет с ошибкой о рекурсивном вызове подфункции.

можно сделать короче (одной строчкой)
О, как это одной строчкой сделать? (скорость не критична в моём случае, проверяться будет вне цикла).

только если $Nmber есть степень двойки, т.е. в двоичном виде есть последовательность "единичек"
У меня число (в этом конкретном случае), всегда 15, т.е нужно проверить, если исло болльше чем 15, то вернуть 15, если меньше, то вернуть то которое меньше (это подходит под критерии сказанного? :) я просто в математике совсем не силён)... понимаю что решать подобные задачи для конкретного случая нет особого смысла, но мне больше для расширения своего круга знании, вот такие мелочи иногда помагают решить серъёзную проблему.

amel27
19-10-2007, 08:34
Creat0R
А жаль - Я как раз написал собственный редактор реестралюбую рекурсию можно так или иначе заменить на циклы... вот вариант решения задачи (http://forum.oszone.net/post-662153-1619.html) для списка каталогов без использования рекурсии:#include <File.au3>
#include <Array.au3>

Global $DirArray[1]
_ArrayAddFileListSubDir($DirArray, "c:\windows")
_ArrayDisplay($DirArray,'')

Func _ArrayAddFileListSubDir (ByRef $aGDir, $sPath = @ScriptDir)
Local $i = UBound($aGDir), $aLDir = _FileListToArray($sPath, "*", 2)
_ArrayAddFileList($aGDir, $sPath)
While $i < UBound($aGDir)
_ArrayAddFileList($aGDir, $aGDir[$i])
$i+=1
WEnd
EndFunc

Func _ArrayAddFileList(ByRef $aGDir, $sPath)
Local $i, $aLDir = _FileListToArray($sPath, "*", 2)
If UBound($aGDir, 0)=1 And UBound($aLDir, 0)=1 Then
For $i = 1 To $aLDir[0]
_ArrayAdd($aGDir, $sPath & '\' & $aLDir[$i])
Next
EndIf
EndFunc
как это одной строчкой сделать?арифметический вариант _IIF() :) :$res = ($Value<$Nmber)*$Value + Not($Value<$Nmber)*$Nmber
мне больше для расширения своего круга знаниив такой формулировке одними битовыми операциями все равно не обойтись, поэтому получится еще длиннее... вот если бы $value с каждым шагом изменялось на 1, то отфиксировать переход "границы" можно контролем одного бита... или можно "обрезать" часть старших разрядов... ну и т.д.

NikLok
22-10-2007, 23:10
Корифеи! Кто нибуть реализовал просмотр сети?

Creat0R
22-10-2007, 23:57
amel27,
любую рекурсию можно так или иначе заменить на циклы
Ну тут как мне кажется, не так циклы как вызов подфункции играют главную роль.
И кстати, а почему While $i < UBound($aGDir) а не простое использоване For? :shuffle: вроде как разницы нет?

арифметический вариант _IIF()
Супер! Спасибо!

NikLok,
Кто нибуть реализовал просмотр сети?
Полагаю что да.

amel27
23-10-2007, 05:01
Creat0R
не так циклы как вызов подфункции играют главную рольвыделение функций лишь вопрос удобства - можно объединить и в одну :)
почему While $i < UBound($aGDir) а не простое использоване For?потому что заранее неизвестно количество элементов массива - они добавляются по ходу прохождения... кстати, у этого способа есть один недостаток по сравнению с рекурсией - результирующий массив не отсортирован по каталогам/подкаталогам

Кто нибуть реализовал просмотр сети?Полагаю что да.вы о чем? :blink:

Creat0R
23-10-2007, 05:30
amel27,
выделение функций лишь вопрос удобства - можно объединить и в одну
Точно, я не присмотрелся поглубже в работу функции...

у этого способа есть один недостаток по сравнению с рекурсией - результирующий массив не отсортирован по каталогам/подкаталогам
Хм... в некоторых случаях довольно весомый недостаток :(.

вы о чем
Если бы я знал, ответил бы наверное более подробно :lol:




© OSzone.net 2001-2012