Перейти к содержимому

Фотография

Динамическое содержание формы


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 16

#1 OlgaV

OlgaV

    Новый участник

  • Members
  • Pip
  • 38 сообщений
  • Город:Киев


Отправлено 11 января 2007 - 10:54

Добрый день. Есть win32 приложение. В нем есть форма, в которой находятся текстовые поля. Их количество зависит от настройки приложения.
например это описание прикрепленного окна:
[+] window DialogBox SearchForDemographics
[ ] tag "Search for demographics"
[+] parent EXText
[+] TextField TextField1
[ ] tag "$302"
[+] TextField TextField2
[ ] tag "$303"
[+] TextField TextField3
[ ] tag "$304"
[+] TextField TextField4
[ ] tag "$305"
[+] TextField TextField5
[ ] tag "$306"
[+] TextField TextField6
[ ] tag "$307"
[+] TextField TextField7
[ ] tag "$308"
[+] TextField TextField8
[ ] tag "$309"
[+] TextField TextField9
[ ] tag "$310"
[+] TextField TextField10
[ ] tag "$311"
[+] TextField TextField11
[ ] tag "$312"
[+] TextField TextField12
[ ] tag "$313"
[+] TextField TextField13
[ ] tag "$314"
[+] TextField TextField14
[ ] tag "$315"
[+] TextField TextField15
[ ] tag "$316"
[+] TextField TextField16
[ ] tag "$317"
[+] TextField TextField17
[ ] tag "$300"
[+] CheckBox ShowEnterpriseWideDemograph
[+] multitag "Show Enterprise-wide demographics also"
[ ] "$1272"
[+] PushButton OK
[+] multitag "OK"
[ ] "$1"
[+] PushButton Cancel
[+] multitag "Cancel"
[ ] "$2"
[+] CustomWin EtchedFrame1
[ ] tag "[EtchedFrame]$65535"
как бы сделать работу с таким окном удобнее?
Свойства Caption у этих полей нет, то, что выглядит как имя поля - это тоже текстовое поле, только с четным индексом. Получается, чтобы ввести значение в поле, мне надо найти поле-заглавие через GetText и обратиться к соседнему полю по его индексу.
Как это можно работу с этими полями красивее сделать?

Прикрепленные файлы

  • Прикрепленный файл  form.GIF   16,06К   57 Количество загрузок:

  • 0

#2 Genka

Genka

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 328 сообщений
  • ФИО:Геннадий Алпаев
  • Город:Украина, Днепр


Отправлено 11 января 2007 - 11:26

