Results 1 to 13 of 13

Thread: Font.Charset voor bv Tmemo. Wat doet dit eigenlijk?

  1. #1

    Font.Charset voor bv Tmemo. Wat doet dit eigenlijk?

    Hoi,
    Ik had eigenlijk verwacht dat het setten van de Font.Charset voor bv een TMemo de characters met ascii code van 128 tot 255 (waarvan het eigenlijke getoonde teken afhangt van de codepage) getoond zouden worden volgens die charset.
    Niks is minder waar. Enkel de 'Symbol' charset is duidelijk anders (uitgenomen bij Richedit). Soms verander de fontgrootte een beetje.

    Om de juiste characters (CP afhankelijk) te tonen moet ik manueel (in de code) de omzetting doen naar Unicode (widestring).

    Mijn code is beperkt (dit is de code zonder manueele omzetting):
    Code:
    S := '';
      for I := 128 to 255 do // extended ascii characters
      begin
        S := S + chr(I);
      end;
    
      Memo1.Lines.Add(S);
      Memo1.Lines.Add('------');   
    
      RichEdit1.Lines.Add(S);
      RichEdit1.Lines.Add('------');
    Bovenstaande code toont dus altijd dezelfde tekst in de memo en de richedit.
    Om de goede teksten (dus CP afhankelijk) te tonen moet ik het volgende doen:

    Code:
    S2 := StringToWideStringCP(S, CodePage_); // <--------------- omzetting naar unicode
      Memo1.Lines.Add(S2);
      Memo1.Lines.Add('------');  
    
      RichEdit1.Lines.Add(S2);
      RichEdit1.Lines.Add('------');
    Om compleet te zijn:
    Code:
    function StringToWideStringCP(const S: RawByteString; CP: Integer): UnicodeString;
    var
      P: PAnsiChar;
      pw: PWideChar;
      I, J: Integer;
    begin
      Result := '';
    
      if S = '' then
        Exit;
    
      P := @S[1];
      I := MultiByteToWideChar(CP, 0, P, Length(S), nil, 0);
      if I <= 0 then
        Exit;
    
      SetLength(Result, I);
      pw := @Result[1];
      J := MultiByteToWideChar(CP, 0, P, Length(S), pw, I);
    
      if I <> J then
        if I < J then SetLength(Result, I)
        else if J < I then SetLength(Result, J);
      //  SetLength(Result, Min(I, J));
    
    end;
    Mijn vraag is nu: waar wordt die Font.Charset eigenlijk voor gebruikt? Ik denk dat ik duidelijk e.e.a. niet heel begrijp.

    Ik gebruik Delphi 10.1.

    Alvast bedankt!
    Last edited by Dany; 12-Nov-23 at 21:32.

  2. #2
    Ik denk dat je theorie in basis wel klopt. Een font kan meerdere character sets ondersteunen, en met die property geef je aan welke je wilt gebruiken.

    Maarrr, dat werkt dus alleen als je daadwerkelijk met ansistrings, single byte strings, werkt. In de praktijk is dat niet zo. string is al multi-byte, en dat geldt ook voor de onderliggende API's voor de memo en/of richedit.
    Dat betekent dus dat je string al omgezet is naar unicode voordat je berhaupt de font glyphs gaat tekenen, dus ik denk dat die hele code page dan niet meer van toepassing is. Is m'n vermoeden, ik heb hier weinig ervaring mee.
    1+1=b

  3. #3
    Maarrr, dat werkt dus alleen als je daadwerkelijk met ansistrings, single byte strings, werkt. In de praktijk is dat niet zo. string is al multi-byte, en dat geldt ook voor de onderliggende API's voor de memo en/of richedit.
    Kijk wat ik hier nog heb gevonden: https://www.nldelphi.com/showthread....hlight=charset, dat zou het inderdaad bevestigen.

    In mijn geval bevat de multi byte string S wel degelijk nog altijd de ansistring tekens. Je zult dus gelijk hebben: Tmemo denkt te maken te hebben met een Unicode string, terwijl het gewoon een extended ascii string is...

    Dit zijn de codes van S (v麑r manuele omzetting), met charset van TMemo en TRichedit op 'Cyrillic" (charset=204, codepage=1251):
    De zichtbare string in de memo:
    €‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ*﹜ㄓ它夾帚型*悖停 眾斯須號獄播噶擱藏霰っ圴佮迓玿旂衲欶趹欹詘棰葮摵 麧緗鴇膹擨闀貘覷鏷禴矙
    de codes:
    128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    p.s.: de tekens die getoond worden v麑r de manuele omzetting zijn wel degelijk die uit de unicode tabellen voor codes 128 tot 255.

    Dit zijn de codes na manuele omzetting door "StringToWideStringCP(S, CodePage_);" met charset = 'Cyrillic" (charset=204, codepage=1251) (S2 in de code)
    de string in de memo:
    ?Ѓ???????????Ќ?Џђ????????????ќ??*ЎўЈҐ戍ЁЄ型*Ї停 Ііґ絮ё№єјЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвг дежзийклмнопрстуфхцчшщъыьэюя
    de codes:
    63 1027 63 63 63 63 63 63 63 63 63 63 63 1036 63 1039 1106 63 63 63 63 63 63 63 63 63 63 63 63 1116 63 63 160 1038 1118 1032 164 1168 166 167 1025 169 1028 171 172 173 174 1031 176 177 1030 1110 1169 181 182 183 1105 8470 1108 187 1112 1029 1109 1111 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103

    Je kan inderdaad zien dat bijna alle tekens omgezet zijn naar een andere code.
    Ik deed alle testen met de Tahoma font.

    Ter vervollediging nog wat van m'n Delphi code:
    Code:
    function StrCharsetToInt(CharSet: string): Byte;
    begin
      Result := DEFAULT_CHARSET;
      if CharSet = 'ANSI' then Result := ANSI_CHARSET else
        if CharSet = 'Default' then Result := DEFAULT_CHARSET else
          if CharSet = 'Symbol' then Result := SYMBOL_CHARSET else
            if CharSet = 'Shiftjis' then Result := SHIFTJIS_CHARSET else
              if CharSet = 'Hangeul' then Result := HANGEUL_CHARSET else
                if CharSet = 'Johab' then Result := JOHAB_CHARSET else
                  if CharSet = 'GB2312' then Result := GB2312_CHARSET else
                    if CharSet = 'Chinese BIG5' then Result := CHINESEBIG5_CHARSET else
                      if CharSet = 'Greek' then Result := GREEK_CHARSET else
                        if CharSet = 'Turkish' then Result := TURKISH_CHARSET else
                          if CharSet = 'Vietnamese' then Result := VIETNAMESE_CHARSET else
                            if CharSet = 'Hebrew' then Result := HEBREW_CHARSET else
                              if CharSet = 'Arabic' then Result := ARABIC_CHARSET else
                                if CharSet = 'Baltic' then Result := BALTIC_CHARSET else
                                  if CharSet = 'Cyrillic' then Result := RUSSIAN_CHARSET else
                                    if CharSet = 'Thai' then Result := THAI_CHARSET else
                                      if CharSet = 'EastEurope' then Result := EASTEUROPE_CHARSET;
    end;
    
    var Strngs, Strngs2: TStrings;
      CharSet_, CodePage_: UInt;
    
    function TranslateCharsetInfo(lpSrc: PDWORD; var lpCs: TCharsetInfo; dwFlags: DWORD): BOOL; stdcall; external gdi32 name 'TranslateCharsetInfo';
    
    function CharSetToCodePage(ciCharset: UINT): Cardinal;
    var
      C: TCharsetInfo;
    begin
      if ciCharset = DEFAULT_CHARSET then Result := GetACP else //added by adenry - IMPORTANT! - fixes a bug - Otherwise Default charset can't be used properly
      begin
        TranslateCharsetInfo(PDWORD(ciCharset), C, TCI_SRCCHARSET);
        Result := C.ciACP;
      end;
    end;
    ----------------
    Show routine.
    var CharSet_, CodePage_: UInt;
    
      Charset_ := StrCharsetToInt(ListBox2.Items[ListBox2.ItemIndex]);
      CodePage_ := CharSetToCodePage(CharSet_);
    
      Memo1.Font.Charset := CharSet_;  
      RichEdit1.Font.Charset := CharSet_;
    
      S := '';
      for I := 128 to 255 do
      begin
        S := S + chr(I);
      end;
    
      Memo1.Lines.Add(S);
      Memo1.Lines.Add('------');
      Dumpstring(S);
      Memo1.Lines.Add('-----');
    
      RichEdit1.Lines.Add(S);
      RichEdit1.Lines.Add('------');
    
      S2 := StringToWideStringCP(S, CodePage_); // <---- manuele omzetting van extended ascii naar unicode.
      Memo1.Lines.Add(S2);
      Memo1.Lines.Add('------');
      Dumpstring(S2);
    
      RichEdit1.Lines.Add(S2);
      RichEdit1.Lines.Add('------');
    Ook de TRichEdit toont zowel S als S2 goed (op een paar characters na).
    Last edited by Dany; 13-Nov-23 at 20:17.
    Vriendelijke groeten,
    Dany

  4. #4
    Even een testje gedaan met RawByteString, met een al even verrassend resultaat (voor mij dan toch):
    Code:
    var RStr: RawByteString;
      RStr := '';
      for I := 128 to 255 do
      begin
        RStr := RStr + chr(I);
      end;
    Als ik dan een dump doe levert dat op:
    63 129 63 63 63 63 63 63 63 63 63 63 63 141 63 143 144 63 63 63 63 63 63 63 63 63 63 63 63 157 63 63 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    terwijl ik gewoon weer de getalletjes van 128 tot 255 verwacht....
    RawByteString doet dus wel degelijk iets met conversie (eigenlijk geen conversie, gewoon de rare codes vervangen door vraagteken), terwijl dat volgens de documentatie niet het geval zou moeten zijn, of zie ik weeral iets over het hoofd (zoals gewoonlijk als het iets unicode-achtigs betreft)?
    Last edited by Dany; 14-Nov-23 at 18:22.
    Vriendelijke groeten,
    Dany

  5. #5
    Quote Originally Posted by Dany View Post
    Als ik dan een dump doe levert dat op:
    terwijl ik gewoon weer de getalletjes van 128 tot 255 verwacht....
    RawByteString doet dus wel degelijk iets met conversie (eigenlijk geen conversie, gewoon de rare codes vervangen door vraagteken), terwijl dat volgens de documentatie niet het geval zou moeten zijn, of zie ik weeral iets over het hoofd (zoals gewoonlijk als het iets unicode-achtigs betreft)?
    Het is niet RawByteString die de conversie doet maar jouw +Chr().

    Chr is een Unicode character en dan wordt er dus tijdelijk een Unicodestring van gemaakt.

    Probeer dit maar eens:
    Delphi Code:
    1. var
    2.   RStr: RawByteString;
    3.   I: Integer;
    4. begin
    5.   RStr := '';
    6.   for I := 128 to 255 do
    7.   begin
    8.     RStr := RStr + AnsiChar(I); // <- !!! AnsiChar
    9.   end;

    Je mag natuurlijk ook gewoon #1, #2 etc aan de RawString toevoegen. Zolang je maar geen Unicode functie gebruikt.

  6. #6

  7. #7
    Quote Originally Posted by rvk View Post
    Het is niet RawByteString die de conversie doet maar jouw +Chr().

    Chr is een Unicode character en dan wordt er dus tijdelijk een Unicodestring van gemaakt.

    Probeer dit maar eens:
    Delphi Code:
    1. var
    2.   RStr: RawByteString;
    3.   I: Integer;
    4. begin
    5.   RStr := '';
    6.   for I := 128 to 255 do
    7.   begin
    8.     RStr := RStr + AnsiChar(I); // <- !!! AnsiChar
    9.   end;

    Je mag natuurlijk ook gewoon #1, #2 etc aan de RawString toevoegen. Zolang je maar geen Unicode functie gebruikt.
    Nu begrijp ik er nog minder van (test met AnsiChar):
    --Ansichar Rstr----
    8364 129 8218 402 8222 8230 8224 8225 710 8240 352 8249 338 141 381 143 144 8216 8217 8220 8221 8226 8211 8212 732 8482 353 8250 339 157 382 376 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

    Zelfde resultaat met #128#129 etc.

    Blijkbaar wordt hier toch een vertaling van codepage 1252 (charset 0) gedaan naar Unicode charcters. Code 128 (het Euroteken in CP 1252) wordt vertaald naar code 8364 (het Eutoteken in Unicode U+20AC).
    Last edited by Dany; 15-Nov-23 at 13:38.
    Vriendelijke groeten,
    Dany

  8. #8
    Quote Originally Posted by Dany View Post
    Nu begrijp ik er nog minder van (test met AnsiChar):
    --Ansichar Rstr----
    8364 129 8218 402 8222 8230 8224 8225 710 8240 352 8249 338 141 381 143 144 8216 8217 8220 8221 8226 8211 8212 732 8482 353 8250 339 157 382 376 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255

    Zelfde resultaat met #128#129 etc.
    Hoe kon jij aan dat resultaat??????
    Als je dat met code doet... laat die code dan eens zien (want daar kan ook weer conversie komen).

    Ook in de debug kan er een conversie optreden.

  9. #9
    Hoe kon jij aan dat resultaat??????
    Als je dat met code doet... laat die code dan eens zien (want daar kan ook weer conversie komen).
    Code:
    RStr := '';
      for I := 128 to 255 do
      begin
        RStr := RStr + Ansichar(I);
      end;
    
      Memo1.Lines.Add('--Ansichar Rstr----');
      DumpString(Rstr);
      Memo2.Lines.Add(RStr);
      Memo2.Lines.Add('---');
    
      RStr := #128#129#130#131#132#133; // ....
    
      Memo1.Lines.Add('--Ansichar Rstr met #...----');
      DumpString(Rstr);
      Memo2.Lines.Add(RStr);
      Memo2.Lines.Add('---');
    Jij hebt blijkbaar hetzelfde resultaat als ik volgens jouw evaluate/modify window:
    *﹜ㄓ它夾帚型*悖停 眾斯須號獄播噶擱藏霰っ圴佮迓玿旂衲欶趹欹詘棰葮摵 麧緗鴇膹擨闀貘覷鏷禴矙

    De dumpstring (toont de codes) procedure die ik gebruik:
    Code:
    procedure TForm1.DumpString(str: string);
    var I: integer;
        S: string;
    begin
      S := '';
      for I := 1 to length(Str) do S := S + inttostr(ord(Str[I])) + ' ';
      Memo1.Lines.Add(S);
    end;
    Last edited by Dany; 15-Nov-23 at 15:47.
    Vriendelijke groeten,
    Dany

  10. #10
    En waar en hoe is DumpString gedefinieerd?
    Gebruikt die een String of RawByteString ?

    Want als die weer een string gebruikt dan krijg je daar ook weer conversie.

    En Memo2.Lines.Add(RStr) gaat ook de RStr weer omzetten naar (Unicode)String.

    Als je met RawByteString wilt werken dan moet je er ook zeker van zijn dat je dat overal doet.
    En eventueel het resultaat in je uiteindelijke code als AnsiString met de juiste codepage gebruiken.

  11. #11
    De dumpstring (toont de codes) procedure die ik gebruik:
    Code:
    procedure TForm1.DumpString(str: string);
    var I: integer;
        S: string;
    begin
      S := '';
      for I := 1 to length(Str) do S := S + inttostr(ord(Str[I])) + ' ';
      Memo1.Lines.Add(S);
    end;
    Ik krijg geen conversie als ik met een gewone string werk:
    Code:
      S := '';
      for I := 128 to 255 do
      begin
        S := S + chr(I);
      end;
    
      Memo1.Lines.Add(S);
      Memo1.Lines.Add('------');
      Dumpstring(S);
      Memo1.Lines.Add('-----');
    Resultaat:
    *﹜ㄓ它夾帚型*悖停眾斯須號獄播噶擱藏霰っ圴佮迓玿 眑婭笫崷窙嗲睧颬睼麧緗鴇膹擨闀貘覷鏷禴矙
    ------
    128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    Last edited by Dany; 15-Nov-23 at 15:56.
    Vriendelijke groeten,
    Dany

  12. #12
    Quote Originally Posted by Dany View Post
    De dumpstring (toont de codes) procedure die ik gebruik:
    Code:
    procedure TForm1.DumpString(str: string);
    Als je het doet met een RawByteString dan moet je het uiteraard wel zo doen:

    Delphi Code:
    1. procedure TForm1.DumpString(str: rawbytestring);

    Resultaat:

    Memo1
    128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
    Prima toch ??

  13. #13
    Inderdaad. Nu zie ik het. Welbedankt!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •