Форум: "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