2016-08-16 3 views
-2

Je le code suivant qui obtient les données de l'entrée de zone de texte (winapi pur)GetWindowTextW ne marche pas saisir une grande chaîne

BOOL CALLBACK DlgProc(HWND hw, UINT msg, WPARAM wp, LPARAM lp) { 
    switch (msg) 
    { 
    case WM_INITDIALOG: 
     SendDlgItemMessage(hw, IDC_EDITMASK, EM_SETLIMITTEXT, 512, 0); 
     return true; 

     case WM_CLOSE: 
      DestroyWindow(hw); 
      return TRUE; 


     case WM_COMMAND: 
      HWND hCtrl; 
      int length; 
      wchar_t * text; 
      switch (LOWORD(wp)) 
      { 

       case IDCPROCESS: 

        nElements = 1; 
        hCtrl = GetDlgItem(hw, IDC_EDITMASK); 

        length = GetWindowTextLengthW(hCtrl);   
        if (length == 0) { 
         MessageBox(hw, L"Неверная маска", L"Ошибка", 0); 
         return FALSE; 
        } 

        text = (wchar_t*)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, length * sizeof(wchar_t) + sizeof(wchar_t)); 

        GetWindowTextW(hCtrl, text, length + sizeof(wchar_t)); 

        char *test = (char*)text; 

        int pos = 0; 
        int startPos = 0; 
        char dbg[2] = { 0 }; 
        while (pos <= length) { 
         dbg[0] = text[pos]; 
         OutputDebugStringA(dbg); // here i output the text by characters 
         if (text[pos] == ',' || pos == length) { 

          if(!szMasks) 
           szMasks = (wchar_t**)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(wchar_t*)*nElements); 
          else 
           szMasks = (wchar_t**)HeapReAlloc(hProcessHeap, HEAP_ZERO_MEMORY,szMasks, sizeof(wchar_t*)*nElements); 

          int bufferSize = pos - startPos; 
          szMasks[nElements - 1] = (wchar_t*)HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, (bufferSize + 2) * sizeof(wchar_t)); 
          if(bufferSize % sizeof(wchar_t) != 0) 
           bufferSize++; 
          int copyLength = bufferSize/sizeof(wchar_t); 

          wcsncpy(szMasks[nElements - 1], text + startPos, copyLength); 
          OutputDebugStringW(szMasks[nElements - 1]); 
          OutputDebugStringW(L"\r\n"); 

          nElements++; 
          startPos = pos+1; 

         } 

         pos++; 
        } 

        searchMasks.count = nElements-1; 
        searchMasks.szMasks = szMasks; 

        HeapFree(hProcessHeap, 0, text); 
        DestroyWindow(hw); 

        return TRUE; 


      } 
      break; 



    case WM_DESTROY: 
      PostQuitMessage(0); 
      return TRUE; 
    } 

    return FALSE; 
} 

Donc, si j'entrer du texte russe par exemple, je reçois la chaîne large valide, tout c'est ok. Si je passe à l'anglais, et l'entrée disons "mot", je reçois le tampon dans le texte qu'il n'est pas formé comme une chaîne large, je m'attends à ce qu'il soit: "w \ 0o \ 0r \ 0d" mais je reçois "mot"

Mais j'obtiens une chaîne normale char* à la place, ce qui est vraiment mauvais parce que j'ai besoin d'analyser le texte selon une règle, en recherchant le caractère ',' et en copiant les données dans l'autre tampon, en utilisant wcsncpy, donc je dois toujours avoir une bonne chaîne formatée wchar_t*. Y at-il un moyen de traiter cela, et pourquoi GetWindowTextW ne forme pas une chaîne large appropriée? Je compile mon projet en utilisant UNICODE jeu de caractères, et non multi-octets.

MISE À JOUR DU CODE

char * test = (char*) text Donnez une chaîne ansi valide, si l'entrée seulement chracters latin dans la zone d'entrée, pas un bon formatage wchar_t*

+1

Comment regardez-vous 'text' que vous pouvez dire que ce n'est pas' w \ 0o \ 0r \ 0d'? – andlabs

+0

Nous ne savons pas ce que * hCtrl * est. S'il vous plaît fournir toutes les informations requises. Dans ce cas: le handle référence-t-il un contrôle? Dans le même processus ou un autre processus? Est-ce un contrôle standard ou un contrôle personnalisé? Dans le cas où il s'agit d'un contrôle personnalisé, affichez le code correspondant. – IInspectable

+0

@andlabs i sortie dans une boucle for – Vlad

Répondre

2

Une chaîne de style C est une séquence de caractères, terminée par un caractère NUL. Tout élément du premier caractère NUL n'est pas considéré comme faisant partie de la chaîne.

Lorsque vous appelez OutputDebugStringA avec un argument de type char[2], où le premier élément est un caractère ASCII et le second caractère est \0 il est interprété comme une chaîne de longueur 1. Par conséquent, vous imprimez les caractères ASCII seulement.

Vous avez affaire à des chaînes de caractères larges. Votre logique pour déduire le type de chaîne est incorrecte.


Voilà comment un caractère ASCII codé UTF-16LE sera stocké dans votre scénario donné.

+0

J'ai vérifié dans le débogueur, chaque fois que' dbg [0 ] 'n'est pas un' \ 0'. Tellement le mot "mot" que je reçois exactement 4 itérations – Vlad

+0

@yasofiz: Bien sûr 'dbg [0]' est différent de '0' lorsqu'il s'agit de caractères ASCII, codés comme UTF-16LE. C'est 'dbg [1]' c'est '' 0''. Et oui, il faut 4 itérations pour parcourir plus de 4 unités de code. Pourquoi cela vous surprend-il? – IInspectable

+0

je vois maintenant j'ai foiré grand temps. – Vlad

2

votre variable text est un pointeur wchar_t (même si la la définition n'est pas montrée), donc bien sûr toute tentative de l'afficher montrera des caractères entiers UTF-16. Vous obtiendrez uniquement les caractères \0 intégrés si vous inspectez un tampon char *, car il casse toutes les unités wchar_t en plusieurs parties.

+0

Je sortie dans la boucle pour tester, voir mon code mis à jour – Vlad

+0

@ yasofiz ce code est presque impossible à suivre. Je vois que vous êtes en train de déclarer un test de char, mais je ne vois nulle part où vous l'utilisez. –

+0

Je l'ai placé là pour tester, si le «texte» serait un format large approprié. Je peux voir que la valeur de test de char * est "mot", ce qui signifie que ce n'est pas w \ 0o \ 0r \ 0d comme je l'attend – Vlad

0

Basé sur le code mis à jour ...

Lorsque vous appelez OutputDebugStringA pour l'un des octets qui devrait être zéro, vous ne verrez aucune sortie. Vous avez effectivement imprimé une chaîne vide. Donc, il apparaîtra comme si les octets zéro ne sont pas là, mais ils le sont.

+0

Mais je vois dans le débogueur que 'dbg [0]' n'est pas zéro, et le compteur s'arrête à exactement '4' pour le texte" mot " – Vlad

+0

aussi vous voyez dans mon code une ligne' char * test = (char *) texte; 'si je saisis un texte" mot "et point de rupture, ligne Je peux voir que la valeur de 'char * test' est" mot ", ce qui signifie que ce n'est pas" w \ 0o \ 0r \ 0d "comme je l'attend – Vlad