Use GDI32 functions in fixed scale forms
SionOkay, the title may be a bit cryptic but it's hard to explain my question in a sentence that short. I have a form where ScaleMode is vbUser. The scale could for instance be 100 wide and 100 heigh, with left and top set to 0. In this form I would like to use some of the GDI32 functions such as "Polygon" and "Polyline" to paint on the form. But all the GDI32 functions are operating in pixels and dosn't take the custom form scale into account. I've tried to convert the custom scale values of the polygon into pixel values with the following code: [code] Private Sub DrawPoly(poly() As Coord) Dim ix As Integer 'Converts custom scale to pixels For ix = LBound(poly) To UBound(poly) poly(ix).X = Me.ScaleLeft + (poly(ix).X - 5) * (((Me.Width / Screen.TwipsPerPixelX) / (Me.ScaleWidth - Me.ScaleLeft))) poly(ix).Y = Me.ScaleTop + poly(ix).Y * (((Me.Height / Screen.TwipsPerPixelY) / (Me.ScaleHeight - Me.ScaleTop))) Next ix 'Polygon function creates unfilled polygon on screen. Polygon Me.hDC, poly(1), UBound(poly) End Sub [/code] But it dosn't work very well. It's not very precise, and when the form is resized it becomes less and less precise. Isn't there a way (or prehabs a API call) to make a stable conversion from a custom scale to a pixel scale? Thanks in advance [:)]
Eric ColemanUse ScaleX and ScaleY. poly(ix).X = Object.ScaleX(poly(ix).X, vbUser, vbPixels) poly(ix).Y = Object.ScaleY(poly(ix).Y, vbUser, vbPixels) Object can be the form, a picturebox, the printer, or a user control.
SionAnd once again Eric Coleman comes to the rescue!™ So simple and elegant... Guess I couldn't see the forest for trees or however the saying goes. However, when I first tried it it didn't work. I realized that it - for some reason - only works if the scale is reset each time the object is resized. But now it works! Yeah! EDIT: I didn't think straight when I tried it out - the scale must always be reset in order for the custom scale to work. That's common pratice. I'd actually done that in the game I should use this for... Phew, must be the heat [;)] Mr. Coleman is now officially my programming rolemodel. [:P]
SionFor completeness here is the same code Eric posted, but also taking Object.ScaleLeft and Object.ScaleTop into account. [code] poly(ix).x = Object.ScaleX(poly(ix).x - Object.ScaleLeft, vbUser, vbPixels) poly(ix).y = Object.ScaleY(poly(ix).y - Object.ScaleTop, vbUser, vbPixels) [/code]
SionI ran a bit low on clock cycles in my game, and found a lot of wasted cycles in this rutine. Instead of using the code as presented in my last post directly, it should be rearranged to be more efficiant. [code] Dim XScale As Single, YScale As Single XScale = Object.ScaleX(1, vbUser, vbPixels) YScale = Object.ScaleY(1, vbUser, vbPixels) LOOP poly(ix).x = (poly(ix).x - Object.ScaleLeft) * XScale poly(ix).y = (poly(ix).y - Object.ScaleTop) * YScale END LOOP [/code] Using the above approach I managed to reduce the cycle usage by ~40%. I ran both versions 2000 times on a polygon with 60 sides. First approach took ~2700ms and second approach took ~1650ms. That's 44,444.44 calculations per second compared to 72,727.27 [;)]
Eric ColemanThat's a great tip! Thanks for sharing.