Головна сторінка
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.65 MB
Час: 0.037 c
6-91437
Makatuka
2003-03-06 14:57
2003.04.28
TWebBrowser і пошук фрагмента тексту


1-91262
Semion
2003-04-17 00:48
2003.04.28
зображення


6-91421
FND
2003-02-25 01:42
2003.04.28
Срочно нужна помощь по ISAPI / NSAPI для отримання файлу з HTTP


14-91472
Погана людина
2003-04-09 23:57
2003.04.28
Чим працювати з палітрами.


7-91577
Ifrit
2003-03-09 13:37
2003.04.28
Народ, помогите !!! Як визначити чи Word в системі?





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