exact scale graphs in VB

Q&A for Visual Basic, Visual Basic .NET, and PowerBasic developers using DPlot

Moderator: DPlotAdmin

Post Reply
zmorris
Posts: 3
Joined: Fri Mar 05, 2004 1:09 pm

exact scale graphs in VB

Post by zmorris »

Could you provide any tips or code on displaying metafiles in VB (as in btest4.exe) but with the axes sized to a specific scale?
In other words, I want to be able to say 'make the x-axis 5 inches and the y-axis 2 inches' and have it display and print the metafile correctly sized.

Thanks!
User avatar
DPlotAdmin
Posts: 2312
Joined: Tue Jun 24, 2003 9:34 pm
Location: Vicksburg, Mississippi
Contact:

Post by DPlotAdmin »

I haven't tried this myself, so it make take a few iterations to get this right...

1) Use [Size(1,5,2,1)] in the DPlot_Plot call to make the axes the correct size (or, at least, a 5:2 ratio).

2) DPlot_GetEnhMetaFile takes size arguments, but the size in this case refers to the entire plot, not just the axes. Regardless of what size we specify, if a 5" X axis will fit and a 2" Y axis will fit, then that's what we'll get (crossing fingers as I write). So use size values that we're certain are large enough to accomodate the specified X and Y axes, say

Code: Select all

hemf = DPlot_GetEnhMetaFile(DocNum, 8#, 5#)
3) Now we need to size our output target rectangle to the size of the metafile we just produced. To get the size of the metafile, use

Code: Select all

Type ENHMETAHEADER
    iType As Long
    nSize As Long
    rclBounds As RECT
    rclFrame As RECT
    dSignature As Long
    nVersion As Long
    nBytes As Long
    nRecords As Long
    nHandles As Integer
    sReserved As Integer
    nDescription As Long
    offDescription As Long
    nPalEntries As Long
    szlDevice As SIZE
    szlMillimeters As SIZE
    cbPixelFormat As Long
    offPixelFormat As Long
    bOpenGL As Long
End Type

Declare Function GetEnhMetaFileHeader Lib "gdi32" (ByVal hemf As Long, ByVal cbBuffer As Long, ByRef lpemh As ENHMETAHEADER)

Dim header as ENHMETAHEADER

ret=GetEnhMetaFileHeader(hemf,len(header),header)
At this point header.rclFrame contains "the dimensions, in .01 millimeter units, of a rectangle that surrounds the picture stored in the metafile"

So if we want a 1:1 scale we need to size our output rectangle to those same dimensions. Our VB picture control has units of twips, so we need to convert .01 mm units to twips. 1 twip = 1/1440 inches, so .01 mm units * 1440/(100*25.4) gives us twips:

Code: Select all

        hdc = GetDC(Picture1.hwnd)
        Picture1.Width = (header.rclFrame.Right - header.rclFrame.Left) * 0.566929
        Picture1.Height = (header.rclFrame.Bottom - header.rclFrame.Top) * 0.566929
        ret = GetClientRect(Picture1.hwnd, rcPic)
        ret = FillRect(hdc, rcPic, GetStockObject(WHITE_BRUSH))
        ret = PlayEnhMetaFile(hdc, hemf, rcPic)
        ret = ReleaseDC(Picture1.hwnd, hdc)
And... believe it or not, that comes out pretty close on the first try. Both axes are just a bit long - it appears that VB uses the same tomfoolery with "logical" inches that DPlot does. If you really want exact dimensions then we'll need to fool around with GetDeviceCaps a while, but this may be about as good as it gets since anybody can shrink or expand their screen using the control panel on the front w/o Windows knowing about it.

Let me know if you have any questions on the above, and thanks for the exercise :D
Last edited by DPlotAdmin on Tue Mar 09, 2004 2:58 pm, edited 1 time in total.
Visualize Your Data
support@dplot.com
zmorris
Posts: 3
Joined: Fri Mar 05, 2004 1:09 pm

Post by zmorris »

Thanks so much!
My knowledge of Win32 GDI functions is pretty much non-existant. You've really saved me alot of time and stress.

I will give this a try today.
Post Reply