import ide;
import win;
import win.guid;
import com;
import web.script;
import key;
loadcodex("~\extensions\trigger\ideModify\WG.aardio");
/*
var oleacc=raw.loadDll("oleacc.dll");
var ole32=raw.loadDll("ole32.dll");
var accSupport=raw.loadDll(string.load("~\extensions\trigger\ideModify\accSupport.dll"),,"cdecl");
var IID_IAccessible=win.guid.fromString("{618736E0-3C3D-11CF-810C-00AA00389B71}");
var IID_IOleWindow=win.guid.fromString("{00000114-0000-0000-C000-000000000046}")
*/
var jsBeautify = string.load("~\extensions\trigger\ideModify\js_beautify.js");
var mainHwnd,appended,popHwnd,childHwnd=ide.getMainHwnd(),false;
var mainProcAddr,mainOld,popProcAddr,popOld,editorProcAddr,editorOld,tmpHwnd;
var editorTxtTab,editorIdxTab={},{};
var AFX_WM_ONCHANGE_ACTIVE_TAB=::User32.RegisterWindowMessage("AFX_WM_ONCHANGE_ACTIVE_TAB"); //获取自定义消息id
var fmt=function(){ //格式化函数
var editorHwnd=ide.getActiveCodeEditorHwnd(); //获取编辑窗口句柄
if !editorHwnd return 0;
var editorText = win.getText(editorHwnd, 1024 * 1024);
for key,val in editorTxtTab{
if !win.isWindow(tonumber(key)) editorTxtTab[key]=null; //如果文档窗口被关闭,清理其历史记录
}
if editorTxtTab[editorHwnd] { //如果文档窗口在记录里已存在,则新增
var size=table.push(editorTxtTab[editorHwnd],editorText);
if size>10 table.remove(editorTxtTab[editorHwnd]); //只保存10条历史记录
}else { //否则新增该文档的历史记录key
editorTxtTab[editorHwnd]={};
table.push(editorTxtTab[editorHwnd],editorText); //并把文档保存在数组尾部
}
editorIdxTab[editorHwnd]=0; //撤销次数清零
var js = web.script();
js.eval(jsBeautify);
winex.setText(editorHwnd, js.run("js_beautify", editorText));
return 1;
}
var unFmt=function(){ //撤销格式化函数
var editorHwnd=ide.getActiveCodeEditorHwnd();
if !editorHwnd return 0;
if editorTxtTab[editorHwnd] && #editorTxtTab[editorHwnd]>editorIdxTab[editorHwnd]{ //撤销次数不能超过已保存的文档个数
winex.setText(editorHwnd, editorTxtTab[editorHwnd][#editorTxtTab[editorHwnd]-editorIdxTab[editorHwnd]]);
editorIdxTab[editorHwnd]+=1; //记录撤销次数
}
}
var editorWndProc=function(hwnd,msg,wParam,lParam){
if msg==0x100/*_WM_KEYDOWN*/{
if (key.getState('CTRL') && wParam == 'Q'#) fmt(); //格式化快捷键ctrl+q
if (key.getState('CTRL') && wParam == 'W'#) unFmt(); //撤销格式化快捷键ctrl+w
}
return ::CallWindowProc(editorOld,hwnd,msg,wParam:0,lParam:0); //碰到过wParam,lParam有null的情况,这个函数就会报错
}
var popWndProc=function(hwnd,msg,wParam:0,lParam:0){
if msg==0x210/*WM_PARENTNOTIFY*/ && wParam==0x201/*WM_LBUTTONDOWN*/{
var clickCord=::POINT(::LOWORD(lParam),::HIWORD(lParam)); //右键菜单主窗口客户区内坐标
::ClientToScreen(popHwnd,clickCord); //转屏幕坐标
var cldRect=win.getClientRect(childHwnd); //得到右键菜单窗口的子窗口客户区坐标
win.toScreenRect(childHwnd,cldRect); //转屏幕坐标
var fmtRect=::RECT();
raw.convert(cldRect,fmtRect); //下面复制两个rect结构体
var unfmtRect=::RECT();
raw.convert(cldRect,unfmtRect);
fmtRect.top+=345; //设置连个菜单项的坐标区域
fmtRect.bottom-=27;
unfmtRect.top+=376;
var fmtBol,rct=::User32.PtInRect(fmtRect,clickCord.x,clickCord.y); //下面几句,鼠标左键点击是否在这两个菜单项区域内
var unfmtBol,rct=::User32.PtInRect(unfmtRect,clickCord.x,clickCord.y);
if fmtBol fmt();
if unfmtBol unFmt();
}
var ret=::CallWindowProc(popOld,hwnd,msg,wParam,lParam); //消息传递
if( msg == 0x2/*_WM_DESTROY*/ ) {
::SetWindowPointer(popHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,popOld); //如果窗口关闭,回复原窗口过程
popProcAddr=null;
}
return ret;
}
var mainWndProc=function(hwnd,msg,wParam:0,lParam:0){
if msg==0x117/*WM_INITMENUPOPUP*/{
var strLen=::User32.GetMenuString(wParam,2,null,0,0x00000400); //获取菜单第3条文本长度
var buf;
if strLen {
buf=raw.buffer(strLen*2,0);
::User32.GetMenuString(wParam,2,buf,strLen*2,0x00000400);
}
if strLen && string.fromUnicode(buf)=="复制全部到HTML"{ //判断是否为编辑窗口的右键菜单
if !appended{ //判断是否添加过菜单项
var ret=::User32.AppendMenu(wParam,0x800/*_MF_SEPARATOR*/,20,null); //添加分割线
var ret1=::User32.AppendMenu(wParam,0/*_MF_STRING*/,21,"Beautify Format CTRL+Q"); //添加格式化项
var ret1=::User32.AppendMenu(wParam,0/*_MF_STRING*/,22,"Undo Formated CTRL+W"); //添加撤销格式化项
appended=true; //添加过就置为true
}
var hwndTab=WG.chkHwnd(0,"Afx:00400000:800:00010003:00000010:00000000",,0); //查找右键菜单主窗口
for(i=1;#hwndTab;1){ //同类名的好几个
var parentHwnd,len=tonumber(hwndTab[i]); //所以需要用其子窗口做进一步筛选
childHwnd=win.findEx(parentHwnd,0,null,null);
if childHwnd && win.getClass(childHwnd)=="Afx:ToolBar:400000:8:10003:10"{
popHwnd=parentHwnd; //确定右键菜单主窗口
break;
}
}
if !popHwnd error("找不到指定窗口,请联系作者。");
//-----------------------
/*
var itfAddr={addr val} //这部分做msaa测试的
var hret=oleacc.AccessibleObjectFromWindow(childHwnd,0,IID_IOleWindow,itfAddr);
var oleWinDisp=com.QueryObject(topointer(itfAddr.val));
com.DumpTypeInfo(oleWinDisp);
*/
//------------------------
popProcAddr=raw.tostdcall(popWndProc,"int(addr,INT,ADDR,addr)");
popOld=::SetWindowPointer(popHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,popProcAddr);
if !popOld error("PopWnd Hook Failed");
}
}
if msg==AFX_WM_ONCHANGE_ACTIVE_TAB{ //判断是否为自定义消息
var editorHwnd=ide.getActiveCodeEditorHwnd();
if editorHwnd!=tmpHwnd{ //如果前后窗口非同一个
if editorProcAddr { //如果之前挂过钩子则恢复并释放
::SetWindowPointer(tmpHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,editorOld);
editorProcAddr=null;
}
if editorHwnd{ //如果存在活动编辑器窗口,则挂钩
editorProcAddr=raw.tostdcall(editorWndProc,"int(addr,INT,ADDR,addr)");
editorOld=::SetWindowPointer(editorHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,editorProcAddr);
if !editorOld error("EditorWnd Hook Failed");
tmpHwnd=editorHwnd; //保存本次编辑活动窗口句柄
}
}
}
var ret=::CallWindowProc(mainOld,hwnd,msg,wParam,lParam);
if( msg == 0x2/*_WM_DESTROY*/ ){
::SetWindowPointer(mainHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,mainOld);
mainProcAddr=null;
}
return ret;
}
mainProcAddr=raw.tostdcall(mainWndProc,"int(addr,INT,ADDR,addr)");
mainOld=::SetWindowPointer(mainHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,mainProcAddr);
if !mainOld error("MainWnd Hook Failed");
/*
如果自己写回调函数,不用子类化库,这里必须返回CallWindowProc的返回值。
不然会造成丢失消息,并且造成最小化、关闭等按钮的失效。
return ::CallWindowProc(mainOld,hwnd,msg,wParam,lParam);
*/
/*
Afx:ToolBar:400000:8:10003:10,这个类名,400000是程序实例句柄,8是窗口样式,
10003是光标,10是背景。都是16进制。
*/
/*
菜单项的识别号和位置号不同,位置号为系统给定,0为基。识别号为所有者编写,api中基本需要提供的是位置号。
*/
import ide;
import win;
import win.guid;
import com;
import web.script;
import key;
loadcodex("~\extensions\trigger\ideModify\WG.aardio");
/*
var oleacc=raw.loadDll("oleacc.dll");
var ole32=raw.loadDll("ole32.dll");
var accSupport=raw.loadDll(string.load("~\extensions\trigger\ideModify\accSupport.dll"),,"cdecl");
var IID_IAccessible=win.guid.fromString("{618736E0-3C3D-11CF-810C-00AA00389B71}");
var IID_IOleWindow=win.guid.fromString("{00000114-0000-0000-C000-000000000046}")
*/
var jsBeautify = string.load("~\extensions\trigger\ideModify\js_beautify.js");
var mainHwnd,appended,popHwnd,childHwnd=ide.getMainHwnd(),false;
var mainProcAddr,mainOld,popProcAddr,popOld,editorProcAddr,editorOld,tmpHwnd;
var editorTxtTab,editorIdxTab={},{};
var AFX_WM_ONCHANGE_ACTIVE_TAB=::User32.RegisterWindowMessage("AFX_WM_ONCHANGE_ACTIVE_TAB"); //获取自定义消息id
var fmt=function(){ //格式化函数
var editorHwnd=ide.getActiveCodeEditorHwnd(); //获取编辑窗口句柄
if !editorHwnd return 0;
var editorText = win.getText(editorHwnd, 1024 * 1024);
for key,val in editorTxtTab{
if !win.isWindow(tonumber(key)) editorTxtTab[key]=null; //如果文档窗口被关闭,清理其历史记录
}
if editorTxtTab[editorHwnd] { //如果文档窗口在记录里已存在,则新增
var size=table.push(editorTxtTab[editorHwnd],editorText);
if size>10 table.remove(editorTxtTab[editorHwnd]); //只保存10条历史记录
}else { //否则新增该文档的历史记录key
editorTxtTab[editorHwnd]={};
table.push(editorTxtTab[editorHwnd],editorText); //并把文档保存在数组尾部
}
editorIdxTab[editorHwnd]=0; //撤销次数清零
var js = web.script();
js.eval(jsBeautify);
winex.setText(editorHwnd, js.run("js_beautify", editorText));
return 1;
}
var unFmt=function(){ //撤销格式化函数
var editorHwnd=ide.getActiveCodeEditorHwnd();
if !editorHwnd return 0;
if editorTxtTab[editorHwnd] && #editorTxtTab[editorHwnd]>editorIdxTab[editorHwnd]{ //撤销次数不能超过已保存的文档个数
winex.setText(editorHwnd, editorTxtTab[editorHwnd][#editorTxtTab[editorHwnd]-editorIdxTab[editorHwnd]]);
editorIdxTab[editorHwnd]+=1; //记录撤销次数
}
}
var editorWndProc=function(hwnd,msg,wParam,lParam){
if msg==0x100/*_WM_KEYDOWN*/{
if (key.getState('CTRL') && wParam == 'Q'#) fmt(); //格式化快捷键ctrl+q
if (key.getState('CTRL') && wParam == 'W'#) unFmt(); //撤销格式化快捷键ctrl+w
}
return ::CallWindowProc(editorOld,hwnd,msg,wParam:0,lParam:0); //碰到过wParam,lParam有null的情况,这个函数就会报错
}
var popWndProc=function(hwnd,msg,wParam,lParam){
if msg==0x210/*WM_PARENTNOTIFY*/ && wParam==0x201/*WM_LBUTTONDOWN*/{
var clickCord=::POINT(::LOWORD(lParam),::HIWORD(lParam)); //右键菜单主窗口客户区内坐标
::ClientToScreen(popHwnd,clickCord); //转屏幕坐标
var cldRect=win.getClientRect(childHwnd); //得到右键菜单窗口的子窗口客户区坐标
win.toScreenRect(childHwnd,cldRect); //转屏幕坐标
var fmtRect=::RECT();
raw.convert(cldRect,fmtRect); //下面复制两个rect结构体
var unfmtRect=::RECT();
raw.convert(cldRect,unfmtRect);
fmtRect.top+=345; //设置连个菜单项的坐标区域
fmtRect.bottom-=27;
unfmtRect.top+=376;
var fmtBol,rct=::User32.PtInRect(fmtRect,clickCord.x,clickCord.y); //下面几句,鼠标左键点击是否在这两个菜单项区域内
var unfmtBol,rct=::User32.PtInRect(unfmtRect,clickCord.x,clickCord.y);
if fmtBol fmt();
if unfmtBol unFmt();
}
var ret=::CallWindowProc(popOld,hwnd,msg,wParam:0,lParam:0); //消息传递
if( msg == 0x2/*_WM_DESTROY*/ ) {
::SetWindowPointer(popHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,popOld); //如果窗口关闭,回复原窗口过程
popProcAddr=null;
}
return ret;
}
var mainWndProc=function(hwnd,msg,wParam,lParam){
if msg==0x117/*WM_INITMENUPOPUP*/{
var strLen=::User32.GetMenuString(wParam,2,null,0,0x00000400); //获取菜单第3条文本长度
var buf;
if strLen {
buf=raw.buffer(strLen*2,0);
::User32.GetMenuString(wParam,2,buf,strLen*2,0x00000400);
}
if strLen && string.fromUnicode(buf)=="复制全部到HTML"{ //判断是否为编辑窗口的右键菜单
if !appended{ //判断是否添加过菜单项
var ret=::User32.AppendMenu(wParam,0x800/*_MF_SEPARATOR*/,20,null); //添加分割线
var ret1=::User32.AppendMenu(wParam,0/*_MF_STRING*/,21,"Beautify Format CTRL+Q"); //添加格式化项
var ret1=::User32.AppendMenu(wParam,0/*_MF_STRING*/,22,"Undo Formated CTRL+W"); //添加撤销格式化项
appended=true; //添加过就置为true
}
var hwndTab=WG.chkHwnd(0,"Afx:00400000:800:00010003:00000010:00000000",,0); //查找右键菜单主窗口
for(i=1;#hwndTab;1){ //同类名的好几个
var parentHwnd,len=tonumber(hwndTab[i]); //所以需要用其子窗口做进一步筛选
childHwnd=win.findEx(parentHwnd,0,null,null);
if childHwnd && win.getClass(childHwnd)=="Afx:ToolBar:400000:8:10003:10"{
popHwnd=parentHwnd; //确定右键菜单主窗口
break;
}
}
if !popHwnd error("找不到指定窗口,请联系作者。");
//-----------------------
/*
var itfAddr={addr val} //这部分做msaa测试的
var hret=oleacc.AccessibleObjectFromWindow(childHwnd,0,IID_IOleWindow,itfAddr);
var oleWinDisp=com.QueryObject(topointer(itfAddr.val));
com.DumpTypeInfo(oleWinDisp);
*/
//------------------------
popProcAddr=raw.tostdcall(popWndProc,"int(addr,INT,ADDR,addr)");
popOld=::SetWindowPointer(popHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,popProcAddr);
if !popOld error("PopWnd Hook Failed");
}
}
if msg==AFX_WM_ONCHANGE_ACTIVE_TAB{ //判断是否为自定义消息
var editorHwnd=ide.getActiveCodeEditorHwnd();
if editorHwnd!=tmpHwnd{ //如果前后窗口非同一个
if editorProcAddr { //如果之前挂过钩子则恢复并释放
::SetWindowPointer(tmpHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,editorOld);
editorProcAddr=null;
}
if editorHwnd{ //如果存在活动编辑器窗口,则挂钩
editorProcAddr=raw.tostdcall(editorWndProc,"int(addr,INT,ADDR,addr)");
editorOld=::SetWindowPointer(editorHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,editorProcAddr);
if !editorOld error("EditorWnd Hook Failed");
tmpHwnd=editorHwnd; //保存本次编辑活动窗口句柄
}
}
}
var ret=::CallWindowProc(mainOld,hwnd,msg,wParam:0,lParam:0);
if( msg == 0x2/*_WM_DESTROY*/ ){
::SetWindowPointer(mainHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,mainOld);
mainProcAddr=null;
}
return ret;
}
mainProcAddr=raw.tostdcall(mainWndProc,"int(addr,INT,ADDR,addr)");
mainOld=::SetWindowPointer(mainHwnd,0xFFFFFFFC/*_GWL_WNDPROC*/,mainProcAddr);
if !mainOld error("MainWnd Hook Failed");
/*
如果自己写回调函数,不用子类化库,这里必须返回CallWindowProc的返回值。
不然会造成丢失消息,并且造成最小化、关闭等按钮的失效。
return ::CallWindowProc(mainOld,hwnd,msg,wParam,lParam);
*/
/*
Afx:ToolBar:400000:8:10003:10,这个类名,400000是程序实例句柄,8是窗口样式,
10003是光标,10是背景。都是16进制。
*/
/*
菜单项的识别号和位置号不同,位置号为系统给定,0为基。识别号为所有者编写,api中基本需要提供的是位置号。
*/