В Вашем случае все распознано правильно: если нету кэпшенов и привязаться к порядковому номеру поля (#) нельзя, то именно так и надо распознавать их - по id ($)

Единственный момент: переименуйте сами поля, чтобы они выглядели по-человечески (типа LastName, MRN и т.д.) вместо TextField1, TextField2...
  • 0

TestComplete для начинающих (видеозаписи курса)

Software Testing Automation Tips (50 вещей, которые должен знать каждый автоматизатор, книга на английском языке)

Онлайн-учебник "Автоматизация тестирования от «А» до «Ы»"
Сборник рецептов по TestComplete (книга на английском языке)
Онлайн-учебник по TestComplete
Онлайн-учебник по SilkTest


#3 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 12:02

Что по ID, что по порядковому номеру - это не имеет значение. Все равно придется работать динамически. Особенно, если учесть, что количество полей, да и содержимое полей может различаться в зависимости от настроек.
В этом случае индексы даже предпочтительнее. Что можно сделать для работы с этой формой:

можно написать методы, которые представляют собой интерфейс для работы с данными полями. Например, нам бы полезно было извлечь список всех названий полей ( все строки слева от полей ввода ). Соответственно, нужны методы для извлечения/внесения значений как во все поля ввода сразу, так и для каждого отдельного поля. То есть, все это дело выглядит примерно так:

[-] window DialogBox SearchForDemographics
                [ ] tag "Search for demographics"
                [ ] parent EXText
                [ ] 
                [+] property lsValues
                                   [+] LIST OF STRING Get()
                                                [ ] LIST OF STRING lsValue = {}
                                                [ ] INTEGER i = 1 
                                                [+] while( this.TextField( "#{2*i}" ).Exists() )
                                                                [ ] ListAppend( lsValue , this.TextField( "#{2*i}").sValue ) 
                                                                [ ] i++
                                                [ ] return lsValue
                                   [+] VOID Set( LIST OF STRING lsValue )
                                                [ ] INTEGER i
                                                [ ] 
                                                [+] for i = 1 to ListCount( lsValue )
                                                                [+] if( !this.TextField( "#{2*i}" ).Exists() )
                                                                           	 [ ] break
                                                                 [ ] this.TextField( "#{2*i}" ).SetText( lsValue[i] )


                // Retreives all field names
                [+] LIST OF STRING GetFieldNames()
                                [ ] LIST OF STRING lsNames = {}
                                [ ] INTEGER i = 1 
                                [+] while( this.TextField( "#{2*i-1}" ).Exists() )
                                                [ ] ListAppend( lsNames , this.TextField( "#{2*i-1}").sValue ) 
                                                [ ] i++
                                [ ] return lsNames

                // Sets text to the specified field
                [+] VOID SetFieldText( LISTITEM sField , STRING sValue )
                                [ ] INTEGER iIndex
                                [ ] 
                                [+] switch ( TypeOf( sField ) )
                                                [+] case INTEGER
                                                                [ ] iIndex = sField
                                                [+] case STRING
                                                                [ ] iIndex = ListFind( this.GetFieldNames() , sField )
                                [+] if( !this.TextField("#{2*iIndex}").Exists() )
                                                [ ] return
                                [ ] this.TextField("#{2*iIndex}").SetText( sValue )

                // retreives field text
                [+] STRING GetFieldText( LISTITEM sField )
                                [ ] INTEGER iIndex
                                [ ] 
                                [+] switch ( TypeOf( sField ) )
                                                [+] case INTEGER
                                                                [ ] iIndex = sField
                                                [+] case STRING
                                                                [ ] iIndex = ListFind( this.GetFieldNames() , sField )
                                [+] if( !this.TextField("#{2*iIndex}").Exists() )
                                                [ ] return NULL
                                [ ] return this.TextField("#{2*iIndex}").sValue 
                                [ ] 
    

А дальше уже следуют объявления кнопок. То есть вместо кучи текстовых полей у нас есть одно свойство lsValues и методы GetFieldNames, GetFieldText, SetFieldText
  • 0

#4 OlgaV

OlgaV

    Новый участник

  • Members
  • Pip
  • 38 сообщений
  • Город:Киев


Отправлено 11 января 2007 - 12:22

Да-да, спасибо большое, похоже очень на то, что надо. разбираюсь с кодом. :)
  • 0

#5 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 12:37

Достаточно понять одну такую "фишку". По аналогии с языком С++, имя класса, использованное как функция ( то есть имеет вид <class_name>( <parameter> ) ), возвращает объект-экземпляр данного класса. В Силке такая конструкция возвращает окно-экземпляр оконного класса, а параметр - это его тэг. То есть запись вида:
wSomeWin.TextField( "#1" )

Вернет текстовое поле с тэгом "#1" , которое является дочерним для окна wSomeWin.

На этой особенности и основана динамическая работа с объектами, когда объекты определяются "на лету"
  • 0

#6 Genka

Genka

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 328 сообщений
  • ФИО:Геннадий Алпаев
  • Город:Украина, Днепр


Отправлено 11 января 2007 - 12:47

Что по ID, что по порядковому номеру - это не имеет значение


В данном случае имеет, так как

<skipped> текстовые поля. Их количество зависит от настройки приложения


В случае же использования приведенного кода може возникнуть такая ситуация, когда в форму добавятся новые контролы (например какая-нить кнопка между полем-кэпшеном и полем для ввода данных) и тогда их поряок будет нарушен и придется модифицировать методы Get/Set.

В случае же изменения idшников полей достаточно их поменять в тегах.

ИМХО этот вариант проще и быстрее
  • 0

TestComplete для начинающих (видеозаписи курса)

Software Testing Automation Tips (50 вещей, которые должен знать каждый автоматизатор, книга на английском языке)

Онлайн-учебник "Автоматизация тестирования от «А» до «Ы»"
Сборник рецептов по TestComplete (книга на английском языке)
Онлайн-учебник по TestComplete
Онлайн-учебник по SilkTest


#7 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 13:08

Если какой-то контрол будет вставлен, то скорее всего и ID-шники поползут. Вообще для GUI приложений ID-шники в тэгах - это крайность. Индексы предпочтительнее. И в обоих случаях тэги менять придется. Это если описывать во фрейме. А если это дело делать динамически (о чем и просили собственно говоря), то ни о каких ID-шниках и речи быть не может, так как их вид в общем случае неопределен
  • 0

#8 Genka

Genka

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 328 сообщений
  • ФИО:Геннадий Алпаев
  • Город:Украина, Днепр


Отправлено 11 января 2007 - 13:21

Если какой-то контрол будет вставлен, то скорее всего и ID-шники поползут


Не поверил, решил проверить. :help:

На прикрепленной картинке обведены два поля, которые были вставлены отдельно, после того. Так вот, айдишники контролов, которые были до этого, не изменились. Ибо id контрола изменяется только в том случае, если сам контрол удаляют, а потом создают заново.

Прикрепленные файлы

  • Прикрепленный файл  id.JPG   10,18К   48 Количество загрузок:

  • 0

TestComplete для начинающих (видеозаписи курса)

Software Testing Automation Tips (50 вещей, которые должен знать каждый автоматизатор, книга на английском языке)

Онлайн-учебник "Автоматизация тестирования от «А» до «Ы»"
Сборник рецептов по TestComplete (книга на английском языке)
Онлайн-учебник по TestComplete
Онлайн-учебник по SilkTest


#9 OlgaV

OlgaV

    Новый участник

  • Members
  • Pip
  • 38 сообщений
  • Город:Киев


Отправлено 11 января 2007 - 13:24

В случае же использования приведенного кода може возникнуть такая ситуация, когда в форму добавятся новые контролы (например какая-нить кнопка между полем-кэпшеном и полем для ввода данных)



Кнопка не добавится - динамические поля, слава богу, сгруппированы вместе.
И если добавится ,то еще одно такое поле.

Зато такая группа встречается в нескольких окнах. с разным набором полей. :) Мне в каждом таком окне прописывать этот набор свойств и методов или можно еще больше укрупнить? :help:
  • 0

#10 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 13:27

Если какой-то контрол будет вставлен, то скорее всего и ID-шники поползут


Не поверил, решил проверить. :help:

На прикрепленной картинке обведены два поля, которые были вставлены отдельно, после того. Так вот, айдишники контролов, которые были до этого, не изменились. Ибо id контрола изменяется только в том случае, если сам контрол удаляют, а потом создают заново.

Просмотр сообщения


Ну тогда надо будет только обработчик скорректировать. У индексов есть еще одно преимущество - они есть у любого контрола. А вот ID-шники определены не для всех контролов
  • 0

#11 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 13:31

В случае же использования приведенного кода може возникнуть такая ситуация, когда в форму добавятся новые контролы (например какая-нить кнопка между полем-кэпшеном и полем для ввода данных)


Кнопка не добавится - динамические поля, слава богу, сгруппированы вместе.
И если добавится ,то еще одно такое поле.

Зато такая группа встречается в нескольких окнах. с разным набором полей. :) Мне в каждом таком окне прописывать этот набор свойств и методов или можно еще больше укрупнить? :help:

Просмотр сообщения


Вот эти методы, что я написал, запихни в какой-нибудь оконный класс и нужные окна объявляй как экземпляры данного класса
  • 0

#12 OlgaV

OlgaV

    Новый участник

  • Members
  • Pip
  • 38 сообщений
  • Город:Киев


Отправлено 11 января 2007 - 14:24

