2013-03-12 7 views
5

Sagen Sie mir bitte, warum ich diese Fragen bekommen:GetClipboardData (CF_UNICODETEXT);

  • wenn Zwischenablage Unicode-Zeichen (e.q. Russisch) enthält bekomme ich nur das erste Wort ausgewählt. Erstes Wort vor "Leerzeichen".

  • Wenn die Zwischenablage keine Unicode-Zeichen enthält (nur Englisch), erhalte ich das erste Zeichen des ausgewählten Textes.

Get Text ausgewählt:

CStringA getClipboard() 
{ 
    CStringA strData; 

    if (OpenClipboard(NULL)){ 

     HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT); 
     char *pchData = (char*)GlobalLock(hClipboardData); 
     strData = pchData; 
     GlobalUnlock(hClipboardData); 
     CloseClipboard(); 

    } 
    return strData; 
} 

Set Text:

bool setClipboard(CStringA textToclipboard) 
{ 
    bool success = true; 

    if (OpenClipboard(NULL)){ 

     EmptyClipboard(); 
     HGLOBAL hClipboardData; 
     size_t size = (textToclipboard.GetLength()+1) * sizeof(TCHAR); 
     hClipboardData = GlobalAlloc(NULL, size); 
     TCHAR* pchData = (TCHAR*)GlobalLock(hClipboardData); 
     memcpy(pchData, LPCTSTR(textToclipboard.GetString()), size); 
     SetClipboardData(CF_UNICODETEXT, hClipboardData); 
     GlobalUnlock(hClipboardData); 
     CloseClipboard(); 
    } 

    return success; 

} 

einfach und legen Sie den Inhalt der Zwischenablage erhalten.

CStringA str = getClipboard(); 
setClipboard(str); 
+2

CStringA ist eine ANSI-Zeichenfolge - für UNICODE benötigen Sie CStringW. –

+0

Funktioniert nicht. Ich erhalte Symbole B5: AB und seltsame "Ecken" – user1537809

+0

Ist nicht 'CF_UNICODETEXT' UTF-16, d. H. Die Standardzeichenfolge' W', was bedeutet, dass für Standard-ASCII nur ein Zeichen erhalten wird. – Petesh

Antwort

9

CF_UNICODETEXT Anwendungen UTF-16. Unter Windows wchar_t werden Datenelemente für UTF-16 verwendet, aber Ihr Code verwendet stattdessen char. CStringA ist nicht kompatibel mit UTF-16. Sie stimmen die Daten in beiden Funktionen nicht überein, deshalb erhalten Sie nicht die Ergebnisse, die Sie erwarten.

Eine Lösung ist CStringW statt CStringA zu verwenden:

CStringW getClipboard() 
{ 
    CStringW strData; 

    if (OpenClipboard(NULL)) 
    { 
     HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT); 
     if (hClipboardData) 
     { 
      WCHAR *pchData = (WCHAR*) GlobalLock(hClipboardData); 
      if (pchData) 
      { 
       strData = pchData; 
       GlobalUnlock(hClipboardData); 
      } 
     } 
     CloseClipboard(); 
    } 
    return strData; 
} 

bool setClipboard(CStringW textToclipboard) 
{ 
    bool success = true; 

    if (OpenClipboard(NULL)) 
    { 
     EmptyClipboard(); 
     size_t size = (textToclipboard.GetLength()+1) * sizeof(WCHAR); 
     HGLOBAL hClipboardData = GlobalAlloc(NULL, size); 
     if (hClipboardData) 
     { 
      WCHAR* pchData = (WCHAR*) GlobalLock(hClipboardData); 
      if (pchData) 
      { 
       memcpy(pchData, (WCHAR*) textToclipboard.GetString(), size); 
       GlobalUnlock(hClipboardData); 
       SetClipboardData(CF_UNICODETEXT, hClipboardData); 
      } 
     } 
     CloseClipboard(); 
    } 
    return success; 
} 

