Головна сторінка
Top.Mail.Ru Яндекс.Метрика
Форум: "пошарпану";
Поточний архів: 2003.04.28;
Завантажити: [xml.tar.bz2];

Вниз

Обробка повідомлень в Windows Знайти схожі гілки


Top Gun   (2003-03-31 00:19) [0]

Люди, вот почитав Пачеко и Тейксера про обработку сообщений в windows, осталось много неясностей.

Ощущение, что авторы многое опускает. Помогите разобраться.

1) Итак, если отойти от VCL, получается, что в каждой программе есть класс TWNDClass

В котором параметр lpfnWndProc указывает на функцию, получающую все сообщения, адресованные приложению. Если тип сообщения подразумевает ответ, то оно возвращается в Result этой функции.
Также есть defwindowproc, которая обрабатывает больщую часть стандартных сообщения для приложения.

Сразу вопрос - а что, если в приложении сделать два TWNDClass класса и каждому назначить lpfnWndProc ?
a) Что тогда будет происходить ?

б) У меня уверенность, что и здесь Дельфи сильно облегкчает работу. Неужели создание приложения чисто на WinApi в VC происходит точно также ?

в) Читая ветви на этом сайте наткнулся на процедуры, типа PeekMessage, которые вроде как служать для выборки сообщений из очереди. Ничего не понимаю, даже программируя на чистом WinApi я не использую эти функции... почему ?

2) Вышеприведенное это полбеды. А если учитывать VCL ?

Если вот просто создать новый Application, пустая форма. Откомпилировать.
a) Где там этот самый TWNDClass и lpfnWndProc ?

б) Самый объемный вопрос. Как происходит обработка сообщения при использовании VCL ? Где используются записи TMessage, где TMsg, что за ProccessMessage такое? Где обрабатываются сообщения требующие ответа и где не требующие... что за DefaultHandle?
Как понимаю, все равно все сообщения приходят в главную функцию программы, определенную lpfnWndProc (все это скрыто в дебрях VCL). А потом, куда они перенаправляются ? Какой путь проходят ? В книжке все не очень подробно. Начинается словами:
"Любое сообщеие windows, посланное без требования получения результатов обработки, первоночально обрабатывается методом Application.ProccessMessage()"
Ну как понимаю это уже надстройки VCL. А первоночально, начиная от lpfnWndProc, что происходит ?

в) Цитата: " Для обработки сообщений, посылаемых с требованием предоставления результатов их обработки, неявно вызывается функция API Win32 DispatchMessage()"

Хм. Вот когда я писал на чистом Win32Api я не вызывал никакой DispatchMessage. Ведь можно просто вернуть результат в функции на которую ссылается lpfnWndProc.

Огромная просьба ответить по пунктам (особенно, конечно, пункт 2б).

Заздалегідь дякую !



Palladin   (2003-03-31 00:31) [1]

если посмотришь в файл проекта увидишь там незамысловатую строчку
Application.Run

вот с нее то все и начинается :))



DrPass   (2003-03-31 00:54) [2]

Видимо, ты плохо читал, иначе бы ты понял.
1а Сколько бы ты не делал процедур обработки сообщений, при создании окна указывается только один класс. И его только его оконная функция будет обрабатывать сообщения этого окна.
1б Смотря что ты имеешь в виду. Если обработку сообщений в методах класса через директиву message, то это фишка Delphi. Если обработку сообщений оконной функцией, то это обычный WinAPI. И в VC, и в VB, и везде.
1в. Потому что не пригодилась

2а. TApplication сам по себе тоже создает окно. Только невидимое. И в нем тоже есть цикл обработки сообщений.
2б. Блин, если тебе все это интересно - возьми исходники и посмотри. Или ты думаешь, что тебе здесь учебник программирования напишут?



Top Gun   (2003-03-31 14:17) [3]

Хотелось бы более подробный ответ про 2б

Не учебник программирования, а просо четко с самого начала (с lpfnWndProc) куда какие сообщения идут.

Или ссылочку на статью, где все описано.

Потому что в книге написано плохо, хотя читал я хорошо, раз 10. Я уже процетировал как там начинается:
"Любое сообщеие windows, посланное без требования получения результатов обработки, первоночально обрабатывается методом Application.ProccessMessage()"

А мне бы с самого начала, как в VCL все это организовано...

Смотря в исходники я мало что пойму. Потому что не профи. Был бы профи - не задавал таких бы вопросов



Polevi   (2003-03-31 14:50) [4]

procedure TApplication.Run;
починати
FRunning := True;
намагатися
AddExitProc(DoneApplication);
if FMainForm <> nil then
починати
case CmdShow of
SW_SHOWMINNOACTIVE: FMainForm.FWindowState := wsMinimized;
SW_SHOWMAXIMIZED: MainForm.WindowState := wsMaximized;
end;
if FShowMainForm then
if FMainForm.FWindowState = wsMinimized then
Minimize else
FMainForm.Visible := True;
повторювати
HandleMessage
until Terminated;
end;
в кінці кінців
FRunning := False;
end;
end;


procedure TApplication.HandleMessage;
було
Msg: TMsg;
починати
if not ProcessMessage(Msg) then Idle(Msg);
end;


function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
було
Handled: Boolean;
починати
Result: = False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
починати
Result: = True;
if Msg.Message <> WM_QUIT then
починати
Handled: = False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
починати
TranslateMessage (Msg);
DispatchMessage (Msg);

end;
кінець
ще
FTerminate := True;
end;
end;



Top Gun   (2003-04-01 16:30) [5]

Polevi, я здесь мало что понимаю :(

Мне бы простыми словами все объяснить...



Danilka   (2003-04-01 16:38) [6]

Top Gun (31.03.03 14:17)
>Смотря в исходники я мало что пойму. Потому что не профи.

Честное слово, исходники библиотек дельфи написаны так хорошо, что их поймет даже не профи. Всем-бы так красиво писать.



Top Gun   (2003-04-03 20:02) [7]

Ладно, если у кого есть ссылки на информацию (статьи) по сабжу - поделитесь, пожалуйста



Top Gun   (2003-04-04 19:08) [8]

Нету ? :(((



Top Gun   (2003-04-05 14:23) [9]

ех



Anatoly Podgoretsky   (2003-04-05 14:37) [10]

Наряду с Пачеко надо прочитать еще и Рихтера, они не брали на себя труд по добавлению еще одного тома посвященно Win API тем более имя в лице такого мощного конкурента.
Кроме того если уж работать с Win API то не обойтись без MSDN



nikkie   (2003-04-05 20:25) [11]

>Top Gun
Ты как-то пропустил самое главное. Кроме регистрации WNDCLASS и реализации соответствующей WndProc в приложении должен быть написан цикл выборки сообщений. Непонятно, как ты мог писать приложения на апи, не зная об этом (разве что делая приложение-диалог).

Стандартная схема апи-приложения такая:

// 1. регистрируем класс
wc.hInstance = ...
wc.lpfnWndProc = ...
...
wc.lpszClassName = "название класса";
RegisterClass (wc);

// 2. создаем окно
hwnd = CreateWindow("название класса", ...);
ShowWindow(hwnd, SW_SHOW);

// 3. входим в цикл выборки сообщений
while(GetMessage(&msg, ...))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

Если основное окно приложения - диалог, то пункты 2 и 3 могут быть заменены на DialogBox(...) - эта функция создаст окно и запустит цикл выборки сообщений сама.



Top Gun   (2003-04-06 19:44) [12]

nikkie, это я, конечно, писал.
И есть вопросы:

1) Я говорил про PeekMessage - я его не использовал. И не понимаю зачем использовать, если есть GetMessage

2) До сих пор не очень въехал зачем нужно DispatchMessage (справку смотрел).



nikkie   (2003-04-06 22:32) [13]

>1) И не понимаю зачем использовать PeekMessage, если есть GetMessage

Unlike GetMessage, the PeekMessage function does not wait for a message to be posted before returning.

Кроме этого, у PeekMessage на 1 параметр больше - ее можно использовать, чтобы проверить наличие сообщения в очереди, но не забирать его оттуда.

>2) До сих пор не очень въехал зачем нужно DispatchMessage

А как иначе сообщение полученное с помощью GetMessage попадет в wndproc? Цитата, которую ты привел в первом посте, говорит, что сообщения, отправленные с помощью SendMessage, не попадают в цикл выборки сообщений и ты не вызываешь DispatchMessage для них, но DispatchMessage вызывается для них неявно самой системой.


Top Gun (06.04.03 19:44)
>это я, конечно, писал.

Top Gun (31.03.03 00:19)
>Вот когда я писал на чистом Win32Api я не вызывал никакой DispatchMessage.


Противоречишь сам себе.

Судя по первому посту, пока у тебя присутствует какое-то капитальное непонимание, как работает программа под windows. Конкретные вопросы про функции могут тебя только запутать, пока общая схема не будет понятна. Попробуй обмозговать следующие вещи:

1. WndProc вовсе не главная функция программы. Главная функция на C - WinMain, на дельфи - между begin и end в *.dpr. Там пишется цикл выборки сообщений - вот основная логика win-приложения.

2. В одной программе может быть сколько угодно реально используемых WndProc. Окон в программе может быть много, окна могут быть разные, разных классов. Обычно разные классы используют разные wndproc (никто не запрещает регистрировать разные классы с одной и той же wndproc, но смысла в этом мало).



p77   (2003-04-07 02:04) [14]

2 Anatoly Podgoretsky:
По Вин32АПИ можно читать и не только, и не столько Рихтера, есть и другие: Петцолд, Питтрек, Соломон, Небетт, Гудман, Румянцев, Фроловы и др., просто Рихтер - самый известный.
Вы правы - без MSDN здесь ни в зуб ногой:).



Top Gun   (2003-04-07 19:29) [15]

nikkie, ага ! Кажется, я начал кое-что понимать.

То есть, сообщение "без ответа" попадает в очередь сообщений приложения, откуда "забирается" циклом выборки сообщений. И потом (необязательно) пересылается в главную процедуру окна для которой послано сообщение функцией DispatchMessage?

Если же сообщение "с ответом", то оно сразу перенаправляется главной процедуре окна для которого адресовано сообщение?

Если я все правильно понял, то нафига вообще главной функции забирать сообщения из потока, то есть, зачем вообще сообщения складываются в поток ? Пусть бы сразу пересылались главным функциям тех окон для которых адресованы. Ведь все равно так оно и получается - в главной процедуре сообщение выбирается из потока для того, чтобы быть посланным в MainWindowdProc



nikkie   (2003-04-08 00:01) [16]

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

1. "Главная процедура окна" - это называется просто "оконная процедура". Она у окна одна-единственная :)

2. Сообщение "без ответа", "с ответом" - непонятно почему ты их так называешь. Сообщения могут быть посланы окну двумя путями - через SendMessage и PostMessage (есть еще возможность послать сообщение в очередь потока, не адресуясь конкретному окну, с помощью PostThreadMessage). Большинство сообщений могут быть отправлены как с помощью SendMessage (сообщение отправляется сразу в оконную процедуру), так и с помощью PostMessage (сообщение попадает в очередь потока, в котором окно было создано). В ответ на любое сообщение оконная процедура вернет некоторый результат, независимо от того, как сообщение было отослано. Более того, в оконной процедуре уже невозможно определить каким образом было отправлено сообщение. Поэтому термины "с ответом" и "без ответа" как-то не очень... В английском используются термины sent и posted. Есть ли для них общепринятый перевод на русский, я не знаю.

Некоторые фактические неточности в твоем последнем посте (я бы мог, конечно, не придираться, но надеюсь, это поможет тебе лучше понять ситуацию).

3. "в очередь сообщений приложения" - очередь создается не для приложения, а для каждого потока приложения. Точнее,
The system creates a thread"s message queue when the thread makes its first call to one of the Win32 User or GDI functions.

4. "сообщения складываются в поток" - сообщения складываются в очередь потока.

Теперь к твоему вопросу
>зачем вообще сообщения складываются в поток ? Пусть бы сразу пересылались главным функциям тех окон для которых адресованы.

Один поток не способен выполнять несколько кусков кода одновременно. То есть обрабатывать сообщения он может только последовательно. Когда поток вызывает SendMessage для окна в другом потоке (может быть даже в другом приложении), то его выполнение останавливается до тех пор, пока другой поток не освободится и не обработает это сообщение. Если "другой" поток завис, то и поток, вызвавший SendMessage также зависнет. Было бы нехорошо, если бы зависшее приложение вешало бы систему. Поэтому и сделана очередь сообщений.

Короче, ответ на твой вопрос - так устроена Windows. И хорошо, что она так устроена.



Top Gun   (2003-04-08 18:43) [17]

nikkie, все стало ясно ! Спасибо !

Единственное, что хотел уточнить - ведь нельзя сообщения, требующие код ответа, посылать с помощью PostMessage? Просто из твоего поста как-то неоднозначно это прочитывалось



nikkie   (2003-04-08 19:36) [18]

Поскольку PostMessage помещает сообщение в очередь и сразу "returns without waiting for the thread to process the message", то никакого результата он возвратить и не может.

Это однозначно прочитывается из прототипов функций :)

BOOL PostMessage(...)
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero.

LRESULT SendMessage(...)
The return value specifies the result of the message processing; it depends on the message sent.



Top Gun   (2003-04-08 20:58) [19]

Кстати, интересно. Если послать сообщение, которое требует ответа, через PostMessage, то ведь окно для которого это сообщение ответит ? И куда "уйдет" этот ответ ?



Top Gun   (2003-04-09 18:51) [20]

up



сторінки: 1 вся гілка

Форум: "пошарпану";
Поточний архів: 2003.04.28;
Завантажити: [xml.tar.bz2];

наверх









Пам'ять: 0.66 MB
Час: 0.07 c
1-91254
бовдур
2003-04-13 23:24
2003.04.28
Як дізнатися час виконання процедури


14-91499
Gaber
2003-04-09 11:10
2003.04.28
IB 6.0 backup, restore


3-91221
Джао
2003-04-10 08:45
2003.04.28
День добрый. Комментарии в SQL-запросе при конекте через ADO


1-91323
брат
2003-04-15 14:53
2003.04.28
Майстри подивіться плиз на цей рядок і скажіть що тут невірно


1-91360
Giemgo
2003-04-13 13:07
2003.04.28
Що робить Halt?





африкаанс албанський арабська вірменин азербайджанець баскський білоруський болгарська каталонський Китайська (спрощене письмо) Китайський традиційний) хорватський чеська данську мову нідерландський Ukranian естонець Філіппінська фінську мову французький
галісійська грузинський німецький грецький гаїтянський креольський давньоєврейську хінді угорський ісландський індонезієць ірландський італійський японський корейський латиська литовець македонець малайський мальтійський норвежець
перс полірування португальська румунський російська сербський словацький словенський іспанська суахілі шведську мову тайський турецька український урду в&#39;єтнамський валлійський ідиш бенгальський боснійський
кебуано есперанто гуджараті хауса хмонг ігбо яванський каннада кхмерская Лао латинь маорі маратхі монгольський непальська панджабі сомалійський тамільська телугу йоруба
зулуський
Англійська Французький Німецький Італійський Португальська Русский Іспанська