From da3326a5e4899b38b8127a51bf3c379c9b2fd7c6 Mon Sep 17 00:00:00 2001 From: Edward Jakubowski Date: Tue, 27 May 2014 21:59:26 -0400 Subject: [PATCH] Message Hook Window is working, Added BAR sendKeys and fixed colon key. Message Hook Window is working and will allow you to see all messages being processed by a target window. Had to build Message Hook Window inside the native MsgHook.dll was having issues keep a java window's WndProc callback processing. --- .classpath | 3 +- build.xml | 3 + native/MsgHook.sln | 36 -- native/MsgHook.suo | Bin 24576 -> 0 bytes native/MsgHook/MsgHook.cpp | 8 + native/MsgHook/MsgHook.vcxproj | 9 + native/MsgHook/MsgHook.vcxproj.filters | 20 + .../{MsgHookTest => MsgHook}/MsgHookTest.aps | Bin 54412 -> 54880 bytes .../{MsgHookTest => MsgHook}/MsgHookTest.ico | Bin .../{MsgHookTest => MsgHook}/MsgHookTest.rc | Bin 11288 -> 11554 bytes .../MsgHookWindow.cpp} | 186 +++++--- .../MsgHook.h => MsgHook/MsgLookup.h} | 65 +-- native/MsgHook/bin/MsgHook32.dll | Bin 7680 -> 78336 bytes native/MsgHook/bin/MsgHook64.dll | Bin 9216 -> 80896 bytes native/MsgHook/org_synthuse_MsgHook.cpp | 43 +- native/MsgHook/org_synthuse_MsgHook.h | 28 +- native/{MsgHookTest => MsgHook}/resource.h | Bin 3560 -> 3744 bytes native/{MsgHookTest => MsgHook}/small.ico | Bin native/MsgHook/stdafx.h | 6 + native/MsgHookTest/MsgHookTest.h | 3 - native/MsgHookTest/MsgHookTest.vcxproj | 166 ------- .../MsgHookTest/MsgHookTest.vcxproj.filters | 57 --- native/MsgHookTest/MsgHookTest.vcxproj.user | 3 - native/MsgHookTest/ReadMe.txt | 62 --- native/MsgHookTest/WinMessages.txt | 416 ------------------ native/MsgHookTest/bin/x32/MsgHook.dll | Bin 7680 -> 0 bytes native/MsgHookTest/bin/x32/MsgHook.exp | Bin 1135 -> 0 bytes native/MsgHookTest/bin/x32/MsgHook.lib | Bin 2590 -> 0 bytes native/MsgHookTest/bin/x32/MsgHookTest.exe | Bin 76288 -> 0 bytes native/MsgHookTest/bin/x64/MsgHook.dll | Bin 9216 -> 0 bytes native/MsgHookTest/bin/x64/MsgHook.exp | Bin 1125 -> 0 bytes native/MsgHookTest/bin/x64/MsgHook.lib | Bin 2554 -> 0 bytes native/MsgHookTest/bin/x64/MsgHookTest.exe | Bin 77312 -> 0 bytes native/MsgHookTest/stdafx.cpp | 8 - native/MsgHookTest/stdafx.h | 23 - native/MsgHookTest/targetver.h | 8 - src/org/synthuse/Api.java | 74 +++- src/org/synthuse/CommandPopupMenu.java | 8 +- src/org/synthuse/CommandProcessor.java | 6 + src/org/synthuse/DragTarget.java | 2 +- src/org/synthuse/MessageHookFrame.java | 238 +++++++--- src/org/synthuse/MsgHook.java | 30 +- src/org/synthuse/RobotMacro.java | 6 +- src/org/synthuse/SynthuseDlg.java | 29 +- src/org/synthuse/UiaBridge.java | 7 + src/org/synthuse/commands/BaseCommand.java | 7 + src/org/synthuse/commands/FileCommands.java | 7 + .../synthuse/commands/KeyboardCommands.java | 7 + src/org/synthuse/commands/MainCommands.java | 7 + src/org/synthuse/commands/MouseCommands.java | 11 +- .../synthuse/commands/WindowsCommands.java | 25 ++ 51 files changed, 650 insertions(+), 967 deletions(-) delete mode 100644 native/MsgHook.sln delete mode 100644 native/MsgHook.suo rename native/{MsgHookTest => MsgHook}/MsgHookTest.aps (86%) rename native/{MsgHookTest => MsgHook}/MsgHookTest.ico (100%) rename native/{MsgHookTest => MsgHook}/MsgHookTest.rc (84%) rename native/{MsgHookTest/MsgHookTest.cpp => MsgHook/MsgHookWindow.cpp} (75%) rename native/{MsgHookTest/MsgHook.h => MsgHook/MsgLookup.h} (93%) rename native/{MsgHookTest => MsgHook}/resource.h (95%) rename native/{MsgHookTest => MsgHook}/small.ico (100%) delete mode 100644 native/MsgHookTest/MsgHookTest.h delete mode 100644 native/MsgHookTest/MsgHookTest.vcxproj delete mode 100644 native/MsgHookTest/MsgHookTest.vcxproj.filters delete mode 100644 native/MsgHookTest/MsgHookTest.vcxproj.user delete mode 100644 native/MsgHookTest/ReadMe.txt delete mode 100644 native/MsgHookTest/WinMessages.txt delete mode 100644 native/MsgHookTest/bin/x32/MsgHook.dll delete mode 100644 native/MsgHookTest/bin/x32/MsgHook.exp delete mode 100644 native/MsgHookTest/bin/x32/MsgHook.lib delete mode 100644 native/MsgHookTest/bin/x32/MsgHookTest.exe delete mode 100644 native/MsgHookTest/bin/x64/MsgHook.dll delete mode 100644 native/MsgHookTest/bin/x64/MsgHook.exp delete mode 100644 native/MsgHookTest/bin/x64/MsgHook.lib delete mode 100644 native/MsgHookTest/bin/x64/MsgHookTest.exe delete mode 100644 native/MsgHookTest/stdafx.cpp delete mode 100644 native/MsgHookTest/stdafx.h delete mode 100644 native/MsgHookTest/targetver.h diff --git a/.classpath b/.classpath index a4a6148..1f51963 100644 --- a/.classpath +++ b/.classpath @@ -1,9 +1,10 @@ + - + diff --git a/build.xml b/build.xml index 557de61..154b8ee 100644 --- a/build.xml +++ b/build.xml @@ -61,6 +61,9 @@ + + + diff --git a/native/MsgHook.sln b/native/MsgHook.sln deleted file mode 100644 index 58c03a6..0000000 --- a/native/MsgHook.sln +++ /dev/null @@ -1,36 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MsgHook", "MsgHook\MsgHook.vcxproj", "{8E038A94-7D02-49E9-B9F6-5224D9D11225}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MsgHookTest", "MsgHookTest\MsgHookTest.vcxproj", "{E8016236-E771-4BEC-8407-6BF37C68D174}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|Win32.ActiveCfg = Debug|Win32 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|Win32.Build.0 = Debug|Win32 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|x64.ActiveCfg = Debug|x64 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Debug|x64.Build.0 = Debug|x64 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|Win32.ActiveCfg = Release|Win32 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|Win32.Build.0 = Release|Win32 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|x64.ActiveCfg = Release|x64 - {8E038A94-7D02-49E9-B9F6-5224D9D11225}.Release|x64.Build.0 = Release|x64 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Debug|Win32.ActiveCfg = Debug|Win32 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Debug|Win32.Build.0 = Debug|Win32 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Debug|x64.ActiveCfg = Debug|x64 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Debug|x64.Build.0 = Debug|x64 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Release|Win32.ActiveCfg = Release|Win32 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Release|Win32.Build.0 = Release|Win32 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Release|x64.ActiveCfg = Release|x64 - {E8016236-E771-4BEC-8407-6BF37C68D174}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/native/MsgHook.suo b/native/MsgHook.suo deleted file mode 100644 index e708592a778c812446604620beceaf1106e98f22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24576 zcmeHP3wT?_mA;Piu#*4*(f}cVfzVR0ge1$dl#meX5fZS8iJb(3z{t|ItXP(euI$8l zP#Ut3%>tz%K!KK)E%e13S{8QO1+ojJkKGiy+Y)xS3rit%m+eCPZC~3Y{r`LKSkkqm zd#xyT_xn2je$Ca~(VR0gXU?2CGvgoZJO0fFo}B-dWC%;8TItZ?dTDxIdJUclHO!Hu zDR>|b9X@V z&3yZa! z9iW(&Hb^T$y%$d*X;Zl(#=M&c4J7C@9+RO&0_B&XONvN})GxJ33B*}x4L)V?B+?Zv zTglIb70{;+<@jP)3wm8@A0(w7#G9l}mHsgJiQ>sDoCW$EYaDl0>rb7{G0z~z5@V(b z9gv^SXEFY%3ySFg=Hd7kzvI~FGsi#m1IIsg40Qp=KXpL^U>yJLNaOgYZphaGV*FDV zPzS699DoxbohHO?pc(K0Ex>Dl54aYfxb*-_fTh4iz%rl}@B;xL2!w#;z{S7{U?p$~ z5CcTrF2nOGpaZxZSPgUnUBDXPAAohh6~L9idf+M`3|tLd19Sto1ES2R{>&cl1>!&- zkN`FS{Xh~J08&627zFMFG63b2Wep)7)}J|&IGUNh1@Tt>`Fg~k(4X60`^?_Ok1c3@ ze8ZO`C%O0EjpT8K4+5MaCNXd@p?-%MGt8!RU$a&T$~{Bzj*P6xsca;hNT)g?(f&wW zZfsa9XB2#2;&j;6zs82ZP%=A|k(Z?8p=>6SY;5Ql>PaS|m&zku>3%u2q{q?J+uYmI z>vYDN9g(KU43(ImICZE!5zVBPbZ^$aHlYkflAYP1SR!p#S%}M-(TA>dI=L>9ilsLy z_FyC%=}HVL_Krj<73oRJ>X*=_tejF3J&9x@J7Vu3rwUS{^7(D*gPh^-I#=coFASp#P}<59`H| zMvpWEd5_~MgK-l92T{mA>tY@nq$xG*ei6)nq1iXo9SlbLe()fJhkmq58tuV3u^b=g zR#1QH{5rhTXc2MND;+5RV(eR`&-qZ4Xr$i`DH{M)+QIAewn$4GAuYv2V+Hh2L{YRA z7>x9b>z{m1wBLzOH`<@;usML$`hNs@#rW68fF_%hH5MpwQS>u)OHS{whCjo&lEy-;{+{~tNWx5MHHOY~X;)2fkpq8Qydg)Ex7FviwFDh5o7)%i+5Eoc z9$T}^X);XGt1=JBYgfWmBU6Yk7`bfv0 zk^aRPdDJ|E(A6CK8YiVW!2Da|!fVbSR^>l`{2S?0?{R*xMqQnMYv>o5ULk!y=&_!( zIa2D{FAM4%5%H2b2c$*=?H{g{xZbi_f36p)gBfUV(BjL0B4_#BOeZ~q|5jjFw@m7K5XI`ED*X*o;Cf%;RQa*b)V{zn> zT-)xhP?wqVlFr1tm624oZ%C25bq4L@V60LlYsy$GnH-2DQsd!ek7%Tj*WvWInmo2p zON-Oy_J;yCuiMdL^Z1uHwFErgptHq2s_?sHB`dmy&!syqKc~IVYS-O6fn2HlkE8c) z7QBsfiZty#B^!(MZnEA;HByb3_7k+d+A&g->Nw>JDWc9FoWXyx4;r~U`=JiHy_^m@Z`tma(J_B@M^j6=SChM;KU!lH%r^FvWdYu zEu_0jT|MSgrPr&vR99mr&}J?AOSfVc@qj-&RyTfCXK@AZM-KYUa<#wcsPm!CA5CZ- zGhXNstZtj+YYm<)s&iv%>>(5?w`{A2^ zvv2Q%AygFp?E`bqdF}DD&%XGXci!6ev7P}6BEl-Hu{J=0xz;w$@oOQUW&!?Zb^WLM zbT9##<>&hgfbDw50Az$7ctu^q%aCOw7kb7L5&Z8e{RMb$b^gn@Kg1ZN9W)4DX#LR| z(nb{Ro${d)|3B^3yL1h*2KE%GM%1-WY*c3mUrKrE^dpVm|CL|=PRZLlckiLSr?)-$ zx!7ZOpZ-6-@yU-Fe`fD5Z{QlZnD@!(Ln{1khmR_%_L;VSqbV?@Ir(-XI9OZmB`Mxu)Uh@llJ1bym##Gtk>LUqhT&`NAT#3^oY!N0+ozE&K6Pl2&sR_HGNNQ`gka3cMHCR|B192M0&ZHT5X4(L5zQGymf(#A+<+W zf)nmXX0Q@2XM62_QjC%c*r3m|Ew<>khns>5duwzuemQYLRcDw+Q-M1eDp(Mr|)AN}em%Rmq0sF$Ofd$*v1@pmbH zF21{uvPujhP=Z6TCV+RlhD#H7pVUlkb(Q- zR_Sj<-bVli1%7UNbox}iCqp8P^Q@3_T3EZQEa!!^jAKm9qNUO`nWrGFALVNmp4Ola zA?bRw-PjS?28j<~)zt<`({hl?fI3>Q$JkZS-fngEkVWfL<JOrztp3 zR=WkQ@sQIV#rUG^-Zk2S)zM%_+OtCHW`Vc1G8%0mR+-u^Bj;&q5C!w;TIhCackcU@ zcaC4NPk2H>sDiNUsQHvC@NdnK{67*-63_DHR&UVfvpIY&ug&drIc=@(fZOJ34f&hB zjwZja8E&O@a!&}JKUq;a<;-v*Du>6U*rST-8jLOq$K+u-nH~%etEU_q6!n-xgUjJ` zgqcN-W|ieSO*)#PoldWNf-CE82aie?@p&6`!tRyTUptV@9A%^E*1=)$~n z8iiWheEuDljJAET^#RjL*}_LItEDad6l9y$Q#n}|XH?AVDrO`O?bT&wBvE2mwIgX` zo7-4@DDyO6=OoR-V^LD~Wj4OdCIvuf8*B>OycR=8xpW9^CG`~I@!zqoJ4 zob0Ezuknau1Y}YKR-k0KX_DICSds1ZzMBtp%-VkHd%s?E%KB%1NS!Y#AmU<`*fUA| z7s{ECD>2HR_-6Nsr{49>H{Ln;?5C&O7QRPQPSirgT5YyZDE~$Q(&nV?wNL!+knB3Q z{^zqBJ1+Kzt+qXDVD5h?zkaI3|GF7;|5|H43-p`xoW&zS|7^Tw&lJy9n0g()KBFg@ z*T1>&$A)jD&-)04Qents_)4$B7xgrA`X0lt3%`>7SxEXQV730+koPNkF=q66f1+HV z|BLGY`cbXYzX5r_1~8b>=gGfvf%T^^?F_&w{Tq?jI{lV%% zA^355&dIL&jVT{i!^xn3Dl*f0v|9iC{l8D*ciRD`aZlvW^yixq@6?}nA^r>C7T{Lk zHsDhLfAeX?yMa4^J$l+*h!1pXFy9$@;* zi1z~D2mT&-31B+$ivIjv#NW$H|3^IU1AYL!3cLX@|34xAXW-v~AM0uR_4r>9bI;}9 zfS&;W3A_os1@O0T>+w5!d_a$XrpNz<_-}qs6_#m6TRBdQ$u(w(R zi^4(OJ*ZuRYS3;$Y3{)e;T|*`D-7#ruhKmmNM-tksi9r3$G1?qnT`2$wb46R8~%+ z0W#5nL3>0Qs2aP%qgjky63Gu&pudyYfz)>4BUs_dn3JvEKH{D2DK!gG;0%B=l3#YI z=Re1bCnz`w0eBs?vp3qV8}}S}4mk}@coQ~v8d}S5{N(+M3y?SquuA{4$a^n`D8f3_ zwO8G@Mh4G4*uYaWJfZ>kk6P7O%RTlJ_up!cL9!ShV{?p6`7)CFb^7M^Pk9TB z_Q#nh&jwhn|KA}m=TwH$9^iaWw6)WHOHf{Q{j&KySoej_1Rt%?X*@a2-S_}{IF2-W zqbVmwFRNC&#pvtB=xgp6S@%lvB*|pD5QJB94(he6s87n;4x#4R;wYZ1oj|RBdH;&1 z0X0peU``VIu)MXjM{n!u&6etc77iR;A8Gf8H;wA>!W+FIsO-#OCZWi@%B$D|$%ulR z#!4cdk~7t~SvXqvSB4OnK zZeA}>X9gl!=3JSI$(!b;hviHr5tBokaJ3mFbM~AHhA+^nZx5uCNo*JHaNJ)~%opb={~s@1TR#y1IIfIuYiGFSD%m-x&F23rZi>6k+{h8A6(f z+JgzTQ6rg=Yh71erDxO{wXtD9iKa8jL{Alj@9IWTc&@J$`-+Itm*su;>e9NJ{V_wo z+Fut)4-7^!a;A>dI?>`de_yw|T%+iX6S@x9_i^=J6mYHcsJ776bq$zp%HK~mv(~l$ z!&6-M7p}I1m(%D~*L43$XuxYM&miLb*x0?THL3;2d#pTJN_$eQ^0ZrWw^Ut+o3|nV zqksYo;ieE4G&b8P4jMm?6RqoN!Hq@>f&HAgJMN+vmzf}9^!*AE#TDxu88Sh@} zyYneZgIJe{*k~nQXnyoQr#6ag`s~!}KR&6gwAXX22cf7^4;CP z+;vZQ{!`xPRl7j6xQICh#s>3EGfIBx|9Igx??2)MX{!27(}`je-W z%Y{n(-`_%k^xZO;(|2kaOMH@kBi?-+U`vZpFCcFOVEEGS9=mfhEm$F@A}*;v)Sr!hOxFHw`PJg} z^J;(L+;X6`cky}qf122N3fUDE6R}nW?d&KmApigV`u%&Fe*4De?w#>hzdC$!eUaaY z|3{HKyI<=6GF1K2sm5;ZQ#*4=*P93&2HY$Sj_3Zhx%^SON(agxcPKeZ*|Mc`=H7f8 zk5}qn&FP!&e-`v?j!NmLAK_KEW%}m+H)@Du0ju?Y9eIZ=)8`4c(xDRl^B*Wq)Ia}! ziI~dlk>0;IRs%9T_I?^OrO`gzm5`<4?{R8)xx>}$YWDW1I~g=ga%bGRx51R$x`T_u ziL(id-`mMw57Fl5I(?b6$jba(+|*rv$tRC({M8p{-#_JpE8c$Q6FZ8Vd-%^N1FB<$ zueEz8A?Y%Byy1fm$C4dZ=$BsX2{SCGMrR&+X)yZ0)hpUIzJ6unkGEV_Y;I9G(LTTx z-RC0EcSA;lf6V`gKrky}O%;o8jOoPTeVO1<|1S^4x=*ZD#5gE7GU~wP(xR*W!miC( z-o{0M_P;$*Ohv(x{1>t!hV_S!-g02ajla3*r0)GQT<)8XEjD4B^3+wV0SoDk=OC}< zj(_2tga6m+pWav>*?iyY^$(pvH>5B-M67eR)SP~<=?nRy(c=95@$EY!r#!ar%=zJE z8`^8f-3I3KueWR)RxHNmDw|{$LKSQmoFu?;>whFVdWT_3i)nKs&9| zuSO(9%4+@dXu)$sihIBHlc!HUZQU#3d7zWeT2c1${-2HYf54Jo i0X~maz#_-dyEat8^(?`Zh&8t7im!;z1h|Vjap4bE+BTN} diff --git a/native/MsgHook/MsgHook.cpp b/native/MsgHook/MsgHook.cpp index 5677596..2999281 100644 --- a/native/MsgHook/MsgHook.cpp +++ b/native/MsgHook/MsgHook.cpp @@ -78,11 +78,19 @@ extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId pData->g_hWnd = callerHWnd; // remember the windows and hook handle for further instances pData->g_CwpHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CwpHookProc, (HINSTANCE)pData->g_hInstance, threadId); //pData->g_MsgHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MsgHookProc, (HINSTANCE)pData->g_hInstance, threadId); + if (pData->g_CwpHook == NULL) { + TCHAR tmp[100]; + _stprintf_s(tmp, _T("Last Error # %ld on threadId %ld"), GetLastError(), threadId); + MessageBox(0, tmp, _T("Set Hook Error"), 0); + } return (pData->g_CwpHook != NULL); //pData->g_CwpHook != NULL && } else + { + //MessageBox(0, _T("Error: Not starting process"), _T("Set Hook Error"), 0); return false; + } } extern "C" __declspec(dllexport) BOOL RemoveHook() diff --git a/native/MsgHook/MsgHook.vcxproj b/native/MsgHook/MsgHook.vcxproj index 33a1f06..108ce52 100644 --- a/native/MsgHook/MsgHook.vcxproj +++ b/native/MsgHook/MsgHook.vcxproj @@ -64,6 +64,7 @@ true + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) true @@ -141,10 +142,14 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target + + + + @@ -164,6 +169,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target + Create @@ -172,6 +178,9 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target Create + + + diff --git a/native/MsgHook/MsgHook.vcxproj.filters b/native/MsgHook/MsgHook.vcxproj.filters index 61ce41a..6e37813 100644 --- a/native/MsgHook/MsgHook.vcxproj.filters +++ b/native/MsgHook/MsgHook.vcxproj.filters @@ -16,6 +16,12 @@ + + Resource Files + + + Resource Files + @@ -27,6 +33,12 @@ Header Files + + Header Files + + + Header Files + @@ -41,5 +53,13 @@ Source Files + + Source Files + + + + + Resource Files + \ No newline at end of file diff --git a/native/MsgHookTest/MsgHookTest.aps b/native/MsgHook/MsgHookTest.aps similarity index 86% rename from native/MsgHookTest/MsgHookTest.aps rename to native/MsgHook/MsgHookTest.aps index b48c55daae795bc73061088f936c009649d2b76b..1bcb0dbca1cac1c4e2f43e18b02fd8bdc97adf1d 100644 GIT binary patch delta 1911 zcmZ`)Z%kWN6hH61_O+#@{BbfUrBE1zPGJQ$ij&RNQfQ^64Sl1TA`KA)gn`1)XyyjS z_+evY?)brM@rz$%aoKd3IQ`~a#@|^8X7SUQ*-VUae=urBGE>ie?Ss0ydvkB^`<>tU zch7mR6K92+=Y*3*TTwlo4ef~YVrgE&F%h?9?#HFztlZ)sB-uf zpy3t(w&8lT@XL=nxTCH}*dKCBVW_g(cfpeY-i8F^V^A&RD3B}Qmst+jngq$LI>=3e z!qrUk8OV!co^VS;9568;(&+WMBO%GzDp7!^c&#}<84d(l*icjLa8!dC@C|(qUjTSQ zpUYbSKiB8;g@B9tJYUhKmdodMw#q6Fu*$H%dvH_+>Y$hbF6L13x}c&8N&q6xU?|cO zi1-^_Pz5$XYnp}M4w!E!<{I)d(R!?oNZfIIXbbF82*(4KE_ z2pSNl+YG0_<#=4Xy2{ycc_xhZ+2VjNz{5G!M%Y3#Mm34W-lH`}5~q*J*%$*p zxScq|pxxm3VFY@>14A_X@$Bp_p2~T1Hkh%6k}e{pSWHc899L(ox@=|z{(-NtZ_dqq ziWlZeXkVEtrNGwbMmZY}%|FN0;)VGd?s>dLdo6BVcvjs8tFRBl3wty?g^&${cxJ)D zb>hmxcmjDBUs`k=JqYC#-W|$?Jj%Y5Z4AbP$007i`xyCtI4tYmdyM>eLVo{$TEj{H^rR7jCgKHX zHWSMWZV2ONQ5#o^%h3`w`<$Jm&shooP(Y(#5w8=_tHO8aSWlL^wD_B75iis6iWZM8 zS>zr+r=uP(=6_Ge4nuw^2k>VmtAs#{x`IY#rj8Pbk0~QSeKwxYG?h(h0aR9n8fPR^ zd({AoHr!iI)KUOxhe8!)Q_0jR@@U?VlOa=MFB!Vstx(AYjb!St6qBl7k?T_A<&=P7 z5RVLySBg~{QmFbADoen81Sb!h%2=$oKTxRYsZ>f}U;=L(BdZka&Wj2)BZbNmcz78H zzcYz%l5pTPywPhaW5@Srn3j>&fUIRty4MGUm}hbFs_9j-4?E`=RY&V!oC=#Iuv3Oz zvYfr5Jt?NxEBw_w)0bc26!|4W3{gzGwilOHRQ!V|8lz_XV6zlj_3;PfGwlZfC9o8>#R;eIHR!sko9bUVJl|h+@?~YCMGjl zO*YM9T(`%WWqPq2mn~t53RfEAG=`r-+qE4Rdf`Y+cCiaLubdYS-@?$u@SU9ZJm-0y zeBblF=PXZ}KDuH`){2HRTRqK_S)vzw!=X;2cfURyjP&@!;XQ^PF@}Q^hy7z?$Bfa5 zc=Pxn;uV))y`B)5wpB4&jiw1~9ifiJhwS`B8ME)2dqx8l?$}Po1!uguHLUsggR;ICZroCWVB{ zR>8I1wxdc45~QvUW+2!V4hE>TrDZ2cOxn)FW8aKBvJ?mHt>&W7grwc8sO+Cg*)Mz} z2%~d1MF;fxf%Wt7*}P|9br!3|MAYvf2RUgot*oy1`I-37z$iho|8e$=ll5Oukh32q zKaKHqj2`p?d#YWote`v9FQ-lTG}T;EzP6M29O;xUKES&vC+Zg*jJykva=rr#Z;Bce z7M>FgczCf*w4;Y>1CB2~ZSJL;^c22b+=Z63^=x{FFyKwU$1kdg;rp~#jNs3-n`>pp zZ5g9_j(7)ur?))7ckx{&C;r0eY^6Ad7qgE{{gmwxA^>x)sj`eV?qDca&6Cn8LI#fK z8aT-pIgdFmi9R{=hTH7tb{g?V&aL+GI|L2Dg~GHVbWDQ#<(RyR+zH zI9>d6=5Zm#VV4x?Pa~6gRxRUEY|r4=r5emERmgY|Zj;YsSDD|hKcoiOFp@=SPWuPc Ccxn;= diff --git a/native/MsgHookTest/MsgHookTest.ico b/native/MsgHook/MsgHookTest.ico similarity index 100% rename from native/MsgHookTest/MsgHookTest.ico rename to native/MsgHook/MsgHookTest.ico diff --git a/native/MsgHookTest/MsgHookTest.rc b/native/MsgHook/MsgHookTest.rc similarity index 84% rename from native/MsgHookTest/MsgHookTest.rc rename to native/MsgHook/MsgHookTest.rc index 9c8e9a571406865f44944618d0cb5d15a12b33d4..45f391262a137414781b584cf4336c72f4607aab 100644 GIT binary patch delta 490 zcmZuuze~eV5WWy<#n?e(f5e!!R?!N@CTWtkDpIKxbucKkl}>gjA}T_wIEfAp;$*o+ z9GzSgA%B946)d`o;(y^JUQ#L|avbmO-gozX_uj?YRq3w8@i7R)0xZD{WFb#c0diR9 zMy+FR&W+99TSmr1K5ISjmkgHx8?8VJ64s7)pJ5G9(ew-W#v#jqME z*a+OSI%v4uKZ%dR3Be4C8%|9Uk3uOhXsSwPPd7jV4|EYr%ba2ODjF_@cx5yt0mlcf zr8Fc7tw7r8PW{u`>?meFSwOgg(QtC7uro|_^J(GP zjNE1nIt&U7h76_*W}6E|OBtDs8B8a?6iep^(m*Lw1_K~z$Y3(LUs!*0pSTSpvk`;E z8+`EsBh5Us!2N 25000) {//need to truncate the beginning so the text doesn't go past it's limit @@ -125,13 +103,20 @@ void StartMessageHook() { AppendText(txtbox, _T("Starting Message Hook\r\n")); targetHwnd = FindWindow(targetClassname, NULL); + + if (_tcscmp(targetHwndStr, _T("")) != 0) //if target HWND was used then override classname hwnd + { + TCHAR *stopStr; + targetHwnd = (HWND)_tcstol(targetHwndStr, &stopStr, 10); + } + DWORD tid = GetWindowThreadProcessId(targetHwnd, NULL); InitMsgFiltersAndLookup(); //InitializeMsgLookup(); TCHAR tmp[50]; - _stprintf_s(tmp, _T("Targetting %ld, %ld\r\n"), targetHwnd, tid); + _stprintf_s(tmp, _T("Target Handle: %ld, and Thread Id: %ld\r\n"), targetHwnd, tid); AppendText(txtbox, tmp); //block self/global msg hook @@ -140,8 +125,11 @@ void StartMessageHook() return; } - if (InitMsgHook(mainHwnd, tid)) + //if (InitMsgHook(mainHwnd, tid)) + if (SetMsgHook(mainHwnd, tid)) { + EnableMenuItem(mainMenu, ID_FILE_STOPHOOK, MF_ENABLED); + EnableMenuItem(mainMenu, ID_FILE_STARTHOOK, MF_DISABLED | MF_GRAYED); AppendText(txtbox, _T("Hook successfully initialized\r\n")); } else @@ -150,8 +138,11 @@ void StartMessageHook() void StopMessageHook() { + EnableMenuItem(mainMenu, ID_FILE_STOPHOOK, MF_DISABLED | MF_GRAYED); + EnableMenuItem(mainMenu, ID_FILE_STARTHOOK, MF_ENABLED); AppendText(txtbox, TEXT("Stopping Message Hook\r\n")); - KillHook(); + //KillHook(); + RemoveHook(); } bool OnCopyData(COPYDATASTRUCT* pCopyDataStruct) // WM_COPYDATA lParam will have this struct @@ -188,7 +179,7 @@ bool OnCopyData(COPYDATASTRUCT* pCopyDataStruct) // WM_COPYDATA lParam will have if (_tcscmp(msgName, _T("")) != 0) { TCHAR tmp[200]; - _stprintf_s(tmp, _T("%d hwnd: %ld, msg: %s (%ld), wparam: '%s'[%ld], lparam: '%s'{%ld}\r\n"),Event.dwHookType, Event.hWnd, msgName, Event.nCode, Event.wParamStr, Event.wParam, Event.lParamStr,Event.lParam); + _stprintf_s(tmp, _T("hwnd: %ld, msg: %s (%ld), wparam: '%s'[%ld], lparam: '%s'{%ld}\r\n"), Event.hWnd, msgName, Event.nCode, Event.wParamStr, Event.wParam, Event.lParamStr,Event.lParam); AppendText(txtbox, tmp); } } @@ -209,9 +200,78 @@ void SendWmSettext() //ID_TESTMSGS_WM void SendWmCommand() //ID_TESTMSGS_WM { TCHAR *stopStr; + HWND sendHwnd = targetHwnd; + if (_tcscmp(targetHwndStr, _T("")) != 0) + { + sendHwnd = (HWND)_tcstol(targetHwndStr, &stopStr, 10); + } long wparam = _tcstol(testWmCommandW, &stopStr, 10); long lparam = _tcstol(testWmCommandL, &stopStr, 10); - SendMessage(targetHwnd, WM_COMMAND, wparam, lparam); + SendMessage(sendHwnd, WM_COMMAND, wparam, lparam); +} + +void HotKeyPressed(WPARAM wParam) +{ + //AppendText(txtbox, _T("hotkey test")); + if (wParam == (pauseHotKey + hotkeyIdOffset)) + { + if (!isPaused) + { + AppendText(txtbox, _T("Paused\r\n")); + isPaused = true; + } + else + { + isPaused = false; + AppendText(txtbox, _T("Unpaused\r\n")); + } + } +} + +extern "C" __declspec(dllexport) void CreateMsgHookWindow(LPTSTR lpCmdLine) +{ + //StartWinMain(GetModuleHandle(NULL), NULL, lpCmdLine, SW_SHOW); + StartWinMain((HINSTANCE)pData->g_hInstance, NULL, lpCmdLine, SW_SHOW); + +} + +int APIENTRY StartWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) +{ + + UNREFERENCED_PARAMETER(hPrevInstance); + UNREFERENCED_PARAMETER(lpCmdLine); + + // TODO: Place code here. + MSG msg; + HACCEL hAccelTable; + + // Initialize global strings + LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + LoadString(hInstance, IDC_MSGHOOKTEST, szWindowClass, MAX_LOADSTRING); + MyRegisterClass(hInstance); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MSGHOOKTEST)); + + // Main message loop: + while (GetMessage(&msg, NULL, 0, 0)) + { + //if (msg.message == WM_HOTKEY) + // HotKeyPressed(msg.wParam); + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + UnregisterHotKey(mainHwnd, pauseHotKey + hotkeyIdOffset); + + return (int) msg.wParam; } // @@ -265,10 +325,13 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); + CW_USEDEFAULT, 0, 700, 300, NULL, NULL, hInstance, NULL); - if (!hWnd) - return FALSE; + if (!hWnd) { + DWORD lastErr = GetLastError(); + printf("Error Creating Window %d\n", lastErr); + return FALSE; + } mainHwnd = hWnd; RECT rect; @@ -276,11 +339,24 @@ BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) // make the txtbox edit control almost the same size as the parent window //WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL txtbox = CreateWindow(TEXT("Edit"),TEXT(""), WS_CHILD | WS_VISIBLE | ES_MULTILINE | WS_VSCROLL | ES_AUTOVSCROLL | ES_READONLY, - 10, 10,rect.right - 20, rect.bottom - 20, hWnd, NULL, NULL, NULL); + txtboxSpacing, txtboxSpacing,rect.right-(txtboxSpacing*2), rect.bottom-(txtboxSpacing*2), hWnd, NULL, NULL, NULL); + + HFONT hFont = CreateFont(14, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, ANSI_CHARSET, + OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial")); + SendMessage(txtbox, WM_SETFONT, (WPARAM)hFont, TRUE); + + mainMenu = GetMenu(mainHwnd); + EnableMenuItem(mainMenu, ID_FILE_STOPHOOK, MF_DISABLED | MF_GRAYED); + + RegisterHotKey(mainHwnd, pauseHotKey + hotkeyIdOffset, MOD_NOREPEAT | MOD_SHIFT | MOD_CONTROL, pauseHotKey); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); + //set always on top + SetWindowPos(mainHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE| SWP_NOMOVE); + return TRUE; } @@ -342,6 +418,9 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, message, wParam, lParam); } break; + case WM_HOTKEY: + HotKeyPressed(wParam); + break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... @@ -351,7 +430,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { //resize the txtbox when the parent window size changes int nWidth = LOWORD(lParam); int nHeight = HIWORD(lParam); - SetWindowPos(txtbox, HWND_NOTOPMOST, 10, 10, nWidth-20, nHeight-20, SWP_NOZORDER|SWP_NOMOVE); + SetWindowPos(txtbox, HWND_NOTOPMOST, txtboxSpacing, txtboxSpacing, nWidth-(txtboxSpacing*2), nHeight-(txtboxSpacing*2), SWP_NOZORDER|SWP_NOMOVE); } break; case WM_DESTROY: @@ -383,6 +462,8 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) SendDlgItemMessage(hDlg, IDC_WMCOML, WM_SETTEXT, 0 , (LPARAM)testWmCommandL); SendDlgItemMessage(hDlg, IDC_WMSETW, WM_SETTEXT, 0 , (LPARAM)testWmSettextW); SendDlgItemMessage(hDlg, IDC_WMSETL, WM_SETTEXT, 0 , (LPARAM)testWmSettextL); + SendDlgItemMessage(hDlg, IDC_HWND, WM_SETTEXT, 0 , (LPARAM)targetHwndStr); + } return (INT_PTR)TRUE; @@ -394,6 +475,7 @@ INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) GetDlgItemText(hDlg, IDC_WMCOML, testWmCommandL, MAX_TEST_SIZE); GetDlgItemText(hDlg, IDC_WMSETW, testWmSettextW, MAX_TEST_SIZE); GetDlgItemText(hDlg, IDC_WMSETL, testWmSettextL, MAX_TEST_SIZE); + GetDlgItemText(hDlg, IDC_HWND, targetHwndStr, MAX_TEST_SIZE); // check filter options if (SendDlgItemMessage(hDlg, IDC_CHECK_CMD, BM_GETCHECK, 0, 0) == BST_CHECKED) // the hard way filterWmCommand = true; diff --git a/native/MsgHookTest/MsgHook.h b/native/MsgHook/MsgLookup.h similarity index 93% rename from native/MsgHookTest/MsgHook.h rename to native/MsgHook/MsgLookup.h index 792d5e6..f8413b3 100644 --- a/native/MsgHookTest/MsgHook.h +++ b/native/MsgHook/MsgLookup.h @@ -1,68 +1,5 @@ -/* - * Copyright 2014, Synthuse.org - * Released under the Apache Version 2.0 License. - * - * last modified by ejakubowski7@gmail.com -*/ -#include - -#define MSGHOOKER_FILE TEXT("MsgHook.dll") - -HINSTANCE msgHookDll; - -//BOOL SetMsgHook(HWND callerHWnd, DWORD threadId) -typedef BOOL (* SETMSGHOOK)(HWND, DWORD); -SETMSGHOOK SetMsgHook; - -//BOOL RemoveHook() -typedef BOOL (* REMOVEHOOK)(VOID); -REMOVEHOOK RemoveHook; - -typedef struct -{ - HWND hWnd; - int nCode; - DWORD dwHookType; - WPARAM wParam; - LPARAM lParam; - TCHAR wParamStr[25]; - TCHAR lParamStr[25]; -}HEVENT; - -/* -typedef struct { - DWORD vkCode; - DWORD scanCode; - DWORD flags; - DWORD time; - ULONG_PTR dwExtraInfo; -} KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; -*/ - -BOOL InitMsgHook(HWND hw, int threadId) -{ - msgHookDll = LoadLibrary(MSGHOOKER_FILE); - if (msgHookDll != NULL) - { - SetMsgHook = (SETMSGHOOK)GetProcAddress(msgHookDll, "SetMsgHook"); - RemoveHook = (REMOVEHOOK)GetProcAddress(msgHookDll, "RemoveHook"); - if (SetMsgHook) - { - return SetMsgHook(hw, threadId); - } - } - return false; -} - -void KillHook() -{ - if (RemoveHook) - RemoveHook(); - - if (msgHookDll != NULL) - FreeLibrary(msgHookDll); -} +#include "stdafx.h" // MSG Array LOOKUP const int MAX_MSG_LOOKUP = 1024; diff --git a/native/MsgHook/bin/MsgHook32.dll b/native/MsgHook/bin/MsgHook32.dll index fc01f289c8ff928e4c82eaa6e8a0e570748bc986..e08c44d255c45e91ab25acf685cc234066437892 100644 GIT binary patch literal 78336 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 La9iL{v%voYNl<{y delta 3438 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 WXyKY+?8y4y#|)2w@f`nC7Wh9Ticd@c delta 3870 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 LJoWUh+lK!F>)vN) diff --git a/native/MsgHook/org_synthuse_MsgHook.cpp b/native/MsgHook/org_synthuse_MsgHook.cpp index a5665c1..3dc824b 100644 --- a/native/MsgHook/org_synthuse_MsgHook.cpp +++ b/native/MsgHook/org_synthuse_MsgHook.cpp @@ -8,12 +8,53 @@ #include "stdafx.h" #include "org_synthuse_MsgHook.h" + +/* + * Class: org_synthuse_MsgHook + * Method: createMsgHookWindow + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_createMsgHookWindow(JNIEnv *env, jobject obj) +{ + CreateMsgHookWindow(NULL); + return true; +} + +/* + * Class: org_synthuse_MsgHook + * Method: setMsgHookWindowTargetHwnd + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMsgHookWindowTargetHwnd(JNIEnv *env, jobject obj, jint jhwnd) +{ + _stprintf_s(targetHwndStr, _T("%ld"), (long)jhwnd); + return true; +} + +/* + * Class: org_synthuse_MsgHook + * Method: setMsgHookWindowTargetClass + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMsgHookWindowTargetClass(JNIEnv *env, jobject obj, jstring jclassname) +{ + const char *classname = env->GetStringUTFChars(jclassname, 0);//convert string + + memset((void *)&targetClassname, '\0', sizeof(TCHAR) * MAX_TEST_SIZE); // set TCHAR array to all 0 + int tstrLen = MultiByteToWideChar(CP_UTF8, 0, classname, (int)strlen(classname), NULL, 0); //get t len + MultiByteToWideChar(CP_UTF8, 0, classname, (int)strlen(classname), targetClassname, tstrLen); // convert char to tchar + + env->ReleaseStringUTFChars(jclassname, classname); //release string + return true; +} + /* * Class: org_synthuse_MsgHook * Method: setMessageHook * Signature: (JJ)Z */ -JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook(JNIEnv *env, jobject obj, jlong jhWnd, jlong jthreadId) +//JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook(JNIEnv *env, jobject obj, jlong jhWnd, jlong jthreadId) +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook(JNIEnv *env, jobject obj, jint jhWnd, jint jthreadId) { return SetMsgHook((HWND)jhWnd, (DWORD)jthreadId); } diff --git a/native/MsgHook/org_synthuse_MsgHook.h b/native/MsgHook/org_synthuse_MsgHook.h index 93144b7..6e1e704 100644 --- a/native/MsgHook/org_synthuse_MsgHook.h +++ b/native/MsgHook/org_synthuse_MsgHook.h @@ -7,13 +7,37 @@ #ifdef __cplusplus extern "C" { #endif +/* + * Class: org_synthuse_MsgHook + * Method: createMsgHookWindow + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_createMsgHookWindow + (JNIEnv *, jobject); + +/* + * Class: org_synthuse_MsgHook + * Method: setMsgHookWindowTargetHwnd + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMsgHookWindowTargetHwnd + (JNIEnv *, jobject, jint); + +/* + * Class: org_synthuse_MsgHook + * Method: setMsgHookWindowTargetClass + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMsgHookWindowTargetClass + (JNIEnv *, jobject, jstring); + /* * Class: org_synthuse_MsgHook * Method: setMessageHook - * Signature: (JJ)Z + * Signature: (II)Z */ JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook - (JNIEnv *, jobject, jlong, jlong); + (JNIEnv *, jobject, jint, jint); /* * Class: org_synthuse_MsgHook diff --git a/native/MsgHookTest/resource.h b/native/MsgHook/resource.h similarity index 95% rename from native/MsgHookTest/resource.h rename to native/MsgHook/resource.h index 596d9a1db605785d008d07b01e67f14dd6a05a5f..8f5c0a298fbc95ab63d6316f99cbe8d5ecf7d921 100644 GIT binary patch delta 70 zcmaDMy+C%uFZRhBm|1wk8GIR>8T^4{ID^sTjZE5;FEFw&8!%W-W@MFR_W+9eF}MK5 RbteljvcTjvKV)ZT0|2K45uX46 delta 16 YcmZ1=`$BrdFZRg-oC2E #include #include #include @@ -41,6 +42,7 @@ typedef struct #ifndef GLOBAL_VARS_H // header guards #define GLOBAL_VARS_H +extern "C" __declspec(dllexport) void CreateMsgHookWindow(LPTSTR lpCmdLine); extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId); extern "C" __declspec(dllexport) BOOL RemoveHook(); @@ -49,4 +51,8 @@ extern HANDLE hMappedFile; extern GLOBALDATA* pData; extern bool bStartingProcess; +#define MAX_TEST_SIZE 100 +extern TCHAR targetHwndStr[MAX_TEST_SIZE]; +extern TCHAR targetClassname[MAX_TEST_SIZE]; + #endif \ No newline at end of file diff --git a/native/MsgHookTest/MsgHookTest.h b/native/MsgHookTest/MsgHookTest.h deleted file mode 100644 index d00d47e..0000000 --- a/native/MsgHookTest/MsgHookTest.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -#include "resource.h" diff --git a/native/MsgHookTest/MsgHookTest.vcxproj b/native/MsgHookTest/MsgHookTest.vcxproj deleted file mode 100644 index 677680c..0000000 --- a/native/MsgHookTest/MsgHookTest.vcxproj +++ /dev/null @@ -1,166 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - {E8016236-E771-4BEC-8407-6BF37C68D174} - Win32Proj - MsgHookTest - - - - Application - true - Unicode - - - Application - true - Unicode - - - Application - false - true - Unicode - - - Application - false - true - Unicode - - - - - - - - - - - - - - - - - - - true - - - true - - - false - - - false - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Windows - true - - - - - Use - Level3 - Disabled - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Windows - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - Level3 - Use - MaxSpeed - true - true - WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) - - - Windows - true - true - true - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - - - - - - - - {8e038a94-7d02-49e9-b9f6-5224d9d11225} - - - - - - \ No newline at end of file diff --git a/native/MsgHookTest/MsgHookTest.vcxproj.filters b/native/MsgHookTest/MsgHookTest.vcxproj.filters deleted file mode 100644 index 7343c35..0000000 --- a/native/MsgHookTest/MsgHookTest.vcxproj.filters +++ /dev/null @@ -1,57 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hpp;hxx;hm;inl;inc;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - - Resource Files - - - Resource Files - - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - - - Source Files - - - Source Files - - - - - Resource Files - - - \ No newline at end of file diff --git a/native/MsgHookTest/MsgHookTest.vcxproj.user b/native/MsgHookTest/MsgHookTest.vcxproj.user deleted file mode 100644 index ace9a86..0000000 --- a/native/MsgHookTest/MsgHookTest.vcxproj.user +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/native/MsgHookTest/ReadMe.txt b/native/MsgHookTest/ReadMe.txt deleted file mode 100644 index 6d81f3a..0000000 --- a/native/MsgHookTest/ReadMe.txt +++ /dev/null @@ -1,62 +0,0 @@ -======================================================================== - WIN32 APPLICATION : MsgHookTest Project Overview -======================================================================== - -AppWizard has created this MsgHookTest application for you. - -This file contains a summary of what you will find in each of the files that -make up your MsgHookTest application. - - -MsgHookTest.vcxproj - This is the main project file for VC++ projects generated using an Application Wizard. - It contains information about the version of Visual C++ that generated the file, and - information about the platforms, configurations, and project features selected with the - Application Wizard. - -MsgHookTest.vcxproj.filters - This is the filters file for VC++ projects generated using an Application Wizard. - It contains information about the association between the files in your project - and the filters. This association is used in the IDE to show grouping of files with - similar extensions under a specific node (for e.g. ".cpp" files are associated with the - "Source Files" filter). - -MsgHookTest.cpp - This is the main application source file. - -///////////////////////////////////////////////////////////////////////////// -AppWizard has created the following resources: - -MsgHookTest.rc - This is a listing of all of the Microsoft Windows resources that the - program uses. It includes the icons, bitmaps, and cursors that are stored - in the RES subdirectory. This file can be directly edited in Microsoft - Visual C++. - -Resource.h - This is the standard header file, which defines new resource IDs. - Microsoft Visual C++ reads and updates this file. - -MsgHookTest.ico - This is an icon file, which is used as the application's icon (32x32). - This icon is included by the main resource file MsgHookTest.rc. - -small.ico - This is an icon file, which contains a smaller version (16x16) - of the application's icon. This icon is included by the main resource - file MsgHookTest.rc. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named MsgHookTest.pch and a precompiled types file named StdAfx.obj. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" comments to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// diff --git a/native/MsgHookTest/WinMessages.txt b/native/MsgHookTest/WinMessages.txt deleted file mode 100644 index e27e2f4..0000000 --- a/native/MsgHookTest/WinMessages.txt +++ /dev/null @@ -1,416 +0,0 @@ - -WM_NULL = 0x00 -WM_CREATE = 0x01 -WM_DESTROY = 0x02 -WM_MOVE = 0x03 -WM_SIZE = 0x05 -WM_ACTIVATE = 0x06 -WM_SETFOCUS = 0x07 -WM_KILLFOCUS = 0x08 -WM_ENABLE = 0x0A -WM_SETREDRAW = 0x0B -WM_SETTEXT = 0x0C -WM_GETTEXT = 0x0D -WM_GETTEXTLENGTH = 0x0E -WM_PAINT = 0x0F -WM_CLOSE = 0x10 -WM_QUERYENDSESSION = 0x11 -WM_QUIT = 0x12 -WM_QUERYOPEN = 0x13 -WM_ERASEBKGND = 0x14 -WM_SYSCOLORCHANGE = 0x15 -WM_ENDSESSION = 0x16 -WM_SYSTEMERROR = 0x17 -WM_SHOWWINDOW = 0x18 -WM_CTLCOLOR = 0x19 -WM_WININICHANGE = 0x1A -WM_SETTINGCHANGE = 0x1A -WM_DEVMODECHANGE = 0x1B -WM_ACTIVATEAPP = 0x1C -WM_FONTCHANGE = 0x1D -WM_TIMECHANGE = 0x1E -WM_CANCELMODE = 0x1F -WM_SETCURSOR = 0x20 -WM_MOUSEACTIVATE = 0x21 -WM_CHILDACTIVATE = 0x22 -WM_QUEUESYNC = 0x23 -WM_GETMINMAXINFO = 0x24 -WM_PAINTICON = 0x26 -WM_ICONERASEBKGND = 0x27 -WM_NEXTDLGCTL = 0x28 -WM_SPOOLERSTATUS = 0x2A -WM_DRAWITEM = 0x2B -WM_MEASUREITEM = 0x2C -WM_DELETEITEM = 0x2D -WM_VKEYTOITEM = 0x2E -WM_CHARTOITEM = 0x2F -WM_SETFONT = 0x30 -WM_GETFONT = 0x31 -WM_SETHOTKEY = 0x32 -WM_GETHOTKEY = 0x33 -WM_QUERYDRAGICON = 0x37 -WM_COMPAREITEM = 0x39 -WM_COMPACTING = 0x41 -WM_WINDOWPOSCHANGING = 0x46 -WM_WINDOWPOSCHANGED = 0x47 -WM_POWER = 0x48 -WM_COPYDATA = 0x4A -WM_CANCELJOURNAL = 0x4B -WM_NOTIFY = 0x4E -WM_INPUTLANGCHANGEREQUEST = 0x50 -WM_INPUTLANGCHANGE = 0x51 -WM_TCARD = 0x52 -WM_HELP = 0x53 -WM_USERCHANGED = 0x54 -WM_NOTIFYFORMAT = 0x55 -WM_CONTEXTMENU = 0x7B -WM_STYLECHANGING = 0x7C -WM_STYLECHANGED = 0x7D -WM_DISPLAYCHANGE = 0x7E -WM_GETICON = 0x7F -WM_SETICON = 0x80 -WM_NCCREATE = 0x81 -WM_NCDESTROY = 0x82 -WM_NCCALCSIZE = 0x83 -WM_NCHITTEST = 0x84 -WM_NCPAINT = 0x85 -WM_NCACTIVATE = 0x86 -WM_GETDLGCODE = 0x87 -WM_NCMOUSEMOVE = 0xA0 -WM_NCLBUTTONDOWN = 0xA1 -WM_NCLBUTTONUP = 0xA2 -WM_NCLBUTTONDBLCLK = 0xA3 -WM_NCRBUTTONDOWN = 0xA4 -WM_NCRBUTTONUP = 0xA5 -WM_NCRBUTTONDBLCLK = 0xA6 -WM_NCMBUTTONDOWN = 0xA7 -WM_NCMBUTTONUP = 0xA8 -WM_NCMBUTTONDBLCLK = 0xA9 -WM_KEYFIRST = 0x100 -WM_KEYDOWN = 0x100 -WM_KEYUP = 0x101 -WM_CHAR = 0x102 -WM_DEADCHAR = 0x103 -WM_SYSKEYDOWN = 0x104 -WM_SYSKEYUP = 0x105 -WM_SYSCHAR = 0x106 -WM_SYSDEADCHAR = 0x107 -WM_KEYLAST = 0x108 -WM_IME_STARTCOMPOSITION = 0x10D -WM_IME_ENDCOMPOSITION = 0x10E -WM_IME_COMPOSITION = 0x10F -WM_IME_KEYLAST = 0x10F -WM_INITDIALOG = 0x110 -WM_COMMAND = 0x111 -WM_SYSCOMMAND = 0x112 -WM_TIMER = 0x113 -WM_HSCROLL = 0x114 -WM_VSCROLL = 0x115 -WM_INITMENU = 0x116 -WM_INITMENUPOPUP = 0x117 -WM_MENUSELECT = 0x11F -WM_MENUCHAR = 0x120 -WM_ENTERIDLE = 0x121 -WM_CTLCOLORMSGBOX = 0x132 -WM_CTLCOLOREDIT = 0x133 -WM_CTLCOLORLISTBOX = 0x134 -WM_CTLCOLORBTN = 0x135 -WM_CTLCOLORDLG = 0x136 -WM_CTLCOLORSCROLLBAR = 0x137 -WM_CTLCOLORSTATIC = 0x138 -WM_MOUSEFIRST = 0x200 -WM_MOUSEMOVE = 0x200 -WM_LBUTTONDOWN = 0x201 -WM_LBUTTONUP = 0x202 -WM_LBUTTONDBLCLK = 0x203 -WM_RBUTTONDOWN = 0x204 -WM_RBUTTONUP = 0x205 -WM_RBUTTONDBLCLK = 0x206 -WM_MBUTTONDOWN = 0x207 -WM_MBUTTONUP = 0x208 -WM_MBUTTONDBLCLK = 0x209 -WM_MOUSEWHEEL = 0x20A -WM_MOUSEHWHEEL = 0x20E -WM_PARENTNOTIFY = 0x210 -WM_ENTERMENULOOP = 0x211 -WM_EXITMENULOOP = 0x212 -WM_NEXTMENU = 0x213 -WM_SIZING = 0x214 -WM_CAPTURECHANGED = 0x215 -WM_MOVING = 0x216 -WM_POWERBROADCAST = 0x218 -WM_DEVICECHANGE = 0x219 -WM_MDICREATE = 0x220 -WM_MDIDESTROY = 0x221 -WM_MDIACTIVATE = 0x222 -WM_MDIRESTORE = 0x223 -WM_MDINEXT = 0x224 -WM_MDIMAXIMIZE = 0x225 -WM_MDITILE = 0x226 -WM_MDICASCADE = 0x227 -WM_MDIICONARRANGE = 0x228 -WM_MDIGETACTIVE = 0x229 -WM_MDISETMENU = 0x230 -WM_ENTERSIZEMOVE = 0x231 -WM_EXITSIZEMOVE = 0x232 -WM_DROPFILES = 0x233 -WM_MDIREFRESHMENU = 0x234 -WM_IME_SETCONTEXT = 0x281 -WM_IME_NOTIFY = 0x282 -WM_IME_CONTROL = 0x283 -WM_IME_COMPOSITIONFULL = 0x284 -WM_IME_SELECT = 0x285 -WM_IME_CHAR = 0x286 -WM_IME_KEYDOWN = 0x290 -WM_IME_KEYUP = 0x291 -WM_MOUSEHOVER = 0x2A1 -WM_NCMOUSELEAVE = 0x2A2 -WM_MOUSELEAVE = 0x2A3 -WM_CUT = 0x300 -WM_COPY = 0x301 -WM_PASTE = 0x302 -WM_CLEAR = 0x303 -WM_UNDO = 0x304 -WM_RENDERFORMAT = 0x305 -WM_RENDERALLFORMATS = 0x306 -WM_DESTROYCLIPBOARD = 0x307 -WM_DRAWCLIPBOARD = 0x308 -WM_PAINTCLIPBOARD = 0x309 -WM_VSCROLLCLIPBOARD = 0x30A -WM_SIZECLIPBOARD = 0x30B -WM_ASKCBFORMATNAME = 0x30C -WM_CHANGECBCHAIN = 0x30D -WM_HSCROLLCLIPBOARD = 0x30E -WM_QUERYNEWPALETTE = 0x30F -WM_PALETTEISCHANGING = 0x310 -WM_PALETTECHANGED = 0x311 -WM_HOTKEY = 0x312 -WM_PRINT = 0x317 -WM_PRINTCLIENT = 0x318 -WM_HANDHELDFIRST = 0x358 -WM_HANDHELDLAST = 0x35F -WM_PENWINFIRST = 0x380 -WM_PENWINLAST = 0x38F -WM_COALESCE_FIRST = 0x390 -WM_COALESCE_LAST = 0x39F -WM_DDE_FIRST = 0x3E0 -WM_DDE_INITIATE = 0x3E0 -WM_DDE_TERMINATE = 0x3E1 -WM_DDE_ADVISE = 0x3E2 -WM_DDE_UNADVISE = 0x3E3 -WM_DDE_ACK = 0x3E4 -WM_DDE_DATA = 0x3E5 -WM_DDE_REQUEST = 0x3E6 -WM_DDE_POKE = 0x3E7 -WM_DDE_EXECUTE = 0x3E8 -WM_DDE_LAST = 0x3E8 - - - - - -WM_NULL -WM_CREATE -WM_DESTROY -WM_MOVE -WM_SIZE -WM_ACTIVATE -WM_SETFOCUS -WM_KILLFOCUS -WM_ENABLE -WM_SETREDRAW -WM_SETTEXT -WM_GETTEXT -WM_GETTEXTLENGTH -WM_PAINT -WM_CLOSE -WM_QUERYENDSESSION -WM_QUIT -WM_QUERYOPEN -WM_ERASEBKGND -WM_SYSCOLORCHANGE -WM_ENDSESSION -WM_SYSTEMERROR -WM_SHOWWINDOW -WM_CTLCOLOR -WM_WININICHANGE -WM_SETTINGCHANGE -WM_DEVMODECHANGE -WM_ACTIVATEAPP -WM_FONTCHANGE -WM_TIMECHANGE -WM_CANCELMODE -WM_SETCURSOR -WM_MOUSEACTIVATE -WM_CHILDACTIVATE -WM_QUEUESYNC -WM_GETMINMAXINFO -WM_PAINTICON -WM_ICONERASEBKGND -WM_NEXTDLGCTL -WM_SPOOLERSTATUS -WM_DRAWITEM -WM_MEASUREITEM -WM_DELETEITEM -WM_VKEYTOITEM -WM_CHARTOITEM -WM_SETFONT -WM_GETFONT -WM_SETHOTKEY -WM_GETHOTKEY -WM_QUERYDRAGICON -WM_COMPAREITEM -WM_COMPACTING -WM_WINDOWPOSCHANGING -WM_WINDOWPOSCHANGED -WM_POWER -WM_COPYDATA -WM_CANCELJOURNAL -WM_NOTIFY -WM_INPUTLANGCHANGEREQUEST -WM_INPUTLANGCHANGE -WM_TCARD -WM_HELP -WM_USERCHANGED -WM_NOTIFYFORMAT -WM_CONTEXTMENU -WM_STYLECHANGING -WM_STYLECHANGED -WM_DISPLAYCHANGE -WM_GETICON -WM_SETICON -WM_NCCREATE -WM_NCDESTROY -WM_NCCALCSIZE -WM_NCHITTEST -WM_NCPAINT -WM_NCACTIVATE -WM_GETDLGCODE -WM_NCMOUSEMOVE -WM_NCLBUTTONDOWN -WM_NCLBUTTONUP -WM_NCLBUTTONDBLCLK -WM_NCRBUTTONDOWN -WM_NCRBUTTONUP -WM_NCRBUTTONDBLCLK -WM_NCMBUTTONDOWN -WM_NCMBUTTONUP -WM_NCMBUTTONDBLCLK -WM_KEYFIRST -WM_KEYDOWN -WM_KEYUP -WM_CHAR -WM_DEADCHAR -WM_SYSKEYDOWN -WM_SYSKEYUP -WM_SYSCHAR -WM_SYSDEADCHAR -WM_KEYLAST -WM_IME_STARTCOMPOSITION -WM_IME_ENDCOMPOSITION -WM_IME_COMPOSITION -WM_IME_KEYLAST -WM_INITDIALOG -WM_COMMAND -WM_SYSCOMMAND -WM_TIMER -WM_HSCROLL -WM_VSCROLL -WM_INITMENU -WM_INITMENUPOPUP -WM_MENUSELECT -WM_MENUCHAR -WM_ENTERIDLE -WM_CTLCOLORMSGBOX -WM_CTLCOLOREDIT -WM_CTLCOLORLISTBOX -WM_CTLCOLORBTN -WM_CTLCOLORDLG -WM_CTLCOLORSCROLLBAR -WM_CTLCOLORSTATIC -WM_MOUSEFIRST -WM_MOUSEMOVE -WM_LBUTTONDOWN -WM_LBUTTONUP -WM_LBUTTONDBLCLK -WM_RBUTTONDOWN -WM_RBUTTONUP -WM_RBUTTONDBLCLK -WM_MBUTTONDOWN -WM_MBUTTONUP -WM_MBUTTONDBLCLK -WM_MOUSEWHEEL -WM_MOUSEHWHEEL -WM_PARENTNOTIFY -WM_ENTERMENULOOP -WM_EXITMENULOOP -WM_NEXTMENU -WM_SIZING -WM_CAPTURECHANGED -WM_MOVING -WM_POWERBROADCAST -WM_DEVICECHANGE -WM_MDICREATE -WM_MDIDESTROY -WM_MDIACTIVATE -WM_MDIRESTORE -WM_MDINEXT -WM_MDIMAXIMIZE -WM_MDITILE -WM_MDICASCADE -WM_MDIICONARRANGE -WM_MDIGETACTIVE -WM_MDISETMENU -WM_ENTERSIZEMOVE -WM_EXITSIZEMOVE -WM_DROPFILES -WM_MDIREFRESHMENU -WM_IME_SETCONTEXT -WM_IME_NOTIFY -WM_IME_CONTROL -WM_IME_COMPOSITIONFULL -WM_IME_SELECT -WM_IME_CHAR -WM_IME_KEYDOWN -WM_IME_KEYUP -WM_MOUSEHOVER -WM_NCMOUSELEAVE -WM_MOUSELEAVE -WM_CUT -WM_COPY -WM_PASTE -WM_CLEAR -WM_UNDO -WM_RENDERFORMAT -WM_RENDERALLFORMATS -WM_DESTROYCLIPBOARD -WM_DRAWCLIPBOARD -WM_PAINTCLIPBOARD -WM_VSCROLLCLIPBOARD -WM_SIZECLIPBOARD -WM_ASKCBFORMATNAME -WM_CHANGECBCHAIN -WM_HSCROLLCLIPBOARD -WM_QUERYNEWPALETTE -WM_PALETTEISCHANGING -WM_PALETTECHANGED -WM_HOTKEY -WM_PRINT -WM_PRINTCLIENT -WM_HANDHELDFIRST -WM_HANDHELDLAST -WM_PENWINFIRST -WM_PENWINLAST -WM_COALESCE_FIRST -WM_COALESCE_LAST -WM_DDE_FIRST -WM_DDE_INITIATE -WM_DDE_TERMINATE -WM_DDE_ADVISE -WM_DDE_UNADVISE -WM_DDE_ACK -WM_DDE_DATA -WM_DDE_REQUEST -WM_DDE_POKE -WM_DDE_EXECUTE -WM_DDE_LAST \ No newline at end of file diff --git a/native/MsgHookTest/bin/x32/MsgHook.dll b/native/MsgHookTest/bin/x32/MsgHook.dll deleted file mode 100644 index fc01f289c8ff928e4c82eaa6e8a0e570748bc986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7680 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 diff --git a/native/MsgHookTest/bin/x32/MsgHook.lib b/native/MsgHookTest/bin/x32/MsgHook.lib deleted file mode 100644 index 80a7bdeb8b9523c68a9cdd0e8934945ea1bc399d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2590 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 TghG2v?ron4?W4U>ZTtKM*c3%1 diff --git a/native/MsgHookTest/bin/x64/MsgHookTest.exe b/native/MsgHookTest/bin/x64/MsgHookTest.exe deleted file mode 100644 index 0cad9a2f811c8a9ab8bb178db4df4b074a4fc360..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 77312 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 MeunR zEj0VX7g|r2ZPpJiW&^!mmgjR;pFG#i>5efD1$?3H^}~;vlVosh!>@U)U;DWt_+#7a zhYz=^{CE6?Pq@8)_>v3wK@0dq3;0M&g1@wogkw9erAZm^c3GCuNMTz9{ICW5uLb?JpLhX(djTJP0snjf-+TcdeHHVuPMoIk@a4Dj zc3DmX!LMJyXJ5e2UOXI00zUi#zWid<2omti7x2#)@Y5G<+O*;NgW(S^;8!o;e=p#F zFW`4C;Bzly_~8rq$_x0)OM>scN(T;qd`a-vS7~`TX38P~|9b)7djY?F0Y7{JzkGo` z1_b=c1@=jha-BML`aA0H^ky!dfiJv(PrHDRyMV7d;%fx_-vxZ)1$^EGeB=du<;Cd- zBS3=${Nn}uB|M|mga7%%*Ea<{GmfoBfg(Dclqh0V?!y1wz5gA07mykAI?4lQVO=6x%j zIRN_j20C+W5q0^+>9-F7Kx@g>sDkh=kt@MuE!ElWps{k$x?^GT+gwOBuPjcZ9z@J>B z=JFW6=7^b^3HX%@_?HX#rwjPGiwCZs_$Klvy|=)>=Cj*-ee-$66(>Hwwf%|DmbN?b z*)5l!_^hJiiO=|WN$V4z+}z^C=eM*waqQN%Cq7;peDaN(`hUGWhyThYH3t2mp_GQ; z-Im$`>gU9K4mdbJ5B0uCTS~Rf3re*;3=ne?e%$+SD|@QnKVW}weIsTWyZ7IA?a0p8 z)8D?I>-B4=<>&9atvXVEi7LRo|F(PoZTJ4$?)|s*Y2^=(f5DcOf37U<{kQAe%T}ei z_up>VHbC6_Z(qTw||A+E8Cnla9M#c^=&zwO?C+r9s`d;e`*bGx|r-*)f6t*#2{I-~RaO!h+86#bbk%e(jA z)~$AFv3vh*_x{`N{kL6j0ssFz)@O{;->>=Z{kPrwZ(s1*&ewhZ9@@SCwtN3=eOmfo z_uuAn0;xNV#GjqZCW|cAw=@}?75}m*mu69+UKwI9U{*?_0{oiDOnLanoA(oWOC*o- zUD72;jZ33t`J9t?K**w4)LMerisL{^L5+p7%rS`dI(EHgS-;w0UZFnJb+T8_}3$GrzYcxBi1V#eKMEQ=Vq;5=ke}*1~@0@OQBaB&MA+>QK)S!M*A4d6Q)c0H<1z{pCt1% zlq23j#>Eg)kNkS{cRp9H`g0!|PctY4edsG``^8QLGj7xHQw`wb(O)_L*A3t{4L@BE zt}1H^JJmP87^<)YTh)wS#N(dl-()%e5@zgcFoW=X+fT+kqxzA_6o}ZHYB4N5C@@eR zg?QkMQ5YsDmRZxBd%4M^9bp>vhNL>0?L*|FNt$R)HzHq65=W3}q)D1+HYRL8N{mwZ z9P4fDRBscfdYd}c+svt6f2VqzJJlQDRBs^ay*jP1(2_GVdx5DWCp))rSeK%L+#!YO zvn@Gkg?)3f(hKqm^D?b{)AMqMq!s3b&hOvFl#`a5m1!xoPOuadX65A$>(W0otjlo! zCMMI>)`Fr!Yg}$--X)e6uJR#gp(VYjAj`TymSaM=y1+882(?%;5(~2CXJuPvSqkl- zBOF_TtX3!zZ<%k&Hf8hgur6tZak=yJ=2{B6n2NHZ($g)4Xj^7lcA=%q@T>dT%XZFe zFW*6;PVHCsbJF$de)dKq`_=t)dk#;GN{ot$i5oj=(j<*>A79)a6iHZJ5aq94x_bHQ Qn$^2jyMzp=po11k1)>;M1& diff --git a/native/MsgHookTest/stdafx.cpp b/native/MsgHookTest/stdafx.cpp deleted file mode 100644 index 56acf67..0000000 --- a/native/MsgHookTest/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// MsgHookTest.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/native/MsgHookTest/stdafx.h b/native/MsgHookTest/stdafx.h deleted file mode 100644 index 24919b6..0000000 --- a/native/MsgHookTest/stdafx.h +++ /dev/null @@ -1,23 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include - -// C RunTime Header Files -#include -#include -#include -#include -#include -#include - - -// TODO: reference additional headers your program requires here diff --git a/native/MsgHookTest/targetver.h b/native/MsgHookTest/targetver.h deleted file mode 100644 index 87c0086..0000000 --- a/native/MsgHookTest/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include diff --git a/src/org/synthuse/Api.java b/src/org/synthuse/Api.java index 8add96b..f3d26f3 100644 --- a/src/org/synthuse/Api.java +++ b/src/org/synthuse/Api.java @@ -8,14 +8,17 @@ package org.synthuse; import java.awt.Point; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import com.sun.jna.Callback; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.Structure; import com.sun.jna.platform.win32.WinDef.*; import com.sun.jna.platform.win32.Advapi32Util; +import com.sun.jna.platform.win32.BaseTSD.LONG_PTR; import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR; import com.sun.jna.platform.win32.WinDef; import com.sun.jna.platform.win32.WinNT.HANDLE; @@ -24,6 +27,7 @@ import com.sun.jna.platform.win32.WinUser; import com.sun.jna.platform.win32.WinNT.LARGE_INTEGER; import com.sun.jna.platform.win32.WinUser.WNDENUMPROC; import com.sun.jna.ptr.PointerByReference; +import com.sun.jna.win32.StdCallLibrary.StdCallCallback; import com.sun.jna.win32.W32APIOptions; public class Api { @@ -198,11 +202,48 @@ public class Api { public int cch; //The length of the menu item text, in characters, when information is received about a menu item of the MFT_STRING type. public HBITMAP hbmpItem; //A handle to the bitmap to be displayed, or it can be one of the values in the following table. } + + public static class COPYDATASTRUCT extends Structure { + //The by-reference version of this structure. + public static class ByReference extends COPYDATASTRUCT implements Structure.ByReference { } + + public COPYDATASTRUCT() { } + + //Instantiates a new COPYDATASTRUCT with existing data given the address of that data. + public COPYDATASTRUCT(final long pointer) { + this(new Pointer(pointer)); + } + + //Instantiates a new COPYDATASTRUCT with existing data given a pointer to that data. + public COPYDATASTRUCT(final Pointer memory) { + super(memory); + read(); + } + + public ULONG_PTR dwData; // The data to be passed to the receiving application. + public int cbData; //The size, in bytes, of the data pointed to by the lpData + public Pointer lpData; + + @SuppressWarnings("rawtypes") + @Override + protected final List getFieldOrder() { + return Arrays.asList(new String[] {"dwData", "cbData", "lpData" }); + } + } + } + + interface WNDPROC extends StdCallCallback { + + LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); + } public interface User32 extends W32APIOptions { User32 instance = (User32) Native.loadLibrary("user32", User32.class, DEFAULT_OPTIONS); + int SetWindowLongPtr(HWND hWnd, int nIndex, Callback callback); + LRESULT CallWindowProc(LONG_PTR proc, HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam); + boolean ShowWindow(HWND hWnd, int nCmdShow); boolean SetForegroundWindow(HWND hWnd); void SwitchToThisWindow(HWND hWnd, boolean fAltTab); @@ -291,13 +332,16 @@ public class Api { kernel32 = Kernel32.instance; } - public static String GetHandleAsString(HWND hWnd) { + public static Long GetHandleAsLong(HWND hWnd) { if (hWnd == null) - return "0"; + return (long)0; //String longHexStr = hWnd.toString().substring("native@".length()); String longHexStr = hWnd.getPointer().toString().substring("native@".length()); - Long l = Long.decode(longHexStr); - return l.toString(); + return Long.decode(longHexStr); + } + + public static String GetHandleAsString(HWND hWnd) { + return GetHandleAsLong(hWnd).toString(); } public static HWND GetHandleFromString(String hWnd) { @@ -583,4 +627,26 @@ public class Api { return false; } + public static HWND FindMainWindowFromPid(final long targetProcessId) { + + final List resultList = new ArrayList(); + class ParentWindowCallback implements WinUser.WNDENUMPROC { + @Override + public boolean callback(HWND hWnd, Pointer lParam) { + PointerByReference pointer = new PointerByReference(); + User32.instance.GetWindowThreadProcessId(hWnd, pointer); + long pid = pointer.getPointer().getInt(0); + if (pid == targetProcessId) + if (resultList.isEmpty()) + resultList.add(hWnd); + return true; + } + } + + Api.User32.instance.EnumWindows(new ParentWindowCallback(), 0); + if (!resultList.isEmpty()) + return resultList.get(0); + return null; + } + } diff --git a/src/org/synthuse/CommandPopupMenu.java b/src/org/synthuse/CommandPopupMenu.java index e49f294..0bbe7b9 100644 --- a/src/org/synthuse/CommandPopupMenu.java +++ b/src/org/synthuse/CommandPopupMenu.java @@ -98,6 +98,7 @@ public class CommandPopupMenu extends JPopupMenu { CommandMenuItem mntmSetTargetOffset = new CommandMenuItem("setTargetOffset", 3, false); mnMouse.add(mntmSetTargetOffset); + JMenu mnWinMessages = new JMenu("Win Messages"); add(mnWinMessages); @@ -112,6 +113,9 @@ public class CommandPopupMenu extends JPopupMenu { CommandMenuItem mntmSelectContextMenuId = new CommandMenuItem("selectContextMenuId", 3); mnWinMessages.add(mntmSelectContextMenuId); + + CommandMenuItem mntmSendCommandMsg = new CommandMenuItem("sendCommandMsg", 4); + mnWinMessages.add(mntmSendCommandMsg); CommandMenuItem mntmSetcursorposition = new CommandMenuItem("setCursorPosition", 3); mnWinMessages.add(mntmSetcursorposition); @@ -142,7 +146,7 @@ public class CommandPopupMenu extends JPopupMenu { CommandMenuItem mntmGetwindowclass = new CommandMenuItem("getWindowClass", 2); mnWinMessages.add(mntmGetwindowclass); - + CommandMenuItem mntmDisplayText = new CommandMenuItem("displayText", 3, false); add(mntmDisplayText); @@ -226,6 +230,8 @@ public class CommandPopupMenu extends JPopupMenu { actionStr += "on | " + xpathItem + " | "; if (paramCount > 2) actionStr += "with | |"; + if (paramCount > 3) + actionStr += " and | |"; return actionStr; } } diff --git a/src/org/synthuse/CommandProcessor.java b/src/org/synthuse/CommandProcessor.java index f568651..5bfb2ac 100644 --- a/src/org/synthuse/CommandProcessor.java +++ b/src/org/synthuse/CommandProcessor.java @@ -102,6 +102,8 @@ public class CommandProcessor implements Runnable{ if (!line.trim().startsWith("|")) continue; //skip if it doesn't start with bar String[] parsed = line.split("\\|"); + // + //System.out.println("line: " + line); //System.out.println("parsed len = " + parsed.length); //System.out.println("parsed 2 = " + parsed[2]); @@ -113,6 +115,8 @@ public class CommandProcessor implements Runnable{ execute(parsed[2].trim(), new String[] {parsed[4].trim()}); if (parsed.length == 7) execute(parsed[2].trim(), new String[] {parsed[4].trim(), parsed[6].trim()}); + if (parsed.length == 9) + execute(parsed[2].trim(), new String[] {parsed[4].trim(), parsed[6].trim(), parsed[8].trim()}); if (executeErrorCount > 0) //check if any errors occurred ++scriptErrorCount; @@ -215,6 +219,8 @@ public class CommandProcessor implements Runnable{ return win.cmdSelectMenu(args); if (command.equals("selectContextMenuId")) return win.cmdSelectContextMenuId(args); + if (command.equals("sendCommandMsg")) + return win.cmdSendCommandMsg(args); if (command.equals("windowMinimize")) return win.cmdWindowMinimize(args); if (command.equals("windowMaximize")) diff --git a/src/org/synthuse/DragTarget.java b/src/org/synthuse/DragTarget.java index ce94497..e5a36c3 100644 --- a/src/org/synthuse/DragTarget.java +++ b/src/org/synthuse/DragTarget.java @@ -130,7 +130,7 @@ public class DragTarget extends JLabel { @Override public boolean importData(TransferSupport support) { - System.out.println("importData"); + //System.out.println("importData"); return true; } diff --git a/src/org/synthuse/MessageHookFrame.java b/src/org/synthuse/MessageHookFrame.java index 887a0fb..4fef6ad 100644 --- a/src/org/synthuse/MessageHookFrame.java +++ b/src/org/synthuse/MessageHookFrame.java @@ -1,3 +1,12 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + +// This class is not actually used and is only here as a reference + package org.synthuse; import javax.swing.JFrame; @@ -6,37 +15,57 @@ import java.awt.BorderLayout; import javax.swing.JTextArea; import javax.swing.JScrollPane; import javax.swing.JButton; +import javax.swing.WindowConstants; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; import com.sun.jna.platform.win32.User32; import com.sun.jna.platform.win32.WinDef.*; -import com.sun.jna.platform.win32.Kernel32; -import com.sun.jna.platform.win32.WinUser.HHOOK; -import com.sun.jna.platform.win32.WinUser.HOOKPROC; -import com.sun.jna.platform.win32.WinUser.MSG; +import com.sun.jna.platform.win32.BaseTSD.LONG_PTR; +import com.sun.jna.ptr.IntByReference; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JLabel; +import javax.swing.JTextField; +import java.awt.Dimension; +import java.awt.Component; +import java.util.Arrays; +import java.util.List; + +import javax.swing.Box; + public class MessageHookFrame extends JFrame { private static final long serialVersionUID = -5863279004595502801L; + public static final String newLine = System.getProperty("line.separator"); + public static final int WH_CALLWNDPROC = 4; public static final int WH_GETMESSAGE = 3; public static final int WH_KEYBOARD_LL = 13; public static final int WM_COPYDATA = 74; + public static final int GWLP_WNDPROC = -4; private JTextArea textArea; private JButton btnSave; private JButton btnStartMsgHook; private JButton btnPause; private JButton btnClear; + private LONG_PTR oldWndProc; + private MsgHook msgHook = null; - public static HHOOK hHook = null; - //public static LowLevelKeyboardProc lpfn; public static volatile boolean quit = false; + private JLabel lblTargetHwnd; + public JTextField txtTarget; + private Component horizontalStrut; public MessageHookFrame() { setTitle("Message Hook"); @@ -60,11 +89,42 @@ public class MessageHookFrame extends JFrame { } } }); + + lblTargetHwnd = new JLabel("Target HWND: "); + toolBar.add(lblTargetHwnd); + + txtTarget = new JTextField(); + txtTarget.setMaximumSize(new Dimension(70, 2147483647)); + txtTarget.setText("0"); + toolBar.add(txtTarget); + txtTarget.setColumns(10); + + horizontalStrut = Box.createHorizontalStrut(20); + toolBar.add(horizontalStrut); toolBar.add(btnStartMsgHook); btnPause = new JButton("Pause"); btnPause.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + + final HWND myHwnd = new HWND(Native.getWindowPointer(MessageHookFrame.this)); + oldWndProc = User32.INSTANCE.GetWindowLongPtr(myHwnd, GWLP_WNDPROC); + + Api.WNDPROC wndProc = new Api.WNDPROC() { + public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) { + if (uMsg == WM_COPYDATA){ + System.out.println("WM_COPYDATA"); + //handle the window message here + } + else + System.out.println("MESSAGE: " + uMsg); + return Api.User32.instance.CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); + //return new LRESULT(0); + //return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam); + } + }; + + Api.User32.instance.SetWindowLongPtr(myHwnd, GWLP_WNDPROC, wndProc); } }); toolBar.add(btnPause); @@ -89,62 +149,142 @@ public class MessageHookFrame extends JFrame { textArea = new JTextArea(); scrollPane.setViewportView(textArea); + + this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + this.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + //TestIdeFrame.this.setVisible(false); + MessageHookFrame.this.dispose(); + } + }); + super.setAlwaysOnTop(SynthuseDlg.config.isAlwaysOnTop()); + } + /* + typedef struct + { + HWND hWnd; + int nCode; + DWORD dwHookType; + WPARAM wParam; + LPARAM lParam; + TCHAR wParamStr[25]; + TCHAR lParamStr[25]; + }HEVENT; + */ + + public static class HEVENT extends Structure { + //The by-reference version of this structure. + public static class ByReference extends HEVENT implements Structure.ByReference { } + + public HEVENT() { } + + //Instantiates a new COPYDATASTRUCT with existing data given the address of that data. + public HEVENT(final long pointer) { + this(new Pointer(pointer)); + } + + //Instantiates a new COPYDATASTRUCT with existing data given a pointer to that data. + public HEVENT(final Pointer memory) { + super(memory); + read(); + } + + public WORD hWnd; + public WORD nCode; + public DWORD dwHookType; + public DWORD wParam; + public DWORD lParam; + //public TCHAR wParamStr[25]; + //public TCHAR lParamStr[25]; + + @SuppressWarnings("rawtypes") + @Override + protected final List getFieldOrder() { + return Arrays.asList(new String[] {"hWnd", "nCode", "dwHookType", "wParam", "lParam" }); + } + } + public void createMessageHook() { - /* - // Below set windows hook is called from inside the native DLL - if (hHook != null) - return; //hook already running don't add anymore - System.out.println("starting global message hook"); - HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null); - int threadId = Kernel32.INSTANCE.GetCurrentThreadId(); - HOOKPROC lpfn = new HOOKPROC() { - @SuppressWarnings("unused") - public LRESULT callback(int nCode, WPARAM wParam, LPARAM lParam) { - //System.out.println("Msg " + nCode); - - return User32.INSTANCE.CallNextHookEx(hHook, nCode, wParam, lParam); - } - }; - hHook = User32.INSTANCE.SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hMod, threadId); - if (hHook == null) - return; - */ - MsgHook mh = new MsgHook(); - //mh.setMessageHook(hwnd, threadId); + quit = false; //don't quit - MSG msg = new MSG(); - try { - - while (!quit) { - User32.INSTANCE.PeekMessage(msg, null, 0, 0, 1); - if (msg.message == WM_COPYDATA){ // && msg.wParam.intValue() == 1 - System.out.println("WM_COPYDATA"); - msg = new MSG(); //must clear msg so it doesn't repeat + //find the HWND and current WNDPROC on this java window + final HWND myHwnd = new HWND(Native.getWindowPointer(MessageHookFrame.this)); + oldWndProc = User32.INSTANCE.GetWindowLongPtr(myHwnd, GWLP_WNDPROC); + + Api.WNDPROC wndProc = new Api.WNDPROC() { + public LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) { + if (uMsg == WM_COPYDATA){ + //(COPYDATASTRUCT *) lParam + //if( pCopyDataStruct->cbData == sizeof(HEVENT)) { + // HEVENT Event; + // memcpy(&Event, (HEVENT*)pCopyDataStruct->lpData, sizeof(HEVENT)); // transfer data to internal variable + //} + + Api.WinDefExt.COPYDATASTRUCT cds = new Api.WinDefExt.COPYDATASTRUCT(lParam.longValue()); + HEVENT he = new HEVENT(cds.lpData); + appendLine("msg: WM_COPYDATA" + cds.cbData); + appendLine("hwnd: " + he.hWnd + ", msg: " + he.nCode + ", wParam: " + he.wParam + ", lParam: " + he.lParam); + //System.out.println("WM_COPYDATA"); + //handle the window message here } - Thread.sleep(10); - } - } catch (Exception e) { - e.printStackTrace(); + //else + // System.out.println("MESSAGE: " + uMsg); + + return Api.User32.instance.CallWindowProc(oldWndProc, hWnd, uMsg, wParam, lParam); + //return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam); + } + }; + + //Set the wndproc callback on this MessageHookFrame so we can process Windows Messages + Api.User32.instance.SetWindowLongPtr(myHwnd, GWLP_WNDPROC, wndProc); + + IntByReference intByRef = new IntByReference(0); + final int threadId = User32.INSTANCE.GetWindowThreadProcessId(Api.GetHandleFromString(txtTarget.getText()), intByRef); + + //int myPid = Kernel32.INSTANCE.GetCurrentProcessId(); + //HWND myHwnd = Api.FindMainWindowFromPid(myPid); + final long myHwndLong = Api.GetHandleAsLong(myHwnd); + + //System.out.println("Starting Msg Hook for " + myHwndLong + " on id " + threadId); + if (threadId == 0 ) // don't allow global + { + System.out.println("Not allowing global message hook " + threadId); + User32.INSTANCE.SetWindowLongPtr(myHwnd, GWLP_WNDPROC, oldWndProc); //restore default WNDPROC + quit = true; + return; } - System.out.println("message loop stopped"); - unhook(); + + msgHook = new MsgHook(); + if (!msgHook.setMessageHook((int) myHwndLong, threadId)) + appendLine("Error setting message hook"); + else + appendLine("Message hook started"); + } - public void unhook() { - if (hHook == null) - return; - if (!User32.INSTANCE.UnhookWindowsHookEx(hHook)) - System.out.println("Failed to unhook"); - System.out.println("Unhooked"); - hHook = null; + public void unhook(MsgHook msgHook) { + msgHook.removeMessageHook(); } //stops Keyboard hook and causes the unhook command to be called - public static void stopMessageHook() { + public void stopMessageHook() { + //if (!quit) //if not hooked skip + // return; quit = true; + appendLine("Message hook stopped"); + final HWND myHwnd = new HWND(Native.getWindowPointer(MessageHookFrame.this)); + User32.INSTANCE.SetWindowLongPtr(myHwnd, GWLP_WNDPROC, oldWndProc); //restore default WNDPROC + unhook(msgHook); + } + + public void appendLine(String txt) + { + textArea.append(txt + newLine); + textArea.setCaretPosition(textArea.getDocument().getLength()); } } diff --git a/src/org/synthuse/MsgHook.java b/src/org/synthuse/MsgHook.java index ed8228c..002b1be 100644 --- a/src/org/synthuse/MsgHook.java +++ b/src/org/synthuse/MsgHook.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + package org.synthuse; import java.io.File; @@ -7,6 +14,7 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; + import javax.swing.JOptionPane; public class MsgHook { @@ -78,7 +86,27 @@ public class MsgHook { System.load(temp.getAbsolutePath()); } - public native boolean setMessageHook(long hwnd, long threadId); + //public native boolean initialize(int hwnd); + public native boolean createMsgHookWindow(); + public native boolean setMsgHookWindowTargetHwnd(int hwnd); + public native boolean setMsgHookWindowTargetClass(String classname); + public native boolean setMessageHook(int hwnd, int threadId); public native boolean removeMessageHook(); + //public native boolean shutdown(); + + public static Thread createMsgHookWinThread(final long targetHwnd) + { + Thread t = new Thread() { + public void run() { + MsgHook mh = new MsgHook(); + mh.setMsgHookWindowTargetClass(""); + if (targetHwnd != 0) + mh.setMsgHookWindowTargetHwnd((int)targetHwnd); + mh.createMsgHookWindow(); + } + }; + t.start(); + return t; + } } diff --git a/src/org/synthuse/RobotMacro.java b/src/org/synthuse/RobotMacro.java index e9bf9fd..aeaabe9 100644 --- a/src/org/synthuse/RobotMacro.java +++ b/src/org/synthuse/RobotMacro.java @@ -428,6 +428,10 @@ ALT % specialKeyFlag = false; pressKeyCodes(robot, new int[]{KeyEvent.VK_CANCEL} ); } + else if (specialKey.equals("{BAR}")) { + specialKeyFlag = false; + pressKeyCodes(robot, new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH}); + } else if (specialKey.equals("{{}")) { specialKeyFlag = false; pressKeyCodes(robot, new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET} ); @@ -602,7 +606,7 @@ ALT % case '}': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_CLOSE_BRACKET}); case '|': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH}); case ';': return(new int[]{KeyEvent.VK_SEMICOLON}); - case ':': return(new int[]{KeyEvent.VK_COLON}); + case ':': return(new int[]{KeyEvent.VK_SHIFT, KeyEvent.VK_SEMICOLON}); case '\'': return(new int[]{KeyEvent.VK_QUOTE}); case '"': return(new int[]{KeyEvent.VK_QUOTEDBL}); case ',': return(new int[]{KeyEvent.VK_COMMA}); diff --git a/src/org/synthuse/SynthuseDlg.java b/src/org/synthuse/SynthuseDlg.java index 94ec29a..228c317 100644 --- a/src/org/synthuse/SynthuseDlg.java +++ b/src/org/synthuse/SynthuseDlg.java @@ -50,7 +50,7 @@ public class SynthuseDlg extends JFrame { /** * */ - public static String VERSION_STR = "1.2.0"; + public static String VERSION_STR = "1.2.1"; public static String RES_STR_MAIN_ICON = "/org/synthuse/img/gnome-robots.png"; public static String RES_STR_REFRESH_IMG = "/org/synthuse/img/rapidsvn.png"; @@ -83,7 +83,7 @@ public class SynthuseDlg extends JFrame { private JButton btnAdvanced; private TestIdeFrame testIde = null; - private MessageHookFrame msgHook = null; + //private MessageHookFrame msgHook = null; private int targetX; private int targetY; private UiaBridge uiabridge = new UiaBridge(); @@ -187,9 +187,19 @@ public class SynthuseDlg extends JFrame { public void actionPerformed(ActionEvent event) { //System.out.println("Popup menu item [" + event.getActionCommand() + "] was pressed."); if (event.getActionCommand() == "Message Hook"){ + /* if (msgHook == null) msgHook = new MessageHookFrame(); msgHook.setVisible(true); + msgHook.txtTarget.setText(lastDragHwnd); + */ + long lastHwndLong = 0; + try { + lastHwndLong = Long.parseLong(lastDragHwnd); + } catch (Exception ex) { + } + MsgHook.createMsgHookWinThread(lastHwndLong); + } } }; @@ -224,7 +234,9 @@ public class SynthuseDlg extends JFrame { about += " disableUiaBridge - " + config.isUiaBridgeDisabled() + "\n"; about += " disableFiltersUia - " + config.isFilterUiaDisabled() + "\n"; - about += "\nSystem information: \n"; + about += " Synthuse location - " + SynthuseDlg.class.getProtectionDomain().getCodeSource().getLocation().toString(); + + about += "\n\nSystem information: \n"; about += " Java version - " + System.getProperty("java.version") + "\n"; about += " Java home - " + System.getProperty("java.home") + "\n"; about += " OS Name - " + System.getProperty("os.name") + "\n"; @@ -380,12 +392,17 @@ public class SynthuseDlg extends JFrame { lblStatus.setText(status); } @Override - public void executionCompleted(Object input, String results) { //buildXpathStatementThreaded finished, with results being the xpath statement + public void executionCompleted(Object input, final String results) { //buildXpathStatementThreaded finished, with results being the xpath statement if (input instanceof HWND) { // in case thread takes long time to process lastDragHwnd = Api.GetHandleAsString((HWND)input); } - XpathManager.nextXpathMatch(results, textPane, lblStatus, true); - cmbXpath.setSelectedItem(results); + SwingUtilities.invokeLater(new Runnable() {//swing components are not thread safe, this will run on Swings event dispatch thread + public void run() { + XpathManager.nextXpathMatch(results, textPane, lblStatus, true); + cmbXpath.setSelectedItem(results); + } + }); + } }; diff --git a/src/org/synthuse/UiaBridge.java b/src/org/synthuse/UiaBridge.java index e049dcc..017b3e8 100644 --- a/src/org/synthuse/UiaBridge.java +++ b/src/org/synthuse/UiaBridge.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + package org.synthuse; import java.awt.Point; diff --git a/src/org/synthuse/commands/BaseCommand.java b/src/org/synthuse/commands/BaseCommand.java index 1d41ac9..a0080a0 100644 --- a/src/org/synthuse/commands/BaseCommand.java +++ b/src/org/synthuse/commands/BaseCommand.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; diff --git a/src/org/synthuse/commands/FileCommands.java b/src/org/synthuse/commands/FileCommands.java index 3f1cb8c..46fb55b 100644 --- a/src/org/synthuse/commands/FileCommands.java +++ b/src/org/synthuse/commands/FileCommands.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; import java.io.*; diff --git a/src/org/synthuse/commands/KeyboardCommands.java b/src/org/synthuse/commands/KeyboardCommands.java index 8e13835..f5f1c1a 100644 --- a/src/org/synthuse/commands/KeyboardCommands.java +++ b/src/org/synthuse/commands/KeyboardCommands.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; import org.synthuse.*; diff --git a/src/org/synthuse/commands/MainCommands.java b/src/org/synthuse/commands/MainCommands.java index a12cd61..af63554 100644 --- a/src/org/synthuse/commands/MainCommands.java +++ b/src/org/synthuse/commands/MainCommands.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; import java.awt.Dimension; diff --git a/src/org/synthuse/commands/MouseCommands.java b/src/org/synthuse/commands/MouseCommands.java index dd1e50a..4f90236 100644 --- a/src/org/synthuse/commands/MouseCommands.java +++ b/src/org/synthuse/commands/MouseCommands.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; import java.awt.Point; @@ -18,9 +25,9 @@ public class MouseCommands extends BaseCommand { if (handle.isEmpty()) return false; String wtype = getWindowTypeWithXpath(args[0]); - System.out.println("wtype: " + wtype + " hwnd " + handle.hWnd + " hmenu " + handle.hmenuStr + " pos " + handle.hmenuPos); + //System.out.println("wtype: " + wtype + " hwnd " + handle.hWnd + " hmenu " + handle.hmenuStr + " pos " + handle.hmenuPos); Point p = getCenterWindowPosition(handle, wtype); - System.out.println("cmdClick: " + p.x + "," + p.y); + //System.out.println("cmdClick: " + p.x + "," + p.y); RobotMacro.mouseMove(p.x + parentProcessor.targetOffset.x, p.y + parentProcessor.targetOffset.y); RobotMacro.leftClickMouse(); return true; diff --git a/src/org/synthuse/commands/WindowsCommands.java b/src/org/synthuse/commands/WindowsCommands.java index bc85be8..9fdf007 100644 --- a/src/org/synthuse/commands/WindowsCommands.java +++ b/src/org/synthuse/commands/WindowsCommands.java @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski +*/ + package org.synthuse.commands; import org.synthuse.*; @@ -152,4 +159,22 @@ public class WindowsCommands extends BaseCommand { return true; } + + public boolean cmdSendCommandMsg(String[] args) { + if (!checkArgumentLength(args, 3)) + return false; + WinPtr handle = findHandleWithXpath(args[0]); //xpath to HWND is first argument + if (handle.isEmpty()) + return false; + int id = Integer.parseInt(args[1]); //context menu id is supplied as second argument + int idLparam = Integer.parseInt(args[2]); //context menu id is supplied as second argument + handle.convertToNativeHwnd(); + //LRESULT result = + //System.out.println("Send Message WM_COMMAND to " + handle.toString() + " PARAMS: " + id + ", " + idLparam); + //api.user32.PostMessage(handle.hWnd, Api.WM_COMMAND, new WPARAM(id), new LPARAM(0)); + api.user32.SendMessage(handle.hWnd, Api.WM_COMMAND, new WPARAM(id), new LPARAM(idLparam)); + + return true; + } } +