//外部进程窗口操作
namespace winex;
import win; //winex基于win库扩展,重用普通窗口操作模块
//AllowSetForegroundWindow := ::User32.api( "AllowSetForegroundWindow", "int(INT dwProcessId)" )
AttachThreadInput := ::User32.api( "AttachThreadInput", "int(INT idAttach,INT idAttachTo,int fAttach)" )
EnumWindows := User32.api( "EnumWindows", "int(POINTER lpEnumFunc ,int lParam )" )
EnumChildWindows := User32.api( "EnumChildWindows", "int(int hWndParent,POINTER lpEnumFunc ,int lParam )" )
isUnicode := User32.api( "IsWindowUnicode", "int(int hwnd)" )
/**intellisense(winex)
isUnicode(__/*窗口句柄*/) = 判断窗口是否Unicode窗口
end intellisense**/
var getWindow = win.GetWindow;
match = function(hwnd,text,cls,id){
if( cls ){
if( not ..string.find( win.getClass(hwnd), cls ) ) {
return false;
}
}
if( text ) {
if( not ..string.find( win.getText(hwnd,30/*不要取太长的标题*/),text ) ){
return false;
}
}
if( id ) {
if( win.getId(hwnd) != id) {
return false;
}
}
return true;
}
//枚举所有子窗口 - 深度递归遍历
var enumWindows
enumWindows=function( onfind, parent, cls ,text, id,depth ){
//取到第一个子窗口
var next = getWindow( parent ,0x5/*_GW_CHILD*/ ) ;
if(!next)
return;
do{
sleep(0);
if( enumWindows( onfind, next, cls ,text, id ,depth+1 ) === false )
return;
do{
if( ! match(next,text,cls,id ) )
break;
if( onfind( next,depth ) === false )
return false;
}while(0)
next = getWindow( next ,0x2/*_GW_HWNDNEXT*/ )
}while( next )
}
enum = function( onfind, parent, cls ,text, id ){
parent := ..win.getDesktop();
enumWindows(onfind, parent, cls ,text, id,2)
}
function enumTop( onfind ) {
// 须是一个字符串
assert( where===null || type(where) == type.string ,"查询条件必须是字符串")
var EnumwndProc = function( hwnd,lparam ){
if( onfind( hwnd ) === false)
return 0;
else
return 1 ;
}
pEnumwndProc = ..raw.tostdcall(EnumwndProc,"int(int hwnd,int lparam )"/* ,{ tag='crane' } */ );
EnumWindows(pEnumwndProc ,0); //回调函数声明了_topointer无方法,因此可以自动转换为pointer指针
pEnumwndProc = null;//确认不会再用到的回调函数,可以显示声明为null进行释放
}
/**intellisense(winex)
enum(onfind,parent)=@.enum( \n function(hwnd,depth){\n ..io.print( depth/*深度*/,hwnd/*窗口*/,win.getText(hwnd)/*标题*/ )\n /*return false*/\n } \n ,__/*输入父窗口*/\n ,要查找的类名\n ,要查找的标题\n ,要查找的控件ID\n)
enum(onfind)=@.enum( \n function(hwnd,depth){\n ..io.print( depth/*深度*/,hwnd/*窗口*/,win.getText(hwnd)/*标题*/ )\n /*return false*/\n } \n)
enumTop=@.enumTop(\n function(hwnd){\n ..io.print(hwnd)\n }\n)\n//枚举桌面顶层窗口;
end intellisense**/
//迭代指定父窗口的子级窗口 - 广度迭代遍历
function each( mcls,mtitle,parent ) {
parent := ..win.getDesktop();
return function(hwnd) { //接收for循环传递的参数得到迭代器控制变量
var title;
do{
hwnd = getWindow( hwnd ,0x2/*_GW_HWNDNEXT*/ );
if(!hwnd)
return null;
if( ! match(hwnd,mtitle,mcls ) )
continue;
if(!title)
title = ..win.getText(hwnd);
return hwnd,title, ..win.getThreadProcessId(hwnd);
}while(1)
} , , getWindow( parent ,0x5/*_GW_CHILD*/ ) ;
}
/**intellisense(winex)
each("类名","查找标题") = @for hwnd,title,theadId,processId in winex.each( "", ".*__/*请输入标题包含字符串\n可使用模式匹配语法*/" ) { \n//遍历所有进窗口\n \n}
each() = @for hwnd,title,theadId,processId in winex.each( __/*无参数则返回桌面所有顶层窗口\n可在此输入标题包含字符串\n可使用模式匹配语法*/ ) { \n//遍历所有进窗口\n \n}
each("类名","查找标题",父窗口) = @for hwnd,title,theadId,processId in winex.each("",__/*请输入父窗口句柄*/) { \n//遍历所有进窗口\n \n}
end intellisense**/
//模糊匹配查找顶层窗口,可选参数(类名,标题,进程ID,线程ID)
find = function(cls,title,pid,tid){
for hwnd,title,theadId,processId in each( cls,title ) {
if( pid ){
if( pid != processId )
continue;
}
if( tid ){
if( tid != theadId )
continue;
}
return hwnd,theadId,processId
}
}
findEx = function(parent,count,cls ,text, id ){
var count2=0;
var result;
enum(
function( hwndfind,depth ){
result = hwndfind;
if( count ){
count2++;
if( count2 < count )
return true; //接着找
}
return false;//停止查找
}
,parent
,cls
,text
,id
)
return result;
}
findExists = function(title,text,cls,ctrlcls,ctrlid){
if( text || ctrlcls || ctrlid ) {
var ctrl;
for parent,title,theadId,processId in each( cls,title ) {
ctrl = findEx( parent,null,ctrlcls ,text, ctrlid )
if( ctrl )
return parent,ctrl,theadId,processId
}
}
else {
parent,theadId,processId = find(cls,title);
return parent, ,theadId,processId;
}
}
findActivate = function(title,text,cls,ctrlcls,ctrlid){
parent,ctrl,theadId,processId = findExists(title,text,cls,ctrlcls,ctrlid);
if(parent){
..win.setForeground(parent)
sleep(1)
}
return parent,ctrl,theadId,processId;
}
waitTimeout = null;
waitDelay = 100;
wait = function( title,text,cls,ctrlcls,ctrlid){
var tk = ..time.tick();
var parent,ctrl,theadId,processId ;
var fctrl = text || ctrlcls || ctrlid;
while(!parent){
if(fctrl)
parent,ctrl,theadId,processId = findExists(title,text,cls,ctrlcls,ctrlid)
else
parent,theadId,processId = find(cls,title)
if( waitTimeout ){
if( ..time.tick() - tk > waitTimeout ){
return parent,ctrl,theadId,processId
}
}
sleep(0)
..win.delay(waitDelay)
}
return parent,ctrl,theadId,processId;
}
waitClose = function( title,text,cls,ctrlcls,ctrlid){
var tk = ..time.tick();
var waitfunc = type(title)==type.number? ..win.isWindow : findExists
while( waitfunc(title,text,cls,ctrlcls,ctrlid) ){
if( waitTimeout ){
if( ..time.tick() - tk > waitTimeout ){
return false
}
}
sleep(0)
..win.delay(waitDelay)
}
return true;
}
waitActive = function( title,text,cls,ctrlcls,ctrlid){
var tk = ..time.tick();
var hwnd = type(title)==type.number ? title;
var f;
while( 1 ){
f = ..win.getForeground();
if( hwnd ){
if(hwnd == f )
return f;
}
else {
if( match(f,title,cls ) ){
var ctrl = findEx(f,null,ctrlcls ,text, ctrlid )
if( ctrl )
return f,ctrl,..win.getThreadProcessId(f);
}
}
if( waitTimeout ){
if( ..time.tick() - tk > waitTimeout ){
return;
}
}
sleep(0)
..win.delay(waitDelay)
}
}
//MenuItemFromPoint = ::User32.api("MenuItemFromPoint","int(int hWnd,int hMenu,int x,int y)")
//叶级子窗口
fromPoint= User32.api("WindowFromPoint", "int(int x, int y)");
//叶级子窗口,并穿透groupbox
fromPointReal = function(x,y){
var hwnd = fromPoint(x,y);
if(hwnd){
var parent = ..win.getParent(hwnd);
if(parent)
hwnd= fromClientPointReal(parent,
..win.toClient(parent,x,y) );
}
return hwnd;
}
//子窗口,而非叶级窗口
var childWindowFromPointEx = User32.api("ChildWindowFromPointEx","int(int hwnd,int x,int y,INT flags)")
fromClientPoint = function(hwnd,x,y,un=0x0001/*_CWP_SKIPINVISIBLE*/){
return childWindowFromPointEx(hwnd,x,y,un);
}
//子窗口,而非叶级窗口,穿透groupbox
fromClientPointReal = User32.api("RealChildWindowFromPoint","int(int hwnd,int x,int y )")
attachThread = function(tid,att = true){
var cid = ..thread.getId();
if(tid==cid)
return att;
return AttachThreadInput(tid, cid, att?1:0)
}
attach = function(hwnd,att = true){
if(!hwnd)
error("无效的窗口句柄",2)
var tid,pid = ..win.getThreadProcessId(hwnd); // 当前窗口的线程ID
return attachThread(tid,att);
}
getFocus = function(hwnd){
hwnd := win.getForeground();
if(type(hwnd)!=type.number)
error("错误的句柄",2)
var tid,pid = ..win.getThreadProcessId(hwnd); // 当前窗口的线程ID
var cid = ..thread.getId();
var hwndChildAfter = ..win.findEx(hwnd,0);
if(hwndChildAfter){
if(tid == cid )
return ..win.getFocus(),cid,pid;
else if( AttachThreadInput(tid, cid, 1)) {
var hCtrl = ..win.getFocus();
AttachThreadInput(tid, cid, 0);
return hCtrl,tid,pid;
}
}
else
return hwnd,tid,pid;
}
/**intellisense(winex)
match(.(句柄,文本,类名,ID) = 指定一个窗口句柄,检测是否符合给定参数\n所有参数可选,类名与文本支持模式表达式
find(.(类名模式串,标题模式串,进程ID,线程ID)=查找顶层窗口,所有参数都是可选参数\n返回值为:句柄,线程ID,进程ID
findEx(.(父窗口句柄,返回第几个匹配句柄,类名模式串 ,标题模式串, 控件ID )=查找子窗口,除父窗口句柄外所有参数可选\n返回值为句柄
findExists(.(父窗口标题,控件文本,父窗口类名,控件类名,控件ID) = 查找包含指定控件窗口的父窗口,所有参数可选\n返回值为:窗口句柄,控件句柄,线程ID,进程ID
findActivate(.(父窗口标题,控件文本,父窗口类名,控件类名,控件ID) = 调用winex.findExists查找并激活包含指定控件窗口的父窗口,所有参数可选\n返回值为:窗口句柄,控件句柄,线程ID,进程ID
wait(.(父窗口标题,控件文本,父窗口类名,控件类名,控件ID) = 等待指定窗口创建,所有参数可选\n成功返回窗口句柄,控件句柄,线程ID,进程ID,超时返回空值
waitClose(.(父窗口标题,控件文本,父窗口类名,控件类名,控件ID) = 等待指定窗口关闭,所有参数可选\n成功返回true,超时返回false
waitClose(窗口句柄) = 等待指定窗口关闭,所有参数可选\n成功返回true,超时返回false
waitActive(.(父窗口标题,控件文本,父窗口类名,控件类名,控件ID) = 等待指定窗口激话,所有参数可选\n成功返回窗口句柄,控件句柄,线程ID,进程ID,超时返回false
waitActive(窗口句柄) = 等待指定窗口激话,所有参数可选\n成功返回窗口句柄,超时返回false
waitTimeout = 指定winex库所有wait前缀的等待函数的默认超时值\n以毫秒为单位,默认为null表示永不超时.
waitDelay = 指定winex库所有wait前缀的等待函数的的检测时间间隔;\n以毫秒为单位,默认为100毫秒
fromPoint(.(x坐标,y坐标)=从指定的屏幕坐标查找窗口\n获取叶级子窗口。
fromPointReal(.(x坐标,y坐标)=从指定的屏幕坐标查找窗口\n获取叶级子窗口,穿透groupbox。
fromClientPoint(.(窗口句柄,x坐标,y坐标) = 从指定的窗口坐标查找子窗口\n仅子窗口,非叶级窗口
fromClientPoint(.(窗口句柄,x坐标,y坐标,_CWP_ALL) = 从指定的窗口坐标查找子窗口\n_CWP_ALL指定包含隐藏、禁用控件
fromClientPointReal(.(窗口句柄,x坐标,y坐标) = 从指定的窗口坐标查找子窗口\n仅子窗口,非叶级窗口,穿透groupbox。
attach(__/*窗口句柄*/) = 附加到输入线程\n返回值为是否成功附加
attach(__/*窗口句柄*/,false) = 解除附加\n返回值为是否成功解除
attachThread(__/*线程ID*/) = 附加到输入线程\n返回值为是否成功附加
attachThread(__/*线程ID*/,false) = 解除附加\n返回值为是否成功解除
getFocus(__/*输入父窗口句柄*/)=获取输指定窗口输入焦点所在的控件句柄
getFocus()=获取前台窗口、输入焦点所在的控件句柄
end intellisense**/
say2 = function(str,hwnd){
//注入对方进程,并发送文本
hwnd = getFocus(hwnd);
for(i=1;#str ) {
//双字节字符
if(str[i]>0x80){
::PostMessage(hwnd, 0x102/*_WM_CHAR*/, ( ( ( str[i+1] << 8) | str[i] ) ) , 1);
i++
}
else
::PostMessage(hwnd, 0x102/*_WM_CHAR*/, str[i] , 1);
}
..win.delay(1)
}
sayIme = function(str,hwnd){
hwnd = getFocus(hwnd);
for(i=1;#str ) {
//双字节字符
if(str[i]>0x80){
::PostMessage(hwnd, 0x286/*_WM_IME_CHAR*/, ( ( ( str[i] << 8) | str[i+1] ) ) , 1);
i++
}
else
::PostMessage(hwnd, 0x286/*_WM_IME_CHAR*/, str[i] , 1);
}
..win.delay(1)
}
say = function(str,hwnd){
//自动发送文本
hwnd = getFocus(hwnd);
if( ..win.isWindow(hwnd) ){
for(i=1;#str) {
//这里如果用SendMessage,就发不出字体
::PostMessage(hwnd, 0x102/*_WM_CHAR*/, str[i] & 0xFF, 0x0001);
}
}
..win.delay(1)
}
sendString = function(str,hwnd){
//自动发送文本
hwnd = getFocus(hwnd);
if( ..win.isWindow(hwnd) ) {
::SendMessage(hwnd,0xC2/*_EM_REPLACESEL*/,null,str);
}
}
click = function( hwnd,cmdid ){
if( ! cmdid )
::PostMessage(hwnd, 0xf5/*_BM_CLICK*/, 0, 0)
else
::PostMessage(hwnd, 0x111/*_WM_COMMAND*/,cmdid ,0);
}
quit = function(hwnd){
::PostThreadMessage(win.getThreadProcessId(hwnd),0x12/*_WM_QUIT*/ ,0,0);
}
close = function(hwnd){
::PostMessage(hwnd,0x10/*_WM_CLOSE*/,0,0);
}
setText = function(hwnd,str){
::SendMessage(hwnd,0xC/*_WM_SETTEXT*/,,str);
}
//菜单函数
GetMenu = ::User32.api("GetMenu","int(int hwnd)")
GetSubMenu = User32.api("GetSubMenu","int(int hMenu,int nPos)");
GetMenuItemID = User32.api("GetMenuItemID","INT(int hMenu,int nPos)");
GetMenuItemCount = User32.api("GetMenuItemCount","int(int hMenu)");
GetMenuString = User32.api("GetMenuStringA","int(int hMenu,int wIDItem,string& lpString,int nMaxCount,int wFlag)")
MENU_ITEM_IS_SUBMENU = 0xFFFFFFFF
findMenu = function(target_window,...) {
lables = {...}
var hMenu = GetMenu(target_window);
if (!hMenu)
return 0;
if( not #lables )
return hMenu;
var menuId = MENU_ITEM_IS_SUBMENU;
var itmeCount = GetMenuItemCount(hMenu);
if (itmeCount < 1)
return;
var hMenuFind;
onFindSubMenu = function( menu_pos ){
menuId = GetMenuItemID(hMenu, menu_pos);
if (menuId == MENU_ITEM_IS_SUBMENU) {
hMenu = GetSubMenu(hMenu, menu_pos);
itmeCount = GetMenuItemCount(hMenu);
hMenuFind = hMenu;
}
else {
itmeCount = 0;
hMenu = null;
}
}
for(i=1;#lables ) {
if (!hMenu)
return;
if( type(lables[i])==type.number ){
if ( (lables[i] <= -1) || ( lables[i] >= itmeCount) )
return;
onFindSubMenu(lables[i])
}
else if(type(lables[i])==type.string) {
for(pos=0;itmeCount-1){
var len, target= GetMenuString(hMenu, pos, 1024, 1024-1, 0x400/*_MF_BYPOSITION*/);
if( not ..string.find( lables[i],"\&" ) )
target = ..string.replace(target,"\&","");
if( ..string.find( target,lables[i] ) ){
onFindSubMenu(pos)
break;
}
}
}
else
return ;
}
if (menuId == MENU_ITEM_IS_SUBMENU)
return hMenuFind;
else
return hMenuFind,menuId
}
/**intellisense(winex)
findMenu(.(窗口句柄,"子菜单标题",或子菜单序号,.....) = 例如:\nhmenu,menuid = winex.findMenu(hwnd ,"文件","另存为" )
click(.(窗口句柄,命令ID) = 模拟点击命令
click(.(按钮窗口句柄) = 模拟点击按钮
sendString("") = 向前台窗口的文本框发送文本
sendString("",__/*输入窗口句柄*/) = 向指定窗口上的文本框发送文本
say("") = 向前台窗口的文本框发送文本
say("",__/*输入窗口句柄*/) = 向指定窗口上的文本框发送文本
say2("") = 向前台窗口的文本框发送文本
say2("",__/*输入窗口句柄*/) = 向指定窗口上的文本框发送文本
sayIme("") = 向前台窗口的文本框发送文本\n使用_WM_IME_CHAR消息
sayIme("",__/*输入窗口句柄*/) = 向指定窗口上的文本框发送文本\n使用_WM_IME_CHAR消息
quit(__/*输入窗口句柄*/) = 退出程序(WM_QUIT)
close(__/*输入窗口句柄*/) = 关闭窗口(WM_CLOSE)
setText(.(窗口句柄,文本) = 修改外部程序窗口标题或文本
end intellisense**/
阅读(2927) | 评论(0) | 转发(0) |