已经把代码发布到npm上了,就这样……https://www.npmjs.com/package/nw-penetrate
首先知道,nwjs,即原node-webkit,可以通过配置package.json + CSS来实现透明背景(详见https://github.com/nwjs/nw.js/wiki/Transparency )。但是,鼠标穿透怎么解决呢?
看API,很明显这么奇葩的需求没人做……纯JavaScript肯定实现不了,就只能上API了。这样就是和平台有关了,所以做个Windows版就够了,Linux和Mac就懒得做了(哈哈哈哈哈哈哈哈哈哈哈)
OK,先用ffi
库来调Win32 API。很好,直接npm install
的ffi
是不能用的,其用的req
库有fs.existSync
,在nwjs中被accessSync
给替代。爽!
然后,试着上C++吧。Well done, nan
库用不了!好吧,为了省事,就直接写Node 0.12.0的代码了。Node 0.10.0对照修改即可。
另外,似乎在nwjs下,bindings
库也有相当麻烦的兼容问题。于是为了实现这个库,我不得不把那个库fork了一份然后修改……
完整代码见:https://github.com/zsxsoft/nw-penetrate
nwjs里没有提供获得自己Handle(Windows下hWnd)的API(https://github.com/nwjs/nw.js/issues/1337) ,所以我看也只能硬来。用GetWindowThreadProcessId
+ process.pid
的话,考虑到因为可能有Developer Tool同时开启的缘故,所以还是用了FindWindow
。反正标题也不太重要嘛是吧。另外因为不是MFC项目的缘故,ModifyStyleEx
是不能用的,只能自己用SetWindowLong
自行拼
以下为最核心C++代码。
#include <node.h>
#include <v8.h>
#ifdef __WINDOWS_
#include <windows.h>
#endif
using namespace v8;
void penetrate(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
v8::String::Utf8Value str(args[0]->ToString());
char *name = *str;
HWND h = FindWindow(NULL,(LPCSTR)name);
if (h != NULL) {
int extendedStyle = GetWindowLong(h, GWL_EXSTYLE);
SetWindowLong(h, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT | WS_EX_LAYERED);
args.GetReturnValue().Set(true);
return;
}
args.GetReturnValue().Set(false);
}
void Init(Handle<Object> exports) {
Isolate* isolate = Isolate::GetCurrent();
exports->Set(String::NewFromUtf8(isolate, "penetrate"),
FunctionTemplate::New(isolate, penetrate)->GetFunction());
}
NODE_MODULE(penetrate, Init)