Форум: "Прочее";
Текущий архив: 2009.08.23;
Скачать: [xml.tar.bz2];
Внизсделать для формы (фрейма, WinControl) аналог Begin/EndUpdatе Найти похожие ветки
← →
Игорь Шевченко © (2009-06-03 16:31) [0]Ситуация следующая: на ScrollBox расположено несколько фреймов, в каждом фрейме несколько контролов. По определенным условиям определенные контролы становятся невидимыми и те, что под ними, поднимаются на их место. Соответственно, общая высота фрейма тоже подстраивается.
Все бы хорошо, но медленно, потому что при каждом изменении свойства Visible, Top и.т.п контролы начинают обмениваться массой сообщений.
Сообщениями они не обмениваются только в случае csLoading in ComponentState или если не создан Handle окна для наследников TWinControl.
Немного помогает DisableAlign ... заполнение контролов, расчет видимости и положения...EnableAlign
Нет ли какого-то более радикального метода, чтобы можно было запретить отображение изменений вовсе, заполнить, посчитать, а потом отобразить одним махом ?
Фреймов много, контролов на каждом фрейме тоже много.
← →
Хитрий Лис (2009-06-03 16:36) [1]LockWindowUpdate() ?
← →
Игорь Шевченко © (2009-06-03 16:54) [2]
> LockWindowUpdate() ?
Это с самого начала сделано
То есть, общая последовательность такая
LockWindowUpdate (ScrollBox.Handle);
try
...
создание и заполнение тысячи фреймов, включая расчет видимости контролов каждого
...
finally
LockWindowUpdate(0);
end;
Все равно, каждый контрол при изменении его свойств считает, что он видимый, а GDI его отрисует так, как надо, поэтому и рассылает кучу сообщений родителю.
Хотелось бы найти способ либо не рассылать вовсе, либо свести число рассылок (и действий, ими обусловленных) к минимуму - очень не хочется фреймы менять на собственное окно, потому как контролы во фреймах должны быть функциональными (хотя бы позволять копировать текст, содержащийся в них).
Суть задачи - отобразить набор коллекций, в каждой коллекции произвольное число элементов (максимум 100), элементы каждой коллекции имеют один тип (и один вид отображения), в каждой коллекции содержатся элементы своего типа.
Разномастных коллекций десяток, каждый элемент хочется отображать в "красивом и понятном" виде, для чего для каждого элемента создается свой экземпляр фрейма.
← →
pasha_golub © (2009-06-03 18:06) [3]
> создание и заполнение тысячи фреймов
Огого... Скрин можно одним глазком? Попугаться на ночь :)
← →
oxffff © (2009-06-03 18:20) [4]
> Игорь Шевченко © (03.06.09 16:31)
Запретить неизвестному VCL контролу слать сообщения не удастся.
Но погасить реакцию на них можно.
Рекомендации.
-перекрытие Tobject.Dispatch
-перекрытие WndProc
-програлатывание WMPAINT у WndProc в качестве достойной замены
LockWindowUpdate
← →
clickmaker © (2009-06-03 18:24) [5]WM_SETREDRAW ?
← →
Игорь Шевченко © (2009-06-03 18:39) [6]oxffff © (03.06.09 18:20) [4]
Дело не в WM_PAINT - до него не доходит.
Контролы обмениваются сообщениями WM_WINDOWPOSCHANGING, WM_MOVE, WM_SIZE, CM_CHANGED и т.п.
Менять у всех контролов Dispatch - а как ты себе представляешь такую замену, а заодно и восстановление, для нормальной работы.
Я могу создавать нужные мне контролы динамически - всяко быстрее будет, но пропадает полезный эффект - так я создал фреймы в дизайнере, сделал им нужный мне вид, а потом отображаю с доработкой напильником под нужный размер (в смысле, делаю невидимыми те контролы, которые содержат незначащую информацию по данному экземпляру элемента коллекции).
С динамическим созданием я увижу только результат, и если он меня не устроит, то нужно будет долго и мучительно подбирать нужные позиции, комбинации размеров, и т.д.
← →
oxffff © (2009-06-03 19:02) [7]
> Менять у всех контролов Dispatch - а как ты себе представляешь
> такую замену, а заодно и восстановление, для нормальной
> работы.
Технически вам никто не мешает заменить (вне рамок ООП)
1.
TControl = class(TComponent)
private
FParent: TWinControl;
FWindowProc: TWndMethod;
2. TControl.procedure WndProc(var Message: TMessage); virtual;
Вопрос как сделать красиво, чтобы design time работал.
1a. Пропатчить VMT нужных классов run time для всех экземпляров зтих классов.
1.б. Патчить ссылку на VMT только у нужных объектов.
2. Пропатчить
procedure TObject.Dispatch(var Message);
asm
<- inject code run time
PUSH ESI
MOV SI,[EDX]
3. Пропатчить
procedure Tcontrol.WndProc(var Message: TMessage);
<- inject code run time
4. Пропатчить
procedure TWinControl.WndProc(var Message: TMessage);
<- inject code run time
5. До кучи, если так необходимо.
Пропатчить
procedure TWinControl.MainWndProc(var Message: TMessage);
<- inject code run time
Решение не из совсем простых. Но и задача соответсвующая.
Но решаемая с минимумом кода.
← →
oxffff © (2009-06-03 19:12) [8]
> но пропадает полезный эффект - так я создал фреймы в дизайнере,
> сделал им нужный мне вид, а потом отображаю с доработкой
> напильником под нужный размер (в смысле, делаю невидимыми
> те контролы, которые содержат незначащую информацию по данному
> экземпляру элемента коллекции).
Тогда насколько я понимаю, для нужных классов перекрыть нормальным способом
procedure Tcontrol.WndProc(var Message: TMessage);
с кодом
IF SuppressWnd then exit;
inherited WndProc(Message)
или
procedure Tobject.Dispatch
← →
Игорь Шевченко © (2009-06-03 19:18) [9]oxffff © (03.06.09 19:12) [8]
Идея понятна, но слегка затруднительна - это мне для каждого контрола надо создавать враппер и в дизайн-тайме именно этот враппер класть, потому что контролы находятся в ран-тайм пакетах.
Мне б несколько другое - мне б какой-то глобальный механизм задействовать, я уже писал, что при csLoading in ComponentState контролы сообщения не посылают.
Я к чему - может я недостаточно тщательно Controls.pas и Forms.pas изучал и пропустил какой механизм...
← →
Медвежонок Пятачок © (2009-06-03 19:21) [10]все переписать на асп.нет с помошью мультивью
:)
← →
Игорь Шевченко © (2009-06-03 19:22) [11]Медвежонок Пятачок © (03.06.09 19:21) [10]
Тогда еще больше тормозить будет :)
← →
oxffff © (2009-06-03 19:29) [12]
> Игорь Шевченко © (03.06.09 19:18) [9]
> oxffff © (03.06.09 19:12) [8]
>
> Идея понятна, но слегка затруднительна - это мне для каждого
> контрола надо создавать враппер и в дизайн-тайме именно
> этот враппер класть, потому что контролы находятся в ран-
> тайм пакетах.
Совсем необязетельно. cм. [7]-1a
Написать придется только вызов
procedure PatchVMT(Classes:Array of Tclass);
var Aclass:Tclass;
begin
for Aclass in Classes do PPointer(@(pbyte(Classes)[offset to WndProc])))^ = @MyFunc;
end;
PatchVMT([Tbutton, Tedit, TmyFrame.....]);
← →
oxffff © (2009-06-03 19:31) [13]
> PatchVMT([Tbutton, Tedit, TmyFrame.....]);
Правда это для всех экземпляров. Т.е придется все же как хотя бы по классам распределить. Как Минимум.
TMyButton=class(TButton)
end;
PatchVMT([TMyButton.....]);
:)
← →
Игорь Шевченко © (2009-06-03 19:49) [14]oxffff © (03.06.09 19:31) [13]
Не работает. Может, по теории оно и должно сработать, но на практике получается фигня. Контролы зависят-таки от сообщений :)
← →
oxffff © (2009-06-03 22:23) [15]
> Игорь Шевченко © (03.06.09 19:49) [14]
> oxffff © (03.06.09 19:31) [13]
>
> Не работает. Может, по теории оно и должно сработать, но
> на практике получается фигня. Контролы зависят-таки от сообщений
> :)
Естественно зависят.
Но никто не запрещает пропускать только подмножество сообщений CM_*.
Здесь от вас(ваших действий по оптимизации) зависит какую часть множества сообщений вы хотите пропустить, а в момент предъявления пользователю.
← →
Игорь Шевченко © (2009-06-03 22:52) [16]oxffff © (03.06.09 22:23) [15]
Увы, твое предложение лишено разумного смысла. Например, отображение Edit зависит от WM_SETTEXT, отображение CheckBox зависит от BM_SETCHECK, и т.д.
Прописывать все это в коде, да еще и отлаживать потом - это слишком длинная и чреватая ошибками работа.
В этом случае проще создавать контролы динамически заранее на нужных местах - то есть то, от чего я хочу отказаться сразу.
Собственно, тормоза ограничиваются 5..10-ю секундами при отображении десятка тысяч контролов, если не получится радикально (и безболезненно с точки зрения трудозатрат) ускорить - придется подождать, такие объемы встречаются не часто, в основном порядка тысячи-двух контролов на картинку, а то и меньше.
← →
oxffff © (2009-06-03 23:07) [17]
> Игорь Шевченко © (03.06.09 22:52) [16]
> oxffff © (03.06.09 22:23) [15]
>
> Увы, твое предложение лишено разумного смысла.
Я решал задачу
> Все бы хорошо, но медленно, потому что при каждом изменении
> свойства Visible, Top и.т.п контролы начинают обмениваться
> массой сообщений.
Но не обратил внимание на
> Нет ли какого-то более радикального метода, чтобы можно
> было запретить отображение изменений вовсе, заполнить,
> посчитать, а потом отобразить одним махом ?
Чую бухгалтерские отчеты меня делают не внимательным.
:)
Тогда естестенно для всех оберточных windows object контролов(Tedit, TButton, Tmemo.... ) запретить сообщения нельзя.
То есть насколько я понимаю вопрос исчерпан.
Ответ дан вами сами в [14].
> Контролы зависят-таки от сообщений
← →
Mystic © (2009-06-03 23:13) [18]Такой изврат так brainstorm idea. Сохранить TScrollBox в DFM, изменить нужные свойства и загрузить обратно?
← →
oxffff © (2009-06-03 23:19) [19]
> Mystic © (03.06.09 23:13) [18]
Так а разницы вроде же не будет.
Так при загрузке все равно будут дергаться методы установки соответствующих свойств с посылом сообщений.
← →
Mystic © (2009-06-03 23:25) [20]
> Так при загрузке все равно будут дергаться методы установки
> соответствующих свойств с посылом сообщений.
> Мне б несколько другое - мне б какой-то глобальный механизм
> задействовать, я уже писал, что при csLoading in ComponentState
> контролы сообщения не посылают.
← →
Игорь Шевченко © (2009-06-03 23:28) [21]oxffff © (03.06.09 23:07) [17]
В любом случае спасибо за участие.
Вопрос не то, чтобы исчерпан, путем перестановки вызовов SetParent после заполнения фрейма и подгонки его размеров и внутренностей под данные, путем установки свойства Visible в общем предке всех фреймов в false, и переустановке его в true после, опять же, заполнения и подгонки, путем запрета выравнивания на время установки свойств компонентов мне удалось ускорить вывод всей этой массы контролов (ну скажем, на 50% по сравнению с первоначальным вариантом), так что обсуждение в любом случае представляет практическую ценность.
Откуда берется такая масса контролов: существует выборка из десятка таблиц базы данных записей по некоему критерию. В каждой таблице записи разные по составу полей, объединяет их только критерий. Записей разумеется в каждой конкретной выборке разное количество, в том числе, в какой-то таблице записей может не оказаться, это не страшно. Максимальное количество не ограничивается, но отображаю я максимум сто записей.
Стоит задача максимально втиснуть на экран содержимое такой вот выборки, причем, каждое поле каждой записи желательно показать с меткой (может быть одна метка на несколько полей). Если в полях нет информации (допустим они содержат логически пустые значения), то показывать их нет смысла, чтобы не тратить место на экране.
Текст полей хочется выбирать (мышкой/клавиатурой), помещать в буфер обмена и т.д.
Поэтому для каждой таблицы был сделан свой фрейм, в котором контролы сгруппированы так, чтобы наиболее часто встречающиеся пустые значения были в одной строке. В этом случае, при показе строка просто убирается, а нижние контролы двигаются вверх, на ее место. Поля имеют разный размер, потому группировка учитывает и то, чтобы заданная площадь фрейма использовалась по максимуму. Ну и с точки зрения прикладной области, разумеется, чтобы не слишком путались.
Фреймы динамически помещаются в скроллбокс.
После выборки начинается заполнение скроллбокса фреймами с левого верхнего угла, вниз и вправо (по вертикали содержимое всех записей одной таблицы, затем содержимое всех записей другой таблицы, и, возможно третьей), в следующем "столбце" содержимое записей еще одной (возможно двух) таблиц и.т.д
Соответсвтенно, если какой-то столбец оказался пуст (не выбралось в таблицах ничего), на его место помещаяется следующий.
Вот когда выборка большая, при отображении начинаются тормоза (померено, именно при отображении, а не при выборке).
Может, я велосипед изборетаю и есть более разумное решение ?
← →
Игорь Шевченко © (2009-06-03 23:33) [22]Mystic © (03.06.09 23:13) [18]
> Такой изврат так brainstorm idea. Сохранить TScrollBox в
> DFM, изменить нужные свойства и загрузить обратно?
Думал :)
Но это тоже динамическое создание компонент конкретно по месту, от чего бы мне хотелось уйти
← →
Petr V. Abramov © (2009-06-03 23:43) [23]
> Может, я велосипед изборетаю и есть более разумное решение
> ?
похоже на разумную реализацию неразумного метода.
как тебя вывести на путь истинный :) из обсуждения мне инфы не хватает, "не чувствую" задачу.
← →
тимохов © (2009-06-03 23:45) [24]Игорь, ты меня, конечно, извини за совет, что называется, не в кассу, но я бы такую штуку однозначно делал в рантайм, вставляя все ручками.
Прямо так бы и создавал контролы в скроллбоксе без всяких там фреймов, элайнов, анкоров и прочей тормозящей функциональности.
Придется потрудиться, но зато у тебя в руках мощные инструменты настройки всего этого богатства.
Хотя тут все зависит от целевого использования данного механизма. Точнее - от частоты предполагаемых изменений в будущем.
ЗЫ Излагал ессесно из моего понимания описания задачи. Может я понял не так.
← →
Игорь Шевченко © (2009-06-03 23:55) [25]Petr V. Abramov © (03.06.09 23:43) [23]
тимохов © (03.06.09 23:45) [24]
Насчет задачи - есть десяток таблиц, в каждой записи от 10 до 30 полей :)
Все записи объединены некоторым общим критерием, по которому они выбираются. Всю выборку надо показать так, чтобы на экране уместилось максимальное количество полезной информации.
Я не совсем представляю, какой можно аналогичный пример привести, но допустим:
Есть человек. Во время его жизни у него меняются телефоны, адреса электронной почты места жительства, места учебы, работы, партнеры, в конце концов :)
Представь, что каждое изменение записано в базу (досье на него ведется), места жительства в одну таблицу, телефоны в другую, друзья в третью, и т.д. Разумеется, у каждой записи куча атрибутов, которые тоже хочется смотреть.
Вот это досье хочется максимально полно отобразить, чтобы по человеку было видна вся его история на одном экране.
(пример отвлеченный, к задаче отношения не имеет)
← →
Игорь Шевченко © (2009-06-03 23:58) [26]тимохов © (03.06.09 23:45) [24]
Почему не хочу динамически - потому что нарисовав фрейм я сгруппировал данные логически. Причем, с одной точки зрения логическая группировка одна, с другой - другая, с третьей - третья. Я ее (группировку) вижу и могу показать другому, дескать, устраивает тебя так или ты хочешь иначе сгруппировать ? Если иначе - нарисовал другой фрейм и все радостно.
Делать такие вещи в динамике мне представляется недостаточно наглядным :)
← →
oxffff © (2009-06-04 00:03) [27]
> Mystic © (03.06.09 23:25) [20]
При csLoading и csReading in ComponentState контролы могут делать все что угодно, в том числе и слать сообщения. Это не запрещено.
← →
Petr V. Abramov © (2009-06-04 00:14) [28]
> Вот это досье хочется максимально полно отобразить, чтобы
> по человеку было видна вся его история на одном экране.
а эволюцию вселенной от Большого Взрыва до Большого Агромного Коллайдера не хочется отобразить?
Я бы пошел от дизайна формы, на котором макс информации в разумных пределах, и при этом любая фигня (телефоны, личная жизнь) детализируется максимально быстро и чтоб даже дурак догадался, где кнопка детализации.
На экране один фиг все не уместишь, а если уместишь, то здохнешь че на этом экране найти.
Говорят, 5-7 - волшебгое число, что подчиненных, которыми можно эффективно управлять, это "сущностей" на экране, в которых внимание не рассеишь, копаясь.
← →
Игорь Шевченко © (2009-06-04 00:20) [29]Petr V. Abramov © (04.06.09 00:14) [28]
> Я бы пошел от дизайна формы, на котором макс информации
> в разумных пределах, и при этом любая фигня (телефоны, личная
> жизнь) детализируется максимально быстро и чтоб даже дурак
> догадался, где кнопка детализации.
Было с отдельной детализацией - неудобно. Как выяснилось, обычно люди смотрят на детализированное изображение и сразу находят те куски, которые им надо.
Когда ты смотришь на веб-страницу, скажем, мастаков, ты там не всегда видишь кнопку детализации. И количество веток больше, чем 5-7 тебя тоже не удивляет. Вот представь, что вместо начальных двух-трех строк из первого поста каждой ветки там было по одной-две строки каждого поста с первой страницы.
← →
Германн © (2009-06-04 00:21) [30]
>
> Есть человек. Во время его жизни у него меняются телефоны,
> адреса электронной почты места жительства, места учебы,
> работы, партнеры, в конце концов :)
> Представь, что каждое изменение записано в базу (досье на
> него ведется), места жительства в одну таблицу, телефоны
> в другую, друзья в третью, и т.д. Разумеется, у каждой записи
> куча атрибутов, которые тоже хочется смотреть.
>
> Вот это досье хочется максимально полно отобразить, чтобы
> по человеку было видна вся его история на одном экране.
Мне аж страшно стало! Значит теперь и авиакомпании на нас досье будут заводить?
)))
← →
MsGuns © (2009-06-04 00:23) [31]>Игорь Шевченко © (03.06.09 23:28) [21]
Аналогичную проблему решили заменой тучи контролов (причем на каждое поле минимум 2: для наименования поля и значения) на банальный стрингрид. В целях избежания торможения стрингрид прячется (самый просто способ - сетку на табшит, а перед обновлением у владельца табшита (пайждконтрола) активировать другой, неменяемый, шит)
Суть задачи была сродни твоей - есть БД с кучей таблиц - надо было нарисовать софт для универсального отображения-корректировки любого набора полей любой таблмцы (или смеси их).
← →
sniknik © (2009-06-04 00:23) [32]> Может, я велосипед изборетаю и есть более разумное решение ?
может TDBCtrlGrid?
← →
Игорь Шевченко © (2009-06-04 00:27) [33]MsGuns © (04.06.09 00:23) [31]
sniknik © (04.06.09 00:23) [32]
Гриды были. Неудобно. Грид широкий и скролировать его в двух направлениях в поисках нужной информации настолько никуда не годится, что о гридах лучше не вспоминать.
> надо было нарисовать софт для универсального отображения-
> корректировки любого набора полей любой таблмцы (или смеси
> их).
Мне не надо универсального. Мне надо логически сгруппировать поля по принципам прикладоной области, так, чтобы это было наглядно. Что, собственно, уже сделано.
Для универсальных корректировок существует масса неудобных инструментов :)
← →
Petr V. Abramov © (2009-06-04 00:30) [34]
> Игорь Шевченко © (04.06.09 00:20) [29]
из [25] я предствил себе форму, на которой мастаки отобраны, например, для приличия, по возрасту, и на ней же, на том же экране, статискика статистика постов в конференциях, история участия в ММР со всеми подробностями, фрагменты постов, сцылки на резюме ...
В общем, <с потолка>, думаю, надо кол-во условий фильтра расширить, и все.
хотя, похоже, без пива и реальной задачи подсказать тебе невозможно, стандартные ситуации ты и сам уммешь рулить.
← →
Игорь Шевченко © (2009-06-04 00:33) [35]MsGuns © (04.06.09 00:23) [31]
sniknik © (04.06.09 00:23) [32]
В принципе, у меня и получается подобие некоего грида, в котором каждая ячейка - это отдельный фрейм, с той только разницей, что пустые ячейки схлопываются.
Кроме того, значения полей надо выделять мышью, текст оттуда копировать, еще какие-то полезные действия совершать.
← →
тимохов © (2009-06-04 00:45) [36]
> Игорь Шевченко © (03.06.09 23:58) [26]
Одну вещь тебе скажу. Немного филосовскую.
По моему мнению дзен начинается там, где ты достигаешь уровня, чтобы понять - пора создавать свой DSL (domain specific language). Delphi со своим design-tim"ом - тоже DSL: той предметной области, которую видят разработчики среды.
Так получилось, что я знаю язык дельфи, но не принимаю ихний DSL - так уж получилось. Поэтому я по молодости писал свои DSL на любой случай. Сейчас поумнел. Начал, наконец, разделять случаи, когда можно и стандартом пользоваться, а когда ну никак не могу -нужно писать свое.
В общем тут важно что? Понять, а нужно ли упираться в стандарт - может он тебя только держит. Может ты напряжешься денек, напишешь свою библиотечку под это дело, опишешь ее. И будет внятнЕй и понятней, чем сейчас?
В общем - я бы написал свое )
← →
Игорь Шевченко © (2009-06-04 00:51) [37]тимохов © (04.06.09 00:45) [36]
Серьезную вещь за денек не напишешь, а на несерьезную тратить время не стоит.
Delphi в данном случае удобна чем - можно быстро надизайнить, посмотреть, повертеть со всех сторон, не понравилось - написал иначе.
В принципе, я задавал вопрос на тему, может, существует какая-то неизвестная мне гайка/набор гаек, которые позволят безболезненно сделать аналог BeginUpdate/EndUpdate.
Если не существует, ну что же - будем с тормозами жить :)
← →
Eraser © (2009-06-04 03:55) [38]а как оно себя ведет в висте, с включенным аеро?
← →
oxffff © (2009-06-04 09:17) [39]
> Игорь Шевченко © (04.06.09 00:51) [37]
Посмотрите oxffff © (04.06.09 00:03) [27].
При csLoading и csReading in ComponentState посылка сообщения проиходит.
Однако вот код который подавляет обработку(хотя для произвольных контролов никто не мешает обработать)
procedure TWinControl.DefaultHandler(var Message);
begin
if FHandle <> 0 then
begin
Отсюда делаем вывод. Нужно устанавливать 0
(не не будем же рушить окно :) ) до вашей обработки.
И востанавливать после.
← →
Игорь Шевченко © (2009-06-04 10:43) [40]oxffff © (04.06.09 09:17) [39]
[39]
> При csLoading и csReading in ComponentState посылка сообщения
> проиходит.
[27]
> При csLoading и csReading in ComponentState контролы могут
> делать все что угодно, в том числе и слать сообщения. Это
> не запрещено.
Тебе не кажется, что это несколько разные утверждения ? То есть, наличие МПХ у индивидуума еще не означает, что он тут же начнет насиловать все, что движется.
> Однако вот код который подавляет обработку(хотя для произвольных
> контролов никто не мешает обработать)
>
> procedure TWinControl.DefaultHandler(var Message);
> begin
> if FHandle <> 0 then
> begin
>
> Отсюда делаем вывод. Нужно устанавливать 0
> (не не будем же рушить окно :) ) до вашей обработки.
> И востанавливать после.
Все у тебя по теории хорошо, но без практики она мертва. Ты забываешь, что есть TGraphicControl и его наследники, ты забываешь, что есть такой способ вызова обработчика сообщений, как Perform.
Страницы: 1 2 3 вся ветка
Форум: "Прочее";
Текущий архив: 2009.08.23;
Скачать: [xml.tar.bz2];
Память: 0.6 MB
Время: 0.006 c