//RUNAS//窗口探测
import win.ui;
/*DSG{{*/
var winform = win.form(text="窗口探测器";left=-2;top=100;right=688;bottom=526)
winform.add(
chkPassword={cls="checkbox";text="允许抓取密码";left=280;top=89;right=420;bottom=108;dl=1;dt=1;z=29};
chkSkipDiabled={cls="checkbox";text="忽略禁用窗口";left=288;top=354;right=390;bottom=376;db=1;dl=1;z=34};
chkSkipInvisible={cls="checkbox";text="忽略隐藏窗口";left=183;top=355;right=285;bottom=376;checked=1;db=1;dl=1;z=33};
chkSkipTransparent={cls="checkbox";text="忽略透明窗口";left=77;top=354;right=179;bottom=376;db=1;dl=1;z=32};
editClass={cls="edit";left=77;top=151;right=214;bottom=172;dl=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=22};
editHwnd={cls="edit";left=77;top=9;right=185;bottom=32;dl=1;dt=1;edge=1;hidesel=1;multiline=1;readonly=1;tabstop=1;z=17};
editHwnd10={cls="edit";left=78;top=35;right=184;bottom=54;dl=1;dt=1;readonly=1;z=35};
editId={cls="edit";left=353;top=181;right=455;bottom=204;dl=1;dr=0.34;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=26};
editOwnerHwnd={cls="plus";left=395;top=12;right=470;bottom=26;align="left";color=16711680;dl=1;dt=1;notify=1;z=16};
editOwnerHwnd10={cls="edit";left=399;top=35;right=488;bottom=54;dl=1;dt=1;readonly=1;z=37};
editParenHwnd={cls="plus";left=245;top=12;right=320;bottom=26;align="left";color=16711680;dl=1;dt=1;notify=1;z=14};
editParentHwnd10={cls="edit";left=248;top=35;right=342;bottom=54;dl=1;dt=1;readonly=1;z=36};
editPath={cls="edit";left=77;top=57;right=494;bottom=80;dl=1;dr=0.28;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=18};
editPid={cls="edit";left=77;top=89;right=142;bottom=110;dl=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=19};
editPoint={cls="edit";left=77;top=181;right=298;bottom=204;dl=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=25};
editStyle={cls="edit";left=254;top=151;right=340;bottom=172;dl=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=23};
editStyleEx={cls="edit";left=406;top=151;right=494;bottom=172;dl=1;dr=0.28;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=24};
editText={cls="edit";left=77;top=119;right=494;bottom=142;dl=1;dr=0.28;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=21};
editTid={cls="edit";left=199;top=89;right=264;bottom=110;dl=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=20};
hotkey={cls="hotkey";left=306;top=391;right=430;bottom=411;db=1;dl=1;edge=1;z=28};
lbClass={cls="static";text="窗口类名:";left=0;top=153;right=73;bottom=170;align="right";dl=1;dt=1;z=4};
lbHwnd={cls="static";text="窗口句柄:";left=10;top=11;right=73;bottom=28;align="right";dl=1;dt=1;z=1};
lbId={cls="static";text="命令ID:";left=303;top=184;right=348;bottom=201;align="right";dl=1;dt=1;z=5};
lbOwner={cls="static";text="所有窗口:";left=327;top=11;right=386;bottom=28;align="right";dl=1;dt=1;z=15};
lbParenHwnd={cls="static";text="父窗口:";left=192;top=11;right=240;bottom=28;align="right";dl=1;dt=1;z=6};
lbPid={cls="static";text="进程ID:";left=26;top=90;right=73;bottom=107;align="right";dl=1;dt=1;z=9};
lbPoint={cls="static";text="窗口坐标:";left=3;top=184;right=73;bottom=201;align="right";dl=1;dt=1;z=12};
lbStyle={cls="static";text="样式:";left=214;top=153;right=251;bottom=170;align="right";dl=1;dt=1;z=2};
lbStyleEx={cls="static";text="扩展样式:";left=340;top=153;right=402;bottom=170;align="right";dl=1;dt=1;z=3};
lbText={cls="static";text="窗口文本:";left=12;top=121;right=73;bottom=138;align="right";dl=1;dt=1;z=7};
lbTid={cls="static";text="线程ID:";left=147;top=90;right=193;bottom=107;align="right";dl=1;dt=1;z=8};
plusCur={cls="plus";left=22;top=380;right=54;bottom=412;background="\.res\1.gif";db=1;dl=1;notify=1;repeat="center";z=10};
richedit={cls="richedit";left=77;top=213;right=494;bottom=345;db=1;dl=1;dr=0.28;dt=1;edge=1;hscroll=1;multiline=1;tabstop=1;vscroll=1;z=27};
static={cls="static";text="启动文件:";left=5;top=59;right=73;bottom=76;align="right";dl=1;dt=1;z=11};
static2={cls="static";text="请拖动左侧瞄准器图标到目标窗口";left=64;top=392;right=293;bottom=417;db=1;dl=1;dr=1;z=13};
static3={cls="static";text="下级子窗口:";left=502;top=4;right=602;bottom=18;dl=0.73;dt=1;transparent=1;z=31};
treeview={cls="treeview";left=501;top=23;right=686;bottom=416;asel=false;bgcolor=16777215;db=1;dl=0.73;dr=1;dt=1;edge=1;hscroll=1;vscroll=1;z=30}
)
/*}}*/

import winex;
import mouse;
import process;
import process.wmi;
import win.ui.mask;
var frmMask = win.ui.mask(winform);

function showWindowInfo(hwnd){
	winform.editParenHwnd.text = string.format("0x%X",win.getParent(hwnd) );
	winform.editParentHwnd10.text = tonumber(winform.editParenHwnd.text);
	winform.editOwnerHwnd.text = string.format("0x%X",win.getOwner(hwnd) );
	winform.editOwnerHwnd10.text = tonumber(winform.editOwnerHwnd.text);
	winform.editHwnd.text = string.format("0x%X",hwnd );
	winform.editHwnd10.text = hwnd;
	winform.editClass.text = win.getClass(hwnd) 
	winform.editId.text = win.getId(hwnd);
	
	var tid,pid = win.getThreadProcessId(hwnd)
	winform.editTid.text,winform.editPid.text = tid,pid;
	try{
		 var cmdline = process.wmi(pid).CommandLine; 
		 if(!#cmdline){
		 	cmdline = process.getPath(pid);
		 }
		 winform.editPath.text = cmdline;
	}
	catch(e){
		winform.editPath.text = process.getPath(pid)
	} 
	
	var str = winex.getText(hwnd,50); 
	if(#str){
		winform.editText.text = string.replace(str,"[\r\n]","")
	} 
	else { 
		winform.editText.text = "";
		
		if( hwnd != winform.lastSpyHwnd
			&& winform.chkPassword.checked
			&& winform.editClass.text == "Edit"
			&& ..win.getStyle(hwnd,0x40000000/*_WS_CHILD*/) 
			&& !..win.isChild(winform.hwnd,hwnd) ){
			var tid,pid = win.getThreadProcessId(hwnd)
			var tid2,pid2 = win.getThreadProcessId(winform.hwnd);
			if( pid2 != pid ){ 
				var prcs = process( pid )
				if(prcs){ 
					var tid,pid = win.getThreadProcessId(hwnd);
					var prcs = process( pid );
					var getWindowText = prcs.remoteApi("int(addr hwnd,ustring& lpString,int cch)" ,"User32.dll","GetWindowTextW" )
					if(getWindowText){
						var len,str = getWindowText(hwnd,100,50);
						if(len) winform.editText.text = str;
					}
					prcs.free();
				}
			}
		}
	}
	
	winform.editStyle.text =  string.format("0x%X",win.getStyle(hwnd) );
	winform.editStyleEx.text =  string.format("0x%X",win.getStyleEx(hwnd) );
	
	var x,y = mouse.getPos();
	x,y = win.toClient(hwnd,x,y);
	winform.editPoint.text = ..string.format("%d,%d",x,y)
	
	winform.treeview.clear();
	var hRootItem = winform.treeview.insertItem({text=..win.getClass(hwnd);hwnd=hwnd});
	for hChild in win.eachChild(hwnd) {
	    var hChildItem = winform.treeview.insertItem({text=..win.getClass(hChild);hwnd=hChild},hRootItem); 
	    for hChild2 in win.eachChild(hChild) {
	    	winform.treeview.insertItem({text=..win.getClass(hChild2);hwnd=hChild2},hChildItem);  
		}
	}
	if(hRootItem) winform.treeview.expand(hRootItem);
	
	winform.showSampleCode();
	winform.lastSpyHwnd = hwnd;
}

winform.treeview.onnotify = function(id,code,ptr){
 
    if( code == 0xFFFFFFFE/*_NM_CLICK*/){  
		var hItem,tvht = winform.treeview.hitTest();
		if(hItem && tvht == 4/*_TVHT_ONITEMLABEL*/   ){
			var data  = winform.treeview.getItemData(hItem);
            if( data[["hwnd"]] ) {
                winform.setTimeout( 
                	function(){
            			if( frmMask.moveToWindow(data[["hwnd"]]) ){
							showWindowInfo(data[["hwnd"]]);
							win.delay(600);
            				frmMask.show(false);	
						}
                	}
                );	
            	
            }
		}
    } 
}
    
var validPattern = function(str){
	if(!#str) return "";
		
	var mbs = string.match(str,"[\s\w]*:+[\s\w]*")
	if(#mbs)
		return mbs;
		
	str = string.replace(str,"(\p)","\\\1") 	
	str = string.replace(str,"\x+",function(str){
	 	if(..string.find(str,"\d") ) return "\x+"
	 	return str;
	} ) 	
    
    str = string.replace(str,"\d+","\\d+") 	
    return str;
}

winform.showSampleCode = function(){
    var hwnd = tonumber(winform.editHwnd.text);
    if(!hwnd) return;
    
	winform.richedit.text = "";
	winform.richedit.print("import winex");
	winform.richedit.print("import winex.mouse");
	
	
	if( win.getParent(hwnd) ){
		winform.richedit.printf("var hwnd = winex.findEx(%d,,""%s"",""%s"")",
			win.getParent(hwnd),validPattern(win.getClass(hwnd)),validPattern(winex.getText(hwnd,50)));
	}
	else{
		var x,y,cx,cy = win.getPos(hwnd)
		winform.richedit.printf("win.setPos(hwnd,%d,%d,%d,%d)",x,y,cx,cy);
		
		if( win.getOwner(hwnd) ){
			winform.richedit.printf("var hwnd = winex.waitEx(%d,,""%s"",""%s"")",
				win.getOwner(hwnd),validPattern(win.getClass(hwnd)),validPattern(winex.getText(hwnd,50)));
		}
		else {
			winform.richedit.printf("var hwnd = winex.waitVisible(""%s"",,""%s"")",
				validPattern(winex.getText(hwnd,50)),validPattern(win.getClass(hwnd)));
		}
	}
	winform.richedit.printf("winex.mouse.click(hwnd,%s)",winform.editPoint.text);	
}

winform.plusCur.skin(
	background = { 
		active = "\.res\2.gif"; 
	}
)

import win.cur;
var hCursor = win.cur.loadfile("\.res\spy.cur") ;
winform.plusCur.onMouseDown = function(wParam,lParam){
	win.cur.beginCur();
	winform.plusCur.capture = true;
	winform.lastSpyHwnd = null;
}
	
winform.plusCur.onMouseUp = function(wParam,lParam){
	winform.plusCur.capture = false;
	win.cur.endCur();
	frmMask.show(false);
}

var hwndTarget;
tmid = winform.setInterval(
	function(hwnd,msg,id,tick){
		if ( win.cur.beginning ){ 
			var cwp = 0;
			if( winform.chkSkipInvisible ) cwp = cwp | 0x0001/*_CWP_SKIPINVISIBLE*/
			if( winform.chkSkipTransparent ) cwp = cwp | 0x0004/*_CWP_SKIPTRANSPARENT*/
			if( winform.chkSkipDiabled ) cwp = cwp | 0x0002/*_CWP_SKIPDISABLED*/
			var x,y = mouse.getPos();
			hwndTarget = winex.fromPointReal( x,y,cwp );
			if( frmMask.moveToWindow(hwndTarget) ){
				showWindowInfo(hwndTarget);
			} 
		} 
	},700
)
winform.editParenHwnd.skin(
	color = {
		hover = 0xFFFF0000;
		active = 0xFF00FF00;
	}
)
winform.editOwnerHwnd.skin(
	color = {
		hover = 0xFFFF0000;
		active = 0xFF00FF00;
	}
)

winform.editParenHwnd.oncommand = function(id,event){
	var hwnd = tonumber( winform.editParenHwnd.text,16 )
	if(hwnd){
		if( frmMask.moveToWindow(hwnd) ){
			showWindowInfo(hwnd);
			win.delay(600);
        	frmMask.show(false);
		}
   }
}

winform.editOwnerHwnd.oncommand = function(id,event){
	var hwnd = tonumber( winform.editOwnerHwnd.text,16 )
	if(hwnd){
		if( frmMask.moveToWindow(hwnd) ){
			showWindowInfo(hwnd);
			..win.delay(600);
        	frmMask.show(false);
		}
   }
}


import fsys.config;
config = fsys.config("/.res/config-winspy/");
if( config.hotkey.vk === null ){
    config.hotkey.vk = 0x7B/*_VK_F12*/;
    config.hotkey.mod = 0x2/*_MOD_CONTROL*/
} 
winform.hotkey.sethotkey(config.hotkey.mod,config.hotkey.vk)

var onHotkey = function(){
    winform.lastSpyHwnd = null;
    var cwp = 0;
	if( winform.chkSkipInvisible ) cwp = cwp | 0x0001/*_CWP_SKIPINVISIBLE*/
	if( winform.chkSkipTransparent ) cwp = cwp | 0x0004/*_CWP_SKIPTRANSPARENT*/
	if( winform.chkSkipDiabled ) cwp = cwp | 0x0002/*_CWP_SKIPDISABLED*/
	var x,y = mouse.getPos();
	hwndTarget = winex.fromPointReal( x,y,cwp );
	
    if( hwndTarget == winform.editParenHwnd.hwnd ){
       hwndTarget = tonumber(winform.editParenHwnd.text );
       if(hwndTarget){ 
       	showWindowInfo(hwndTarget);
       	winform.plusCur.background = "\.res\1.gif"
	   	win.cur.endCur();
	   	frmMask.show(false);
	   	return;
	   }
    }
    elseif( hwndTarget == winform.editOwnerHwnd.hwnd ){
       hwndTarget = tonumber(winform.editOwnerHwnd.text );
       if(hwndTarget){ 
       	showWindowInfo(hwndTarget);
       	winform.plusCur.background = "\.res\1.gif"
	   	win.cur.endCur();
	   	frmMask.show(false);
	   	return;
	   }
    };  

	if( win.cur.beginning){
		winform.plusCur.background = "\.res\1.gif"
		win.cur.endCur();
		frmMask.show(false);
	}
	else {
		win.cur.beginCur();
		winform.plusCur.background = "\.res\2.gif"  
	}
}

var hkid = winform.reghotkey(onHotkey,config.hotkey.mod,config.hotkey.vk);

winform.hotkey.oncommand = function(id,event){
	winform.unreghotkey(hkId);
	
	hkId = winform.reghotkey(onHotkey,winform.hotkey.gethotkey()  );
	
	config.hotkey.mod,config.hotkey.vk = winform.hotkey.gethotkey();
	config.hotkey.save();
}

win.setTopmost(winform.hwnd,true);
winform.editStyle.oncommand = function(id,event){
	if( event != 0x100/*_EN_SETFOCUS*/){
		return;
	}
	
	winform.richedit.text = "";
	
	var style={
		_WS_POPUP = 0x80000000;
		_WS_CHID = 0x40000000;
		_WS_MINIMIZE = 0x20000000;
		_WS_VISIBE = 0x10000000;
		_WS_DISABED = 0x8000000;
		_WS_CIPSIBINGS = 0x4000000;
		_WS_CIPCHIDREN = 0x2000000;
		_WS_MAXIMIZE = 0x1000000;
		_WS_CAPTION = 0xC00000;    
		_WS_BORDER = 0x800000;
		_WS_DGFRAME = 0x400000;
		_WS_VSCROLL = 0x200000;
		_WS_HSCROLL = 0x100000;
		_WS_SYSMENU = 0x80000;
		_WS_THICKFRAME = 0x40000;
		_WS_GROUP = 0x20000;
		_WS_TABSTOP = 0x10000; 
		_WS_MINIMIZEBOX = 0x20000;
		_WS_MAXIMIZEBOX = 0x10000;
	}

	var s = tonumber(winform.editStyle.text);
	if(!s) return;
	
	if( ! ( s&0x80000000 || s&0x40000000 ) ){
		winform.richedit.print("_WS_OVERAPPED") 
	}
	
	for(k,v in style){
		if( v &  s) winform.richedit.print(k) 
	}
	
	
};

winform.editStyleEx.oncommand = function(id,event){
	if( event != 0x100/*_EN_SETFOCUS*/){
		return;
	}

	winform.richedit.text = "";
	
	var style={
		_WS_EX_DLGMODALFRAME =  0x1;
		_WS_EX_NOPARENTNOTIFY =  0x4;
		_WS_EX_TOPMOST =  0x8;
		_WS_EX_ACCEPTFILES =  0x10;
		_WS_EX_TRANSPARENT =  0x20;
		_WS_EX_MDICHILD =  0x40;
		_WS_EX_TOOLWINDOW =  0x80;
		_WS_EX_WINDOWEDGE =  0x100;
		_WS_EX_CLIENTEDGE =  0x200;
		_WS_EX_CONTEXTHELP =  0x400;
		_WS_EX_RIGHT =  0x1000;
		_WS_EX_RTLREADING =  0x2000;
		_WS_EX_LEFTSCROLLBAR =  0x4000;
		_WS_EX_CONTROLPARENT =  0x10000;
		_WS_EX_STATICEDGE =  0x20000;
		_WS_EX_APPWINDOW =  0x40000;
		_WS_EX_LAYERED =  0x80000; 
		_WS_EX_NOINHERITLAYOUT =  0x100000; 
		_WS_EX_LAYOUTRTL =  0x400000; 
		_WS_EX_COMPOSITED =  0x2000000; 
		_WS_EX_NOACTIVATE =  0x8000000;
	}

	var s = tonumber(winform.editStyleEx.text);
	if(!s) return;
	
	for(k,v in style){
		if( v &  s) winform.richedit.print(k) 
	}
};

winform.editClass.oncommand = function(id,event){
	winform.showSampleCode(); 	
}

winform.editHwnd.oncommand = function(id,event){
	winform.showSampleCode(); 
}

winform.editText.oncommand = function(id,event){
	winform.showSampleCode(); 	
}

winform.editPoint.oncommand = function(id,event){
	winform.showSampleCode(); 	
}

import win.ui.tooltip; 
var tooltipCtr = win.ui.tooltip( winform );//在窗口上创建tooltip控件 
tooltipCtr.add( 
	plusCur = "请按住此图标并拖动到目标窗口";
	editParenHwnd = "点击这里切换到父窗口(parent window),也可以将鼠标指针对准这里按下面设置的热键切换到父窗口";
	editOwnerHwnd = "点击这里切换到所有窗口(owner window),也可以将鼠标指针对准这里按下面设置的热键切换到所有窗口";
	editStyle = "点这里显示详细的样式列表";
	editStyleEx = "点这里显示详细的扩展样式列表";
	editClass = "点这里显示演示代码";
	editText = "点这里显示演示代码";
	hotkey = "设置抓取窗口的热键，按此热键可以开始、或停止抓取窗口，适用于抓取弹出窗口";
	editPath = "启动目标应用程序的执行文件路径与启动参数";
	editHwnd10 = "窗口句柄10进制值,选中可复制";
	editParentHwnd10 = "父窗口句柄10进制值,选中可复制";
	editOwnerHwnd10 = "所有窗口句柄10进制值,选中可复制";
	editPoint = "相对于父窗口的坐标,点这里显示演示代码";
	editPid = "这是窗口所在目标进程的10进制ID，进程是正在运行的程序的实例,也就是一个执行中的程序。每一个进程都有它自己的地址空间，在一个进程中可以包含若干个执行线程";
	editTid= "这是窗口所在执行线程的10进制ID，线程被包含在进程（执行中的程序实例）之中，一个执行线程指的是进程中一个单一顺序的控制流，一个进程中可以并发执行多个线程";
	editHwnd = "句柄是一个系统对象的唯一标识，在 aardio 中窗口句柄是一个数值（静态类型为 addr )，其他类型句柄一般用指针表示( 静态类型 pointer )，当然他们的本质都是数值。";
	editId = "控件的 ID 值"
);

winform.richedit.enablePopMenu();
winform.show(true);
win.loopMessage();