Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перехват Windows сообщений для Console окна. 
:(
    Опции темы
TuXAPuK
Дата 29.4.2006, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 29.4.2006

Репутация: нет
Всего: нет



Вобщем занемаюсь я програмированием серверов много чего изпытывал но всеравно лучше старой доброй консоли нечего не нашол. К сожелению дошол я до такого момента когда консоли мне окозалось мало, но от старого удобного движка отказыватся я некак не хотел. Вот я и решил извратится по полной с помощью ResHack'а создал ресурс, в нём меню. И через винапи прилепил меню к консольному окну. AllocConsole, Repaint и вот долгожданное меню уже прилеплено. Но тут я встал как вкопанный и обзадался вопросом а как-же поймать сообщение от меню?? smile Ну вобщем я уже 2-й день спокойно спать немогу в нете дофига всякой чипухи валяется типо как от формы получить, от TApplication но всё это мне не подходит. Ладно подумал я и поставил старый добрый Turbo Pascal 7.1 нашол то что мне нужно, начал транслировать на свой Delphi 7 и что вы думаете?? Ха! Делфя меня потихоньку послала на тот самый забор где 3 буквы написаны. Вобщем ну нечего у меня путного так и не вышло, и я был-бы очень благодарен любой помощи со стороны жителей вашего форума.
С уважением Евгений a.k.a. TuXAPuK  smile
 
PM MAIL   Вверх
Quadr0
Дата 29.4.2006, 16:45 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











...

Это сообщение отредактировал(а) Quadr0 - 15.7.2011, 11:07
  Вверх
TuXAPuK
Дата 2.5.2006, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 29.4.2006

Репутация: нет
Всего: нет



В этом вся суть проблемы. В том что мне не нужна ещё одна форма с менюшкой, и не желательна реализация при помощи крюка (hook). Так как в первом случее пользователю будет не удобно искать а где-же это окошко с менюшкой там пропало.. А во втором случее прийдётся использовать DDE сервер/клиент что-бы передовать сообщения от крюка (hook) к консоли, а через SendMessage на HWND консоли я тоже нечего сделать немогу.

Вот мой сокращённый

Пример:
Код
Program ConMenuExam;
{$APPTYPE CONSOLE}
{$R rMenu.res}

Uses
  Windows;

Const
  sCaption = 'Console Menu Example';

Begin
  SetConsoleTitle(sCaption);
  AllocConsole;
  SetMenu(FindWindow(Nil, sCaption), LoadMenu(hInstance, MakeIntResource(128)));
End.


с Картинкой:
user posted image

Где мы:
1) Устанавливаем Caption для консоли.
2) Заставляем Windows покозать наше окошко и создать для него все заголовки.
3) Устанавливаем меню к нашей консоли загруженное из собственного ресурса с RESNAME = '128'

Пологаю вопрос остаётся в силе: Каким образом получить сообщения от своего меню? smile
С уважением Евгений a.k.a. TuXAPuK
 
PM MAIL   Вверх
Snowy
Дата 2.5.2006, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Могет такой вариант подойдет?
Код
type
  TForm1 = class(TForm)
    mm1: TMainMenu;
    Menu1: TMenuItem;
    ClickMe1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure ClickMe1Click(Sender: TObject);
  private
  end;

var Form1: TForm1;

implementation

{$R *.dfm}

procedure cons;
var s: string;
begin
  repeat
    write('>'); Readln(s);
    Writeln(s + ' Ok');
  until s = 'exit';
  ExitThread(0);
end;

function GetConsoleWindow: THandle;
var
  S: AnsiString;
  C: Char;
begin
  Result := 0;
  Setlength(S, MAX_PATH + 1);
  if GetConsoleTitle(PChar(S), MAX_PATH) <> 0 then
  begin
    C := S[1];
    S[1] := '$';
    SetConsoleTitle(PChar(S));
    Result := FindWindow(nil, PChar(S));
    S[1] := C;
    SetConsoleTitle(PChar(S));
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  h, t: THandle;
  rect: TRect;
