如题:
请用SetWindowLong和WH_CALLWNDPROC消息完成!补充:不管在什么时候,当有记事本窗口创建时,我希望改变它的窗口过程,即当按下记事本窗口上的最小化按钮之前,弹出一个对话框(随意),然后再执行最小化.其他大侠们也欢迎帮忙,另给分.

解决方案 »

  1.   

    etomahawk最近比较忙,你看我开贴向他提问,所以你也向他提问。你的问题我可以给你写出代码。不难。今天我也比较忙。到周末了,事多。
      

  2.   

    library TmHook;
    uses
      SysUtils,
      Classes,
      Windows,
      Messages,
      CommCtrl;var
      hhook: Windows.HHOOK;
      hwndListView: HWND;
      na:array[0..300] of char;{$R *.res}function TmHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): Integer; stdcall;
    var
      cwp: PCwpStruct;
      cs: PCreateStruct;
    begin
      Result := 0;  if (nCode < 0) then 
      begin
        Result := CallNextHookEx(hhook, nCode, wParam, lParam);
        exit;
      end;  cwp := PCwpStruct(lParam);
      if cwp^.message <> WM_SYSCOMMAND then //设置要钩的消息。
      begin
        Result := CallNextHookEx(hhook, nCode, wParam, lParam);
        exit;
      end;  if cwp.wParam<>SC_MINIMIZE then
      begin
        Result := CallNextHookEx(hhook, nCode, wParam, lParam);
        exit;
      end;  GetClassName(cwp^.hwnd,na,299);
      if lstrcmpi(na,'notepad')=0 then
       begin
         MessageBox(0,'记事本窗口正准备最小化!请注意','事件激发!',MB_OK+MB_ICONINFORMATION);
       end;
        Result := CallNextHookEx(hhook, nCode, wParam, lParam);end;procedure Hook(bEnable: Boolean); stdcall; export;
    begin
      if bEnable then
      begin
        if hhook = 0 then
        begin
          hhook := SetWindowsHookEx(WH_CALLWNDPROC, TmHookProc, HInstance, 0);
        end;
      end
      else
      begin
        if hhook <> 0 then
        begin
          UnhookWindowsHookEx(hhook);
          hhook := 0;
        end;
      end;
    end;exports
      Hook;begin
      hhook := 0;
      hwndListView := 0;end.代码已经写好,上面的已经测试成功!如果你要整个工程,留下你的信箱,我发给你!
      

  3.   

        请用SetWindowLong和WH_CALLWNDPROC消息完成!
    ---------------------------------------------------------
        我怎么感觉像是考试题一样,所有条件已经限制住了你应当说,其中选一个就可以了。WH_CALLWNDPROC不是消息,是钩子的一种类型。SetWindowLong是用来改变窗口类的窗口属性,在这里的作用就是子类化。所以,你想用的做法要么是钩子,要么是子类化。    那么我想到的方法是当然还是的创建一个隐藏进程(当然你也可以把一个线程插入到其他系统进程中来实现),定时检测记事本进程的出现,如果出现,再将DLL注入到记事本进程。这时候就要用到你刚才说到的两种方法,一是钩子(WH_CALLWNDPROC这种钩子必须进行进程注入),第二种就是OldWndProc:= SetWindowLong(Handle, GWL_WNDPROC, @NewWndProc)。   接下来,截获并且处理: WM_SYSCOMMAND消息,如果wParam = SC_MAXIMIZE,那么就自己弹出对话框。
       其实,这两种方法的最终目的只有一个,就是截获这个消息。   代码的话,你可以将我上次写给mwy654321的这个不太符合要求的代码进行修改(将WH_CALLWNDPROCRET修改成WH_CALLWNDPROC,然后在消息里进行截获),这个可以达到你的效果:
       http://download.csdn.net/source/750946就是把DLL中的内容修改成下面的就OK了,测试通过!
    -------------------------------------------------------------------
    library Hook;uses
      SysUtils,
      Windows,
      Messages,
      Classes;var
      g_hBtn : HWND  = 0;
      g_hHook: HHook = 0;
      g_hWin : HWND  = 0;{$R *.res}function MsgFilter(nCode: Integer; wPar: WPARAM; lPar: LPARAM): LResult; stdcall;
    begin
      if (PCWPSTRUCT(lPar)^.message = WM_SYSCOMMAND) and
         (PCWPSTRUCT(lPar)^.wParam  = SC_MINIMIZE) then
      begin
        MessageBox(PCWPSTRUCT(lPar)^.hwnd, '截获最小化消息!', '提示', MB_OK);
      end;  Result:= CallNextHookEx(g_hHook, nCode, wPar, lPar);
    end;procedure InstallHook; stdcall;
    begin
      g_hWin:=FindWindow('Notepad', nil);
      if g_hWin = 0 then
      begin
        MessageBox(0, '记事本没有出现!', 'ERROR', MB_OK);
        exit;
      end;  g_hHook:= SetWindowsHookEx(WH_CALLWNDPROC, @MsgFilter,
                                 HInstance,
                                 GetWindowThreadProcessId(g_hWin));  // 检查钩子是否成功挂接
      if g_hHook = 0 then
      begin
        MessageBox(0, PChar(Format('Hook failed: %d', [GetLastError])),
                  'ERROR', MB_OK);
      end;
    end;exports
      InstallHook;begin
    end.
    -------------------------------------------------------------------   PS: 最近公司对网络进行了限制,有时候上不来,所以有问题的话,请向其他人提问吧。我可能不能及时给你答复。
      

  4.   

    7楼的代码是一个局部钩子,只可以钩住某一个记事本的最小化事件。我的是一个全局钩子,可以钩住任何一个打开的记事本最小化事件。不知道楼主是要哪一种?
    ---------------------------------------对于钩子必须要放到DLL里面我一直觉得很不爽。其实放在DLL里面也行,但要把DLL做到EXE里面就好了,调用时释放或者直接读资源里面的调用接口指针。我看有些钩子就可以做到,但过程肯定不能用这种方式引用DLL:
    procedure Hook(bEnable: Boolean); stdcall; external 'tmhook.dll';
    目前我还没有尝试把楼主该问题所对应的DLL做到EXE里面。有空我试一下,如果试不出来,估计还要开贴向etomahawk求助。
      

  5.   

    WH_CALLWNDPROC,它是一个消息钩子,我想用它监视系统中,所有窗口的创建."所以,你想用的做法要么是钩子,要么是子类化。" 我以为,只单纯地用钩子或子类化,无法完成我的需要.所以提出了两个方便出来.
      

  6.   

    function MsgFilter(nCode: Integer; wPar: WPARAM; lPar: LPARAM): LResult; stdcall; 
    begin 
      if (PCWPSTRUCT(lPar)^.message = WM_SYSCOMMAND) and 
        (PCWPSTRUCT(lPar)^.wParam  = SC_MINIMIZE) then 
      begin 
        MessageBox(PCWPSTRUCT(lPar)^.hwnd, '截获最小化消息!', '提示', MB_OK); 
      end;   Result:= CallNextHookEx(g_hHook, nCode, wPar, lPar); 
    end; etomahawk我不知你有没有时间回来看帖,这个函数,我想请教一下,是不是当前所有的窗口,按下最小化按钮都会出现提示框?
    还是只当记事本最小化按钮被按下时,才出现提示框?
      

  7.   

    cwp.wParam 
    关于PCwpStruct的结构,不知谁能帮讲一下.特别是里面的这个wParam里保存的是什么?
    我之所以失败没写成,就失败在这两句上:
     if cwp^.message <> WM_SYSCOMMAND then //设置要钩的消息
    if cwp.wParam <>SC_MINIMIZE then 看了你的代码,才恍然大悟.!!
      

  8.   

    他的那个程序,只有记事本最小化时,才可以截到。不是所有最小化消息都可以截到的。它是局部钩子。我是全局钩子。我的是所有窗口最小化都可以截到,只不过对所有窗口中又指定了必须是记事本这种类型。其实方法都是一样,区别关键在于SetWindowsHookEx的最后一个参数,我用是零,能截到所有最小化消息。
      

  9.   

    原来如此
    我明天加100,两人各得一百分.
    另外,如果能实现exe的朋友,我再加100分给他!
    不好意思,我分不多!
      

  10.   

    全局消息钩子加子类化函数,两位已经达到我的要求了,谢谢!
    我会及时结帖给分你们
    现在我想给这个帖子加分,得到另外一种方法,即用exe方法实现它!
    1,用exe实现的,单独获分100分
    2,用exe里加载dll,但不释放dll,而是直接把dll加载到内存运行,单独获分200分.我分不多,所以,以上两种实现方法,只是测试最先的,测试后给分.多了,我也给不起!关于第二种方法实现,我只是听说过,具体的不知道.不知难易程序如何?
    另外第一种方法,我似乎听说过,全局消息钩子不能在exe中运行,只有低级的键盘钩子才能运行于exe中?
      

  11.   

    算了,你不用加分了,节省点吧。结贴吧,每人50分。etomahawk 也不是一个在乎分的人。
      

  12.   

    你这条,我或者可以做到。etomahawk 应该也可以做到吧。呵呵。正在研究中……
      

  13.   


    说得好,你结贴后系统会返回你分。周末了,下周来了解决你这个问题,看看能不能把DLL做进EXE中!
      

  14.   

    现在我想给这个帖子加分,得到另外一种方法,即用exe方法实现它! 
    1,用exe实现的,单独获分100分 
    2,用exe里加载dll,但不释放dll,而是直接把dll加载到内存运行,单独获分200分. 我分不多,所以,以上两种实现方法,只是测试最先的,测试后给分.多了,我也给不起! 关于第二种方法实现,我只是听说过,具体的不知道.不知难易程序如何? 
    另外第一种方法,我似乎听说过,全局消息钩子不能在exe中运行,只有低级的键盘钩子才能运行于exe中? 
      

  15.   

    再等两天,我就结帖了
    其实,我在学子类化函数和哪个消息钩子,所以"请用SetWindowLong和WH_CALLWNDPROC消息完成"无奈两位大侠只用其中之一,就完成了.哎!!