AVC |
Отправлено: 26.08.2004, 15:18 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Давно назревала необходимость (для меня), да и на форумах несколько раз видел подобные вопросы. Вот решил поизучать проблему и предлагаю чесному (ударение на о) народу свое решение.
Предполагалось что при работе с DBGrid где то присутствует буфер, в котором хранятся отображаемые записи. Была идея добраться до этого буфера. Исследование исходников показало, что да такой буфер есть и получить буфер нужной строки не представляет проблемы, но (облом) каждый наследник TDadaSet (TBDEDataSet, TADODataSet, TYOracleDataSet и т.д) хранит в нем информацию так как это ему удобно. Конечно, в каждом конкретном случае можно написать свои или воспользоваться функциями разработчика компонента для извлечения и преобразования данных поля из буфера. Но зачем если я работаю, например, с ADO мне нужны вызовы DBI. Это конечно можно решить условной компиляцией но это не красиво и требует доработки под каждый новый компонент. Поэтому для обеспечения универсальности было принято решение — а пусть DataSet сам этим занимается, тем более что есть прецеденты (DBGrid). Т.е. блокируются контролы, делается бросок к нужной записи, сохраняется значение поля, бросок обратно.
Таким образом следует признать, что Данные не из активной записи получить можно, но крайне сложно. Намного проще получать из текущей записи.
После получения ответа на первый вопрос, организация использования значения поля любой видимой записи в качестве hint’а для наследника TCustomDBGrid было просто развлекушкой.
Итак результат.
Предлагаемые функции должны (очень надеюсь) работать с любыми наследниками TDataSet и TCustomDBGrid
Прототипы функций (GUM_Etr.h)
CODE |
// Привязывается к DBGrid'у для показа Hint'а из строки над которой в данный момент находится курсор мыша
extern PACKAGE void __fastcall DBGrid_UnderMouse_FieldAsHint
(TDBGrid *grd
,const AnsiString &pFieldName = ""
);
// Возвращает Field над которым в сетке в данный момент завис курсор мыша
extern PACKAGE TField* __fastcall DBGrid_UnderMouse_ColumnFiled (TDBGrid *grd);
// Возвращает значение поля над которым в сетке в данный момент завис курсор мыша
extern PACKAGE Variant __fastcall DBGrid_UnderMouse_FieldValue
(TDBGrid *grd
,const AnsiString& pFieldName = ""
,bool AsString = false
);
|
* Для Hint поле должно быть приводимо к типу string
Использование: подключить к проекту GrdUndM.cpp (желательно в резидентную часть) в нужные формы включить
#include “GUM_Etr.h”
Простой пример использования Hint
В запросе
Select …, (Account || chr(10) || FIO || chr(10) || Address) as Abon_InfoHint From …
В конструкторе формы DBGrid_UnderMouse_FieldAsHint(Grd_Main, “Abon_InfoHint”)
Результат
Буду признателен за любые замечания и предложения.
файлы можно взять здесь
Для получения последней версии переходите к последним постам.
Отредактировано AVC — 28/12/2005, 10:15
|
|
Gedeon |
Отправлено: 26.08.2004, 17:11 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
О, инфа полезная, протестить времени пока нету, но в том, что работает я не сомневаюсь, будет время возьмем на вооружение.
|
|
Kate |
Отправлено: 08.09.2004, 13:31 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 9
|
Вещь действительно должна получиться полезная.
Вот только я попробовала, и у меня не получилось (наверное сказывается недостаток опыта).
Итак, у меня CB6. Я создала абсолютно новый проект, добавила к нему GrdUndM.cpp (что значит "в резидентную часть" извините, не знаю ). Пробую откомпилить, и на все места, где встречается ESTRorNULL выдает ошибку
E2354 Two operands must evaluate to the same type
т.е., как я понимаю, проблема в строке
(AsString? Variant(AnsiString("")) : Null)
но я обычно пишу попроще и не совсем понимаю, что бы это значило.
Прошу простить за ламерство |
|
AVC |
Отправлено: 08.09.2004, 14:05 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
В резидентную часть означает что надо включить не в динамически загружаемую библиотеку.
ESTRorNULL используется просто для сокращения записи. Проверяется значение bool'евой переменной AsString и возвращается либо пустая строка, либо Null.
Попробуйте в ней изменить Null на Variant().AsType(varNull) |
|
AVC |
Отправлено: 08.09.2004, 15:58 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Да действительно 6-ая стройка не понимает глобальной переменной Null
Для исправления этой ошибки тем, кто уже скачал тексты нужно
в файле GrdUndM.h заменить строку
#define ESTRorNULL (AsString? Variant(AnsiString("")) : Null)
заменить на
#define ESTRorNULL (AsString? Variant(AnsiString("")) : Variant().AsType(varNull))
или взять исправленный вариант здесь.
Работоспособность проверена для 5 и 6. На 3-ке работать не будет из за изменения Borland'ом способа доступа к полям в DataSet. С 4-кой не работал.
|
|
Kate |
Отправлено: 09.09.2004, 09:23 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 9
|
Спасибо. Теперь все работает.
Еще заметила такую особенность: У Grid'а при ShowHint == false не срабатывает обработчик OnMouseMove, а при ShowHint == true — срабатывает. Но мне-то он не нужен, так, случайно заметила. |
|
AVC |
Отправлено: 09.09.2004, 10:17 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
О спасибо. Мы с вами все таки доведем эту функцию до совершенства
Исправить в файле GrdUndM.cpp
строки начиная с 357
TDBGrid *grd = dynamic_cast(Sender);
if (!grd || !grd->ShowHint) return;
TGUM_GridList_Item *gumi = Find(grd);
if (!gumi) return;
на
TDBGrid *grd = dynamic_cast(Sender);
if (!grd) return;
TGUM_GridList_Item *gumi = Find(grd);
if (!gumi || !grd->ShowHint)
{ if (gumi->OldMouseMove) gumi->OldMouseMove(grd, Shift, X, Y); // Родной MouseMove
return;
}
Очередной вариант здесь (v3)
|
|
Gedeon |
Отправлено: 09.09.2004, 10:58 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Пусть меня простит AVC, так как обычным TDBGrid давно не пользуюсь переделал только что Ваше творение под TDBGridEh простой заменой TDBGrid на TDBGridEh .
Тут такая мысль появилась — завернуть это все в визуальный компонент, чтобы и на несколько гридов на одной форме лепить можно было бы.
P.S. Последнее изменение в файл не внесено
P.P.S.
не
CODE | TDBGrid *grd = dynamic_cast(Sender); |
а
CODE | TDBGrid *grd = dynamic_cast<TDBGrid*>(Sender);
|
Отредактировано Gedeon — 09/09/2004, 12:09
|
|
AVC |
Отправлено: 09.09.2004, 11:11 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE |
Пусть меня простит AVC, так как обычным TDBGrid давно не пользуюсь переделал только что Ваше творение под TDBGridEh простой заменой TDBGrid на TDBGridEh .
|
Раскажите гениалогию TDBGridEh. На самом деле мне важно наследие от TCustomDBGrid. Судя по тому, что у вас все получилось у TDBGrid и TDBGridEh общие предки.
QUOTE |
Тут такая мысль появилась — завернуть это все в визуальный компонент, чтобы и на несколько гридов на одной форме лепить можно было бы
|
Вызывайте DBGrid_UnderMouse_FieldAsHint с теми сетками, которые вам нужны. Естественно, что число сеток на форме нигде не лимитировано. Визуальный компонент для вызова одной единственной функции? хмм... жирновато будет.
|
|
AVC |
Отправлено: 09.09.2004, 11:17 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE |
CODE |
не
TDBGrid *grd = dynamic_cast(Sender);
а
CODE
TDBGrid *grd = dynamic_cast<TDBGrid*>(Sender);
|
| Нет мне прощения. Поленился взять код в тэги и поэтому TBDGrib* корова языком слизала. |
|
Gedeon |
Отправлено: 09.09.2004, 14:18 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (AVC @ 09/09/2004, 12:13) | Раскажите гениалогию TDBGridEh. На самом деле мне важно наследие от TCustomDBGrid. Судя по тому, что у вас все получилось у TDBGrid и TDBGridEh общие предки.
|
TObject->TPersistent->TComponent->TControl->TWinControl->TCustomControl->TCustomGrid->TCustomDBGridEh
Как видите общий предок TCustomGrid
Вот похоже от него надо плясать, проверяя наличие некоторых методов.
QUOTE |
Вызывайте DBGrid_UnderMouse_FieldAsHint с теми сетками, которые вам нужны. Естественно, что число сеток на форме нигде не лимитировано. Визуальный компонент для вызова одной единственной функции? хмм... жирновато будет. |
Да это-то понятно я имел ввиду один контрол в котором можно было бы назначать несколько сеток (по типу Fields в гриде) с указанием поля подсказки для каждого, но возможно Вы правы и это лишний труд. Я думаю такой компонент был бы интересен тем же разработчикам EhLib, а самому конечно проще руками 1 функцию написать
|
|
AVC |
Отправлено: 09.09.2004, 14:47 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
TCustomGrid меня не устраивает. Нужен хотя бы TCustomDBGrid. Придется сделать либо через define либо две функции. Склоняюсь ко второму варианту.
На счет компонента — конечно можно сделать. Но например у меня форма когда стартует еще не знает с каким (какими) запросами она будет работать. Она их зачитыает с сервера. Что уж говорить об имени поля для Hint которое то же хранится на сервере в описании запроса. |
|
AVC |
Отправлено: 09.09.2004, 17:34 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
v4. Теперь работает с TDBGrid и TDBGridEh.
На одной форме могут быть как простые DBGrid так и DBGridEh одновременно.
Для тех, кто не любит читать начало краткое содержание предыдущих серий
CODE |
...
Привязывается к DBGrid'у для показа Hint'а из строки над которой
в данный момент находится курсор мыша.
void DBGrid_UnderMouse_FieldAsHint
(TDBGrid *grd
, const AnsiString &pFieldName = ""
);
void DBGridEh_UnderMouse_FieldAsHint
(TDBGridEh *grd
, const AnsiString &pFieldName = ""
);
если pFieldName пусто, то опрашивается поле под мышом
иначе значение этого поля с именем в pFieldName
Показывает Hint если DataSet открыт и непуст и значение ShowHint
сетки равно true
Для показа Hint'а использует параметры Application
Многократный вызов с одним и те же значением DBGid не является ошибкой
— используются параметры последнего вызова
Вызывается для каждой сетки, к которой нужен такой Hint.
...
Использование:
1. Включить в проект (желательно не в динамическую библиотеку) модуль
GrdUndM.cpp или GrdUndME.cpp для EhLib
2. В тех модулях, где необходимо использовать функции добавить
#include "GUM_Etr.h" или #include "GUM_EtrE.h"
3. Для начала показа нint'а вызвать DBGrid_UnderMouse_FieldAsHint там,
где вам это удобно (например в конструкторе формы)
Пример:
На форме DataSet, DataSource, Query правильно связанные друг с другом
и кнопка
в обработчике события нажатия кнопки:
if (QryPdx->Active) QryPdx->Active = false;
QryPdx->DatabaseName = "BCDEMOS";
QryPdx->SQL->Text = "Select t.*, (t.Name + ' (' + t.Capital + ')') as Hint From country.db t";
DBGrid_UnderMouse_FieldAsHint (Grd_Main, "Hint");
или DBGridEh_UnderMouse_FieldAsHint (Grd_Main, "Hint");
QryPdx->Active = true;
|
(Gedeon в вашем архиве вы мне выложили мои же тексты — это ошибка?)
Исходные тексты здесь
|
|
Gedeon |
Отправлено: 09.09.2004, 18:12 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
QUOTE (AVC @ 09/09/2004, 18:36) | (Gedeon в вашем архиве вы мне выложили мои же тексты — это ошибка?)
|
позор мне, не то заархивировал.
|
|
AVC |
Отправлено: 10.09.2004, 08:08 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Gedeon, если вас не затруднит, проверьте, пожалуйста, работоспособность v4 на EhLib.
Я ей не пользуюсь поэтому работать пришлось почти "в темную"
|
|
Gedeon |
Отправлено: 10.09.2004, 18:49 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Млин целый день с инетом какая-то хрень не мог никуда попасть, но он как бы есть, не мог работать .
С EhLib все прекрасно работает.
2AVC большое спасибо за данный топик, узнал много нового, да и вещь очень полезная получилась.
2Всем Очень рекомендую использовать.
|
|
Michael99 |
Отправлено: 21.12.2006, 05:47 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 7
|
Использую DBGridEh и при использовании напоролся на 2 проблемы.
1. И самая главная — У таблицы есть нижняя колонка, т.е. свойство FooterRowCount=1. Если количество отображаемых записей в таблице например 20-30% и курсор мыши двигать под данными — активная запись переходит на одну вверх с каждым движением.
2. У меня стоит свойство UseMultiTitle=true, при движении мыши над данными Title и FooterRow — мигает.
|
|
olegenty |
Отправлено: 21.12.2006, 07:46 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
версия EhLib какая?
|
|
Michael99 |
Отправлено: 25.12.2006, 06:10 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 7
|
Версия EhLib 3.6 |
|
olegenty |
Отправлено: 25.12.2006, 08:08 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
так вот, вполне вероятно, что в версии 4.1/4.2b этих проблем нет.
эксперимент поставить времени нет, сам пользуюсь 4.2b и проблем не знаю.
|
|
Michael99 |
Отправлено: 25.12.2006, 09:17 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 7
|
Я в Inete нашел только 3.6 халявную версию, поэтому рад и ей. Я полагал, может в коде Gum'a кто-нибудь из знатоков подскажет — что подправить. Может и другим пригодится исправленная версия. |
|
AVC |
Отправлено: 25.12.2006, 18:13 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE |
1. И самая главная — У таблицы есть нижняя колонка, т.е. свойство FooterRowCount=1. Если количество отображаемых записей в таблице например 20-30% и курсор мыши двигать под данными — активная запись переходит на одну вверх с каждым движением.
|
Теперь работает правильно с FooterRowCount> 0.
Заменить соответствующие файлы из прилагаемого архива.
|
|
AVC |
Отправлено: 26.01.2007, 11:46 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Новое обновление по замечаниям от Gedeon, связанных с фильтрами DBgridEh
Касается только тех, кто использует DBgridEh и её STFilter
(для остальных ни чего не изменилось)
Эта версия больше адаптирована для EhLib v4. Для компиляции c v4 нужно снять комментарий со строки
//#define EhLibV_4
в файле Gum_EtrE.h строка 15
|
|