1

グローバルキーバインディングを使用して特定の機能を実行できる Electron node.js アプリケーションを作成しようとしています。残念ながら、Electron のグローバル キーバインド API はゲームでは機能しないため、これらの低レベルのキー イベントをリッスンするネイティブ ノード モジュールを作成する必要があります。

そのため、node-gyp を使用してプロジェクトを Visual Studio 2015 でコンパイルし、nan を使用してノードと C++ 間の通信を提供しています。プロジェクトの両方の側面(低レベルのキーバインディングとnode.js <--> nan通信)を別々に機能させることができましたが、それらを組み合わせるのに問題があります。また、c++ の経験がほとんどないことも認めています (c++ プログラムを 1 つも作成したことがありません)。

#include "node_modules/nan/nan.h"

using namespace std;
using namespace Nan;

HHOOK _hook;
KBDLLHOOKSTRUCT kbdStruct;

class KeyboardEventWorker : public AsyncProgressWorker {
 public:
  KeyboardEventWorker(Callback *callback, Callback *progress)
    : AsyncProgressWorker(callback), progress(progress) {}
  ~KeyboardEventWorker() {}
  
  LRESULT CALLBACK HookCallback(int nCode,WPARAM wParam,LPARAM lParam) {  
    executionProgress->Send(reinterpret_cast<const char*>(nCode), sizeof(nCode));
    return CallNextHookEx(_hook, nCode, wParam, lParam);
  }
  
  void Execute (const AsyncProgressWorker::ExecutionProgress& progress) {
    executionProgress = &progress; //PROBLEM #1
        _hook = SetWindowsHookEx(13, HookCallback, NULL, 0); //PROBLEM #2
    
    SleepEx(INFINITE, true);
  }


  void HandleProgressCallback(const char *data, size_t size) {
    HandleScope scope;
    
    v8::Local<v8::Value> argv[] = {
        New<v8::Integer>(*reinterpret_cast<int*>(const_cast<char*>(data)))
    };
    progress->Call(1, argv);
  }
  
  private:
    Callback *progress;
    AsyncProgressWorker::ExecutionProgress *executionProgress;
};

NAN_METHOD(DoProgress) {
  Callback *progress = new Callback(info[0].As<v8::Function>());
  Callback *callback = new Callback(info[1].As<v8::Function>());
  AsyncQueueWorker(new KeyboardEventWorker(callback, progress));
}

NAN_MODULE_INIT(Init) {
  Set(target
    , New<v8::String>("init").ToLocalChecked()
    , New<v8::FunctionTemplate>(DoProgress)->GetFunction());
}

NODE_MODULE(asyncprogressworker, Init)

問題 #1: メッセージを node.js に送り返すには、AsyncProgressWorker::ExecutionProgress のポインターをコピーしてクラス全体で使用できるようにする必要があります。これにより、HookCallback がトリガーされたときに node.js にメッセージを送信できます。 .

コンパイラはこれを好まない

..\binding.cc(21): エラー C2440: '=': 'const Nan::AsyncProgressWorker::ExecutionProgress *' から 'Nan: :AsyncProgressWorker::ExecutionProgress *' に変換できません [C:\Users\eksrow\ gdrive\projects\vscode\node-native-hello-world\build\bindin g.vcxproj].

..\binding.cc(21): 注: 変換により修飾子が失われます

フォーマット:

「const Nan::AsyncProgressWorker::ExecutionProgress *」

「Nan::AsyncProgressWorker::ExecutionProgress *」

これは、キーワード const をプライベート メンバー *executionProgress; に追加することで解決できました。しかし、なぜそれが修正されるのかわかりません。 const 変数は、一度設定すると変更されるべきではありません。なぜこれがコンパイルされるのですか?

問題#2:これは非常に独特です:

..\binding.cc(22): エラー C3867: 'KeyboardEventWorker::HookCallback': 非標準の構文。「&」を使用してメンバーへのポインターを作成します [C:\Users\eksrow\gdrive\projects\vscode\node-native-hello-world\build\binding.vcxproj]

私はオンラインで多くの例を調べましたが、これに関してはすべて同じ構文を持っています:

  1. SetWindowsHookEx #1
  2. SetWindowsHookEx #2

その行に関して、私のコードと彼らのコードの違いがわかりません。

コンパイラが言うことを実行してその行にアンパサンドを追加すると、まったく異なるエラーが発生します。

..\binding.cc(22): エラー C2276: '&': バインドされたメンバー関数式に対する不正な操作 [C:\Users\eksrow\gdrive\proj ects\vscode\node-native-hello-world\build\binding .vcxproj] ..\binding.cc(22): エラー C2660: 'SetWindowsHookExA': 関数は 3 つの引数を取りません [C:\Users\eksrow\gdrive\project s\vscode\node-native-hello-world\build \binding.vcxproj]

4

1 に答える 1

1

問題 #1 についてconstは、修飾子を問題として正しく識別しました。

const宣言後にメンバー変数に割り当てることができる理由は、 constinの配置のためですconst AsyncProgressWorker::ExecutionProgress *executionProgress。これは、定数 AsyncProgressWorker::ExecutionProgress への変数ポインターです。これは、ポインターの値を変更できることを意味します (たとえば、上記の例のように再割り当てします) が、ポインターが指すデータを変更することはできません。この質問の一番の答えには、この概念の非常に良い説明があります。

問題 #2の場合、クラスのメンバー関数を関数コールバックとして渡そうとすると、エラーが発生します。これは単に不可能です (まあ、回避策がなければ...以下を参照してください) - メンバーメソッドは関数と同じではありません。これSetWindowsHookExは期待されていることです。コールバック関数を作成できますが、メンバーstaticにアクセスできなくなります。_hook

これは、この正確な問題に対する(非常にハックな)回避策を備えた外部ページです。SetWindowsHookEx現在使用しようとしている方法で使用できるようにする必要があります。ただし、アプリケーションのフック方法を再考し、代わりに単一のグローバル関数または静的メンバー関数をアプリケーションのコールバックとして登録する方法があるかどうかを確認することをお勧めします。

質問とは関係ありません:サンプルでコードを省略していない限り、で設定されているフックを決して解除しませんSetWindowsHookExのMSDNをUnhookWindowsHookEx見てください。

于 2015-11-26T00:25:00.960 に答える