Avatar billede ullesan Nybegynder
22. september 2005 - 13:14 Der er 19 kommentarer og
1 løsning

Forskyde tekst

Hej

Følgende billede viser et label med borderstyle sat til fixedsingle og font størrelse sat til 72.
http://users.cybercity.dk/~dsl53379/t.jpg

Den røde firkant angiver afstanden mellem label venstre top og tekst venstre top.
Det jeg gerne kunne tænke mig er at forskyde T'et helt op til label venstre top, men hvordan gør jeg det?... Ved forskellige skriftstørelser er afstanden forskellig, så jeg kan ikke helt hardcode mig ud af det.

Jeg extender Label og arbejder med onPaint() metoden, men kan ikke rigtig komme videre

protected override void OnPaint(PaintEventArgs e) {
    Brush b = new SolidBrush(this.ForeColor);
    e.Graphics.DrawString(this.Text, this.Font, b, 0,0);
}


Koordinaterne 0,0 hjælper ikke, men hvis jeg angiver minus koordinater så flytter den sig, men igen jeg skal gerne kunne bruge løsningen ved alle skriftstørelser

Nogen der har en ide til hvordan det kan takles?

mvh
ullesan
Avatar billede bitsch Nybegynder
22. september 2005 - 22:22 #1
Det tror jeg faktiskt ikke at du kan. Problemet er at det ekstra space såvidt jeg ved er defineret inde i fonten, så uanset hvordan du laver measure string får du lidt luft omkring teksten, afhængigt af den valgte font.

Jeg har dog lidt input alligevel.

Husk at pens, og brushes bør disposes! dette klares flottest med et using statement. Efterfølgende kode viser hvordan, samt viser en nyere anbefalet måde at skrive tekst til UI. Der kan nemlig være skaleringsproblemer ved anvendelsen af DrawString, som viser sig ved at spaces mellem karakterer kan blive mindre hvis teksten er lang.
En nyere og pænere metode er at anvende de nye renderer klasser.

      protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            string text = "Hello World";

            // Almindelig Draw String. Bemærk at using sikrer korrekt dispose af din brush!
            using (Brush brush = new SolidBrush(this.ForeColor))
            {
                StringFormat stringFormat = new StringFormat();
                stringFormat.Alignment = StringAlignment.Near;
                stringFormat.LineAlignment = StringAlignment.Near;

                e.Graphics.DrawString(text, this.Font, brush, 0, 0, stringFormat);
            }

            // Samme resultat, men pænere metode. Fjerner bl.a. eventuelle skaleringsproblemer i tekst.
            TextFormatFlags textFormatFlags = TextFormatFlags.Left | TextFormatFlags.Top;
            TextRenderer.DrawText(e.Graphics, text, this.Font, new Point(0, 0), this.ForeColor, this.BackColor, textFormatFlags);
        }
Avatar billede bitsch Nybegynder
22. september 2005 - 22:54 #2
Rent faktiskt ser det ud til at det tætteste du kan komme er som følger:

            string text = "Hello World";
            TextFormatFlags textFormatFlags = TextFormatFlags.Left | TextFormatFlags.Top | TextFormatFlags.NoPadding;
            TextRenderer.DrawText(e.Graphics, text, this.Font, new Point( 0, 0), this.ForeColor, textFormatFlags);

Men det løser desværre ikke dit problem helt. Spacingen er forskellig i højden ved forskellige fontstørrelser, men ser altid ud til at være to pixels til venstre.
Avatar billede bitsch Nybegynder
22. september 2005 - 22:57 #3
Personligt har jeg dog aldrig været udsat for et design hvor det har været nødvendigt at positionere teksten som du ønsker. Mellemrummet er jo til for at gøre teksten læsbar.
Avatar billede bitsch Nybegynder
22. september 2005 - 23:00 #4
Nb! Bemærk at DrawText kun er til UI. Skal du f.eks skrive til printer, er det stadig DrawString du skal bruge.
Avatar billede ullesan Nybegynder
22. september 2005 - 23:11 #5
Hmm, tjaa... Using kender jeg godt til, det var bare et midlertidig eksempel. Jeg kan ikke bruge TextRenderer da jeg kører med .NET 1.1. Brugen af stringformat hjælper heller ikke. Men hvis jeg kan bare kunne finde/beregne afstanden, så kan man godt flytte det helt op til hjørnet.

Fx ved font størelse 72 ms sans serif og med x = -23 y = -20 kommer den op til ventre hjørne. (x,y til drawstring metoden)


Jeg skal bruge det til en rapport designer, hvor jeg trækker labels rundt. Designeren skal senere gemme rapport siden ud til pdf (bruger itextsharp) hvor jeg bruger x/y koordinaterne fra labelen til at placere på pdfcanvas. Men måden itextsharp virker og det tomme afstand rundt om teksten i labelen, så ser det endelige rapport udskrift og det jeg ser på skærmen ikke ens ud... En smule forvirende :S

Jeg har dog fundet en halvdårlig løsning ved at bruge en textbox, hvor afstanden mellem højrekant og teksten inde i den, er mindre end ved hvis det var en label. Dog er afstanden fra textbox top til tekst top det samme som ved en label, øv!
Avatar billede bitsch Nybegynder
22. september 2005 - 23:25 #6
Ellers må du lave din egen measure string. Tegn teksten til en dummy bitmap og scan gennem blanke pixels i top og til venstre. Derved kan du beregne hvor meget du må flytte teksten. Umiddelbart en langsom og dårlig løsning, men trods alt mere dynamisk end blot at trække et tilfældigt antal pixels fra (Og du kan nøjes med at beregne det én gang).

