Silly VB 6 Problem Involving Control Positioning.



  • In Payback (an app that's been the subject of several WTFs on this site), I have a VB 6 form on which I am creating controls dynamically.  Let's just focus on one set of button controls for now.

    I'd like all of the dynamically created buttons to line up nicely in a vertical line.  That's simple enough.  I do:

    'approximation of a snippet of code from the middle of a for loop
    'buttons all have .Height = 315
    Button(i).Top = (Button(i - 1).Top + Button(i - 1).Height) + Margin      'Margin = the gap I'd like to have between the buttons


    This works well, unless I choose a Margin that is not evenly divisible by 15.  For example, if I set Margin = 5, I get something looking like this: http://www.unclemidriff.com/images/irritatinggap.jpg

    Notice how the first two marked gaps are different from the third marked gap.  This pattern repeats.  If I set Margin = 10, then the gap shows up every other button.

    I set the up click events for the buttons to do:

    MsgBox Button(Index).Top - (Button(Index - 1).Top + Button(Index - 1).Height)

    The answer I get is the value of Margin, even if the button clicked on is one immediately following a gap.

    This isn't all that big of a deal, but it's bothering me that it's happening and I don't really know why.

    What (likely obvious thing) am I missing?



  • If I remember correctly, VB6's standard measurement unit is twips.  I vague remember having to poll the display adapter's twips/pixel property to do any kind of positioning.  I haven't done VB6 in years so I may be wrong.




  • VB6 uses a unit of measurement called "twips" - they are resolution-indipentent or someting, I don't know why they use them instead of pixels (at least VB.Net uses pixels).  You are looking for a function called Screen.TwipsPerPixelX and Screen.TwipsPerPixelY to get the average values:

    Margin = Screen.TwipsPerPixelY * (MarginInPixels)

    will give you a nice even layout.



  • If you do not want to deal with twips for measurement, there is a form option that allows you to hard set the form to use pixels instead of twips.  Now I can't exactly remember the name of it, but if you browse the properties you should be able to find it...



  • Something like,

    Me.ScaleMode = vbPixels
    and Me.ScaleLeft (... Top, Width, Height)

    There is also .ScaleX and ScaleY for use in height/width calculation (NB. Any twips/pixels conversions are dependant on current dpi).

    You can also change the coordinate system of a form with .Scale



  • @Albatross said:

    VB6 uses a unit of measurement called "twips" - they are resolution-indipentent or someting, I don't know why they use them instead of pixels (at least VB.Net uses pixels).  You are looking for a function called Screen.TwipsPerPixelX and Screen.TwipsPerPixelY to get the average values:

    Margin = Screen.TwipsPerPixelY * (MarginInPixels)

    will give you a nice even layout.



    ... twips?


    Is this a joke?


  • No joke.  It's equivalent to something like 1/16" divided by 1440 - don't quote me on the exact calcs.   That's why you get some ridiculously large measurements where 800x600 pixels is almost 40,000x30,000 twips. 

    Man, twips were pain.  I'm glad I gave up the WTF that was VB6 and moved on to .Net.  OO and positioning that actually makes sense.



  • @lpope187 said:

    No joke.  It's equivalent to something like 1/16" divided by 1440 - don't quote me on the exact calcs.   That's why you get some ridiculously large measurements where 800x600 pixels is almost 40,000x30,000 twips. 

    Man, twips were pain.  I'm glad I gave up the WTF that was VB6 and moved on to .Net.  OO and positioning that actually makes sense.


    Oh my god.
    I bet I know how that came to be:

    [i]Int; MS office building. 18:45[/i]
    VB Architect: "HEY JOE, I HAVE AN IDEA."

    Joe the Cleaner ([i]unpacks mop and bucket[/i]): "What?"

    VB Architect: "THINK OF TWO RANDOM NUMBERS, WOULDYA?"



  • I think in 10 years from now, "Pixel" will have no more meaning in PC software, since the drawing APIs will be vector-based. Maybe this will be the time when twips return.



  • @ammoQ said:

    I think in 10 years from now, "Pixel" will have no more meaning in PC software, since the drawing APIs will be vector-based. Maybe this will be the time when twips return.


    Agreed. At some point, the pixel will be just as invisible as a printer's ink dot. though resolution would have to be upwards of 200 dpi to make that feasible. A 19" monitor display 1600*1200 has something of 120 dpi. Games look great, even without hardware antialias, but for it to be perfect, it would have to be 150+.

    Another upside of pixels too small to see individually is that expensive antialiasing calculations will become obsolete. Aliasing will then be treasured as providing sharpness.



  • @Albatross said:

    VB6 uses a unit of measurement called
    "twips" - they are resolution-indipentent or someting, I don't know why
    they use them instead of pixels (at least VB.Net uses pixels).  You are
    looking for a function called Screen.TwipsPerPixelX and
    Screen.TwipsPerPixelY to get the average values:

    Margin = Screen.TwipsPerPixelY * (MarginInPixels)

    will give you a nice even layout.



    Holy new forum software, Batman!

    Thanks Albatross, that did the trick.  I figured that problem had something to do with that whole twips versus pixels thing.

    Not surprisingly, Screen.TwipsPerPixelY = 15, so multiplying my Margin by that gives me a Margin evenly divisble by 15, which I had already noticed made the problem go away.  So how's that work, anyway?  With Margin = 5, it places the next control 5 twips away from the current one.  Since the current control's height is evenly divisible by 15, we get a X pixels with 5 twips left over.  Then we place the next control and Margin of 5 twips, and we get a X more pixels with 10 twips left over.  Then we place the next control and Margin of 5 twips, we get X more pixels with 15 twips left over, but since 15 twips = 1 pixel, we actually get X + 1 pixels.  So on and so forth, thus the periodically recurring gap.  Does that make sense?

    What I don't get is why changing the form's ScaleMode property didn't change anything?  Why can't I change the ScaleMode property from twips to pixels and then have Margin = 5 mean that I want a margin of 5 pixels rather than 5 twips?  I tried that and it didn't solve or alter the problem.


  • @ammoQ said:

    I think in 10 years from now, "Pixel" will have no more meaning in PC software, since the drawing APIs will be vector-based. Maybe this will be the time when twips return.

    Oe they might just use points instead...



  • BTW, even though Screen.TwipsPerPixelY on your computer is 15, make sure that you don't hard code it (margin = 15), as Screen.TwipsPerPixelX and Y seem to be different on every computer.

     



  • @Albatross said:

    BTW, even though Screen.TwipsPerPixelY on your computer is 15, make sure that you don't hard code it (margin = 15), as Screen.TwipsPerPixelX and Y seem to be different on every computer.

    I didn't hard code it, but what determines the number of twips per pixel?  I changed the resolution, font size and DPI on my computer several times to several different resolutions etc., but each time, I get 15 twips per pixel.



  • @UncleMidriff said:

    @Albatross said:

    BTW, even though Screen.TwipsPerPixelY on your computer is 15, make sure that you don't hard code it (margin = 15), as Screen.TwipsPerPixelX and Y seem to be different on every computer.

    I didn't hard code it, but what determines the number of twips per pixel?  I changed the resolution, font size and DPI on my computer several times to several different resolutions etc., but each time, I get 15 twips per pixel.



    I found this article that explains that TwipsPerPixel is set by whether your using Large or Regular Font sizes.

    If the forum software eats the hyperlink it is this: http://support.asna.com/kb/Generic/kb000197.asp



  • @lpope187 said:

    If I remember correctly, VB6's standard measurement unit is twips.  I vague remember having to poll the display adapter's twips/pixel property to do any kind of positioning.  I haven't done VB6 in years so I may be wrong.


    A twip is a twentieth of a point ... TWentIeth of a Point

    Had to use it maintaining someone's Access database VBA thingy.


Log in to reply