Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Hello, World!
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  09:37[Войти] | [Зарегистрироваться]

Обсуждение материала
Message методы, или обработка сообщений классами
Полный текст материала


Другие публикации автора: Сергей Галездинов

Цитата или краткий комментарий:

«... Данная статья предназначения для более глубокого понимания того, как реализована обработка сообщений Windows в VCL и как это можно и нужно использовать в своих целях и использовать правильно. ...»


Важно:
  • Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
  • Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
  • При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
  • Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.



Добавить свое мнение.

Результаты голосования
Оценка содержания

  Содержит полезные и(или) интересные сведения
[1]571.4%
 
  Ничего особенно нового и интересного
[2]114.3%
 
  Написано неверно (обязательно укажите почему)
[3]114.3%
 
Всего проголосовали: 7

Оценка стиля изложения

  Все понятно, материал читается легко
[1]685.7%
 
  Есть неясности в изложении
[2]114.3%
 
  Непонятно написано, трудно читается
[3]00%
 
Всего проголосовали: 7




Смотрите также материалы по темам:
[Структура VCL-приложения] [Отправка и получение сообщений]

Комментарии жителей
Отслеживать это обсуждение

Всего сообщений: 24

02-07-2009 04:00
В моем случае реализовано в основном потоке, все работает. Можете пояснить, что Вы имели в виду?

Ага, точно. Это вы из другого потока шлете, неверно понял. А имел в виду вот что: если вы создаете окно в другом потоке и в нем же хотите ловить и обрабатывать сообщения, то в коде потока необходимо самому создать цикл извлечения сообщений на GetMessage. Иначе сообщения в очередь складываться будут, а вот извлекаться и доставляться окну - нет. Но это не ваш случай, в главном потоке у вас цикл выборки сообщений уже есть, так что ничего предпринимать по этому поводу не нужно.
 Ins


02-07-2009 03:42
В моем случае реализовано в основном потоке, все работает. Можете пояснить, что Вы имели в виду?


02-07-2009 02:28
Только в этом случае нужно цикл выборки сообщений на Get(Peek)Message в функции потока реализовать самому.

Хотя, это нужно в любом случае. И в первом - тоже, если окно создано неосновным потоком.
 Ins


01-07-2009 07:01
Как бы соорудить аналог PostMessage для объекта без Хэндла? Вот тут это и сделано http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1169 Используется PostThreadMessage

взгляните как реализован в RTL TPopupList к примеру Если создавать невидимое окно, то можно еще посмотреть реализацию TTimer
 Cep


01-07-2009 06:59
Здорово, когда профессионалы еще и просто хорошие люди! :-)


01-07-2009 06:49
Неужели создавать его ручками??

Обычно так и делают: AllocateHWND создает невидимое message-only окошко (вызовите в конструкторе, хэндл сохраните), а в методе, который вы передадите параметром, вызывайте Dispatch. Тогда такому окошку можно и Send и Post слать. PS: Только не забудьте две вещи: вызывать DefWindowProc и по окончанию работы - DeallocateHWND. PPS: можно не создавать окно, а слать сообщения прямо потоку через PostThreadMessage. Только в этом случае нужно цикл выборки сообщений на Get(Peek)Message в функции потока реализовать самому.
 Ins


01-07-2009 06:47
Да, пришлось пойти по этому пути. Хоть и некрасиво, мне кажется... Смотрю в исходниках, как сделан TForm. Спасибо за ответы!


01-07-2009 06:45
сообщение от автора материала
что мешает реализовать свое окно? там есть хендл, очередь сообщений будет работать. В чем проблема?
Если интересно - взгляните как реализован в RTL TPopupList к примеру. Общеизвестный прием


01-07-2009 06:33
'Ну как бы данный механизм не был предназначен для подобных извратов:)'
Как же в таком случае реализовать сбор и обработку данных? Вроде бы, такая схема часто предлагается... А для SendMessage/PostMessage отсутствует Handle. Неужели создавать его ручками??


01-07-2009 06:29
сообщение от автора материала
Ну как бы данный механизм не был предназначен для подобных извратов:) Реализовать очередь можно как угодно. Как фантазия разыграется. Но я бы все-таки порекоммендовал бы юзать SendMessage/PostMessage как более уместные здесь, ибо врядли вы сделаете настолько же thread-safe реализацию


01-07-2009 06:25
Понадобилось для того, чтобы генерировать сообщения из потока, в котором реализовано чтение данных из СОМ-порта. По приходу сообщений нужно инициировать расчеты. А как сделать аналог системной очереди сообщений? Неужели опять ручками, посредством TThread? Где можно посмотреть что-нибудь подобное? Спасибо.


01-07-2009 06:19
сообщение от автора материала
реализуйте свой аналог системной очереди сообщений, только вместо хендла закладывайтесь на объекты
Только честно говоря непонятно для чего вам это понадобилось


01-07-2009 06:15
Если Dispatch будет работать в контексте вызывающего потока, то он нам не нужен. Как бы соорудить аналог PostMessage для объекта без Хэндла?


07-04-2009 23:18
2 DRON

Причина такого поведения кроется, скорее всего, в желании повысить производительность.

Дело скорее не в желании, а просто в наличии такой возможности :) Текущий класс на этапе компиляции точно известен, предок - тоже, ничто не мешает вычислить адрес статически, в отличии от вызова виртуального или динамического метода "извне".
 NS


16-02-2009 07:44
афтор, пеши исчо! +1
 Cep


16-02-2009 06:41
Собственная выгода :)

Кстати да :) message-методы - это на самом деле гибкий и элегантный механизм, аналогов которого в других языках я не видел. Он имеет смысл и вне обработки Windows-сообщений, а пишут на эту тему увы очень мало. :( Если отвлечься от того, что это методы для обработки сообщений Windows, и посмотреть на них с другой точки зрения, то возможности открываются очень широкие. А вот собственно эта другая точка зрения:
- Существует возможность ассоциировать определенный метод с целочисленным индексом
- Существует возможность вызова такого метода по индексу, не известному на этапе компиляции
- Метод может быть перекрыт в потомках и его вызов по индексу полиморфен.

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

А с практической точки зрения - это элегантный способ избавления от длинных case-ов, причем с описанием case-а (и возможностью вызова) в базовом предке, а обработкой - в потомках. Такой вот объектно-ориентированный case.

Достаточно того, чтобы структура имела первое поле типа DWORD, чтобы можно было осуществить переход по адресу, равному числовому значению этого поля.

Если копнуть глубже, то даже это условие не обязательно, учитывая что Dispatch - виртуальный ;-) Эх, жаль только что компилятор позволяет ассоциировать message-методы с весьма ограниченным набором значений.
 Ins


05-02-2009 05:52
сообщение от автора материала
Теперь автор и копирайт указаны:) даже большими буквами и в начале, так что без паники:)


04-02-2009 11:47
Опять:

http://www.interface.ru/home.asp?artId=19705

Автор не указан. Правда, в конце есть маленькая ссылочка на оригинал...


03-02-2009 09:31
Было интересно почитать, т.к. сам не пользовался подобным механизмом.


31-01-2009 13:47
этот метод располагается в vmt по адресу, кратному числовому значению сообщения, стоящего после ключевого слова message.
Нет, в VMT находится только указатель на DMT, а сама DMT состоит из двух массивов: идентификаторов и указателей на соответствующие методы. Вообще в HelloWorld можно было ничего не писать про внутреннюю организацию, кому надо тот посмотрит исходник, но раз уж написал...
Код примера:
procedure WMNull(var Message: TMessage); message WM_NULL;
Приведёт к ошибке компиляции, причём причины этого описаны в самой статье ;-)
Пусть в обработчике будет произведен вызов inherited. Метод динамический, поэтому будет производиться поиск среди message методов родителя (то есть TControl).
Это не так: для динамических методов компилятор производит связывание inherited ещё на этапе компиляции. То есть, грубо говоря, поиск по DMT производится только внутри Dispatch, а все методы предков (или DefaultHandler в случае их отсутствия) вызываются как обычные статические методы. Причина такого поведения кроется, скорее всего, в желании повысить производительность (сообщений приходит много, а поиск по DMT не быстрый).
Достаточно того, чтобы структура имела первое поле типа DWORD, чтобы можно было осуществить переход по адресу, равному числовому значению этого поля.
Не DWORD, а WORD. Это кстати приводит к "забавным" глюкам: например сообщение посланное таким образом "SendMessage(Handle, WM_USER or $10000, 0, 0);" пройдёт мимо "case Message of ... WM_USER:...", но попадёт в обработчик "...;message WM_USER". Это можно использовать для "пробивания" сообщения через WndProc в ситуациях аналогичных той, что описана в "Подводные камни".
Почему 49151?
Первопричина не в наличии RegisterWindowMessage, а в том что компилятору нужно некоторое количество свободных слотов для обычных (не message) динамических методов. Если не ограничить диапазон для message методов, то Dispatch мог бы приводить к вызову обычных dynamic методов, что не есть хорошо.
 DRON


31-01-2009 02:56
сообщение от автора материала
Про MainWndProc - каюсь, mea culpa:)
Про проблемы с сабклассингом - даже если прямой вызов Dispatch и противоречит правильной работе VCL, тем не менее проблема от этого не перестала существовать и нужно быть к этому готовым:)

Правильнее было бы сказать, что Dispatch всегд обрабатывает сообщение в той нити, которая его вызвала, а не в той, которая создала окно.
Ну, это было написано применительно к использованию message-методов для своей выгоды. Это не обязательно должна быть обработка сообщений для окон. Если класс, его данные, является разделяемым ресурсом при использовании в нескольких потоках, то Dispatch будет работать в контексте вызывающего потока, а не в главной нити. То есть ни о какой синхронизации потоков не может быть и речи. Если многие привыкли при использовании окон и SendMessage, что поток будет остановлен и дожидаться, когда сообщение будет обработано в другом потоке, создавшем окно, то тут нужно быть аккуратным и проводить синхронизацию самому.


30-01-2009 23:34
Сергей, я ведь вам обещал, что если некоторые принципиальные моменты вы не исправите, мне придётся писать отрицательный отзыв? Обещал. Так что теперь не обижайтесь :)

которая, как известно получается из приведения WndProc к виду, которому требует Windows через MakeObjectInstance

WndProc не "приводится к требуемому виду" с помощью MakeObjectInstance. MakeObjectInstance строит оконную процедуру на основе MainWndProc, а не WndProc. В одном месте вы это исправили, а здесь вот осталось.

В чём противоречия сабклассинга и message-методов, я так и не понял. В нормальных условиях перекрытая оконная процедура срабатывает существенно раньше, чем Dispatch, и если сообщение не доходит до message-метода, значит, так было задумано при перекрытии. Обход же перекрытой оконной процедуры в случае приямого вызова Dispatch проблемой не является, т.к. прямой вызов Dispatch извне для визуального компонента - это уже проблема сама по себе, безотносительно сабклассинга. При этом обходится WndProc, которая содержит важный для правильной работы VCL код.

Dispatch — это не SendMessage, при передаче сообщения классу в потоке с другим контекстом остановки потока не будет!

Не совсем верная фраза. Dispatch не работает асинхронно, он вернёт управление только после того, как сообщение будет полностью обработано. Правильнее было бы сказать, что Dispatch всегд обрабатывает сообщение в той нити, которая его вызвала, а не в той, которая создала окно.


30-01-2009 18:57
сообщение от автора материала
Собственно, изначально статья так и планировалась :) Дать затравку. Но по ходу написания и исправления статьи приходилось уточнять и уточнять, и в итоге на статью для чего-то большего, чем Hello World это недотянуло, а для Hello World слишком много информации:) А описывать всю работу VCL в этой статье не планировалось - так что извините, первый ком блином:)


30-01-2009 17:04
Больше всего мне нравятся статьи из цикла Hello, world!
т.к. обычно туда пишут то, что все знают, все используют, но не все до конца понимают.
а вот чтобы в доступной форме раскрыть подлинную красоту, кот-ую закладывали разработчики, и пишутся такие статьи.

вот тут такого нет. тема - интересная, написано - неплохо. но вот для кого - непонятно. для новичка... - ну только если ему постоянно на пути встречаются фразы типа
private
procedure MyCoolHandler(var Message: TMessage); message WM_USER;
, а таких новичков, наверное, немного.

а для того, кто уже задумался - ничего особо нового.

резюме:
в HelloWorld надо выкладывать только основной смысл - что, зачем и (очень приблизительно!) как делается. все остальное человек сам найдет, если тема интересна.
а в следующий уровень - недотягивает.

ЗЫ: афтор, пеши исчо! мы любим читать. и твои статьи нам тоже нравятся.


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Жил-был у бабушки серенький КТО?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.

Оценка содержания
 
Содержит полезные и(или) интересные сведения
 
Ничего особенно нового и интересного
 
Написано неверно (обязательно укажите почему)


Оценка стиля изложения
 
Все понятно, материал читается легко
 
Есть неясности в изложении
 
Непонятно написано, трудно читается

Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования