Avatar billede tille Nybegynder
08. maj 2002 - 14:39 Der er 16 kommentarer og
4 løsninger

beregne længden af streng, i pixels

Hej

Jeg skal fylde en listbox med resultatet af en query.

Der er 2 kolonner i Query , men jeg vil gerne have begge kolonner med lige venstrekant:

asdfasdf  asdfafd
asdf      fdfdf
ddf      ddfdfd 
asdfasdf  dfasdfasdf

Det er ikke så nemt når første kolonne ikke har fast længde.

som det er nu konkatenerer jeg blot de 2 kolonner, række for række, men det ser jo ikke så pænt ud.

jeg ville derfor høre om i viste hvilken apifunktion jeg skal bruge for at beregne længden i pixels af en given streng.

Sådan så jeg kunne sige at første kolonne altid skulle fylde f.eks. 50 pixels og så blot tilføje anden kolonne

hvad det forståeligt hvad jeg ville opnå?
Avatar billede tille Nybegynder
08. maj 2002 - 14:41 #1
istedet for at vise hvad jeg ville opnå i listboxen, viser mit eksempel problemet, når der bruges proportionalfont.

en knap så pæn løsning kunne være at skifte fonten i listboksen til at være en ikke-proportional, men hvordan gøres det?
Avatar billede bennytordrup Nybegynder
08. maj 2002 - 14:45 #2
Form1.TextWidth("Xsssss") hvis Form1.ScaleMode er vbPixels
Form1.TextWidth("Xsssss")\Screen.TwipsPerPixelX hvis Form1.ScaleMode er vbTwips
Avatar billede proaccess Nybegynder
08. maj 2002 - 14:52 #3
Din alternative løsning:

Skift til Courier New...  Du markerer list-boksen og vælger egenskaben Font!
Avatar billede tille Nybegynder
08. maj 2002 - 14:53 #4
jeg har ikke en metode textwidth.

jeg arbejder i et udviklingsmiljø hvor jeg kan skrive VB4 kompatibel kode (skulle jeg måske nok lige have fortalt først, sorry), derfor tror jeg at jeg bliver nød til at anvende en WinAPI funktion
Avatar billede martin_moth Mester
08. maj 2002 - 14:59 #5
Nu har jeg måske helt misforstået det hele, men hvis det er et spørgsmål om at få de to kolonner til at stå pænt under hinanden i samme listbox, kan du ikke bare gøre således:

Alle rækker deles op, og første delstreng ("kolonne") smides i Kol1() andes delstreng i Kol2(). Er Kol1() og Kol2() defineret som... :

Dim Kol1() As String * 20
Dim Kol2() As String * 20

... vil de altid fylde 20 karakterer, også hvis de kun indeholder fx. 'asdfasdf'

Herefter kunne du fylde listboxen ved

For Tæller = LBound(Kol1()) To UBound(Kol1())
  List1.AddItem Kol1(Tæller) & Kol2(Tæller)
Next Tæller

Det vil føre til, at de står pænt under hinanden.

Men måske har jeg misforstået dit problem?
Avatar billede tille Nybegynder
08. maj 2002 - 15:01 #6
martin_moth:  nej det lyder korrekt nok, jeg prøver og vender tilbage
Avatar billede martin_moth Mester
08. maj 2002 - 15:06 #7
Mit svar duer kun, hvis du bruger en font hvor hver karakter har samme bredde, f.eks. Courier...

Jeg har lige selv prøvet følgende, og det virker:

Dim Kol1(1) As String * 20
Dim Kol2(1) As String * 20
Dim i As Byte

Kol1(0) = "Blaa"
Kol2(0) = "aalB"
Kol1(1) = "Blaaaaaaa"
Kol2(1) = "aaaaaaalB"

For i = 0 To 1
  List1.AddItem Kol1(i) & Kol2(i)
Next i

/Martin

PS. Hvis du skal have hjælp til at få splittet teksten op og fyldt i de 2 arrays, så sig til...
Avatar billede martin_moth Mester
08. maj 2002 - 15:08 #8
Måske ville du få en mere elegant løsning ved at bruge et MSFlexGrid  (hvis det findes i VB4) i stedet for en listbox - bare en ide ;o) /Martin
Avatar billede tille Nybegynder
08. maj 2002 - 15:14 #9
martin_moth: nej det er ikke løsningen,
Du havde fanget problemet korrekt nok, nemlig at få listet begge kolonner pænt under hinanden, men det er ikke nok at få dem til at være i en streng der er lige lang.
Når der benyttes en proportional font, afhænger længden af hvilke bogstaver der er i strengen, derfor ville jeg finde en funktion der kunne få dannet en streng af en hvis længde i pixels.
Avatar billede martin_moth Mester
08. maj 2002 - 15:23 #10
Netop derfor skrev jeg, at du skulle vælge f.eks. courier... Så virker det!

Men jeg tror ikke du kan løse problemet på "din" måde. Måske kan du vha. API-kald få beregnet længden af din streng i pixels, men hvad så? Du kan jo ikke angive, at en streng skal have en bestemt længde i pixels - kun i karakterer. Hvis jeg nu gav dig en funktion, der som input tog en streng, og output gav længden i pixels, så ville du stadig have et problem.