Jeg skal nok prøve at grave lidt mere i den "rigtige" løsning, men jeg kan ikke love noget, jeg har dog de optimale forbindelser.
Avatar billede ullesan Nybegynder
22. september 2005 - 23:30 #7
Ja, det med bitmap tænkte jeg også på, men vil helst udskyde det så meget som muligt.
På forhånd tak for dit engagement ;)
Avatar billede bitsch Nybegynder
23. september 2005 - 17:04 #8
Du skal nok ikke udskyde det så meget. De foreløbige tilbagemældinger siger at det ikke er muligt på anden måde.
Avatar billede ullesan Nybegynder
23. september 2005 - 17:14 #9
Æv. Du nævnte at det ekstra space er defineret inde i fonten. Er der mulighed for at hente det ud derfra?... Er ved at kigge dokumentationen til font igennem, men har ikke kunne finde noget endnu. Det tætteste, uden at være tæt nok, jeg er kommet er GetHeight() metoden, hvor der står at det blanke spacing bliver lagt til karakter højde, men det er så igen det du skrev.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDrawingFontClassGetHeightTopic.asp
Avatar billede ullesan Nybegynder
23. september 2005 - 19:54 #10
Well... Jeg giver op. Du skal have tak for den tid du har brugt
Avatar billede bitsch Nybegynder
23. september 2005 - 20:15 #11
Nej GetHeight giver et tilsvarende dårligt resultat som MeasureString. Du må lave din egen MeasureString metode som scanner efter "blanke" pixels.
Jeg vil dog forsøge at støve lidt mere information op, men det vil nok tage nogle dage, da folk lige skal have tid til at svare på mit spørgsmål. Jeg forventer dog ikke at modtage noget mere brugbart.
Avatar billede bitsch Nybegynder
23. september 2005 - 21:03 #12
Ups! Jeg fandt en metode til at beregne spacing over fonten! Jeg mangler nu at finde en metode til at beregne spacing til venstre. Det du skal gå ind og rode med er beregninger vedrørende Font Metrics!


        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            string text = "Hello World";

            FontFamily fontFamily = new FontFamily(this.Font.Name);

            int emHeight = fontFamily.GetEmHeight(this.Font.Style);
            int decent = fontFamily.GetCellDescent(this.Font.Style);

            // The numbers returned by these methods are in font design units, so they are independent of the size and units of a particular Font object.
            int above = this.Font.Height * decent / emHeight;

            using (Brush brush = new SolidBrush(this.ForeColor))
            {
                StringFormat stringFormat = new StringFormat();
                stringFormat.Alignment = StringAlignment.Near;

                e.Graphics.DrawString(text, this.Font, brush, new PointF(0, -above), stringFormat);
            }

            // TODO: Find a way to remove the left spacing.
        }
Avatar billede bitsch Nybegynder
23. september 2005 - 21:04 #13
Nb StringFormat har ingen betydning i dette eksemple
Avatar billede bitsch Nybegynder
23. september 2005 - 21:27 #15
husk også lige...
            using (FontFamily fontFamily = new FontFamily(this.Font.Name))....

Smuttede lige i mit eksempel
Avatar billede ullesan Nybegynder
24. september 2005 - 12:13 #16
Jeg må have overset ovenstående link af frustration. Det ser ellers godt ud det du har lavet der, vil arbejde videre med det.
Avatar billede bitsch Nybegynder
26. september 2005 - 09:01 #17
Jeg har lavet en mindre bug... "above" skal være float ikke int! Bruges int kan der forekomme en enkelt pixel luft i toppen.
Avatar billede bitsch Nybegynder
28. september 2005 - 12:39 #18
I\'m back!

Det du skal gøre er som følger:

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            string text = \"Hello World\";

            using (FontFamily fontFamily = new FontFamily(this.Font.Name))
            {
                StringFormat stringFormat = new StringFormat();
                stringFormat.Alignment = StringAlignment.Near;

                // Example on drawing a string where the ink starts at the 0,0
                using (Brush brush = new SolidBrush(this.ForeColor))
                {
                    using (Pen pen = new Pen(brush))
                    {
                        float emSize = this.Font.Height;
                        Point origin = new Point(0, 0);

                        // First add the string to a path.
                        System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
                        path.AddString(text, this.Font.FontFamily, (int)this.Font.Style, emSize, origin, stringFormat);

                        // Then get the bounds for the path. This will tell you where the ink of the font sits
                        // relative to the origin regardless of the vagaries of fonts.
                        RectangleF textBounds = path.GetBounds();

                        // Draw the string according to the text bounds.
                        e.Graphics.DrawString(text, this.Font, brush, new PointF(-textBounds.X, -textBounds.Y), stringFormat);
                    }
                }
            }
        }
Avatar billede bitsch Nybegynder
28. september 2005 - 12:49 #19
Det du skal gøre er altså:

1) Adder din streng til en grafisk Path.
2) Få fat i bounds for denne path. Den returnerer et rectangle som netop omslutter strengens "blæk".
3) Kald din DrawString og brug pathen's bounds som offset.

Let ik? ;-)

(Jeg håber at du stadig er med på tråden)
Avatar billede ullesan Nybegynder
28. september 2005 - 22:48 #20
Jeg følger skam med på tråden... Det er rigtig nice det der. Takker mange gange for hjælpen og du må også takke de mennesker du kender, der har hjulpet til.

Jo, det er egentlig meget nemt når man kigger på det - gælder bare om at vide hvor man skal kigge c",)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester