Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Вниз

Хук на консольное окно   Найти похожие ветки 

 
diMAN   (2003-09-09 11:52) [0]

Нужно перехватить все сообщения, идущие на консольное окно, для того, чтобы узнать каким сообщением windows изменяет консольный шрифт и каким переключает в полноэкранный режим. Делаю так:

var h: hhook;

function MyWndProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
writeln("Callback Work!");
if nCode < 0 then CallNextHookEx(h, nCode, wParam, lParam);
end;

...

{$IFDEF WINDOWS_XP}
ConsoleWindow := GetConsoleWindow();
{$ELSE}
SetConsoleTitle(GUID);
Sleep(40);
ConsoleWindow := FindWindow(nil, GUID);
{$ENDIF}

dwThreadId := GetWindowThreadProcessId(ConsoleWindow);
h := SetWindowsHookEx(WH_GETMESSAGE, @MyWndProc, 0, dwThreadId);
...


И что-то не хочет работать.


 
NightAngel   (2003-09-09 15:34) [1]

Ну что делать, что делать... Извечный русский вопрос. Еще можно узнать - а кто, собственно, виноват.

У консоли нет окна.


 
diMAN   (2003-09-09 16:17) [2]

У консоли есть окно. Его класс - ConsoleClassWindow. Но суть не в этом. Каким образом система общается с консольным окном? Заставляет его сворачиваться, разворачиваться, изменять размер и тип шрифта, переключаться на полный экран?


 
NightAngel   (2003-09-10 01:35) [3]

> У консоли есть окно.

Ну-ну... Это всё фикция.

Вот так:
> Нужно перехватить все сообщения, идущие на консольное окно, для того, чтобы узнать каким сообщением windows изменяет консольный шрифт и каким переключает в полноэкранный режим.
Работать никогда не будет. Догадайтесь, почему?

Теперь, какие решения пришли в голову:
1. Запускать программу через заранее созданный pif файл со всеми необходимыми настройками (наиболее простое и наименее трудоёмкое).
2. Воспользоваться недокументированными функциями Kernel32.dll (не все платформы поддерживают).

Например, переключить консоль в полный экран можно попробовать так:
для Win9x - OS посылает сообщение WM_COMMAND со специальным идентификатором, когда пользователь нажимает ALT+ENTER: #define ID_SWITCH_CONSOLEMODE 0xE00F. Для переключения режимов Вы можете использовать SendMessage(hWnd,WM_COMMAND,ID_SWITCH_CONSOLEMODE,0);
Но это не будет работать в NT/2000 и скорее всего и в XP тоже.

Windows NT/2000 (XP наверное тоже) содержит две недокументированные функции, которые позволяют добраться до консольного окна:

function GetConsoleDisplayMode(var lpdwMode: DWORD): Boolean;
// lpdwMode - Текущий режим

function SetConsoleDisplayMode(hOut: THandle; dwNewMode: DWORD; var lpdwOldMode: DWORD): Boolean;
// hOut - Дескриптор вывода, dwNewMode - Режим, который надо установить
// lpdwOldMode - Предыдущий режим

Эти функции экспортируются Kernel32.dll, но Kernel32.lib их не содержит. Поэтому, это вынуждает использовать функцию GetProcAddress()

А реально до консоли можно добраться только из драйвера.


 
diMAN   (2003-09-10 09:52) [4]

> Теперь, какие решения пришли в голову:
> 1. Запускать программу через заранее созданный pif файл со
> всеми необходимыми настройками (наиболее простое и наименее
> трудоёмкое).
Заранее созданный pif не подходит, т.к. программа должна во время работы анализировать текущее разрешение экрана, и открывать консольное окно с максимальным размером шрифта, доступным для данного режима.
Я пробовал динамически создавать lnk-файл, в котором и задавал тип и размер шрифта, размер консольного окна и буфера экрана, под XP работает, а под 95/98 ругается на отсутствие интерфейса. Я разобрался, должен быть установлен IE (точнее нужная версия shell32.dll), и хоть написано, что версия должна быть 4.01+, но на самом деле это не так. А так как мне нужно универсальное решение, то от данного метода я отказался.