begin
  AllocConsole;
  h := GetConsoleWindow;
  Windows.SetParent(h, Handle);
  SetWindowPos(h, 0, 0, -GetSystemMetrics(SM_CYCAPTION)-4, ClientWidth, ClientHeight, 0);
  GetWindowRect(h, rect);
  SetBounds(rect.Left, rect.Top, rect.Right - rect.Left,
            rect.Bottom - rect.Top + GetSystemMetrics(SM_CYCAPTION)-3);
  CreateThread(nil, 256, @cons, nil, 0, t);
end;

procedure TForm1.ClickMe1Click(Sender: TObject);
begin
  ShowMessage('Меня кликнули!');
end;
  
PM MAIL   Вверх
Rouse_
Дата 3.5.2006, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 469
Регистрация: 23.4.2005

Репутация: 18
Всего: 29



Смотреть нужно примерно в эту сторону:

Код

program Console;

{$APPTYPE CONSOLE}

{$R 'Menu.res' 'Menu.rc'}

uses
  Windows,
  Messages;

const
  sCaption = 'Console Menu Example';

var
  hMainWnd, hMenu, hInput: THandle;
  irConsole: TInputRecord;
  EventCount: Cardinal;

begin
  SetConsoleTitle(sCaption);
  hMenu := LoadMenu(hInstance, MakeIntResource(216));
  hMainWnd := FindWindow(nil, sCaption);
  SetMenu(hMainWnd, hMenu);
  hInput := GetStdHandle(STD_INPUT_HANDLE);
  repeat
    ReadConsoleInput(hInput, irConsole, 1, EventCount);
    case irConsole.EventType of
      MENU_EVENT:
        if irConsole.Event.MenuEvent.dwCommandId = WM_MENUSELECT then
        begin
          // Тут думать...
        end;
    end;
  until False;
end.


К сожалению сабкласинг консоли не проходит, а было бы проще на много... 


--------------------
 Vae Victis
(Горе побежденным (лат.))
Демо с открытым кодом: http://rouse.drkb.ru 
PM MAIL WWW ICQ   Вверх
Snowy
Дата 3.5.2006, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Можно конечно "тут думать". Только консоль нам не говорит, какой пункт меню был выбран...
Мы узнаем только о раскрытии и закрытии меню.
Это вообще может быть не наше меню, а системное.
Можно попробовать думать в сторону событий меню. Например следить за отрисовкой и фиксировать последний выбранный пункт... Извращение конечно.
Можно попробовать хук на выбор пункта меню.
Простого решения здесь пока не видно...  
PM MAIL   Вверх
Rouse_
Дата 3.5.2006, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 469
Регистрация: 23.4.2005

Репутация: 18
Всего: 29



В том то и дело что в сторону событий не получается. Дело в том что у консоли два потока. 
Первый ее родной в котором все это и крутиться и второй который доступен непосредственно программисту.
Можно проверить крутя цил выботки сообщений - сообщения туда не проходят. Хот если установить таймер с нулевым хэндлом, то в этом цикле WM_TIME уже ловиться. Сабклассинг, как я уже сказал - не проходит к сожалению...

Добавлено @ 12:41 
Кстати идея с локальным хуком - очень даже может быть... 


--------------------
 Vae Victis
(Горе побежденным (лат.))
Демо с открытым кодом: http://rouse.drkb.ru 
PM MAIL WWW ICQ   Вверх
maxim1000
Дата 3.5.2006, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



а если попробовать написать обычный цикл сообщений?
правда, тогда нужно будет логику проекта вынести в другой поток

Добавлено @ 12:55 
(сам я этого не пробовал, так что это - просто догадка) 


--------------------
qqq
PM WWW   Вверх
Snowy
Дата 3.5.2006, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 11363
Регистрация: 13.10.2004
Где: Питер

Репутация: 30
Всего: 484



Цитата(maxim1000 @  3.5.2006,  12:54 Найти цитируемый пост)
а если попробовать написать обычный цикл сообщений?
Пробовали - пусто. Ни одного, даже самого маленького сообщения. Тишина полная.
Консоль только эвенты дает. А там информация о меню не дается. Выдает всего один параметр - reserved.
Из чего возникает нездоровый вопрос: почему программеры из M$ считают, что мы не собираемся юзать меню...
 
PM MAIL   Вверх
Rouse_
Дата 3.5.2006, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 469
Регистрация: 23.4.2005

Репутация: 18
Всего: 29



Мдя, вот так да. Собственно обработчик MENU_EVENT:

Код

VOID
HandleMenuEvent(
    IN PCONSOLE_INFORMATION Console,
    IN DWORD wParam
    )
{
    INPUT_RECORD InputEvent;
    ULONG EventsWritten;

    InputEvent.EventType = MENU_EVENT;
    InputEvent.Event.MenuEvent.dwCommandId = wParam;
    EventsWritten = WriteInputBuffer( Console,
                                      &Console->InputBuffer,
                                      &InputEvent,
                                      1
                                     );
}


Его вызов в ConsoleWindowProc
системное меню:
Код

            case WM_SYSCOMMAND:
                if (wParam >= ScreenInfo->CommandIdLow &&
                    wParam <= ScreenInfo->CommandIdHigh) {
                    HandleMenuEvent(Console,(DWORD)wParam);

Остальное:
Код

            case WM_INITMENU:
                HandleMenuEvent(Console,WM_INITMENU);
                InitializeMenu(Console);
                break;
            case WM_MENUSELECT:
                if (HIWORD(wParam) == 0xffff) {
                    HandleMenuEvent(Console,WM_MENUSELECT);
                }
                break;


Я медленно офигеваю...

Как все сделано: сама консоль находиться в сервере, а не реализуется приложением. Обработчик соответвенно тоже сидит в нем же. Функции работы с консолью вызываются со стороны клиента тобишь приложения...
Если интересно как работает сия кухня - могу кинуть родные исходники... 


--------------------
 Vae Victis
(Горе побежденным (лат.))
Демо с открытым кодом: http://rouse.drkb.ru 
PM MAIL WWW ICQ   Вверх
maxim1000
Дата 3.5.2006, 16:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник
Сообщений: 3334
Регистрация: 11.1.2003
Где: Киев

Репутация: нет
Всего: 110



Цитата(Rouse_ @  3.5.2006,  13:37 Найти цитируемый пост)
Как все сделано: сама консоль находиться в сервере, а не реализуется приложением. Обработчик соответвенно тоже сидит в нем же. Функции работы с консолью вызываются со стороны клиента тобишь приложения...

ннндааа... намутили...
хотя, если подумать...
консольные программы далеко не всегда запускаются в своём окне - иногда запускают командную строку, а в ней программу
если каждой запущеной программе давать возможность управлять окном, можетполучиться кашица...
кроме того, если, например, программа зациклилась, любому юзеру будет удобно нажать Ctrl-C
в случае обработки сообщений самой программой ничего не произойдёт (она ж зациклилась)
а сервер, на котором расположена реализация функций консоли, всё сделает, как надо...
а перенаправление потоков ввода/вывода...
что-то в этом есть...

зато у мне пришла в голову другая мысль:
причина такого поведения с консольным окном, насколько я понял в том, чтобы меньше переписывать уже существующий код под консоль...
тогда можно сделать немножко наоборот:
делаем простое окно
на него ставим multiline edit
прикручиваем дополнительные функции
реализуем функции консоли через функции работы с edit'ом
если заменить их не получается - перенаправляем ввод/вывод в каналы и общаемся через них
тут всё зависит от того, насколько широк диапазон используемых функций консоли... 


--------------------
qqq
PM WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.1334 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.