Wenn Sie mit CStringA haften müssen, dann entweder:

  1. Verwendung CF_TEXT statt CF_UNICODETEXT und die Zwischenablage Griff Umwandlungen lassen zwischen Ansi und Unicode für Sie:

    CStringA getClipboard() 
    { 
        CStringA strData; 
    
        if (OpenClipboard(NULL)) 
        { 
         HANDLE hClipboardData = GetClipboardData(CF_TEXT); 
         if (hClipboardData) 
         { 
          CHAR *pchData = (CHAR*) GlobalLock(hClipboardData); 
          if (pchData) 
          { 
           strData = pchData; 
           GlobalUnlock(hClipboardData); 
          } 
         } 
         CloseClipboard(); 
        } 
        return strData; 
    } 
    
    bool setClipboard(CStringA textToclipboard) 
    { 
        bool success = true; 
    
        if (OpenClipboard(NULL)) 
        { 
         EmptyClipboard(); 
         size_t size = (textToclipboard.GetLength()+1) * sizeof(CHAR); 
         HGLOBAL hClipboardData = GlobalAlloc(NULL, size); 
         if (hClipboardData) 
         { 
          CHAR* pchData = (CHAR*) GlobalLock(hClipboardData); 
          if (pchData) 
          { 
           memcpy(pchData, (CHAR*) textToclipboard.GetString(), size); 
           GlobalUnlock(hClipboardData); 
           SetClipboardData(CF_TEXT, hClipboardData); 
          } 
         } 
         CloseClipboard(); 
        } 
        return success; 
    } 
    
  2. convert nach/von UTF-16 manuell bei der Verwendung von CF_UNICODETEXT:

    CStringA getClipboard() 
    { 
        CStringW strData; 
    
        if (OpenClipboard(NULL)) 
        { 
         HANDLE hClipboardData = GetClipboardData(CF_UNICODETEXT); 
         if (hClipboardData) 
         { 
          WCHAR *pchData = (WCHAR*) GlobalLock(hClipboardData); 
          if (pchData) 
          { 
           strData = pchData; 
           GlobalUnlock(hClipboardData); 
          } 
         } 
         CloseClipboard(); 
        } 
    
        return CStringA((WCHAR*)strData.GetString()); 
    } 
    
    bool setClipboard(CStringA strData) 
    { 
        CStringW textToclipboard((CHAR*)strData.GetString()); 
        bool success = true; 
    
        if (OpenClipboard(NULL)) 
        { 
         EmptyClipboard(); 
         size_t size = (textToclipboard.GetLength()+1) * sizeof(WCHAR); 
         HGLOBAL hClipboardData = GlobalAlloc(NULL, size); 
         if (hClipboardData) 
         { 
          WCHAR* pchData = (WCHAR*) GlobalLock(hClipboardData); 
          if (pchData) 
          { 
           memcpy(pchData, (WCHAR*) textToclipboard.GetString(), size); 
           GlobalUnlock(hClipboardData); 
           SetClipboardData(CF_UNICODETEXT, hClipboardData); 
          } 
         } 
         CloseClipboard(); 
        } 
        return success; 
    } 
    

Eine andere Lösung ist CString zu verwenden, anstatt entweder CStringA oder CStringW und verwenden dann CF_TEXT oder CF_UNICODETEXT je nachdem, ob TCHAR ist Ansi oder Unicode:

+0

Wow! Vielen Dank. Ich ändere CStringA in CStringW und char * in WCHAR * und es funktioniert perfekt! Mit Englisch alle Sprachen! Vielen Dank! – user1537809

+0

Schön erklären danke .. –

5

sind Beide Unicode ...

Aber in Unicode, mehr als ein Byte ein Zeichen darstellt. Zum Beispiel werden vielleicht 2 Bytes für ein Zeichen verwendet. Deshalb:

Wenn es Russisch ist, ist die Zeichenfolge wie

              '\0' 
                  ---- 
0x04 0x3F 0x04 0x40 0x04 0x38 0x04 0x32 0x04 0x35 0x04 0x42 0x00 0x20 
~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ 
    п   р   и  в   е   т  space 

Es bis Raum liest.

Wenn es Englisch ist, ist die Zeichenfolge wie

'\0' 
---- 
0x00 0x48 0x00 0x65 0x00 0x6C 0x00 0x6C 0x00 0x6F 0x00 0x20 
~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ ~~~~~~~~~ 
    H   e   l  l   o  space 

Es hat nichts liest. (Wenn Sie zum ersten Mal lesen, ist es wegen der Reihenfolge der Speicherung von Bytes, LE oder BE)

Hinweis: Vielleicht Präzision Ich bin nicht in Worte wählen (Unicode, UTF, ...)

+0

Vielen Dank. Aber bitte erkläre mir, wie ich es benutzen kann. – user1537809

+0

Vielleicht ist die Terminologie falsch (ich weiß es nicht oder interessiert mich), aber die Erklärung ist großartig. Extra Punkte für die Diagramme. :-) – enhzflep

+0

Ok, ich versuche diese Zeile zu ändern: strData = pchData; Ich brauche eine andere Konvertierung? – user1537809