for flooders
:: Главная :: Решения :: Статьи :: Сайт М. Дроздова :: Файловый архив :: Книга по VFP 9 :: Русский Help Online :: OFF-LINE Форум
   Лисоводы   всех   стран,  объединяйтесь !!!  

Список Форумов  :: Visual Foxpro, Foxpro for DOS
  

Как программно развернуть combobox?
At

Сообщений: 187
Дата: 14.03.11 12:49:28
Есть combobox на форме
Стиль dropdown list
rowsourcetype = 6
rowsource = 'table.field1'
controlsource = 'table.field1'
Нужно чтобы по нажатию энтера при фокусе на комбобоксе, комбобокс раскрывался.
Пробовал в keypress
LPARAMETERS nKeyCode, nShiftAltCtrl
DO CASE
case nKeyCode = 13
thisform.combo1.DropDown
nodefault
endcase
не помогает.
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
At

Сообщений: 187
Дата: 14.03.11 13:04:06
Извиняюсь, поиском не нашел, а в Faq не посмотрел, а оно там есть(
Lparameters nKeyCode, nShiftAltCtrl
DO CASE
case nKeyCode = 13
KEYBOARD '{ALT+DNARROW}' PLAIN CLEAR
nodefault
endcase



Исправлено: At, 14.03.11 13:10
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Igor Korolyov

Сообщений: 34580
Дата: 14.03.11 17:12:53
At
rowsource = 'table.field1'
controlsource = 'table.field1'
Есть абсолютно бессмысленная и даже вредная вешь. Выбор из списка запоминается в тот же самый список Надеюсь в реальном комбобоксе это всё же разные таблицы


------------------
WBR, Igor
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
pioner-v

Сообщений: 1656
Дата: 14.03.11 19:11:08
At
Есть combobox на форме
...
Нужно чтобы по нажатию энтера при фокусе на комбобоксе, комбобокс раскрывался.
...

Попробуйте так(поместите этот код в метод KeyPress комбобокса):
If nKeyCode=13  
   fName=ThisForm.Name  
   nRowM=MROW(fName,3)  
   nColM=MCOL(fName,3)  
   nRowDn=OBJTOCLIENT(This,1)+3  
   nColDn=ObjToClient(This,2)+ObjToClient(This,3)-2  
   MOUSE CLICK AT nRowDn, nColDn window(fName) pixels  
   MOUSE AT nRowM, nColM window(fName) pixels  
  endif
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
At

Сообщений: 187
Дата: 15.03.11 12:07:54
Igor Korolyov
At
rowsource = 'table.field1'
controlsource = 'table.field1'
Есть абсолютно бессмысленная и даже вредная вешь. Выбор из списка запоминается в тот же самый список Надеюсь в реальном комбобоксе это всё же разные таблицы
Очень даже не бессмысленная.
Например мне нужно программно установить в комбобоке нужный выбор. Если не использовать контрол соурс придется мудрить с индексом элемента в списке. С такими настройками как у меня достаточно встать на табличку и выполнить locate for. Да и по дефолту отображается первое значение в таблице, а не пустое поле как в случае без указания контролсоурса.
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Igor Korolyov

Сообщений: 34580
Дата: 15.03.11 13:47:56
Если не бессмысленная, значит вредная. Установить в комбобоксе "нужное значение" можно не только по индексу, но и просто .Value="что надо"
То что у тебя написано, вызывает при каждом изменении комбо ЗАПИСЬ выбранного значения обратно в таблицу (особенно это "приятно" если курсор источник открыт в ReadOnly). ControlSource это двусторонняя связь - не только "считать из источника", но и "записать выбор обратно".
При этом комбо привязанный к курсору (с источником Fields) и так вызывает перемещение указателя записи в оном при выборе - независимо от того прописано что в ControlSource или нет. Обратно, конечно же, не будет работать - но это запросто реализовать например через This.Value = table.field1 в рефреше комбо - т.к. и в твоём случае без рефреша контрола (а скорее даже всей формы) после перемещения указателя оно работать не будет - тупо будет обратно перебрасывать на "старое значение"...


------------------
WBR, Igor
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
At

Сообщений: 187
Дата: 16.03.11 17:23:10
Igor Korolyov
1)Установить в комбобоксе "нужное значение" можно не только по индексу, но и просто .Value="что надо"
2)То что у тебя написано, вызывает при каждом изменении комбо ЗАПИСЬ выбранного значения обратно в таблицу (особенно это "приятно" если курсор источник открыт в ReadOnly). ControlSource это двусторонняя связь - не только "считать из источника", но и "записать выбор обратно".
2)При этом комбо привязанный к курсору (с источником Fields) и так вызывает перемещение указателя записи в оном при выборе - независимо от того прописано что в ControlSource или нет.
3)Обратно, конечно же, не будет работать - но это запросто реализовать например через This.Value = table.field1 в рефреше комбо - т.к. и в твоём случае без рефреша контрола (а скорее даже всей формы) после перемещения указателя оно работать не будет - тупо будет обратно перебрасывать на "старое значение"...
1)по индексу значительно удобнее - не нужно думать о типах значения, тримах и прочей фигне.
2)Ну вот свеже сделанная тестовая форма. Курсор в ридонли, все прекрасно работает как при програмных так и при ручных шевелениях курсора. Пробовал привязать к нормальной таблице - изменений в таблице при style = dropdownlist никаких.
3)рефреша комбобокса хватает
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Igor Korolyov

Сообщений: 34580
Дата: 16.03.11 17:49:20
Сам себе противоречишь - то "неудобно" по индексу, то удобно...
Касательно "примера" - ну если не смотреть на то что при "выборе" значения появляется в статусбаре надпись о том что "The record is read-only", и что сам выбор подтормаживает где-то на секунду...
Для не RO курсора - можете мне поверить, запись ПРОИСХОДИТ. Просто он меняет значение на "само же себя", поэтому в большинстве случаев изменений "не видно". Чётко видно что меняется дата изменения файла, если есть триггер на обновление - он тоже срабатывает.
Про рефреш - я и писал что БЕЗ рефреша не работает, а С ним - гораздо лучше работает строчка This.Value = table.field1 в обработчике события Refresh.
И главное - нет никаких мозгодробящих логических циклов - пишу в поле значение из этого же поля. Впрочем каждый ССЗБ - нравится "индусский стиль" в программировании - пиши так, только не удивляйся если другие будут плеваться смотря твой код


------------------
WBR, Igor
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Владимир Максимов
Автор

Сообщений: 13943
Откуда: Москва
Дата: 16.03.11 17:51:34
At
1)по индексу значительно удобнее - не нужно думать о типах значения, тримах и прочей фигне.

Угу. А теперь укажите в качестве ControlSource поле, отличное от символьного или числового. Например, Date или Logical. Немедленно получите сообщение об ошибке о несовпадении типов. Т.е. именно в Вашем случае приходится таки очень даже думать "о типах значения, тримах и прочей фигне"

At
2)Ну вот свеже сделанная тестовая форма. Курсор в ридонли, все прекрасно работает как при програмных так и при ручных шевелениях курсора. Пробовал привязать к нормальной таблице - изменений в таблице при style = dropdownlist никаких.

Ошибок действительно нет. Но выполняется блокировка текущей (выбранной) записи. Некая не явная попытка обновления. Попробуйте такой "фокус".

Откройте Вашу таблицу-источник в другом сеансе FoxPro (можно в Private DataSession) и заблокируйте ее через FLOCK(). А потом вернитесь к своему ComboBox и попробуйте что-нибудь выбрать. Можно через RLOCK() заблокировать какую-то одну запись, а потом в Combo попытаться ее выбрать. Результат будет тот же
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
At

Сообщений: 187
Дата: 17.03.11 10:49:44
[quote Igor Korolyov]1)Сам себе противоречишь - то "неудобно" по индексу, то удобно...
2)Касательно "примера" - ну если не смотреть на то что при "выборе" значения появляется в статусбаре надпись о том что "The record is read-only", и что сам выбор подтормаживает где-то на секунду...
3)Про рефреш - я и писал что БЕЗ рефреша не работает, а С ним - гораздо лучше работает строчка This.Value = table.field1 в обработчике события Refresh.
И главное - нет никаких мозгодробящих логических циклов - пишу в поле значение из этого же поля.
[/quote]
1)по индексному полю таблицы удобно, по индексу комбобокса неудобно
2)никаких надписей не появляется и тормозов тоже
3)Добавил в рефреш This.Value = table.field1, никаких изменений в коде не понадобилось. Ровно те же:
select table1
locate for условие
combobox.refresh
[quote Владимир Максимов]
Угу. А теперь укажите в качестве ControlSource поле, отличное от символьного или числового. Например, Date или Logical. Немедленно получите сообщение об ошибке о несовпадении типов. Т.е. именно в Вашем случае приходится таки очень даже думать "о типах значения, тримах и прочей фигне"
[/quote]

Лично мне не понятно, что не так если в том же хелпе написано:
[quote]Если свойство ControlSource установлено в имя поля таблицы или переменную, свойсто Value всегда будет имть тоже самое значение данных и тот же самый тип данных, что и переменная или поле, в которые установлено свойство ControlSource.[/quote]
[quote]Once the ControlSource property is set to a field or variable, the Value property always has the same data value and the same data type as the variable or field to which the ControlSource property is set.[/qoute]
Именно это мне и нужно - чтобы тип и значение элемента управления было таким же как и в моей таблице.



Исправлено: At, 17.03.11 10:50
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Igor VS

Сообщений: 2193
Откуда: Харьков
Дата: 17.03.11 11:31:14
At
Лично мне не понятно, что не так если в том же хелпе написано:
Цитата:
Если свойство ControlSource установлено в имя поля таблицы или переменную, свойсто Value всегда будет имть тоже самое значение данных и тот же самый тип данных, что и переменная или поле, в которые установлено свойство ControlSource.
Именно это мне и нужно - чтобы тип и значение элемента управления было таким же как и в моей таблице.

Вы у себя в программе устроили, фигурально выражаясь, аттракцион под названием "удав, кусающий себя за хвост". Вам два умных человека говорили, почему этого делать не надо, и какие проблемы можно на этом деле поиметь. Не понимаете сейчас - вам же хуже. Придется срочно понимать в процессе эксплуатации приложения, когда будете горевать над программой, непредсказуемо зависающей в клинче, или думать какого черта указатель уходит с нужной записи без видимых на то причин, или почему при закрытии формы возникает сообщение "update conflict", когда на форме ничего не менялось и т.д. и т.п. Если, конечно, хватит проницательности установить причинно-следственные отношения между проявлением проблемы и ее источником. А отношения эти в вашем случае будут ой какие неочевидные.


------------------
Трехколесный пароход




Исправлено: Igor VS, 17.03.11 11:38
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Владимир Максимов
Автор

Сообщений: 13943
Откуда: Москва
Дата: 17.03.11 11:57:39
Хотите получить проблемы "на ровном месте"? Ну, Вы их получите. Только потом не спрашивайте "почему не работает". Вам уже сказали "почему".

=================================================================

ComboBox - это совокупность нескольких объектов:

1. TextBox - он отображает выбранное значение
2. CommandButton - открывает раскрывающийся список
3. ListBox - собственно раскрывающийся список

Содержимое ListBox - это специфический массив, содержащий только и исключительно символьные данные. Это значит, что содержимое ListBox не есть то, что указано в свойстве RowSource. Это массив, содержимое которого создано на основе тех данных, которые указаны в свойстве RowSource. Но всегда следует помнить, что это другие данные.

При определенном значении свойства RowSourceType (при определенном типе источника данных) FoxPro берет на себя работу по синхронизации перемещения в ListBox и в источнике данных, указанном в RowSource. Но, как правило, подобная синхронизация скорее мешает.

Итак, содержимое раскрывающегося списка - это массив символьных (и только символьных) данных. Следовательно, возвращаемое значение - это либо содержимое элемента массива, либо порядковый номер (индекс) строки массива. Естесственно, что содержимое элемента массива имеет символьный тип данных (и только символьный), а порядковый номер - числовой.

Как следствие, если ожидаемый тип возвращаемого значения должен быть символьным, то будет возвращено содержимое элемента массива. Если же ожидаемый тип возвращаемого значения должен быть числовым, то будет возвращено значение индекса (номер строки массива). Как определяется ожидаемый тип возвращаемого значения чуть ниже.

Это то, как ComboBox будет действовать по умолчанию. Однако у ComboBox есть дополнительная специфическая настройка BoundTo. Если эта настройка имеет значение .T. и ожидаемый тип возвращаемого значения числовой, то в качестве возвращаемого значения будет взято содержимое элемента массива, которое затем будет сконвертировано в числовое значение (вероятно, при помощи функции VAL()).

Если ожидаемый тип возвращаемого значения символьный, то настройка BoundTo - не анализируется.

Как определяется ожидаемый тип возвращаемого значения? По заданному программистом выбранному значению по умолчанию.

Выбранное значение - это свойство Value. Следовательно, если там указать символьное значение, то ComboBox будет возвращать содержимое элемента массива. Если там указать числовое значение, то ComboBox будет возвращать индекс массива или, в случае настройки BoundTo = .T., содержимое элемента массива сконвертированое в число.

Однако выбранное значение может быть указано опосредованно, не через свойство Value, а через свойство ControlSource.

Свойство ControlSource - это то, где будет храниться (куда будет записываться) выбранное значение. Разумеется, при инициализации объекта из этого же источника будет взято и значение по умолчанию. Как уже было сказано, ComboBox может вернуть либо символьное, либо числовое значение. Как следствие, ControlSource также должен содержать либо символьное, либо числовое значение иначе Вы получите сообщение об ошибке о не соответствии типов.

Если Вы не хотите нигде хранить выбранное значение, то для инициализации типа возвращаемого значения следует использовать свойство Value.


Как установить значение по умолчанию, при инициализации объекта (при открытии формы)?

Прежде всего, следует понимать, что отображаемое значение, не всегда совпадает с выбранным значением. Ну, например, в качестве выбранного значения (свойства Value) может быть указан индекс массива. Тем не менее, на форме в ComboBox Вы видите не индекс, а некий текст. Т.е. отображаемое значение не совпадает с выбранным.

Еще раз напомню, что содержимое раскрывающегося списка - это массив. Значит, выбранное значение, это содержиое элемента этого массива. Массив может быть двумерным. Значит, выбранное значение характеризуется двумя координатами: номером строки (индексом) и номером столбца.

По умолчанию, выбранное значение - это содержимое первого столбца массива. Но при помощи настройки BoundColumn можно явно указать из какого столбца следует брать значение. Другими словами, столбец массива всегда известен. И надо определить только строку.

Строку можно определить явно, просто указав ее номер (свойство ComboBox.ListIndex) или не явно, указав предполагаемое выбранное значение (ComboBox.Value или опосредованно через ComboBox.ControlSource).

Во втором случае при инициализации объекта ComboBox попытается найти в раскрывающемся списке указанное значение. Если оно будет найдено, то Вы увидите на форме некое отображаемое значение. Если такого значения нет во внутреннем массиве ComboBox, то и отображаемого значения не будет.

Еще один опосредованный вариант определения значения по умолчанию, это случай, когда FoxPro берет на себя работу по синхронизации перемещения по раскрывающемуся списку ComboBox и источнику данных этого самого раскрывающегося списка. В этом случае достаточно будет просто позиционироваться на нужную строку в источнике данных. А уже FoxPro сам синхронизирует положение в раскрывающемся списке и отобразит (если строка массива будет найдена) соответствующее значение.

Однако это довольно рискованная стратегия, ведь перемещение по записям таблицы-источника может быть не связано с процессом выбора элемента ComboBox. Тут придется открывать таблицу-источник еще раз в другой рабочей области, чтобы не смешивать поиск в раскрывающемся списке и все прочие операции по работе с данной таблицей.
Ratings: 0 negative/1 positive

Re: Как программно развернуть combobox?
rhs72

Сообщений: 1934
Откуда: Алматы - Чарджоу
Дата: 17.03.11 14:19:46
Ответ В.Максимова в FAQ !!!


------------------
"Знание того, что считать ответом, равносильно знанию ответа".
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
B3ersn3V

Сообщений: 595
Откуда: г. Киев
Дата: 17.03.11 16:25:30
rhs72
Ответ В.Максимова в FAQ !
+1


------------------
Не от того, что мы на планете, так солнце светит!
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
SoccerStudio

Сообщений: 5055
Откуда: Подмосковье
Дата: 17.03.11 16:43:03
rhs72
Ответ В.Максимова в FAQ !!!
Ага. А эпиграф к ответу - в качестве заголовка к форуму.
Ratings: 0 negative/0 positive

Re: Как программно развернуть combobox?
Igor Korolyov

Сообщений: 34580
Дата: 17.03.11 16:54:57
At
1)по индексному полю таблицы удобно, по индексу комбобокса неудобно
Понятно, т.е. имеется в виду что удобно пользоваться полем id "справочника", отображать при этом его же поле name, но неудобно пользоваться ListIndex комбобокса, т.к. оно (что вполне естественно) в общем случае не будет совпадать с соответствующим id таблицы. Так вот в этом случае стоит использовать 2-х колончатый комбобокс, настроенный примерно вот так RowSourceType=6, RowSource="table1.name, id", BoundColumn=2, BoundTo=.T. ColumnWidth = "200,0" - при этом ControlSource ну никак не должен быть связан с курсором table1 он должен быть связан с другим курсором (с полем куда должен записываться выбор), с глобальной переменной (фи), некоторым пользовательским свойством формы, либо вообще ни с чем не быть связан (ожидаем чисто програмный прямой доступ к "текущему выбору" через Value, или опосредованный - через перемещение указателя записи в table1 - последнее предполагает что table1 не используется более ни в каких комбобоксах/листбоксах или гридах - иначе не уследить за тем кто же из них последний перемещал указатель записи).
At
2)никаких надписей не появляется и тормозов тоже
Появляется - если курсор table1 открыт в режиме NOUPDATE (т.е. он доступен только для чтения) - ещё печальнее если эта же таблица будет открыта в другой сессии (или даже другой программе) и там будет заблокирована некоторая запись этой таблицы (вручную, или автоматически, например при использовании пессимистической буферизации, или при отсутствии всякой буферизации вовсе), или же вся таблица целиком. Это будет банальное зависание при стандартной настройке SET REPROCESS - висим и ждём пока запись/таблицу "отпустят".
At
3)Добавил в рефреш This.Value = table.field1, никаких изменений в коде не понадобилось. Ровно те же:
select table1
locate for условие
combobox.refresh
Именно так - и теперь можно в ControlSource прописать "" - т.е. ОТВЯЗАТЬ комбо! При том оно будет работать ровно так как и предполагается - но уже без указанных неприятных последствий
At
Лично мне не понятно, что не так если в том же хелпе написано:
"Не так" сама логика смешивания источника строк комбо и места куда записывается выбор текущего элемента
At
Именно это мне и нужно - чтобы тип и значение элемента управления было таким же как и в моей таблице.
Для этого не обязательно привязывать комбо к полю или даже переменной/свойству (против самой привязки, кстати, никаких возражений - вопрос к тому К ЧЕМУ привязывать! К тому же курсору который есть источник строк - это и есть крайне нехорошо) - достаточно проинициализировать один раз свойство Value.


------------------
WBR, Igor
Ratings: 0 negative/0 positive



Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 13 (Гостей: 13)

© 2000-2022 Fox Club 
Яндекс.Метрика