Форум программистов, компьютерный форум, киберфорум
Delphi: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.66/50: Рейтинг темы: голосов - 50, средняя оценка - 4.66
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15

Обработка сообщений в консольном приложении

16.07.2013, 11:20. Показов 11033. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день.
Передо мной стоит достаточно простая задача. Настолько простая, что за два дня поисков я не нашёл решения. Похоже, оно всеми считается очевидным.
Есть консольное приложение, создаваемое в Delphi. Им необходимо управлять с помощью Windows-сообщений из другого приложения (не консольного, тоже в Delphi).
Управление, вроде, работает (SendMessage не выдаёт ошибок):

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...
const
  WM_START_ = WM_USER;
  WM_RUN_    = WM_USER+1;
  WM_PAUSE_ = WM_USER+2;
  WM_STOP_  = WM_USER+3;
...
// СТАРТ
procedure TMain_Form.ButtonStartPRDClick(Sender: TObject);
var hdl: THandle;
    res, err: integer;
begin
  hdl:=FindWindow('ConsoleWindowClass','PRD');
  if hdl=0 then begin
    ShowMessage('Отсутствует ПРД приложение!');
  end;
  res:=SendMessage(hdl, WM_START_, ComboBoxAudioPRD.ItemIndex, 0);
  err:=GetLastError;
end;
...
А вот с консольным приложением - беда. Функция PeekMessage "мышей" не ловит:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
program PRD_Project;
{$APPTYPE CONSOLE}
uses SysUtils, Windows, Messages;
var Msg: TMsg;
begin
  SetConsoleTitle('PRD');
  repeat
    if PeekMessage(Msg,0,0,0,PM_NOREMOVE) then begin
      GetMessage(Msg,0,0,0); 
      Writeln(IntToStr(Msg.message)); // тут будет реальная обработка сообщений
    end;
    // Тут будет полезный код
  until False;
end.
Причём, если из управляющей программы вместо WM_START_ послать стандартное сообщение типа WM_CLOSE, то всё ОК: консольное приложение закроется, но при этом PeekMessage даже не Peek-нет.
Интернет весь перерыл. Ссылки типа следующих не помогли:
http://www.gptelecom.ru/Articles/Console/index.htm
http://vsokovikov.narod.ru/New... e_main.htm

Буду очень благодарен.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.07.2013, 11:20
Ответы с готовыми решениями:

Обработка картинки в консольном приложении
Всем привет, сделал объектную программу (есть форма, кнопки, и т.д.) для простой обработки изображения (а именно печать одной картинки на...

DBChart в консольном приложении
Можно ли построить график с помощью DBChart в консольном приложении? Дело в том, что вроде бы надо указать родителя(Parant), но формы-то...

IdTelnetClient в консольном приложении
Народ подскажите как заставить работать IdTelnetClient в консольном приложении может кто то сталкивался??

29
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15
16.07.2013, 17:17  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от mss Посмотреть сообщение
Передавать дескрипторы через файловый контейнер неразумно, если не сказать глупо)
Я примерно так и написал.
Цитата Сообщение от mss Посмотреть сообщение
Простой вариант : управляющее приложение ищет процесс управляемого приложения по имени и получает искомый дескриптор его осн.потока
Начало понятно (есть в коде первого поста), а как получить дескриптор его осн. потока сходу не нашёл.
Цитата Сообщение от mss Посмотреть сообщение
И в цикл ожидания/выборки желательно вставить sleep(0), особенно если планируешь создавать доп.потоки
Это понятно. Представленный код нужен для понимания работы, остальное - другие задачи. Я, кстати, обычно использую sleep(1), т.к. с нулём процессор всё равно загружен на полную.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
16.07.2013, 17:37
Цитата Сообщение от Dimer2 Посмотреть сообщение
как получить дескриптор его осн. потока
Он будет первым среди перечисленных в CreateToolhelp32Snapshot(TH32CS_SNAPTHRE AD, ..)
http://msdn.microsoft.com/en-u... s.85).aspx

Впрочем при известном хендле окна получить координаты его создателя проще простого:
GetWindowThreadProcessId
1
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15
16.07.2013, 17:52  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Впрочем при известном хендле окна получить координаты его создателя проще простого:
GetWindowThreadProcessId
С каждым часом программа всё лучше! Вот окончательный код.
Управляющая программа:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const
  WM_START_ = WM_USER;
  WM_RUN_   = WM_USER+1;
  WM_PAUSE_ = WM_USER+2;
  WM_STOP_  = WM_USER+3;
var
  Main_Form: TMain_Form;
  HdlPRD: THandle;
implementation
{$R *.dfm}
procedure TMain_Form.FormCreate(Sender: TObject);
begin
  ...
  // Считывание дескриптора потока консольного приложения
  HdlPRD:=GetWindowThreadProcessId(FindWindow('ConsoleWindowClass','PRD'), nil);
  ...
end;
procedure TMain_Form.ButtonStartPRDClick(Sender: TObject);
begin
  PostThreadMessage(HdlPRD, WM_START_, 0, 0); // Передача сообщения потоку консольного приложения
end;
Консольное (управляемое) приложение:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
program PRD_Project;
{$APPTYPE CONSOLE}
uses
  SysUtils, Windows, Messages;
var
  Msg: TMsg;
begin
  SetConsoleTitle('PRD'); // Задание заголовка окна консольного приложения
  repeat
    if PeekMessage(Msg,0,0,0, PM_NOREMOVE) then begin // Проверка, нет ли сообщений
      GetMessage(Msg,0,0,0); // Чтение сообщения
      Writeln(IntToStr(Msg.message)+' '+IntToStr(Msg.wParam)+' '+IntToStr(Msg.lParam)); // Обработка сообщения
    end;
    // Тут будет полезный код
    sleep(1);
  until false; // Тут, возможно, будет реальное условие выхода
end.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
16.07.2013, 17:59
Цитата Сообщение от Dimer2 Посмотреть сообщение
if PeekMessage(Msg,0,0,0, PM_NOREMOVE) then// Проверка, нет ли сообщений GetMessage(Msg,0,0,0); // Чтение сообщения
Достаточно одного вызова:

if PeekMessage(Msg,0,0,0, PM_REMOVE) then
1
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15
16.07.2013, 18:06  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Достаточно одного вызова:
if PeekMessage(Msg,0,0,0, PM_REMOVE) then
Да что ты будешь делать!?
Придётся третий раз "спасибо" жать. Код править не буду, и так уже - почти самая большая тема в разделе.

Кстати, а если придут сообщения, которые я не собираюсь обрабатывать, они не пропадут?
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
16.07.2013, 18:14
Цитата Сообщение от Dimer2 Посмотреть сообщение
Придётся третий раз "спасибо" жать
Не утруждай себя)
"спасибы" мне даром не нужны - кашу из "спасибов" не сварить)

Но вот чуть скорректировать логику , наверно, не помешает:

Code
1
2
3
4
5
6
7
8
if PeekMessage(Msg, 0,0, PM_REMOVE) then
  case Msg.message of
   WM_START_..WM_STOP_: .. обработка своих сообщений ..;
  else
// диспетчеризация чужих
   TranslateMessage(Msg);
   DispatchMessage(Msg);
  end;
0
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15
16.07.2013, 18:25  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
Не утруждай себя)
"спасибы" мне даром не нужны - кашу из "спасибов" не сварить)
Уже утрудил.
Цитата Сообщение от mss Посмотреть сообщение
Но вот чуть скорректировать логику , наверно, не помешает:
А это не лишнее по причине того, что я обрабатываю сообщения ПОТОКУ, у которого нет окна, и чужие сообщения сюда не придут?
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
16.07.2013, 19:54
Нет, не по этой.
"Чужие", имеется ввиду, - это те которые ожидаются (и возможно обрабатываются) не в этом фрагменте алгоритма.
Могу ошибиться, но, например, если ты при ПикМесседж вычерпаешь из очереди тот же, скажем, WM_CLOSE и не диспетчеризуешь его штатному обработчику (поскольку ты не намерен его никак обрабатывать), то окно попросту не закроется.
0
0 / 0 / 0
Регистрация: 16.07.2013
Сообщений: 15
17.07.2013, 09:38  [ТС]
Цитата Сообщение от mss Посмотреть сообщение
"Чужие", имеется ввиду, - это те которые ожидаются (и возможно обрабатываются) не в этом фрагменте алгоритма.
Согласен. Дополнительная пара трок кода на всякий случай не помешает.
Цитата Сообщение от mss Посмотреть сообщение
Могу ошибиться, но, например, если ты при ПикМесседж вычерпаешь из очереди тот же, скажем, WM_CLOSE и не диспетчеризуешь его штатному обработчику (поскольку ты не намерен его никак обрабатывать), то окно попросту не закроется.
Я пробовал посылать WM_CLOSE вместо своих сообщений функцией PostThreadMessage(HdlPRD, WM_CLOSE, 0, 0). Не важно, пропускаю я его или диспетчиризирую, никакого окна оно не закрывает, видимо, потому, что у потока окна нет. А вот если послать это сообщение с помощью ф-ции SendMessage(FindWindow('ConsoleWindowCla ss','PRD'), WM_CLOSE, 0, 0), т.е. не потоку, а консольному окну, оно, как и должно быть, закрывается. При этом мой обработчик сообщений, естественно, его не видит и не мешает.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
17.07.2013, 09:45
Цитата Сообщение от Dimer2 Посмотреть сообщение
пропускаю я его или диспетчиризирую, никакого окна оно не закрывает
Конечно не закроет - в сообщении же не указан хендл целевого окна, ибо сообщение было послано потоку, а не окну ..
Механизм диспетчеризации опирается именно на хендл окна, фигурирующий в выбираемом из очереди потока сообщении
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.07.2013, 09:45

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

