8

私はいくつかの典型的な問題を抱えています。ユーザーが sendText() 関数を利用できるようにします。彼は例えばタイプすることができます

sendText( "mytext{newline}text{up}" )

{text} は、ユーザーが送信できる特別なキーです。特殊なキーがたくさんあります。

したがって、私の最初のステップは、{} ブラケット間の文字列を取得して作成することでした:

if( _specialKey == "newline" ) {
    // action for VK_RETURN
} else if( _specialKey == "up" ) {
    // action for VK_UP
} else .....

例:

if( specialKey == "n" ) {
    // enter click
    unsigned short key = VK_RETURN;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "n+" ) {
    // enter down
    inputs.push_back( keyDown( VK_RETURN ) );

    return 2;
} else if( specialKey == "n-" ) {
    // enter up
    inputs.push_back( keyUp( VK_RETURN ) );

    return 2;
} else if( specialKey == "t" ) {
    // tabulator click
    unsigned short key = VK_TAB;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "t+" ) {
    // tabulator down
    inputs.push_back( keyDown( VK_TAB ) );

    return 2;
} else if( specialKey == "t-" ) {
    // tabulator up
    inputs.push_back( keyUp( VK_TAB ) );

    return 2;
} else if( specialKey == "caps" ) {
    // caps lock click
    unsigned short key = VK_CAPITAL;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "caps+" ) {
    // caps lock down
    inputs.push_back( keyDown( VK_CAPITAL ) );

    return 2;
} else if( specialKey == "caps-" ) {
    // caps lock up
    inputs.push_back( keyUp( VK_CAPITAL ) );

    return 2;
} else if( specialKey == "ralt" ) {
    // right alt click
    unsigned short key = VK_RMENU;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "ralt+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_RMENU ) );

    return 2;
} else if( specialKey == "ralt-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_RMENU ) );

    return 2;
} else if( specialKey == "lalt" ) {
    // right alt click
    unsigned short key = VK_LMENU;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "lalt+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_LMENU ) );

    return 2;
} else if( specialKey == "lalt-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_LMENU ) );

    return 2;
} else if( specialKey == "rctrl" ) {
    // right alt click
    unsigned short key = VK_RCONTROL;
    inputs.push_back( keyDown( key ) );
    inputs.push_back( keyUp( key ) );

    return 2;
} else if( specialKey == "rctrl+" ) {
    // right alt down
    inputs.push_back( keyDown( VK_RCONTROL ) );

    return 2;
} else if( specialKey == "rctrl-" ) {
    // right alt up
    inputs.push_back( keyUp( VK_RCONTROL ) );

    return 2;
} else if( specialKey == "lctrl" ) {

しかし、コンパイラは次のように述べています。

fatal error C1061: compiler limit : blocks nested too deeply

それを解決するための私の最初のアイデアは、整数にマップされるすべての特殊キーを (文字列として) 格納するマップを定義することでした。次に、次のことができます。

switch( map[key] ) {
    case 0:
    ...
}

しかし、コンパイラもそれについて文句を言わないかどうかはわかりません。変えなければならないことがたくさんあるので、結果が出ないから変えたくありません。

それとも、他にもっと良いアイデアがありますか?

ありがとう。

4

3 に答える 3

9

127 個を超えるelse ifブロックがあります。これはコンパイルする必要があり、Microsoft の C++ コンパイラのバグであることは間違いありませんが、それでもコードに何か問題があるというかなり強い匂いがします。

制御フローにデータを保存しています。これらの 128 ブロックの大部分は冗長なコピー アンド ペースト ブロックです。できない場合は、そうすべきではありません。コードとデータを分離し、特殊なケースには制御フローを使用し、すべての一般的なケースを 1 つのタイプとして扱う単一のハッシュ マップにリファクタリングします。

于 2012-07-16T16:08:17.527 に答える
5

次のようなマップを使用できますmap<string, int>。1 つの要素は次のようになりますpair<string,int>("newline", VK_RETURN>

map<string, int> NameToKey;
NameToKey.insert(make_pair("newline", VK_RETURN));

そして、次のような switch ケースでも同じものを使用します。

map<string,int>::const_iterator iter = NameToKey.find(_specialKey);
switch(iter->second)
{
case VK_RETURN: // Handle as "newline"
   ;
 }
于 2012-07-16T16:06:06.517 に答える
2

関数へのポインターの代わりに、少し OOP を使用します。

class ICommand
{
  public:
  virtual void execute() const =0;
  virtual void ~ICommand(){};
};

class KeyUpCommand : public ICommand
{
  DWORD key_; //not suare about win api here
  public:
  KeyUpCommand(key) : key_(key) {};
  virtual void execute() const
  {
     keyUp(key_);
  };
};

class KeyDownCommand : public ICommand
{
  DWORD key_; //not suare about win api here
  public:
  KeyDownCommand(key) : key_(key) {};
  virtual void execute() const
  {
     keyDown(key_);
  };
};


int main()
{
  std::map<std::string, ICommand *> commands;
  commands["t-"]=new KeyUpCommand(VK_TAB);

  //execute now
  std::map<std::string, ICommand *>::const_iterator iter = commands.find(_specialKey);
  iter->second->execute();
};
于 2012-07-16T16:30:07.137 に答える