[Delphi] DBEdit vol is vol

Pagina: 1
Acties:

  • Kluus
  • Registratie: Oktober 2003
  • Laatst online: 23:01

Kluus

Gang is alles

Topicstarter
Ik ben voor mijn werk bezig met een administratie tool in Delphi, en nu moet ik voor elkaar krijgen dat er niet meer in een tekstveld past dan dat ie breedt is (dus onafhankelijk van het aantal karakters (er kunnen minden M'en in dan i's)).

Is dit mogenlijk op een of andere manier, ik kan er namelijk nergens iets over vinden...

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

Wat heb je tot nu toe? In wat voor veld wordt het ingevoerd?

Je kan in een onchange van een TMemo bijv. vrij makkelijk de lengte bepalen en als het te lang is de undo aanroepen (bijv.). Een Tedit heeft een property om een max. lengte in karakters aan mee te geven.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Kluus
  • Registratie: Oktober 2003
  • Laatst online: 23:01

Kluus

Gang is alles

Topicstarter
Het veld is een DBEdit veld, die max lengte daarin is het aantal karakters, maar de limiet moet liggen op de lengte van de string in pixels in principe.

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

TjaBske schreef op maandag 13 december 2004 @ 16:39:
Het veld is een DBEdit veld, die max lengte daarin is het aantal karakters, maar de limiet moet liggen op de lengte van de string in pixels in principe.
Eeeh.. in pixels? Dat moet je me toch ff uitleggen waarom je dat zou willen? De lengte in pixels is namelijk niet evenredig met de lengte in karakters tenzij je een monospaced font gebruikt.

Maar de lengte in pixels van een stuk tekst met het huidige opmaak van het gebruikte canvas is uit te rekenen met TCanvas.TextWidth()

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Kluus
  • Registratie: Oktober 2003
  • Laatst online: 23:01

Kluus

Gang is alles

Topicstarter
Creepy schreef op maandag 13 december 2004 @ 17:02:
[...]

Eeeh.. in pixels? Dat moet je me toch ff uitleggen waarom je dat zou willen? De lengte in pixels is namelijk niet evenredig met de lengte in karakters tenzij je een monospaced font gebruikt.

Maar de lengte in pixels van een stuk tekst met het huidige opmaak van het gebruikte canvas is uit te rekenen met TCanvas.TextWidth()
Jah, zoiets had ik in eerste instantie ook. Maar de invoer wordt gebruikt op een website, en die moet precies per regel overeen komen met de invoer in het programma. Een monospaced font heb ik ook al voorgesteld, maar vind ie (en daar heeft ie natuurlijk wel gelijk in) minder mooi. (Ik weet het, moeilijk verhaal, maar ik vind t zelf ook nogal lastig uitleggen allemaal ;)).

Ik denk dat het er op neer gaat komen om gewoon zelf ff een stukje te schrijven met dat TCanvas gebeuren, ik ga het in ieder geval proberen! Bedankt :).

  • Loesje
  • Registratie: Januari 2000
  • Laatst online: 02-07-2025
Je kan ook simpelweg de een onkey-event schrijven waarin je eerst kijkt of de string te lang is (met TCanvas.TextWidth) en als dat zo is, verander je de key die ingetoetst is in #0.

(Wel controleren op niet-alfanumerieke karakters enzo, maar daar kom je wel uit)

Leven is meervoud van lef


  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 00:34

alienfruit

the alien you never expected

Kijk eens na GetTextMetrics, en DrawText op MSDN. Volgens zijn er wel een paar wrappers in de VCL hiervoor. Maar met DrawText kun je iig een TRect terugkrijgen zo dat je kan controleren of de huidige tekst in een bepaalde kader/rectangle past.

TEXTMETRICS
Met onder andere deze informatie kun een leuke editor maken ;)

Verwijderd

code:
1
2
3
4
5
6
7
8
9
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  var
    cText: String;
  begin
    cText := Edit1.Text + Key;
    Form1.Font := Edit1.Font;
    If Form1.Canvas.TextWidth(cText)+7 > Edit1.Width then 
      Key:=#0;
  end;


Een editbox heeft zelf geen canvas. Ik gebruik hiervoor het canvas van het form. Dit heeft als nadeel dat het form hetzelfde font moet hebben als de editbox. Daarnaast moet je er een aantal pixels bij optellen (de +7 werkt voor een normale editbox) om de borders van de editbox etc. mee te rekenen.

Bovenstaande code werkt perfect. Als ik aan het eind van de box kom kan ik in sommige situaties bv. geen 'm' meer typen, maar nog wel een 'i'.

[ Voor 11% gewijzigd door Verwijderd op 14-12-2004 17:32 ]


  • Loesje
  • Registratie: Januari 2000
  • Laatst online: 02-07-2025
Regel 6 is overbodig? (En de variabele cText ook?)

Leven is meervoud van lef


Verwijderd

Loesje schreef op dinsdag 14 december 2004 @ 17:34:
Regel 6 is overbodig? (En de variabele cText ook?)
De variabele cText kan eventueel weggelaten worden, maar imo is dat smerig. Je krijgt dan:

code:
1
2
 If Form1.Canvas.TextWidth(Edit1.Text + Key)+7 > Edit1.Width then 
      Key:=#0;


Ik vind het zelf dan netter om die waardes eerst in een var te stoppen, zo is je code leesbaarder. In dit voorbeeld is het niet strikt nodig, maar gewoontes he :)

Regel 6 is ZEKER NIET overbodig. Je gebruikt immers de TextWidth functie, welke rekening houdt met het font. Om de juiste waarde te krijgen is het dus noodzakelijk dat het canvas waarop je de TextWidth functie gebruikt, hetzelfde font heeft als de editbox. Aangezien de editbox zelf geen canvas property heeft, gebruik ik die van het form. Voorwaarde hiervoor is DUS dat je mainform hetzelfde font gebruikt.

Stel ik zou de editbox een font met size 12 geven, en het form een font met size 10. Dan klopt deze code (dus) niet meer, omdat de TextWidth functie uitgaat van een font met size 10, terwijl er size 12 gebruikt wordt..

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 20:44

Creepy

Tactical Espionage Splatterer

Hoe kom je daar nu bij? Want als het canvas een ander font heeft dan de TEdit dan klopt de uitkomst in pixels ook niet meer.

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


  • Loesje
  • Registratie: Januari 2000
  • Laatst online: 02-07-2025
Omdat je ervan uit moet gaan dat beide fonts gelijk aan elkaar zijn. (ParentFont true van de edit)

Als dat niet zo is, en je voert deze code uit, en er komt een ChangeFont-message (oid) langs, wordt het hele form ge-redrawd in het font van de TDBEdit.

(Je kan evt. het oorspronkelijke font opslaan en na de textwidth weer terugzetten, dan werkt het altijd.)

[ Voor 18% gewijzigd door Loesje op 14-12-2004 17:46 ]

Leven is meervoud van lef


Verwijderd

Loesje schreef op dinsdag 14 december 2004 @ 17:45:
Omdat je ervan uit moet gaan dat beide fonts gelijk aan elkaar zijn. (ParentFont true van de edit)
Aannames zijn the mother of all fuckups :P
Als dat niet zo is, en je voert deze code uit, en er komt een ChangeFont-message (oid) langs, wordt het hele form ge-redrawd in het font van de TDBEdit.

(Je kan evt. het oorspronkelijke font opslaan en na de textwidth weer terugzetten, dan werkt het altijd.)
Dat is idd mogelijk, evenals het repainten van het form even uitzetten. Daarom noem ik het ook als nadeel, zodat de TS weet dat hij daar rekening mee moet houden. Eventueel is het ook mogelijk om bv. zelf een control aan te maken welke wel een canvas property heeft, en die misbruiken ipv. het form.

Dat valt echter een beetje buiten de vraag, maar goed, dan toch:

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
 oFont: TFont;
begin
 If not Edit1.ParentFont then
     begin
       oFont:=Edit1.Font;
       LockWindowUpdate(Form1.handle);
       Form1.Font := Edit1.Font;
       If (form1.Canvas.TextWidth(Edit1.Text + Key))+7 > Edit1.width then Key:=#0;
       Form1.Font := oFont;
       LockWindowUpdate(0);
     end
   else
     If (form1.Canvas.TextWidth(Edit1.Text + Key))+7 > Edit1.width then Key:=#0;
end;


Ik zou niet de aanname doen dat Parentfont altijd true is; zeker niet daar TS zelf al beschrijft dat e.e.a. moet overeenkomen met het font op een website. Stel nu dat iemand in de toekomst dat font veranderd, dan is erg waarschijnlijk dat dat font in de edit gewijzigd gaat worden, en niet in het form.

Andere optie (mooier imo):

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
  oCanvas: TCanvas;
  notUsed: HWND;
begin
  oCanvas := TCanvas.Create;
  oCanvas.Handle := GetDeviceContext(notUsed);
  Try
    oCanvas.Font:=Edit1.Font;
    If (oCanvas.TextWidth(Edit1.Text + Key))+7 > Edit1.width then Key:=#0;
  Finally
    oCanvas.Free;
  End;
end;

[ Voor 21% gewijzigd door Verwijderd op 14-12-2004 18:08 ]


  • Loesje
  • Registratie: Januari 2000
  • Laatst online: 02-07-2025
Wel mooi dat de Generaal steeds alles netjes uitwerkt. Wil je dat hier op mijn werk ook voor me komen doen? ;-)

Die LockWindow is niet nodig, voor zover ik weet. De Font property wordt alleen gebruikt door de paint-functie van het form zelf. Wat je met LockWindowUpdate uitzet zijn de 'system-redraws' die die property niet uitlezen.

edit:
Stiekem editen, he? Maar je laatste code is idd. de mooiste oplossing, natuurlijk

[ Voor 15% gewijzigd door Loesje op 14-12-2004 18:05 ]

Leven is meervoud van lef


Verwijderd

Loesje schreef op dinsdag 14 december 2004 @ 18:04:
edit:
Stiekem editen, he? Maar je laatste code is idd. de mooiste oplossing, natuurlijk
Stiekem? 't staat er toch onder? >:)

Overigens vind ik zelf nog een probleem met die onderste mogelijkheid.. je zult waarsch. toch op keys moeten gaan controleren, want als ik met die onderste code de editbox vol zet met 'i', dan mag ik geen backspace meer gebruiken. Blijkbaar krijgt hij het dan toch voor elkaar om de textwidth altijd groter te laten zijn dan de width van de editbox.
Pagina: 1