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.
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
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
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.
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
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.
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.
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!
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:
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'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
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.
Hello @tous @m.blt your macro surpasses 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 ) Macro1.swp (76 KB) Macro2.swp (56 KB) Doc1.pdf (237.9 KB)
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)
Sorry, I'm a fan of the adage " Why make it simple when you can make it complicated? ".
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.
It works perfectly as for the previous one, but it's much easier to understand now! 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)
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.
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.