搜索
aardio官方社区 门户 查看主题

请教如何获取外部窗口移动的消息

发布者: abbasky | 发布时间: 2018-4-15 14:20| 查看数: 953| 评论数: 9|帖子模式

  1. import win.ui;
  2. import raw;
  3. import console;
  4. /*DSG{{*/
  5. var winform = win.form(text="aardio form";right=759;bottom=469;parent=...)
  6. winform.add()
  7. /*}}*/

  8. winform.enableDpiScaling();
  9. winform.show();
  10. console.open();


  11. winform.wndproc = function(hwnd,message,wParam,lParam){
  12.         ..console.log(hwnd,message, wParam, lParam);
  13.         if(message == 0x3/*_WM_MOVE*/){
  14.                 ..console.log("window is moved")
  15.         }
  16. }

  17. win.loopMessage();
  18. return winform;
复制代码


使用winform.wndproc只能获取winform窗口的移动消息,不能获取外部窗口的移动消息,请教如何才能获取外部窗口的消息,谢谢!

最新评论

Jacen.He 发表于 2018-4-15 14:47:15
如果你的窗口,能处理别的应用程序中的消息,那不是乱套了。
这相当于全世界的人打电话聊天,你的手机都会响,你都能听到,你也能随时参与或者帮他们挂机。

所以你的 winform.wndproc 不可能收到别的程序的消息,能理解吗?!
abbasky 发表于 2018-4-15 14:49:48
本帖最后由 abbasky 于 2018-4-15 14:56 编辑

嗯,能理解,有什么办法可以可以象shellhook一样获取外部窗口的移动消息呢?

  1. import win.util.shellhook;
  2. win.util.shellhook.RegisterShellHookWindow(winform.hwnd);

  3. winform.wndproc = function(hwnd,message,wParam,lParam){

  4. }
复制代码


我需要监视excel程序的状态,需要同时监视窗口的最大化、最小化、创建、销毁以及移动等消息。目前只解决了窗口创建和销毁以及窗口缩放的消息接收,其它消息获取还没有解决。
我心飞翔1995 发表于 2018-4-15 15:08:00
abbasky 发表于 2018-4-15 14:49
嗯,能理解,有什么办法可以可以象shellhook一样获取外部窗口的移动消息呢?

不管你用什么方法,起码要先找到外部窗口啊,只是内部打交道也不行。
而且,shellhook的用法都能在库函数文档里查到,你要是不会查手册,也不懂系统常量和全局消息,就先学一学基础吧,不要上来就用这么深的知识,否则你要问不少相关的问题。
Jacen.He 发表于 2018-4-15 15:17:12
http://bbs.aardio.com/forum.php?mod=viewthread&tid=13576
学他安装进程钩子。

或者做个定时器,随时获取窗口坐标。

另外你可以想一想,有没有必要搞这么复杂。
abbasky 发表于 2018-4-15 21:35:48
本帖最后由 abbasky 于 2018-4-15 21:36 编辑

学习了winform的源码,我写了一个工具类,如下:
import console;
import win;
import raw;
namespace xf.win;
messageHook = class {
        ctor(winform, hwnd){
                this.hwnd = hwnd;
                this._defaultProc = {};
                this.wndproc =  function( hwnd, message, wParam , lParam) {
                        var proc = this._defaultProc[message]
                        if( proc ){
                                var result = proc(hwnd,message,wParam,lParam)
                                //if( result !== null )
                                        //return result;
                        }else{
                                //return this._defWindowProc(hwnd,message,wParam,lParam);
                                this._defWindowProc(hwnd,message,wParam,lParam);
                        }
                };
                this._wndproc_c = ..raw.tostdcall( this.wndproc,"addr(addr,INT,ADDR,addr)",this/*设为owner对象*/)
                this._wndproc_c_prev = ::SetWindowPointer(hwnd,0xFFFFFFFC/*_GWL_WNDPROC*/, this._wndproc_c);
                ..console.varDump(this._wndproc_c_prev);
                this._defWindowProc = function(hwnd, message, wParam , lParam){
                        return ::CallWindowProc(this._wndproc_c_prev, hwnd, message, wParam , lParam);
                }
                //this._defWindowProc = ::DefWindowProc;
        };
       
        @_metaProperty;
}

namespace messageHook{
    import console;
    import util.metaProperty;
          _metaProperty = util.metaProperty(
                  onWindowMove = {
                         _set = function(func){
                                 owner._defaultProc[0x3/*_WM_MOVE*/] = func;
                         }                        
                 };//end onWindowMove
                
         );//end _metaProperty
}

调用代码如下
import win.ui;
import xf.win;
import console;
/*DSG{{*/
var winform = win.form(text="aardio form";right=759;bottom=469;parent=...)
winform.add()
/*}}*/

winform.enableDpiScaling();
winform.show();
console.open();
var appHwnd = winex.waitVisible(,,"XLMAIN")
..console.log(appHwnd);
msg = ..xf.win.messageHook(winform,appHwnd);
..console.varDump(msg);
msg.onWindowMove = function(){
        console.log("moved");
}


win.loopMessage();
return winform;


实际运行发现this._wndproc_c_prev始终为null,然后我改为this._wndproc_c_prev = ::SetWindowPointer(winform.hwnd,0xFFFFFFFC/*_GWL_WNDPROC*/, this._wndproc_c);时,this._wndproc_c_prev就不为空了,并能够获取winform的移动消息了。

我不明白同样是窗口句柄,为什么winform可以,而excel却不可以?
Jacen.He 发表于 2018-4-15 22:09:32
abbasky 发表于 2018-4-15 21:35
学习了winform的源码,我写了一个工具类,如下:

.................我不明白同样是窗口句柄,为什么winform可以,而excel却不可以?

这个问题已经回答过你一遍了,我不想再复制一遍:
如果你的窗口,能处理别的应用程序中的消息,那不是乱套了。
这相当于全世界的人打电话聊天,你的手机都会响,你都能听到,你也能随时参与或者帮他们挂机。
所以,你不可能直接接收到外部窗口的所有消息,也并不是你想的那样,我找了个借口来糊弄你,所以你大张旗鼓重写标准库的代码,是不必要的。

好心指了你一条明路,为什么非要往坑里踩呢。
abbasky 发表于 2018-4-15 22:14:09
嗯,我明白了,主要是因为我不明白机理,还是要多学习,谢谢
Jacen.He 发表于 2018-4-15 22:33:07
abbasky 发表于 2018-4-15 22:14
嗯,我明白了,主要是因为我不明白机理,还是要多学习,谢谢

其实我上面说的几个方法,应当用不了几句代码,例如:
import win.ui;
/*DSG{{*/
var winform = win.form(text="aardio form";right=505;bottom=336)
winform.add(
edit={cls=
"edit";left=34;top=16;right=476;bottom=316;edge=1;hscroll=1;multiline=1;vscroll=1;z=1}
)
/*}}*/

var spyInfo = {};
winform.addtimer(
    1000,
function(hwnd,msg,id,tick){
        
var hwnd = win.getForeground()
        
var x,y = win.getPos(hwnd);
        
        
if( x != spyInfo.x && y!=spyInfo.y && hwnd != winform.hwnd ){
            winform.edit.print( win.getText(hwnd):
"无标题","移动到:",x,y);
            spyInfo.x = x;
            spyInfo.y = v;
        }
    }
)

winform.show()
win.loopMessage();


abbasky 发表于 2018-4-16 12:16:39
我之前思路一直局限在使用消息上,这个方案提供的思路很有用,让我想到可以用鼠标的点击事件来检测窗口的移动和其它的一些操作,非常感谢!

手机版|未经许可严禁引用或转载本站文章|站长邮箱|aardio.com|aardio官方社区 ( 皖ICP备09012014号 )

GMT+8, 2018-6-25 06:20 , Processed in 0.062500 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表