Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 2 404

/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
Делаю компонент на основе TCustomControl. Он представляет собой что-то вроде списка, который у каждой записи имеет несколько полей. Из стандартных компонентов сделать токое не получится.
Как сделать нормальное получение фокуса ввода для компонента?
Ещё мне нужно при нажатии стрелок вверх и вниз перемещать выделение, как это осуществить?

Виталий Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: Виталий (статус: 2-ой класс)
Вопрос отправлен: 8 февраля 2009, 08:47
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 16; последнее сообщение — 9 февраля 2009, 21:46; участников в обсуждении: 4.
Косолапов Дмитрий Юрьевич

Косолапов Дмитрий Юрьевич (статус: 8-ой класс), 8 февраля 2009, 11:31 [#1]:

И все-таки посмотрите на стандартный компонент ListView в режиме (ViewStyle) vsReport.
Виталий

Виталий (статус: 2-ой класс), 8 февраля 2009, 11:43 [#2]:

Стандартные компоненты и, в частности, ListView, мне не подходят, т.к. у меня особая отрисовка и перемещение элементов. Со всеми функциями у меня проблем нет, только клавиши остались.
Щяс делаю через ApplicationEvents.OnMessage (при клавише и активном контроле делаю отправку сообщения о нажатой клавиши компоненту), но хочется автоматизировать это в компоненте
Вадим К

Вадим К (статус: Академик), 8 февраля 2009, 14:07 [#3]:

НЕ понимаю, зачем изобретать велосипеды и делать полностью свою прорисовку всего. Конечно, можно, и это не так сложно - надо только обрабатывать нужные сообщения.
Но можно сделать проще и красивее. Берём стандартный ListView или ListBox (Да, да да, Косолапов Дмитрий Юрьевич абсолютно прав, просто он не договорил до конца идею) и включаем там стили style = lbOwnerDrawVariable (Это для ListBox). Теперь он стает полностью Ваш. Можно ручками рисовать каждый элемент и самостоятельно указывать его высоту. А выделенным или нет надо его рисовать - это сам лист сообщит.
Пойдём с другой стороны. Вы пишете, что все события перехватываете в OnMessage и оттуда управляете своим компонентом? Это всё равно, что ехать на машине, у которой не руля, и её дубинками с соседних машин направляют на правильный путь. Десять подобных компонентов на форме вы ещё как то перенесете, а вот если они будут на разных - придётся копировать кучу кода. Но если появиться ещё один подобно управляемый компонент - это будет трагедия.
Вообще то компоненты умеют сами обрабатывать события, которые предназначены для них. И сделать это просто. Первым долгом нужно определиться, какое надо событие. Например клик мышки - это WM_CLICK, нажатие кнопки на клавиатуре - WM_CHAR. Пусть мы решили обработать нажатие. Для этого в секции private (или protect, если планируются наследники), надо добавить строку вида
procedure MyCharSend (var msg:TMessage); message WM_CHAR;
Далее жмем Ctrl+Shif+C и опа, делфи сделала нам обработчик. Но полностью проблему мы не решили. Мы ещё не знаем, какую кнопку нажал пользователь. Но эта информация храниться в структуре TMessage, в параметрах lParam и wParam. Для этого идем в MSDN (www.msdn.com), и ищем свое событие. Там будет и описание.
Но для многих событий разработчики уже решили эту проблему - они создали необходимые структуры. Они хранятся в файле Message.pas. В случае с нашим событием, это будет TWMChar. Это значит, что нужно заголовок переписать как
procedure MyCharSend (var msg:TWMChar); message WM_CHAR;
И структура msg теперь будет иметь нужные поля.
Галочка "подтверждения прочтения" - вселенское зло.
Виталий

Виталий (статус: 2-ой класс), 8 февраля 2009, 18:35 [#4]:

Спасибо за развёрнутый ответ, но повторю : ни один компонент не может обеспечить нужную мне функциональность. Я привык уже изобретать велосипед, это для меня легче).
Я делал через :
procedure CharSend (var msg:TMessage); message WM_CHAR;
procedure KeySend (var msg:TMessage); message WM_KEYDOWN;

НО! Сообщения при нажатии стрелок никакого сообщения на компонент не приходит!!! Поэтому и спрашиваю.
Вадим К

Вадим К (статус: Академик), 8 февраля 2009, 19:36 [#5]:

а WM_KEYPRESS пробовали?
Галочка "подтверждения прочтения" - вселенское зло.
Amidamaru

Amidamaru (статус: 4-ый класс), 8 февраля 2009, 19:57 [#6]:

Если мне память не изменяет, сообщения WM_KEYPRESS несуществует, есть только WM_CHAR.

PS А как нaсчет перегрузки методов WndProc или DefaultHandler
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Виталий

Виталий (статус: 2-ой класс), 8 февраля 2009, 20:07 [#7]:

ничего не помогает, сейчас делаю так

procedure TMainForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_SYSKEYDOWN))
and (Self.ActiveControl = box_Playlist) then
begin
SendMessage(box_Playlist.Handle, WM_KEYDOWN, Msg.wParam, msg.lParam);
Handled := true;
exit;
end;
inherited;
end;
Amidamaru

Amidamaru (статус: 4-ый класс), 8 февраля 2009, 20:23 [#8]:

inherited помоему тут не нужно ;)
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Виталий

Виталий (статус: 2-ой класс), 8 февраля 2009, 20:26 [#9]:

ничего не помогает, сейчас делаю так

procedure TMainForm.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean);
begin
if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_SYSKEYDOWN))
and (Self.ActiveControl = box_Playlist) then
begin
SendMessage(box_Playlist.Handle, WM_KEYDOWN, Msg.wParam, msg.lParam);
Handled := true;
exit;
end;
inherited;
end;
Виталий

Виталий (статус: 2-ой класс), 8 февраля 2009, 20:27 [#10]:

возможно)))
Amidamaru

Amidamaru (статус: 4-ый класс), 8 февраля 2009, 20:32 [#11]:

Вот что мне кажется странным ... судя по твему коду должно произойти зацикливание, т.к. ApplicationEvents1Message должен обрабтывать все сообщия приходящие приложению. А SendMessage не возвращается до завершения обработки сообщения
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Виталий

Виталий (статус: 2-ой класс), 9 февраля 2009, 05:45 [#12]:

Зацикливания нет. Просто идёт перехват сообщений при нажатии клавиш, когда компонент является активным окном. Ему напрямую шлётся сообщение о клавише, в обход всего приложения, а в нём уже и идёт обработка. Другие сообщения не задерживаются.
Amidamaru

Amidamaru (статус: 4-ый класс), 9 февраля 2009, 10:54 [#13]:

SendMessage это API функция, а не делфи. Она отправляет сообщение не напрямую компоненту, а дескриптору окна и это сообщение ДОЛЖНО быть обработано в Application (это единственный компонент который именно обрабатывает сообщения) а значит должно попасть и в OnMessage объекта ApplicationEvents
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.
Виталий

Виталий (статус: 2-ой класс), 9 февраля 2009, 12:39 [#14]:

SendMessage(box_Playlist.Handle, WM_KEYDOWN, Msg.wParam, msg.lParam);
Handled := true;
exit;

я посылаю сообщение индивидуально и напрямую к компоненту.
Виталий

Виталий (статус: 2-ой класс), 9 февраля 2009, 12:47 [#15]:

проверьте как-нибудь на досуге, если не верите
Amidamaru

Amidamaru (статус: 4-ый класс), 9 февраля 2009, 21:46 [#16]:

Не верю. Проверил. ^^ Извините, она действительно напрямую вызывает WndProc .

Тогда я даже не знаю, в чем может быть проблема.
Приглашаю Вас на наш IRC-канал: #delphiintru в сети DalNet.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:43
Выполнено за 0.02 сек.