Autor Beitrag
rushifell
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Di 24.01.12 02:58 
Hallo,

Ich programmiere z.Z. mit Delphi2005 und zur Darstellung von Unicode benutze ich die TntUnicode-Controls. Der WideString wird in einer TEdit-Komponenten angezeigt. Nun möchte ich den WideString in der dargestellten Reihenfolge der Zeichenkette (also immer von links nach rechts) an einer bestimmten Stelle in zwei Teile trennen. Gibt es dafür eine einfache Lösung?

EDIT: Das Trennen wird wahrscheinlich doch nicht das Problem sein. Allerdings möchte ich gerne die einzelnen Zeichen des WideStrings wenn möglich in der richtigen Reihenfolge in einem StringGrid anzeigen.

Viele Grüße
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: Di 24.01.12 14:08 
Du könntest Copy verwenden. Ich hab's nicht getestet, aber soweit ich gelesen habe, geht die Funktion auf die Elemente und nicht auf die Bytes.
Copy(Str, n, 1) wird dir also immer das nte Zeichen zurückliefern.
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mi 25.01.12 02:07 
baka0815 hat folgendes geschrieben:
Copy(Str, n, 1) wird dir also immer das nte Zeichen zurückliefern.

Danke. Die Funktionene Copy und Pos funktionieren einwandfrei, das ist mir im Nachhinein aufgefallen. Der WideString wird in der korrekten Reihenfolge geschrieben und auch angezeigt. Das Trennen ist also doch nicht das Problem. Das Problem ist, dass ich nicht weiss, wie der WideString in der visuellen Komponente dargestellt wird.

Interessant wird es nämlich bei Schriften, die von rechts-nach-links geschrieben werden. Diese werden nämlich wirklich von rechts-nach-links dargestellt. Hier ein Beispiel:
Zitat:
Normaler Text arabisch und nochmal normaler Text. //Geschriebene Reihenfolge
Normaler Text hcsibara und nochmal normaler Text. //Dargestellte Reihenfolge

Wenn ich den WideString nun mit For i:=1 to Length(WideString) durchlaufe, wird immer die geschriebene Reihenfolge zurückgeliefert.

Wenn ich nun jeden Buchstaben in der Zelle eines StringGrids anzeigen lasse, wird die "Geschriebene Reihenfolge" angezeigt, ich möchte jedoch die "Dargestellte Reihenfolge" anzeigen ;-)

Wahrscheinlich hab ich mich da zu sehr in etwas festgefahren.

Ich hab's jetzt vorläufig mit folgendem Ansatz gelöst:
Der WideString wird in UTF8 konvertiert. Dann überprüfe ich einfach für jedes Zeichen, um welche Schriftart es sich handelt und und sortiere den Text dementsprechend. Das funktioniertiert zwar, jedoch bin ich mir nicht sicher, ob der Text auch auf wirklich auf jedem PC bidirektional angezeigt wird. Außerdem funktioniert es natürlich nur für Schriftarten, die ich in meinem Programm aufgenommen habe. Ich bräuchte im Grunde eine allgemeine Möglichkeit herauszufinden, in welcher Richtung die Schrift dargestellt wird.

Hintergrund:
Ich möchte in meinem Programm, den Benutzer ein Zeichen wählen lassen, ab dem der String in zwei Teile getrennt wird. Vielleicht mache ich es doch so, dass einfach in einer Edit-Box das entsprechende Zeichen markiert wird, dann spar ich mir den ganzen Ärger :roll:

Edit

Hab gerade folgendes gefunden:
wiki hat folgendes geschrieben:

A language is described as Text direction RTL right to left if writing starts from the right of the page, and continues to the left. Right to left scripts are:
    Arabic alphabet - used for Arabic, Persian, Urdu and many other languages.
    Hebrew alphabet - used for Hebrew, Yiddish and some other Jewish languages.
    Syriac alphabet - used for varieties of the Syriac language.
    Thaana - used for Dhivehi.
    N'Ko script - used for several languages of Africa.

Die ersten vier unterstütze ich sowieso schon in meinem Programm. Ehrlichgesagt brauche ich normalerweise keine der Schriften, aber ich bin Perfektionist ;-) Und wenns wirklich nur die fünf sind, kann ich diese bidirektional anzeigen lassen. Vielleicht mache ich das ganze auch optional.

Viele Grüße
baka0815
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 489
Erhaltene Danke: 14

Win 10, Win 8, Debian GNU/Linux
Delphi 10.1 Berlin, Java, C#
BeitragVerfasst: Mi 25.01.12 12:51 
Vielleicht hilft dir dieser Blog-Eintrag bei deinem Problem?

Für diesen Beitrag haben gedankt: rushifell
rushifell Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 306
Erhaltene Danke: 14



BeitragVerfasst: Mi 25.01.12 20:36 
baka0815 hat folgendes geschrieben:
Vielleicht hilft dir dieser Blog-Eintrag bei deinem Problem?
Dafür gibts von mir ein dickes Danke! :-) Genau das hab ich gesucht und nicht gefunden. :beer:

GetStringTypeEx ist die Lösung.

Hier der Quelltext, falls es noch jemand braucht:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
..
..
Var LWideChars: array [WideChar] of Word; //global
...
{
LOCALE_USER_DEFAULT oder LOCAL_SYSTEM_DEFAULT bei GetStringTypeExW ignoriert
CT_CTYPE2 Retrieve bidirectional layout information.
}

Function FillCharList:Boolean;
Var lpSrcStr: WideChar;
    lpCharType: Word;
Begin
Result:=True;
For lpSrcStr :=Low(WideChar) to High(WideChar) do
  BEGIN
   lpCharType:=0;
     IF not(GetStringTypeExW(LOCALE_USER_DEFAULT, CT_CTYPE2,
            @lpSrcStr, SizeOf(lpSrcStr), lpCharType)) then
        BEGIN
         Result:=False;
         Break;
        END ELSE
         LWideChars[lpSrcStr] := lpCharType;
  END;
End;

{
Mögliche Ergebnisse:
 0 = undefinierte Richtung
 1 = links-nach-rechts
 2 = rechts-nach-links
 3 = beide Richtungen möglich
}

Function GetWriteDirection(Const S:WideChar):Byte;
Const C2_LEFTTORIGHT=$01;
      C2_RIGHTTOLEFT=$02;
Begin
Result:=0;
 IF (LWideChars[S] and C2_LEFTTORIGHT)<>0 then Inc(Result,1);
 IF (LWideChars[S] and C2_RIGHTTOLEFT)<>0 then Inc(Result,2);
End;

{
Beispiele:
+ und - => undefinierte Richtung
*       => beide Richtung
}

Procedure Beispiel;
Var CheckWChar:WideChar;
    WriteDirection:Byte;
Begin
IF FillCharList then //Einmalig beim Programmstart aufrufen
   BEGIN
    CheckWChar:='+';
    WriteDirection:=GetWriteDirection(CheckWChar);

    Case WriteDirection of
     0: ShowMessage('undefinierte Schreibrichtung');
     1: ShowMessage('links-nach-rechts');
     2: ShowMessage('rechts-nach-links');
     3: ShowMessage('beide Richtungen');
   END ELSE
   ShowMessage('Fehler');

End//Beispiel


Viele Grüße