Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Отлов WindowProc до изминения


Автор: Ak47black 22.8.2007, 20:40
Здравствуйте.
Как перехватить WindowProc (главную процедуру окна) до изменения.
Дело в том что я хочу обрабатывать например Alt+F4 и не допускать завершения программы и тому подобное.
Делаю например вот так
Код

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    FOldWndProc: TWndMethod;
    procedure MessageFilterWndProc(var Message: TMessage);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.MessageFilterWndProc(var Message: TMessage);
var
  i: Integer;
begin
  if Message.Msg = WM_KEYDOWN then
  begin
    Beep;
    if Message.WParam = $73 then
      Exit;
  end;
  FOldWndProc(Message);
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  FOldWndProc:= WindowProc;
  WindowProc:= MessageFilterWndProc;
end;

end.

Тоесть делаю процедуру которая фильтрует и не передаёт дальше Alt+F4.
Проблема заключается в том что если добавить например на форму TMemo, то сообщения не будут обрабатываться и при нажатии Alt+F4 форма будет закрываться.
Можно конечно прикрутить и к  TMemo тоже самое что и к форме но так я не могу сделать потому что на форме куча объектов.
Как перехватить реальную процедуру обработки окна?
Тоесть я хочу сделать чтобы все сообщения которые приходят окну сначала я обрабатывал.  smile 

Автор: MetalFan 22.8.2007, 21:52
Цитата(Ak47black @  22.8.2007,  20:40 Найти цитируемый пост)
и не допускать завершения программы и тому подобное.

а OnClose/OnCloseQuery не катит? ))

з.ы. попробуй както так:
Код

...
    procedure OnAppMessage(var Msg: TMsg; var Handled: Boolean);
...

procedure TForm1.FormCreate(Sender: TObject);
begin
  Application.OnMessage := OnAppMessage;
end;

procedure TForm1.OnAppMessage(var Msg: TMsg; var Handled: Boolean);
begin
  if Msg.message = WM_KEYDOWN then
  begin
    Beep;
    Handled := Msg.wParam = $73;
  end;
end;

Автор: Fedia 22.8.2007, 22:28
Цитата(Ak47black @  22.8.2007,  20:40 Найти цитируемый пост)
Проблема заключается в том что если добавить например на форму TMemo, то сообщения не будут обрабатываться и при нажатии Alt+F4 форма будет закрываться.


Попробуй свойство формы KeyPreview, установить в значение true.

Автор: Ak47black 22.8.2007, 23:01
Не оба предложенные способа не работают.
Я всетаки не добиваюсь именно как недать закрыться окну по нажатию Alt+F4 , хочу сделать сам перехват до обработки.  

Автор: Fedia 22.8.2007, 23:10
Цитата(Ak47black @  22.8.2007,  23:01 Найти цитируемый пост)
всетаки не добиваюсь именно как недать закрыться окну по нажатию Alt+F4

Вариант №1:
Код

procedure TMForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose:=False;
end;

Вариант №2 
Код

procedure WndProc(var Message: TMessage); override;
...

procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_CLOSE then
  Message.Msg:=WM_USER ;

Автор: Sunvas 23.8.2007, 01:28
Ak47black, если ты хочешь чтобы форма не закрывала ИМЕННО по alt+F4, то тебе следует обрабатывать OnKeyDown! Т.е. после того, как нажаты эти две кнопки, окну посылается сообщение закрытия. И, когда окно его получает - оно не знает откуда оно к нему пришло: либо от крестика справа вверху, либо от этих кнопок.
Сейчас нарисую пример отлавливания именно alt+F4.

Добавлено через 5 минут и 38 секунд
Код

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
if ((GetKeyState(VK_MENU) AND 128)=128) and
    ((GetKeyState(VK_F4) AND 128)=128) then
begin
ShowMessage('Íàæàòî alt+f4');
key:=0;
end;
end;

Автор: sentry 23.8.2007, 08:47
Sunvas, вот так лучше смотрится  smile :
Код

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_F4) and (ssAlt in Shift) then
  begin
    ShowMessage('Perehvat');
    Key := 0;
  end;
end;


А вот пример отлова WM_CLOSE оконной процедурой:
Код

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure WndProc(var Message: TMessage); override; // перекрываем исходную процедуру
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

{ это сообщение наступает раньше (если KeyPreview = True), чем передается WndProc, поэтому }
{ после вывода perehvat заголовок формы на WM_CLOSE не меняется                                              }
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_F4) and (ssAlt in Shift) then
  begin
    ShowMessage('Perehvat');
    Key := 0;
  end;
end;

{ зато меняется, если щелкнуть на кнопке закрыть, а также при нажатии Alt+F4, }
{ если KeyPreview = False } 
procedure TForm1.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_CLOSE then
    Form1.Caption := 'WM_CLOSE'
  else
    inherited; // для обработки других сообщений вызываем оригинальную оконную процедуру
end;

Автор: Ak47black 23.8.2007, 09:35
Ok. С закрытием тогда понятно как сделать, но всетаки через OnKeyDown всё не перехватываться на ранней стадии.
Например если попробовать перехватить и предотвратить Num Lk вот этим кодом 
Код

  if (Key = VK_NUMLOCK) then
  begin
    ShowMessage('Perehvat');
    Key := 0;
  end;

То он всеровно загорается.
И еше например как Ctrl+Alt+Delete перехватить.

Автор: Ak47black 23.8.2007, 10:00
Тут по какой схеме происходит передача :
  • A. Сначала проверяется на наличие Ctr+Alt+Delete, а потом передаётся в приложение
  • B. Сначала в приложение, а потом проверяется.
?

Автор: Sunvas 23.8.2007, 11:27
Цитата(Ak47black @  23.8.2007,  09:35 Найти цитируемый пост)
То он всеровно загорается.И еше например как Ctrl+Alt+Delete перехватить.

Num Luck - надо хучить клаву.
А по трем веселым кнопкам - ищи по форуму, там Yanis очень хороший пример приводил.

Автор: Yanis 23.8.2007, 12:34
Цитата(Sunvas @  23.8.2007,  12:27 Найти цитируемый пост)
А по трем веселым кнопкам - ищи по форуму, там Yanis очень хороший пример приводил. 

http://yanis.front.ru/files/a/cad.zip.

Автор: MetalFan 23.8.2007, 15:25
Yanis, а ето только под админом наверное будет работать...

Автор: Ak47black 23.8.2007, 19:52
Всетаки будет-ли работать без прав админа для меня важно.
Пробовал поставить хук в самом приложении (тоесть без Dll), но невышло так как винт первый перехватывает.

Автор: MetalFan 23.8.2007, 20:07
Цитата(Ak47black @  23.8.2007,  19:52 Найти цитируемый пост)
невышло так как винт первый перехватывает.

хто перехватывает???


Автор: Ak47black 23.8.2007, 20:22
Цитата

хто перехватывает???

Windows  smile 
Тоесть Windows первый проверяет вызвать-ли TaskManager.

Автор: Ak47black 24.8.2007, 10:40
Yanis, А вообще реально сделать-ли всё это при помощи Hook, тоесть ловить это сочетание клавиш и обнулят? Ато с инджектом то могут возникнуть некоторые проблемы.
У юзера может и не быть прав админа например.
Я пробовал сделать hook в самой проге и в dll но не выходит перехватить до того момента когда windows вызывает сам TaskManager например.  smile 

Автор: Yanis 24.8.2007, 10:53
Что за мания тотального контроля юзера?
ОНО надо юзеру?

Автор: Ak47black 24.8.2007, 10:57
Я хочу просто получать все кнопки которые нажимаются и не дать им исполняться, а потом их воспроизводить например на удалённом компе  smile .

Автор: MetalFan 24.8.2007, 12:48
Ak47black, а разве тот же RAdmin или RemouteDesktop такие сочетания дублируют на "ту сторону"???

Автор: Ak47black 24.8.2007, 13:18
MetalFan, нет.
Он заменяет их другими сочетаниями. Наверно я так и сделаю.
Извиняюсь что поднял тему.

Автор: MetalFan 24.8.2007, 13:36
Цитата(Ak47black @  24.8.2007,  13:18 Найти цитируемый пост)
MetalFan, нет.

да я знаю, что нет) у RAdmin'а эти сочетания через меню вроде можно послать)

Автор: Virtuals 26.8.2007, 17:43
Цитата(MetalFan @ 23.8.2007,  15:25)
Yanis, а ето только под админом наверное будет работать...

под админом онли...

в примере используется дебугпривелегии и запись в память другого процесса (winlogon а) smile 

в винлогоне хук ставится:
Код

        if (!RegisterHotKey(hwnd, 0, MOD_CONTROL | MOD_ALT, VK_DELETE)) {
            DebugLog((DEB_ERROR, "failed to register SAS"));


соответственно хук с помощью RegisterHotKey не прокатит
нужно пользовать
SetWindowsHookEx(WH_KEYBOARD, ...
из длл, тоесть не передать в систему последнее нажатие VK_DELETE //должно получится

удачи

Автор: MetalFan 26.8.2007, 21:47
Virtuals, врядли это пройдет) CAD не на уровне ОС генерируется AFAIK.
а передашь или нет последний Delete, это системе побарабану...
з.ы. кстати, а как интересно Process Explorer от Sysinternals перехватывает CAD и себя вместо стандартного диспетчера подсовывает?!

Добавлено через 6 минут и 26 секунд
p.p.s нашел, как он это делает) http://www.osix.net/modules/article/?id=781

Автор: Yanis 27.8.2007, 10:28
Цитата(MetalFan @  26.8.2007,  22:47 Найти цитируемый пост)
з.ы. кстати, а как интересно Process Explorer от Sysinternals перехватывает CAD

Ниче он не перехватывает.
Он действует как вирус smile

Автор: MetalFan 27.8.2007, 12:01
Цитата(Yanis @  27.8.2007,  10:28 Найти цитируемый пост)
Он действует как вирус

какето как вирус?! тогда все антивирусы и файрфолы и проч. тоже действуют "как вирус" ))

Автор: Ak47black 27.8.2007, 12:22
Цитата

<Marla>
прикинь, у меня тут антивирусы друг друга за вирусы приняли - войну развернули - вот уррроды!))))
<Marla>
так прикольно - вчера каспЕр убил нода,
а седня остаточные файлы ндоа самостоятельно скачали себя и подкрепление из инета за счет моего траффика, даж не спросив - и вместе мочат каспера)))
<Marla>
ес каспЕр проиграет - у меня полсистемы, грят, рухнет))
но се равно за нод сёня болею - живучий падла)

Взято из http://bash.org.ru.

Цитата

под админом онли...

Ну тут тогда как выход можно драйвер написать на уровне ядра который перехватывает, тока этот путь совсем нелёгкий smile.

Автор: Yanis 27.8.2007, 14:11
Цитата(MetalFan @  27.8.2007,  13:01 Найти цитируемый пост)
какето как вирус?!

Ну дебагером процесса становится. Не этично как то smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)