Сделала. :) Работает. :)
Но! Очередной прикол.
в одном из окон динамических полей так много, что им понадобился скроллер. Отображается только 7. Остальные видны, если скроллером прокрутить.
Скроллер не распознается никак. :(
Методы видят только видимые поля.
По полям могу двигаться только табом. - Это если прокручивать вручную...
Что в этот случае можно сделать?
  • 0

#13 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 14:40

Тут сразу сходу решение выдать не могу, но предполагаю, что отталкиваться стоит от перехода по табам. Табать можно до тех пор, пока не упрется в самое последнее поле или не перескочит на первое поле.

Кстати, а на чем написано приложение?
  • 0

#14 Genka

Genka

    Профессионал

  • Members
  • PipPipPipPipPipPip
  • 1 328 сообщений
  • ФИО:Геннадий Алпаев
  • Город:Украина, Днепр


Отправлено 11 января 2007 - 14:49

И еще: убедитесь для начала, что включена опция Options -> Agent -> Other -> Automatically scroll windows into view

Если выключена - включите. Если включена - попробуйте перед тем, как работать с текстовым полем, применить для него метод ScrollIntoView
  • 0

TestComplete для начинающих (видеозаписи курса)

Software Testing Automation Tips (50 вещей, которые должен знать каждый автоматизатор, книга на английском языке)

Онлайн-учебник "Автоматизация тестирования от «А» до «Ы»"
Сборник рецептов по TestComplete (книга на английском языке)
Онлайн-учебник по TestComplete
Онлайн-учебник по SilkTest


#15 OlgaV

OlgaV

    Новый участник

  • Members
  • Pip
  • 38 сообщений
  • Город:Киев


Отправлено 11 января 2007 - 15:23

Если включена - попробуйте перед тем, как работать с текстовым полем, применить для него метод ScrollIntoView


[ ] *** Error: Window '[TextField]$316' was not found
[ ] Occurred in ScrollIntoView
:(((
  • 0

#16 KaNoN

KaNoN

    АЦЦКИЙ СОТОНА

  • Members
  • PipPipPipPipPipPip
  • 1 260 сообщений
  • ФИО:Колесник Николай
  • Город:Днепропетровск > Киев > Лондон

Отправлено 11 января 2007 - 16:09

И еще: убедитесь для начала, что включена опция Options -> Agent -> Other -> Automatically scroll windows into view

Если выключена - включите. Если включена - попробуйте перед тем, как работать с текстовым полем, применить для него метод ScrollIntoView

Просмотр сообщения


Если поле не находится через Exists, то это значит, что его там нет в принципе. Поэтому никакие ScrollIntoView тут не помогут. Это нужно, если поле существует, но оно вне видимой области окна нужно сделать прокрутку, прежде чем работать с данным полем. Так что тут надо скорее всего прокручивать через клавиатуру до упора
  • 0

#17 vass

vass

    Опытный участник

  • Members
  • PipPipPipPip
  • 298 сообщений
  • ФИО:Василий

Отправлено 19 января 2007 - 13:28

ИМХО лучше скроллить вот этим :
[ ] 
[-] dll "user32.dll"
	[ ] LRESULT SendMessageWL (in HWND hWnd, in UINT uiMsg, in WPARAM wParam, in LPARAM lParam) alias "SendMessageA"
[ ] 
[ ] 
[-] WindScroll (WINDOW wWindow, INTEGER iCount optional,
                  BOOLEAN bVScroll optional, BOOLEAN bLines optional, BOOLEAN bFromStart optional)
	[ ] 
	[ ] const WPARAM SB_LINEUP = 0x0
	[ ] const WPARAM SB_LINEDOWN = 0x1
	[ ] const WPARAM SB_PAGEUP = 0x2
	[ ] const WPARAM SB_PAGEDOWN = 0x3
	[ ] const WPARAM SB_TOP = 0x6
	[ ] 
	[ ] HWND hWnd = wWindow.hWnd
	[ ] UINT iScroll = (bVScroll == FALSE) ? WM_HSCROLL : WM_VSCROLL
	[ ] WPARAM iDir
	[ ] INTEGER i
	[ ] 
	[ ] 
	[-] if IsNull (iCount)
  [ ] iCount = 1
	[ ] 
	[-] if bLines == FALSE
  [-] if iCount > 0
 	 [ ] iDir = SB_PAGEDOWN
  [-] else
 	 [ ] iCount = -iCount
 	 [ ] iDir = SB_PAGEUP
	[-] else
  [-] if iCount > 0
 	 [ ] iDir = SB_LINEDOWN
  [-] else
 	 [ ] iCount = -iCount
 	 [ ] iDir = SB_LINEUP
	[ ] 
	[-] if bFromStart == TRUE
  [ ] SendMessageWL (hWnd, iScroll, SB_TOP, 0)
	[ ] 
	[-] for i = 1 to iCount
  [-] if SendMessageWL (hWnd, iScroll, iDir, 0) != 0
 	 [ ] break
[ ] 
........ 
[ ] WindScroll  (wSomeWin, 1, TRUE, FALSE) // скроллит контрол 1 страницу вниз
и вызывайте ее для того дилога, в котором находятся TextField-ы
  • 0


Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 анонимных