0

数値のみを受け入れるようにエディット コントロールをサブクラス化しました。

また、サブクラス化の手順で、クリップボード データを解析して禁止文字を削除します。

私は目的の動作を達成したか、少なくともそう思っていましたが、唯一の問題は、編集コントロールにもドットを入力できることです。

自分のコードの何が問題なのかわからないので、他の誰かが助けてくれることを願ってここに投稿します。

クリップボードの解析は適切なデータを返しますが、問題を引き起こすのは WM_CHAR です。

助けてください、コードの何が問題なのかわかりません。

ありがとうございました。

サブクラス化手順のコードは次のとおりです。

    LRESULT CALLBACK MyEditProc ( HWND hwnd, 
                                  UINT message, 
                                  WPARAM wParam, 
                                  LPARAM lParam, 
                                  UINT_PTR uIdSubclass, 
                                  DWORD_PTR  dwRefData )
    {
        switch (message)
        {
        case WM_PASTE:
              {
                 if ( OpenClipboard( NULL ) ) 
                 {

                     HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT);

                     wchar_t *pchData =
                                        (wchar_t*)GlobalLock(hClipboardData);

                     GlobalUnlock(hClipboardData);

                     CloseClipboard();

                     int i = 0, j = 0;

                     wchar_t *temp = new wchar_t[51]; // parsed string

                     memset( temp, '\0', sizeof(temp) );

                     // integer numbers are parsed here

                     while( ( i < (int)wcslen(pchData) )
                          && ( j < 10 ) ) // I just need first 10
                     {
                         if( isdigit( pchData[i] ) )
                            temp[j++] = pchData[i];
                         i++;
                     }

                     temp[j] = '\0';

                     // replace selection with parsed text

                     SendMessage( hwnd, EM_REPLACESEL, 
                                  (WPARAM)TRUE, (LPARAM)temp );

                     // set caret at the end of the text

                     SendMessage( hwnd, EM_SETSEL, j, j );

                     delete[] temp;
                  }
               }
               return TRUE;
               break;

        case WM_CHAR:
               {

                   if( ! ( isdigit(wParam)
                         || wParam == VK_RETURN
                         || wParam == VK_DELETE
                         || wParam == VK_BACK ) 
                         // this check bellow is needed 
                         // so I can catch WM_PASTE !
                         && ( ! ( GetKeyState( VK_CONTROL ) & 0x8000 ) ) ) 
                   {
                         return 0;
                   }
                }
                break;
        }
        return DefSubclassProc( hwnd, message, wParam, lParam);
    }

次のように WM_CREATE のコントロールをサブクラス化しました。

SetWindowSubclass( hEdit, MyEditProc, 0, 0);

上記の手順では4番目のパラメータとして何も渡さなかったので、呼び出す必要性を感じませんでしたRemoveWindowSubclass

編集:

Passant 氏が私のソリューションのエラーを指摘したので、この投稿を読んで同様の問題の解決策を探している人を混乱させないように、それを削除しました。

4

1 に答える 1

1

中心的な間違いは、WM_CHAR メッセージ ハンドラーで仮想キー コードをテストしていることです。それは正しくありません。仮想キー コードは WM_KEYDOWN/UP メッセージでのみ使用されます。WM_CHAR は、変換されたキーストローク、アクティブなキーボード レイアウトおよびキーボードの状態によって選択された文字を取得します。メッセージ ループで TranslateMessage() を呼び出すと、その作業が完了します。GetKeyState() の使用も同様に間違っています。これは TranslateMessage() によって既に行われています。

VK_RETURN と VK_BACK で運が良かったのですが、これらの仮想キー コードは、変換された制御コード (0x0d と 0x08) と同じコードを持っています。VK_DELETE で運が尽き、文字と同じコード 0x2e を持っています'.'

正しいコードは次のようになります。

   case WM_CHAR:
   {
       if (wParam >= ' ' && !isdigit(wParam) {
           return 0;
       }
   }
   break;
于 2013-09-05T11:06:16.847 に答える