// Создаем .lnk файл
Unknown := CreateComObject(CLSID_ShellLink);
NewLink := Unknown as IShellLink;
NewLink.SetPath(PChar(ApplicationName));
NewLink.SetArguments(PChar(CommandLine));
NewLink.SetDescription("Клиент СЕ-2");
NewLink.SetWorkingDirectory(PChar(ExtractFilePath(ApplicationName)));
NewLink.SetShowCmd(SW_SHOWMAXIMIZED);
NewLink.SetHotkey(0);
NewLink.SetIconLocation(PChar(ParamStr(0)), 0);
DataList := Unknown as IShellLinkDataList;
Result := DataList.CopyDataBlock(NT_CONSOLE_PROPS_SIG, Pointer(NTConsoleProps));
if Result = 0
then begin
DataList.RemoveDataBlock(NT_CONSOLE_PROPS_SIG);
end
else begin
New(NTConsoleProps);
ZeroMemory(NTConsoleProps, SizeOf(TNTConsoleProps));
end;
with NTConsoleProps^ do
begin
dbh.cbSize := SizeOf(TNTConsoleProps);
dbh.dwSignature := NT_CONSOLE_PROPS_SIG;
wFillAttribute := $0007;
wPopupFillAttribute := $00f5;
dwScreenBufferSize.X := 80;
dwScreenBufferSize.Y := 25;
dwWindowSize.X := 80;
dwWindowSize.Y := 25;
dwWindowOrigin.X := 0;
dwWindowOrigin.Y := 0;
nFont := 0;
nInputBufferSize := 0;
dwFontSize.X := 10;
dwFontSize.Y := 18;
uFontFamily := 0;
uFontWeight := 0;
GDIObject := GetStockObject(OEM_FIXED_FONT);
GetObject(GDIObject, SizeOf(LogFont), @LogFont);
StringToWideChar(logFont.lfFaceName, PWideChar(@FaceName), 34);
uCursorSize := 2;
bFullScreen := False;
bQuickEdit := False;
bInsertMode := True;
bAutoPosition := False;
uHistoryBufferSize := 50;
uNumberOfHistoryBuffers := 4;
bHistoryNoDup := False;
ColorTable[0] := 0;
ColorTable[1] := $00800000;
ColorTable[2] := $00008000;
ColorTable[3] := $00808000;
ColorTable[4] := $00000080;
ColorTable[5] := $00800080;
ColorTable[6] := $00008080;
ColorTable[7] := $00c0c0c0;
ColorTable[8] := $00808080;
ColorTable[9] := $00ff0000;
ColorTable[10] := $0000ff00;
ColorTable[11] := $00ffff00;
ColorTable[12] := $000000ff;
ColorTable[13] := $00ff00ff;
ColorTable[14] := $0000ffff;
ColorTable[15] := $00ffffff;
end;
DataList.AddDataBlock(Pointer(NTConsoleProps));
PersistFile := Unknown as IPersistFile;
GetTempPath(MAX_PATH, FilePath);
PersistFile.Save(PWideChar(WideString(FilePath + ChangeFileExt(ExtractFileName(ParamStr(0)), ".lnk"))), False);
Dispose(NTConsoleProps);


> 2. Воспользоваться недокументированными функциями Kernel32.dll
> (не все платформы поддерживают).
Функция GetConsoleDisplayMode уже документирована, но она в паре с SetConsoleDisplayMode позволяет только переключаться в оконный/полноэкранный режимы, причём полноэкранный режим в который переключаешься с помощью этой функции отличается от обычного полноэкранного режима (Alt+Enter). Мне кажется что это графический режим, а не текстовый (или они что-то со шрифтами перемудрили).
Я также нашёл недокументированную функцию SetConsoleFont, определил для неё параметры:
function SetConsoleFont(
hConsoleOutput: THandle; // Дескриптор вывода
nFont: DWORD // Шрифт, который надо установить
): Boolean; stdcall; external "kernel32.dll";

Под XP она работает, а в 95/98 её нет. Правда и под XP она не позволяет сменить тип шрифта.

Я стал копать в сторону того, как сама Windows управляет консолью. Пока результат такой:

// Вызвать диалог изменения свойства консоли
SendMessage(ConsoleWindow, WM_SYSCOMMAND, $FFF7, 0);


А вот как эти измениния передаются обратно в консоль?
Вот и возникла идея перехватывать сообщения, посылаемые windows в "консольное окно".

> А реально до консоли можно добраться только из драйвера
Хотелось бы узнать об этом методе подробнее.



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2003.11.13;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.48 MB
Время: 0.033 c
1-41489
Михааааааааа
2003-10-28 16:47
2003.11.13
TImage


14-41898
Dima_dvp
2003-10-23 21:54
2003.11.13
К вопросу об оптимизации при работе с WinAPI


3-40903
ZA
2003-10-17 07:41
2003.11.13
INSERT и значение поля auto_increment


6-41779
Novenkij
2003-09-19 00:29
2003.11.13
локальная сеть


1-41687
TCrash
2003-11-05 00:07
2003.11.13
ListView. Как раскрасить строки





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский