This is my attempt to make control anchoring as quick and easy as possible in VB6.
VB6 control anchoring can be achieved with one line of code per Control in the Form1 Resize subroutine, with the addition of this one short module "ModuleControlAnchor"
To anchor a control, add this module to your project, and place this one line of code into the Sub Form_Resize():
Anchor ControlName, AnchorTop (True or False) , AnchorLeft, AnchorRight, AnchorBottom
Please check out the demo and use freely.
SeabrookStan
Last edited by SeabrookStan; Jan 11th, 2019 at 02:12 AM.
Reason: Code updated
Frames do not have ScaleWidth,ScaleHeight properties, nor a ScaleMode property (defaulted to twips). The fix might require testing for containers that are Frames and getting their height/width relative to the parent's scalemode (unless a frame in a frame scenario exists, then it gets to be a bit more fun). Looking at the code comments, appears it was intended to align controls on forms only, not in other containers.
And just FYI. I haven't tried the project, just looked at the module. I think there will be problems if an arrayed control is added for anchoring, i.e., Label1(0) and Labe1(1). Reason is that the module finds controls by their name and both of those labels have the same name.
Suggestion. Loop through the OB() array instead. And in doing so, I don't think you'll need the CTL() array.
Code:
If OBJ Is OB(X) Then ...
Last edited by LaVolpe; Jan 10th, 2019 at 01:06 PM.
Insomnia is just a byproduct of, "It can't be done"
Thank you for identifying the Scalemode bug, LaVolpe.
The new attachment, V3, now accommodates for Controls contained within other Controls, such as Frames and Pictureboxes (but assumes TWIPS for all containers) – see Demo.
Known issues are limitations when used on multiple Forms simultaneously, and for anchoring of Control Arrays, and for non-TWIP scales. I believe I can overcome those limitations and will submit an updated version when done.
Tips - as long as you are going to submit a new version
1. Resolve control arrays: already provided in previous post
2. Multiple forms: Passed control's Parent is always the form, usercontrol, propertypage, etc (top level container), regardless of its container
3. Prevent restricting to Twips for scale mode: Specifically test for frame containers and default to twips for them, otherwise, use the scalemode of the container as needed. To test for a frame:
Code:
If TypeOf OBJ.Container Is VB.Frame Then ...
Insomnia is just a byproduct of, "It can't be done"
Just some thoughts I had when looking at the code. Just take them for whatever you like.
1) I agree with LaVolpe that the CTL() array is possibly causing confusion, with everything you need done by the OB() array.
2) If it were me, I'd tend to use a Collection for that OB() array (rather than an array). That would allow a couple of things. You might use the ObjPtr() as your key, and then you could quickly check the collection (using it's binary tree) for the existence of controls. It would also allow you to get out-from-under your Redim Preserve statements.
3) I thought about possibly using API calls for the sizing/moving. That would circumvent all your ScaleMode problems. However, it would be difficult (if not impossible) to do that with light-weight controls (such as labels and drawing objects).
4) LaVolpe gave you a way to check for the Frame control. However, don't forget that UserControls can also be containers, and they don't necessarily have to expose a ScaleMode property either. In fact, they may be a problem in that they can have a ScaleMode other than Twips, but not necessarily expose that fact.
Cool stuff. Take Care,
Elroy
Last edited by Elroy; Jan 10th, 2019 at 06:58 PM.
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Just to give you a bit more information, you could use the following to move things around:
Code:
Public Type RECT
Left As Long
Top As Long
Right As Long ' This is +1 (right - left = width)
Bottom As Long ' This is +1 (bottom - top = height)
End Type
'
Public Declare Function MoveWindow Lib "user32" (ByVal hWnd As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hWnd As Long, lpRect As RECT) As Long
Using those would completely circumvent any concern with ScaleMode, and you'd always be working in pixels.
However, the problem you'd have is with light-weight controls (for example, Labels, Lines, and Shapes). Those light-weight controls don't have a hWnd. Therefore, they're difficult to resize with API calls.
For what you're doing, you may be better off to just "manage" the ScaleMode of the containers. In other words, save it, set it to some standard for you (say Twips), do your work, and then put it back to what it was. With that approach, you could still resize your light-weight controls.
Take Care,
Elroy
Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.
Sorry to ask back: Have you tried your code in production already? I don't like my code. It requires 2 classes while the original code does not even require 1...
If your fix works, then I would prefer yours.
I had to change really much to get it working in all cases.
Byproduct is the ability to preserve initial size and position and prevent going offscreen.
If you should switch from an earlier version to this one, please note that I change the arguments in Sub Anchor:
Previously: Top, Left, Bottom, Right
Now: Left, Top, Bottom, Right
Edit: I found one situation that made me rewrite it.
In my previous version a situation was not covered where a form has WindowStateMaximized.
My old code was not able to handle such an event.
My code takes place in Form_Load now and uses the form as a private variable to get its resize event.
Edit: I fixed a flaw that occured if a control has a hwnd.
Last edited by tmighty2; Sep 22nd, 2024 at 06:12 PM.
Your fix does not work correctly if e. g. a picturebox is set to vbPixels.
Thanks for reporting the bug.
I have my own solution and it is working fine, but I never used Picturebox as container, and never changed the containers ScaleMode property to a value distinct of vbTwips, the atached file contains the versión with it fixed.
My solutions uses a unique class and the tag property to specify the anchor type, sets the minimum form size to the desing size.