Som jeg ser det, bliver du nødt til at gøre f.eks. som jeg siger (og anvende f.eks. Courier), eller anvende f.eks. et MSFlexgrid eller andet, der kan håndterer kolonner. Det ville muligvis også bliver både pænere og mere funtionelt, da brugeren kan skalere bredden af kolonnerneosv.

Men vil du bruge en listbox, vil jeg påstå, at den eneste løsning er den jeg har skitseret, ved anvendelse af f.eks. Courier ...
Avatar billede tille Nybegynder
08. maj 2002 - 15:31 #11
martin_moth: ja du har nok ret, men hvilken funktion sætter så fonten på en listbox? (MSFlexGrid findes ikke i VB4)
Avatar billede martin_moth Mester
08. maj 2002 - 15:35 #12
Enten i runtime ved

List1.Font = "Courier"

Eller når du er i design mode, ved at vælge Courier i dit Properties-vindue - sådan et må der være, elv i VB4 ;o)
Avatar billede martin_moth Mester
08. maj 2002 - 15:35 #13
elv=selv
Avatar billede ocp Nybegynder
08. maj 2002 - 15:40 #14
Gaflet fra google:

You can use the LB_SETTABSTOPS message to set tabstops in the listbox. KB
article Q71067 has details (VB3 code). The tabstops are set in "dialog
units", which if I remember rightly come out at about 4 pixels. The KB
article has a routine for calculating the exact conversion factor, but you
can just use trial and error to find the right values for the tabstop array.
The code below is 32-bit (VB4-32 or VB5):

Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) _
    As Long
Public Const LB_SETTABSTOPS = &H192

    Dim tabstops(1 to 3) As Long
    tabstop(1) = 200
    tabstop(2) = 400
    tabstop(3) = 600
  SendMessage list1.hWnd, LB_SETTABSTOPS, 3, tabstops(1)

    List1.AddItem "Name" & vbTab & "Address" & vbTab & "Phone"
Avatar billede martin_moth Mester
08. maj 2002 - 15:43 #15
Wow - hvis svaret fra ocp virker er det nok det der er løsningen for dig! Smart - det anede jeg ikke at man kunne... Så lærte jeg også noget i dag ;o)
Avatar billede ocp Nybegynder
08. maj 2002 - 15:46 #16
VBs adgang til mange af windows' komponenter er temmelig begrænset. Jeg vil anbefale at du læser nogle af Franseco Balenas artikler om "subclassing" hvis du vil have fuldt indblik.
Prøv evt.: www.vb2themax.com
Avatar billede tille Nybegynder
08. maj 2002 - 20:17 #17
ocp:

Det ser ud som noget jeg kan bruge, men hvor skal jeg fyre beskeden af?

spaghettikode:

Begin dialog load_dialog.....
  ....
  Listbox ,,,,,,.Set_Listbox
  .....
End Dialog
Dim Load_d As load_dialog
SendMessage(Set_listbox.hWnd, LB_SETTABSTOPS,3,tabstops(1))
Dialog(Load_d)

...Spaghetti slut

fyrer jeg den af som ovenfor

får jeg fejl 'left of "." must be an object, structure, or dialog'

altså må jeg referere forkert til listbox objektet, hvordan fanger jeg den?
Avatar billede tille Nybegynder
08. maj 2002 - 21:21 #18
Det ser ud som om jeg ikke kan sende dialogobjekter til eksterne funktioner i den vb udgave jeg har i udviklingsmiljøet, og mit forhavende ikke kan lykkes, men jeg roder lidt videre
Avatar billede ocp Nybegynder
08. maj 2002 - 21:29 #19
Husk lige at skrive Call når du benytter SendMessage med parenteser (eller fjern parenteserne).

Prøv følgende (jeg har desværre ikke installeret VB på denne maskine endnu, så du måp selv "afluse" koden):

Opret først et modul.

1. Indsæt følgende udenfor alle funktioner og subs (dvs. i Declare-delen af modulet):

Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, _
    ByVal wParam As Long, lParam As Any) _
    As Long
Public Const LB_SETTABSTOPS = &H192

2. Opret en funktion:

Function DefineListboxTabs(byref list1 as listbox)

    Dim tabstops(1 to 3) As Long
    tabstop(1) = 200
    tabstop(2) = 400
    tabstop(3) = 600

    SendMessage list1.hWnd, LB_SETTABSTOPS, 3, tabstops(1)

End Function

3. Kald følgende fra Form_Load-eventen på din form:

Public Sub Form_Load

  'Set_listbox er naturligvis navnet på en listbox du vil have tab'et
  DefineListboxTabs Set_listbox

  Set_listbox.additem "Col1" & vbTab & "Col2" & vbTab & "Huraaa"

end Sub

...Nu er din listbox "sat" til at køre med de definerede tabs indtil du afslutter programmet eller om-definerer dem.

FYI:
Grunden til at kun det første element af array'et sendes med er at resten af array'et automatisk sendes med. Det ligger nemlig i forlængelse af første element og API'et sørger for at "slice" array'et i elementer der har en størrelse der svarer til "long". Det vil sige at de efterfølgende tabs også er lagt på listbox'en.
Avatar billede tille Nybegynder
11. maj 2002 - 11:16 #20
den afart der følger med det her datawarehouseprodukt, tillader ikke at jeg kommunikerer med dialogboksen via API'et, så alle anstrengelser er forgæves.

Jeg laver en ekstern dll som kan klare det og kalder den indefra applikationen.

tak for kampen
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
Kurser inden for grundlæggende programmering

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