|
Вопрос # 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 (статус: 4-ый класс), 8 февраля 2009, 19:57 [#6]:
Если мне память не изменяет, сообщения WM_KEYPRESS несуществует, есть только WM_CHAR.
PS А как нaсчет перегрузки методов WndProc или DefaultHandler
|
|
Виталий (статус: 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 (статус: 4-ый класс), 8 февраля 2009, 20:23 [#8]:
inherited помоему тут не нужно
|
|
Виталий (статус: 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 (статус: 4-ый класс), 8 февраля 2009, 20:32 [#11]:
Вот что мне кажется странным ... судя по твему коду должно произойти зацикливание, т.к. ApplicationEvents1Message должен обрабтывать все сообщия приходящие приложению. А SendMessage не возвращается до завершения обработки сообщения
|
|
Виталий (статус: 2-ой класс), 9 февраля 2009, 05:45 [#12]:
Зацикливания нет. Просто идёт перехват сообщений при нажатии клавиш, когда компонент является активным окном. Ему напрямую шлётся сообщение о клавише, в обход всего приложения, а в нём уже и идёт обработка. Другие сообщения не задерживаются.
|
|
Amidamaru (статус: 4-ый класс), 9 февраля 2009, 10:54 [#13]:
SendMessage это API функция, а не делфи. Она отправляет сообщение не напрямую компоненту, а дескриптору окна и это сообщение ДОЛЖНО быть обработано в Application (это единственный компонент который именно обрабатывает сообщения) а значит должно попасть и в OnMessage объекта ApplicationEvents
|
|
Виталий (статус: 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 (статус: 4-ый класс), 9 февраля 2009, 21:46 [#16]:
Не верю. Проверил. ^^ Извините, она действительно напрямую вызывает WndProc .
Тогда я даже не знаю, в чем может быть проблема.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|