Newsgroup: it.comp.lang.visual-basic
Titolo: Larghezza di un carattere

Scusate, ma tra i vecchi post sembra non esserci nulla.
Stavo tentando di prendere la larghezza del carattere
per crearmi poi il cursore lampeggiante.
Bene utilizzo le due api getcharwidth32 e createcaret
solo che la larghezza restituitami dall'api getcharwidth32
è troppo piccola, se faccio textwidth è troppo grande.
Se provo a fare qualche macheggio con operazioni
matematiche i risultati sono approssimativi.
Possibile che non ci sia un modo per prendere la
dimensione corretta?
Ora mi sorge un dubbio getcharwidth32 dice che
restituisce la largheza in logical coordinates mentre
la create caret la vuole in logical unit ... che non
siano la stessa roba??
Ciao
Andrea

 è troppo piccola, se faccio textwidth è troppo grande.
Io ho usato questa funzioncina per calcolare l'esatta posizione del cursore
rispetto a un carattere e funziona benissimo (lavoro con ScaleMode =
vbPixel, ma non dovrebbe essere influente):
Private Sub CursorToCaret(cur As POINTAPI, car As POINTAPI)
    car.y = ((cur.y - 1) * picSheet.TextHeight("^_")) + 1
    car.x = picSheet.TextWidth(Mid$(rows(cur.y), 1, cur.x))
End Sub
car indica la posizione del caret, cur la posizione del cursore, cioè del
carattere incriminato (cur.x è l'x-esimo carattere della riga cur.y, base
1).
Rows() è l'array di stringhe che compongono il testo (base 1).
Dove trovi problemi?
Ciao

Però la tua funzione ti esprime valori in x e y .. a me invece
occorre una larghezza "valida" per la funzione createcaret.
Dunque dichiarazione api per GetCharWidth o anche
per la GetCharWidth32 .... tanto non cambia quasi nulla
se non il fattore compabilità regressa.
In più le api per GetTextMetrics, ReleaseDc e GetDC
Type TEXTMETRIC
   tmHeight As Long
   tmAscent As Long
   tmDescent As Long
   tmInternalLeading As Long
   tmExternalLeading As Long
   tmAveCharWidth As Long
   tmMaxCharWidth As Long
   tmWeight As Long
   tmOverhang As Long
   tmDigitizedAspectX As Long
   tmDigitizedAspectY As Long
   tmFirstChar As Byte
   tmLastChar As Byte
   tmDefaultChar As Byte
   tmBreakChar As Byte
   tmItalic As Byte
   tmUnderlined As Byte
   tmStruckOut As Byte
   tmPitchAndFamily As Byte
   tmCharSet As Byte
End Type
Declare Function GetCharWidth32 Lib "gdi32" Alias "GetCharWidth32A" (ByVal
hdc As Long, ByVal iFirstChar As Long, ByVal iLastChar As Long, lpBuffer As
Long) As Long
Declare Function GetTextMetrics Lib "gdi32" Alias "GetTextMetricsA" (ByVal
hdc As Long, lpMetrics As TEXTMETRIC) As Long
Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As
Long) As Long
Dim lret as long, dc as long, lwidth as long
Dim MyStr as string
Dim tm as TEXTMETRIC
dc = GetDc(Text1.hwnd)
GetTextMetrics dc, tm
if (len(text1.text) > 0) then
    Mystr = mid$(text1.text, text1.selstart, 1)
end if
lret = GetCharWidth(dc, Mystr, Mystr, lwidth)
ReleaseDC Text1.Hwnd, dc
lret torna sempre valore diverso da 0, quindi significa che il
comando lo esegue ... il problema è sempre il valore.
lwidth viene sempre valori piccolissimi che vanno bene
per creare un caret di dimensioni ridotte, tipo quando
il font è di 8 - 10 points. Ma se lo metti a 16-20
venti un cosetto piccolissimo che non copre il caret.
Quello che volevo fare io è una cosa del tipo ... caret
largo tanto quanto il carattere successivo che devo
sovrascrivere.
Ciao
Andrea

Inghippo trovato ... non impostavo il carattere
dello usercontrol = a quello della textbox ... ragion
per la quale le misure erano falsate.
Scusate, ma stavo lavorando su un esempio scaricato
che faceva sta storia del caret e non mi ero accorto
della omissione del programmatore.
E non c'è nemmeno bisogno di usare la getcharwidth
e compagne ... solo la createcaret.
Ciao
Andrea

 e compagne ... solo la createcaret.
Che tra l'altro non funzionano su win9x/ME.
Ciao

> Ricorda di creare il caret nel GetFocus e distruggerlo nella LostFocus.
Perchè ... che succede??
Nell'esempio che ho ... vedo solo che usa il createcaret e lo showcaret.
Non ci sono api destroycaret utilizzate. L'sdk dice che dovrebbe
essere distrutto ... ma non spiega la ragione.
Potrei essere d'accordo se avessi utilizzato un caret con la bitmap ...
ma utilizzando solo il solidblock ... booo ... non ne vedrei la
necessità, anche perchè chi più chi meno, quasi tutti i controlli hanno
il caret.
Questo salvo, che non ci siano degli effetti collaterali che come
al solito non sono documentati.
Ciao
Andrea

essere distrutto ... ma non spiega la ragione.
Handles impegnati?
Messaggi di memoria esaurita con 1GB di RAM libero?
-- 
ciao, hal
giocare col fuoco e' bello, ma...

 Nell'esempio che ho ... vedo solo che usa il createcaret e lo showcaret.
A parte il solito discorso di risorse, che uno potrebbe dire "beh, lo
disctruggo all'uscita dall'app", in MSDN ci sono altre ragioni un po'
nascoste e poco chiare.
A quanto pare è possibile che altre applicazioni utilizzino lo stesso tuo
caret (nonostante il nome sembra che la createcaret serva semplicemente a
dire che la tua app sta chiedendo la possibilità di usare il caret che è uno
solo di sistema), le altre app potrebbero nascondere, modificare o chissà
che altro sul caret che stai usando.
Ciao

Però ho notato che facendo
private sub usercontrol_exitofocus
    call destroycaret()
end sub
e facendo click dal mio controllo su di un textbox,
beh il caret al primo focus non c'è ... poi quando
passo ad un altro controllo il caret c'è di nuovo,
anche tornando sul controllo che prima non dava
segni di caret ....
stessa cosa succede anche con altri controlli ... e
ti parlo di controlli base di vb ... non di chissà
che ...
invece senza la destroycaret tutto ok.
Mica mi indichi quegli articoli a cui ti riferisci?
Ciao
Andrea