1

Тема: AHK: Вызов окна из класса

Добрый день. Есть такая проблема:

i := 0
y := 0

A1:=new test(i)

gui, Show, h200 w300, S7
SetTimer, MAIN, 1000


MAIN:
i++
y:=y+2*i
A1.update(i)
ToolTip, %i%
Return

class test
{
    __new(x) {
        gui, add, text,cff0000 hwndTx1, text000
        this.Tx1 := Tx1
        Gui, Add, text,  gtest.TEST hwndV1, TEXTXXXX

    }
    update(aa) {
        GuiControl,, % this.Tx1, %aa%
        GuiControl,, % this.V1, %A_WorkingDir%\pic\Val-Grey.emf
    }
    TEST() {
        ;gui, 2:Submit
        Gui, 2:add, text, hwndTT44, text
        this.TT44 := TT44
        ;this.TT44:=TT44
    
        GuiControl, 2:, % this.TT44, %y%
        ;gui, 2:Submit
        ;this.TEST:=TEST
        gui, 2:show, h150 w150
    
    }
}


GuiEscape:
GuiClose:
gui destroy
ExitApp

Нужно сделать так что бы по нажатию на второй текст ""TEXTXXX" выводилось окно с изменяющейся переменной "y". Сколько пробовал, нифига не получается. Ну и соответственно это нужно сделать через класс. Как это сделать правильно?

2 (изменено: KusochekDobra, 2018-03-26 16:56:36)

Re: AHK: Вызов окна из класса

У Вас переменная "y" - не глобальна и её не видно в контексте TEST(). Так же, Вы добавляете новое текстовое поле с одним и тем же именем переменной, в которую помещаете новый идентификатор и тут же его используете. Используйте его же без присваивания в поле объекта.


i := 0
Global y := 0

A1:=new test(i)

gui, Show, h200 w300, S7
SetTimer, MAIN, 1000


MAIN:
i++
y:=y+2*i
A1.update(i)
ToolTip, %i%
Return

class test
{
	__new(x) {
		gui, add, text,cff0000 hwndTx1, text000
		this.Tx1 := Tx1
		Gui, Add, text,  gtest.TEST hwndV1, TEXTXXXX
	}
	update(aa) {
		GuiControl,, % this.Tx1, %aa%
		GuiControl,, % this.V1, %A_WorkingDir%\pic\Val-Grey.emf
	}
	TEST() {
		Gui, 2:add, text, hwndTT44, text
		;this.TT44:=TT44

		GuiControl,, % TT44, %y%
		gui, 2:show, h150 w150
	}
}


GuiEscape:
GuiClose:
gui destroy
ExitApp

UPD:
Или сразу добавляйте в новую строку при создании:


TEST() {
		Gui, 2:add, text,,% y
		gui, 2:show, h150 w150
	}

UPD 2:
Имейте так же ввиду, что в Вашем примере, вызываемый метод "test.TEST()" вызывается как статичный и не имеет отношения к объекту "A1", следовательно, обращения к "this" в его контексте, будут пустыми.

3 (изменено: Raven, 2018-03-26 17:52:58)

Re: AHK: Вызов окна из класса

Ну так вся фишка в том что бы в вызываемом по клику окне, были динамические значения. Что бы текст менялся динамично, вместе со значением переменной "y". Не подскажете как это сделать? И как сделать метод "test.TEST()" динамическим?

UPD1 Вроде получилось. Правильно ли будет сделать класс таким???

class test
{
    __new(x) {
        gui, add, text,cff0000 hwndTx1, text000
        this.Tx1 := Tx1
        Gui, Add, text,  gtest.TEST hwndV1, TEXTXXXX
        this.V1 := V1
        Gui, 2:add, text, hwndTT44, XXXXXXXX
        this.TT44 := TT44
    }
    update(aa, bb) {
        GuiControl,, % this.Tx1, %aa%
        GuiControl,, % this.V1, %bb%
        GuiControl, 2:, % this.TT44, %bb%
    }

    TEST() {
		gui, 2:show, h150 w150
	}
}

4 (изменено: KusochekDobra, 2018-03-26 19:24:10)

Re: AHK: Вызов окна из класса

А почему именно класс? И для чего Вы передаёте в конструктор значение, которое не используете?
Что Вам мешает сделать переменную, в которую сохраняется дескриптор контрола, тоже глобальной?


i := 0
Global y := 0, TT44

A1:=new test(i)

gui, Show, h200 w300, S7
SetTimer, MAIN, 1000


MAIN:
i++
y:=y+2*i
A1.update(i, y)
ToolTip, %i%
Return

class test
{
    __new(x) {
        gui, add, text,cff0000 hwndTx1, text000
        this.Tx1 := Tx1
        Gui, Add, text,  gtest.TEST hwndV1, TEXTXXXX
        this.V1 := V1
        Gui, 2:add, text, hwndTT44, XXXXXXXX
        ;this.TT44 := TT44
    }
    update(aa, bb) {
        GuiControl,, % this.Tx1, %aa%
        GuiControl,, % this.V1, %bb%
    }

    TEST() {
        GuiControl,, % TT44, %y%
		gui, 2:show, h150 w150
	}
}


GuiEscape:
GuiClose:
gui destroy
ExitApp

UPD:
Или присваивайте из объекта вызов своего метода, прикручивая его метке через ObjBindMethod():


i := 0
Global y := 0

A1:=new test(i)

gui, Show, h200 w300, S7
SetTimer, MAIN, 1000

MAIN:
i++
y:=y+2*i
A1.update(i, y)
ToolTip, %i%
Return

class test
{
    __new(x) {
        gui, add, text,cff0000 hwndTx1, text000
        this.Tx1 := Tx1
        Gui, Add, text, hwndV1, TEXTXXXX
        this.V1 := V1
		
		callMe := ObjBindMethod(new this, "TEST")
		GuiControl +g, Static2, %callMe%
		
        Gui, 2:add, text, hwndTT44, XXXXXXXX
        this.TT44 := TT44
    }
    update(aa, bb) {
        GuiControl,, % this.Tx1, %aa%
        GuiControl,, % this.V1, %bb%
    }

    TEST() {
        GuiControl,, % this.TT44, %y%
		gui, 2:show, h150 w150
	}
}


GuiEscape:
GuiClose:
gui destroy
ExitApp

5 (изменено: Raven, 2018-03-27 10:10:30)

Re: AHK: Вызов окна из класса

Да, в конструкторе закралась ошибка, при переносе из моего скрипта, забыл убрать переменную. Ну мне требуется множество однотипных объектов. И я хочу получать по клику на объект, окно, с внутренними и внешними переменными объекта. Ну локальные переменные и глобальные. Плюс ко всему этому содержимое обоих окон должно быть динамическим.
И да, по вашему коду:
Первое - состояние не динамичное. Меняется только по нажатию на объект.
Второе - выбивает ошибка Autohotkey

+ открыть спойлер

Сигнатура проблемы:
  Имя события проблемы: APPCRASH
  Имя приложения: AutoHotkey.exe
  Версия приложения: 1.1.27.6
  Отметка времени приложения: 5a5dbb5d
  Имя модуля с ошибкой: AutoHotkey.exe
  Версия модуля с ошибкой: 1.1.27.6
  Отметка времени модуля с ошибкой: 5a5dbb5d
  Код исключения: c00000fd
  Смещение исключения: 00092ccd
  Версия ОС: 6.3.9600.2.0.0.256.4
  Код языка: 1049
  Дополнительные сведения 1: 50d1
  Дополнительные сведения 2: 50d1ec6ad1dca16b7cd85b7dfa8842dc
  Дополнительные сведения 3: 1603
  Дополнительные сведения 4: 1603f04ff56e0f776fef7f0e8619b498

Ознакомьтесь с заявлением о конфиденциальности в Интернете:
  http://go.microsoft.com/fwlink/?linkid=280262

Если заявление о конфиденциальности в Интернете недоступно, ознакомьтесь с его локальным вариантом:
  C:\Windows\system32\ru-RU\erofflps.txt

6

Re: AHK: Вызов окна из класса

Тесты проводили, не глядя перенося содержимое примеров в свой сценарий? У меня работают оба примера, сделанных, между прочим, при минимальных правках Вашего. И, судя по всему, Вы не совсем точно понимаете, с чем имеете дело, от чего не верно и ставите задачу.
Напомню, Вам было нужно отображение содержимого переменной "y" в GUI №2, при клике по второму текстовому полю в GUI №1 и Вы привели пример, код которого демонстрирует эту попытку. Далее, не имея ничего более информативного, все выводы опирались только на это.

Давайте попробуем разобраться. Мы выяснили, что переменная "y" объявленная и модифицируемая вне класса "test", не может быть видна в его контексте, а так же, что метод "TEST()" класса "test", вызывается в Вашем примере как статичная функция, с указанием полного пути, от чего в своих вызовах обращается к пустому содержимому контекста "this", из-за принадлежности к другому объекту, содержимое которого не имеет запрашиваемых полей. Добавить возможность, ради которой задуман описанный функционал можно сразу присваивая новому текстовому полю содержимое "y" при каждом создании, либо, как в следующих примерах объявив переменную "TT44" глобальной, от чего вызов "test.TEST()" будет иметь доступ и к переменной "y" и "TT44" содержащей дескриптор текстового поля второго GUI, либо, вызывать метод "TEST()" по клику, как часть экземпляра "A1", как, вероятно и предполагалось в самом начале.

"Всё гениальное - просто." (с)
А Вы, перегружаете свой код, оборачивая в класс, из-за чего вынуждены искать решения проблем, с которыми можно было бы вообще не сталкиваться. По крайней мере, на это намекает пример, из которого совсем не очевидна выгода такого подхода.

Попробуйте описать пример поподробнее, или приведите весь код, который описывает Вашу задачу.

7

Re: AHK: Вызов окна из класса

Ну хорошо. Опишу задачу. Дело все в том что я пишу простую систему визуализации технологических процессов. Связь с контроллером специальной библиотекой. Связь то я наладил, теперь нужно как то это все визуализировать. Соответственно бочки, насосы клапана и иже с ними я решил сделать классами, которые потом просто инициализировать объектами и обновлять методом update(). Мне это показалось более рациональным, чем делать функцию которая будет обновлять нужные значения в GUI.
А данная задача, которую я поставил в данной теме, нужна для того что бы по нажатию на объект (допустим мотор/насос), у меня появлялось окно, в котором будут отображаться свойства именно данного объекта. Ну и соответственно потом приделать кнопочки, которые будут управлять данным оборудованием. Как то так.

8

Re: AHK: Вызов окна из класса

Организовать код можно по разному, но раз уж вам так хочется ООП, желательно основательно разобраться как это работает.
А создание таймера на update я бы перенес в конструктор.

9

Re: AHK: Вызов окна из класса

Поддерживаю.

В моём понимании, класс полезен для тонкой настройки поведения и описывает за раз одну сущность, отделяя "мух и котлеты" друг от друга. Таким образом, у Вас, по идее, должно быть описание устройств из компонентов, описанных классами, а GUI - всего лишь интерфейс, в который транслируется их состояние. Иными словами, управляющая оболочка работает с экземплярами классов, которые глобальны в контексте сценария, чем удобны в доступе, а не является их частью, из-за чего возникают трудности, как в первом примере.

Например:


#SingleInstance, Force
#NoEnv

Global currVol := 1000	; текущая наполненность бочек(для примера)
allBarrels := {"Красная бочка": New Barrel("Красная бочка", 1000
					, "Синий насос")
			  ,"Зелёная бочка": New Barrel("Зелёная бочка", 2000
					, "Игрушечный насос", 10, 10)}

Gui,1: Add, Text,Border gShowMyBarrel,Красная бочка
Gui,1: Add, Text,x+5 Border gShowMyBarrel,Зелёная бочка
Gui,1: Show,,Бочки
return
ShowMyBarrel:
	if (showed)
		Gui,2: Destroy
	Gui,2: Add, Text,,Бочка:
	Gui,2: Add, Text,x+5,% allBarrels[A_GuiControl].name
	Gui,2: Add, Text,xm y+5,Макс объём:
	Gui,2: Add, Text,x+5,% allBarrels[A_GuiControl].maxVol
	Gui,2: Add, Text,xm y+5,Заполненность:
	Gui,2: Add, Text,x+5,% allBarrels[A_GuiControl].currentVol "%"
	Gui,2: Add, Text,xm y+5,Состояние:
	Gui,2: Add, Text,x+5,% allBarrels[A_GuiControl].state
	Gui,2: Add, GroupBox,xm y+5 w150 h100,Насос
	
	Gui,2: Add, Text,xm+5 yp+15,Наименование:
	Gui,2: Add, Text,xm+5 y+2,% allBarrels[A_GuiControl].oPump.name
	
	pwrOn := allBarrels[A_GuiControl].oPump.state
	Gui,2: Add, Radio,xm+5 y+15 von Checked%pwrOn%,Вкл
	pwrOff := !pwrOn
	Gui,2: Add, Radio,x+5 voff Checked%pwrOff%,Выкл
	
	forw := allBarrels[A_GuiControl].oPump.direction
	Gui,2: Add, Radio,xm+5 y+5 vforward Group Checked%forw%,Вперёд
	bckw := !forw
	Gui,2: Add, Radio,x+5 vbackward Checked%bckw%,Назад
	
	Gui,2: Show,,ЦПУ
	showed := true
return
2GuiClose:
	Gui,2: Destroy
	showed := false
return
GuiClose:
	ExitApp

Class Barrel {
	__New(bName, bMaxVol, pName, pPower := 1000, pMaxPower := 1000, pState := false) {
		this.name       := bName
		this.maxVol     := bMaxVol
		this.currentVol := this.CheckMyself(currVol)
		this.state      := this.currentVol < 100 ? "Наполняется" : "Полная"
		this.oPump      := New Pump(pName, pPower, pMaxPower, pState)
	}
	CheckMyself(vol) {
		; диагностика
		; провеить текущее наполнение
		; вернуть процент заполненности бочки
		return vol * 100 // this.maxVol
	}
	ToFill() {
		this.state := "Наполняется"
		(!this.oPump.direction && this.oPump.Reverse())
	}
	ToEmpty() {
		this.state := "Опустошается"
		(this.oPump.direction && this.oPump.Reverse())
	}
	ToFaster(count) {
		this.oPump.PowerUp(count)
	}
	ToSlower(count) {
		this.oPump.PowerDown(count)
	}
	Stop() {
		this.oPump.PowerOff()
	}
}
Class Pump {
	__New(name, power, maxPower, state) {
		this.name      := name
		this.power     := power
		this.maxPower  := maxPower
		this.state     := state
		this.direction := true
	}
	PowerOn() {
		this.state := true
		{
			; ожидание отклика устройства
			; установка текущей мощности и прочие параметры
		}
	}
	PowerOff() {
		this.state := false
		{
			; остановка
			; ожидание полной остановки
		}
	}
	PowerUp(uPwr) {
		if (!this.state)
			this.PowerOn()
		this.power := this.power + uPwr <= this.maxPower ? this.power + uPwr : this.maxPower
	}
	PowerDown(dPwr) {
		if (this.state) {
			if (this.power - dPwr > 0)
				this.power := this.power - dPwr 
			else {
				this.power := 0
				this.PowerOff()
			}
		}
	}
	Reverse() {
		; сменить направление работы насоса на обратное
		this.PowerOff()
		this.direction := !this.direction
		this.PowerOn()
	}
}

Здесь, в первом GUI отображён кликабельный список бочек, отображающий второй GUI с их состояниями. Все данные доступны глобально и не мешают внутреннему описанию своих компонентов.

10

Re: AHK: Вызов окна из класса

KusochekDobra Спасибо большое за скрипт. Буду использовать как показательный пример.
Еще вопрос возник, а не подскажете как взять указатель, наподобие A_GuiControl, но только на картинку? А то в A_GuiControl сохраняется полный путь к картинке. И hwnd тоже могу понять как использовать.
Вот мои попытки двигать картинки через A_GuiControl.

#z::
Gui, Add, Picture,x+30 w30 h-1 BackgroundTrans gdbg vV1, D:\BKP\SKRPT\lexa\Scada\pic\Val-Grey.emf
Gui, Add, Picture,x+30 w30 h-1 BackgroundTrans gdbg vV2, D:\BKP\SKRPT\lexa\Scada\pic\Val-Grey.emf
Gui, Add, Picture,x+30 w30 h-1 BackgroundTrans gdbg hwndV3, D:\BKP\SKRPT\lexa\Scada\pic\Val-Grey.emf
Gui, Add, Picture,x+30 w30 h-1 BackgroundTrans gdbg hwndV4, D:\BKP\SKRPT\lexa\Scada\pic\Val-Grey.emf
Gui, 1:Show, w1000 h580, Test gui
return

dbg:
Tooltip %A_GuiControl%
ZQ:=A_GuiControl
SetTimer, DR, 1
return

DR:
ToolTip %A_GuiControl%
;SetTimer, DR, 1
MouseGetPos, x, y
y:=y-30
GuiControl, move, A_GuiControl, x%x% y%y% 
return

~RButton Up::
SetTimer, DR, Off
return

11

Re: AHK: Вызов окна из класса

Вообще-то, это другая тема для обсуждения, но надеюсь, нас не накажут.


#SingleInstance, Force
#NoEnv

picPath := "D:\BKP\SKRPT\lexa\Scada\pic\Val-Grey.emf"

Gui,1: Add, Picture,vmyPic1 gMoveMe,% picPath
Gui,1: Add, Picture,vmyPic2 gMoveMe,% picPath
Gui,1: Show,w500 h500

return
MoveMe:
	MouseGetPos,xx_start,yy_start
	GuiControlGet,myPic,Pos,% A_GuiControl
	if (GetKeyState("LButton", "P"))
		while (GetKeyState("LButton", "P"))
			Sleep, 10
	MouseGetPos,xx_finish,yy_finish
	GuiControl,Move,%A_GuiControl%,% Format("x{1} y{2}", myPicX - (xx_start - xx_finish), myPicY - (yy_start - yy_finish))
return

Esc::
	ExitApp