Center a userform on a screen

Hello
We all have PCs with 2 screens and in a macro, I have a userform that has the annoying tendency to open on the wrong screen (Solidworks on the left screen for example and userform on the right screen)
On Excel I had this code that works very well:

Private Sub UserForm_Initialize()
    '-------------------------------------------------------- Positionnement UserForm
    Me.StartUpPosition = 0                                                  'Déclarer position MANUAL
    Me.Left = Application.Left + Application.Width / 2 - Me.Width / 2
    Me.Top = Application.Top + Application.Height / 2 - Me.Height / 2
End Sub

But this code causes a 438 error
The only topic found that comes close to this is this one and the answer page is no longer accessible. (Prb Userform - #7 by jfaradon)
If anyone knows how to fix this problem.

1 Like

Hello

StartUpPosition you modify it directly in the properties window, no need to do it in VBA

example

UserForm1.Move 100, 100 'Uniquement pour déplacer à gauche et en haut.
UserForm1.left = 100 'pour déplacer latéralement
UserForm1.Top = 100 ' pour déplacer verticalement
UserForm1.Move 100, 100, 250, 190 'pour tout modifier


Private Sub UserForm_Initialize()
UserForm1.Move 100, 100, 250, 190
End Sub
2 Likes

Yes on . Move is what I have now, but is a problem with 2 screens.
Current Code:

Private Sub UserForm_Initialize()
    With Me
        .StartUpPosition = 3
        .Move 100, 100
    End With
End Sub

But the problem is that if the solidworks window is on the left screen (2 screens), no worries the userform is well above SW.
But if the user has put Solidworks on his right screen, the userform ends up on the left screen, opposite SW.
That's why I'm looking for an alternative like in Excel (code of the 1st message, but not functional in SW.

I see 1 problem
the USF with startuposition on 1-centerowner should put the USF at the center of the application that launched it, which is not the case

" application.something " does not work

see this topic where I had to replace application, I think it's the same principle, for the moment I haven't found

2 Likes

Hello @sbadenis
Try This

Public swapp as sldworks.Sldworks

And

Private Sub UserForm_Initialize()
    '-------------------------------------------------------- Positionnement UserForm
    Me.StartUpPosition = 0                                                  'Déclarer position MANUAL
    Me.Left = swapp.Frameleft + swapp.Framewidth / 2 - Me.Width / 2
    Me.Top = swapp.Frametop + swapp.Frameheight / 2 - Me.Height / 2
End Sub
2 Likes

Hello
The answer from @Lynkoa15 seems good on the other hand I tested and the values returned are quite strange.
It gives me the following values for a double screen set to the one where SW is open in 1680x1050:
Left = 897
Width = 1024
Top = 0
Height = 768
This results in the UserForm being positioned in the middle of the two screens.
To keep it on the left screen (for me SW is on the left on the main screen) I removed Swapp.FramLeft from the calculation for Me.Left.
It positioned the UserForm on the left screen, not really centered in the window in the width, the height is good even if the height has nothing to do with my display resolution.

1 Like

Cyrille, it's strange, I don't have a dual screen and I haven't tested, but if it allows you to switch the window to the second screen, an analysis of the discrepancy with the dimensions of the latter must be possible, maybe a difference between the screen resolution and the windows display resolution

1 Like

I don't have the same resolution between the left screen and the right screen. Maybe it comes from that, I'll do a test again with a single screen to see.

1 Like

For me not quite centered on the left screen and on the right screen completely off-center.
By adding slightly off-center parenthesis on the 2 screens (same size), I get closer to the truth, but there is still a bit of a weird behavior and different from the solution in excel.

    Me.Left = ((swapp.FrameLeft + swapp.FrameWidth) / 2) - (Me.Width / 2)
    Me.Top = ((swapp.FrameTop + swapp.FrameHeight) / 2) - (Me.Height / 2)

No time to dig for the next 2-3 days, work catches up with me.
I will get back to you as soon as possible.
In any case, @Lynkoa15 , your solution is the closest and most functional to date!

Hello @sbadenis ,

Indeed, Windows manages the two screens as one by accumulating pixels in width.
This is confirmed by the attached macro, picked up in pieces from the net, and adapted to return the dimensions of the two screens and the position of the SolidWorks window.

The discrepancy observed using the @Lynkoa15 proposal seems to me to be related to a confusion of units for the screen coordinates:

  • The dimensions and position of the UserForm form (. Left, . Top. Widt and . Height) are defined by VBA in screen points.
  • The dimensions and position of the SolidWorks window returned by . FrameLeft, . FrameWidth, . FrameTop and . FrameHeights are defined by Windows in pixels.
    The ratio between the two units depends on the display itself, but is usually 4/3.

I have a correct position of the form in the middle of the SolidWorks window with the following expressions, regardless of the screen used:

With UserForm1
   .Left = (swApp.FrameLeft + swApp.FrameWidth / 2) * 3 / 4 - (.Width / 2)
   .Top = (swApp.FrameTop + swApp.FrameHeight / 2) * 3 / 4 - (.Height / 2)
End With

Kind regards.
DoubleEcran.swp (115.5 KB)

1 Like

@m.blt I tested quickly, centered on my left screen, if I switch SW to the right screen it's off-center.
I'll do another test tomorrow if I have time.

1 Like

Same thing as @Cyril.f , @m.blt not really centered and shift on the height, the ratio does not correct the error, and on more than 20 info posts I am afraid that it is very random unfortunately.

I think we will have to measure the right ratio
3/4 doesn't work on my basic screen (no second screen)
I tried to see the technical sheet


I think we'll have to calculate it
(145/25.4/(1920/210.24))=0.62 (the right ratio for me)
I guess this is the same for a second screen only if they have the same ppi
From this point of view I propose to work with two ratios, like if the number of pixels exceeds 1920 (for example) calculate the first (or second) pixels by the first ratio and add the rest with a calculation of the other ratio

1 Like

Hi all

It is true that the use of " screen points" by VBA is often problematic judging by the discussions on different forums (often dedicated to Excel or Access).
The solution is to get rid of it by using Windows API functions that only use pixels.
The attached macro is an adaptation of the previous one, which does the job on my PC with two screens. The UserForm1 form is centered on the SolidWorks window.
Quick test: If the SolidWorks window is moved, clicking the " Center " button resets the Userform.

Kind regards.
DoubleEcran.swp (171.5 KB)

1 Like

Hello @tous
@m.blt your macro surpasses :sweat_smile:me.
So I tried to develop the function I mentioned earlier, taking into account your remark about units.

I put at your disposal a small simple tool that allows you to calculate the ratios (I hope it will work :roll_eyes:)
Macro1.swp (76 KB)
Macro2.swp (56 KB)
Doc1.pdf (237.9 KB)

2 Likes

First of all, thank you very much for the time spent, I didn't imagine that centering a userform on the SW window would be so complicated!
@Lynkoa15 solution is simple, but as this macro will be used on more than 20 workstations with a number of screen(s) from 1 to 2, most often 2, and of completely different size and ratio.
In addition, the ration problem also exists on the height. That's why I'm thinking of turning to the @m.blt solution, which works perfectly.
@m.blt on the other hand I have a little trouble understanding your macro because it is so complete.
I admit that I am reaching my limits as a self-taught developer.
I took your code in a simplified macro with a userform without anything edt I can't adapt it.
Is it necessary in the call to have the 2 arguments (Textbox1 and 2):
CoincidentsCtresWindows UserForm1.TextBox1, UserForm1.TextBox2, True
and not just
CoincidentsCtresWindows UserForm1 , True
I tried to modify your code without achieving what I wanted (Centered the window only with the name of the userform)

Hello @sbadenis ,

Sorry, I'm a fan of the adage " Why make it simple when you can make it complicated? ".
image

Attached is the VBA window's centering macro on the SolidWorks window, stripped of all TextBox, ListBox and other buttons. Its only function is to position the UserForm VBA in the center of the SolidWorks window when it is first displayed.
It works on my PC, with one or two screens. I didn't try with three...

The conditions are as follows:

  • SolidWorks is enabled (which is in principle the case since the macro is launched);
  • the main module is called CentrageUsrFrm and contains only the main procedure;
  • In the main procedure, the first parameter passed to the CoincidentsCtresWindows function is the caption of the SolidWorks window, hard-coded: " SOLIDWORKS ".
    The second parameter is that of the UserForm, retrieved via its caption property;
  • The IdentFenetres module contains the two functions that use the Windows APIs to retrieve the dimensions of the windows and calculate the position of the UserForm. In principle, this module does not require any changes.

Kind regards.
CenteringUsrFrm.swp (102 KB)

2 Likes

It works perfectly as for the previous one, but it's much easier to understand now! :crazy_face:
Thanks for the explanations and the simplified macro!
Even if going through the windows APIs remains complicated to center a simple window, it remains the only viable solution in any case (multi-workstations and different screens)

Hello @sbadenis ,

Satisfied to see that this suits you...

As for the use of Windows APIs, there are no other solutions since Windows manages the windows of the various applications. SolidWorks itself, when it returns the positions and dimensions of its own window (FrameLeft, FrameWidth, etc.), is probably using Windows APIs.

We could probably " hide " the two functions of the IdentFenetres module in a dll, which would allow the module to be removed and leave only two lines in the macro to center the UserForm.
But it's the installation on different workstations that would become tricky: location of the dll, registration in the Windows registry). The advantage of the macro is to be completely autonomous from the point of view of installation.

Kind regards.

2 Likes

Yes indeed it's quite possible, it's just weird that solidworks hasn't implemented something to simplify this feature, via a dll for example!
And it will just make me yet another module in my macro which is already well supplied, nothing to worry about.
And thank you again.

1 Like