Ошибка в консольном приложении
работаю в консольном приложении при компиляции ругается на этот код ShellExecute(handle,'open', 'c:\windows\notepad.exe',...

Таймер в консольном приложении
Создаю таймер в консольном приложении Дельфи. Ошибок нет но он не работает. (проверяю через отладчик что процедура On_Timer не...

Как использовать обработку сообщений Windows в консольном приложении
Здравствуйте! Как все же использовать обработку сообщений Windows в консольном приложении. Хочу использовать простую консоль, но как...

Обработка флагов в консольном приложении
Всем привет! Есть задание написать утилиту наподобии xCopy для расширенного копирования файлов. В оригиналльной утилите около 20 флагов....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Новые блоги и статьи
Как надо было делать правильно - вообще не слушать ИИ, его дело - текст.
Hrethgir 15.07.2026
А вообще надо было делать не так, чтобы не исправлять ошибку https:/ / www. cyberforum. ru/ blogs/ 223907/ 10996. html , правильно было : удалил кнопку, а потом добавил её. Всё это стресс конечно. Почему?. . .
Знаете, от чего появляется стресс?
kumehtar 15.07.2026
Стресс появляется оттого, что вы, зная как поступить правильно, делаете наоборот. Ларри Уингет
Нас бьют, а мы крепчаем? Какая чушь!
kumehtar 15.07.2026
Вот это вот бытующее мнение, что человек меняется только под действием проблем, всегда считал вредоносным. Поверь, от проблем у людей появляются не изменения, а нервное расстройство и ПТСР. А. . .
сукцессия 29. Переход от одних деревьев на другие делать более или менее вероятностным?
anaschu 12.07.2026
Насколько смена типов микоризы — исключительное событие в двухвековой сукцессии? Оценка вероятности в пространстве параметров В текущей версии модели успешно реализован ключевой механизм. . .
сукцессия 27. Думаю, как переделывать уже написанную статью с планами на сукцессию.
anaschu 12.07.2026
Анализ соответствия модели требованиям Реализованные компоненты: Механизм закисления почвы через протонную помпу Конкуренция между типами микориз pH как триггер сукцессии C/ P соотношение. . .
Сукцессия 26. Мат модель создана.
anaschu 12.07.2026
Модель смены растительных сукцессий посредством управления грибами работает внутри небольшой ячейки почвы, восстанавливающейся после пожара, где ненадолго бывшее царство хвойных снова захватили. . .
Решил проблему с ошибкой пагинации сообщений с сервера на алгоритме обхода дерева "Эстафета хвоста".
Hrethgir 12.07.2026
Проблема была в том, что удалялась именно новая кнопка, а не старая. Ни один ИИ не обнаружил это, а сам я смог только когда с работой стало попроще и когда заставил работать будущее автономное. . .
сукцессия 25. Хронология ошибок
anaschu 12.07.2026
# От 50-тонного гриба до устойчивого леса: хроника ошибок при построении модели вековой сукцессии микоризы ## О чём эта статья В процессе построения ОДУ-модели (система дифференциальных. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru