Главная страница
    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;
begin
FRunning := True;
try
AddExitProc(DoneApplication);
if FMainForm <> nil then
begin
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;
repeat
HandleMessage
until Terminated;
end;
finally
FRunning := False;
end;
end;


procedure TApplication.HandleMessage;
var
Msg: TMsg;
begin
if not ProcessMessage(Msg) then Idle(Msg);
end;


function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
Result := True;
if Msg.Message <> WM_QUIT then
begin
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
begin
TranslateMessage(Msg);
DispatchMessage(Msg);

end;
end
else
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.52 MB
Время: 0.008 c
7-91579
BaDeVlad
2003-03-06 19:22
2003.04.28
Как программно свернуть все окна?


1-91391
Jam
2003-04-16 10:18
2003.04.28
Слияние файлов


14-91495
Жорик
2003-04-10 14:05
2003.04.28
Удаленное управление GetRight


6-91419
Leran2002
2003-02-28 10:40
2003.04.28
CGI+POST


11-91238
SPeller
2002-07-20 10:51
2003.04.28
Глюк в тулбаре ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский