Making a UserForm behave as a Tool Window for another process

fitzmorrispr

New Member
Joined
Sep 6, 2024
Messages
4
Office Version
  1. 365
Platform
  1. Windows
Hello

I have followed @Jaafar Tribak 's excellent work in Display Userform in TaskBar with custom Icon and Hide Excel (mimicking a standalone application) to make a userform that appears as a standalone application. It's connected to an instance of SolidWorks through its VBA api. By running the workbook that contains it with the /x, /s, /r and /e switches, the form doesn't get in the way of normal use of excel.

I show the userform in my Workbook_Open sub. I am ashamed to admit that at first, I used Resume Next and a loop that ends when err.number = 0 to show the form, having forgotten about load statements.

The problem:
My userform disappears into the shuffle of windows as I work with browser windows, and though it's easy enough to bring it back to the top with its taskbar button, the point of it is to be in easy reach whenever SolidWorks has focus, serving as a floating toolbar.

I thought I might be able to get it to tie itself to SolidWorks through the windows api using SetParent, and there were no errors when I tried, but the userform window became completely invisible. (incidentally, the hwnd for SolidWorks was obtained from its API, so calling the SetParent function was trivial)

Unfortunately, I have lost the code I had added but it was literally just a Private Declare and a Call.

I suspect that the problem was perhaps partly a result of the window styles and extended window styles that are set on a UserForm window, but I suppose it could be something Solidworks did.

I've been working in Excel for this because the VBE built into the rather old copy of SolidWorks I'm provided with causes it to crash whenever a macro is run from inside it. External macros work perfectly, however. This is due to an incompatibility between Office 365 and SolidWorks 2013, as the problem never occurred when we had Office 2016

I have made some progress on my research into this, and I'm feel I could trial and error my way to a working solution, but I figured I should not be going solo on this

presently, the styles set on my userform are:
Code:
WS_BORDER, WS_CAPTION, WS_CLIPSIBLINGS, WS_DLGFRAME, WS_GROUP, WS_MINIMIZEBOX, WS_OVERLAPPED, WS_SYSMENU, WS_TILED, WS_VISIBLE, WS_EX_DLGMODALFRAME, WS_EX_LEFT, WS_EX_LTRREADING, WS_EX_RIGHTSCROLLBAR, WS_EX_WINDOWEDGE,
 

Excel Facts

Which came first: VisiCalc or Lotus 1-2-3?
Dan Bricklin and Bob Frankston debuted VisiCalc in 1979 as a Visible Calculator. Lotus 1-2-3 debuted in the early 1980's, from Mitch Kapor.
Well, it's not what I was trying to do, but I have a sort of solution
SolidWorks emits an IdleNotify event, which I am already listening to.
I can do the following to bring my form to front whenever SolidWorks is in front:

in the userform:
VBA Code:
Private Function swApp_OnIdleNotify() As Long
    Set swFrame = swApp.Frame
    If Not moving And isForeground(swFrame.GetHWndx64) Then moving = True: MoveUp Me: moving = False
End Function

Added in to the toTaskbar module I got from the aforementioned post by Jaafar:
Private Declare PtrSafe Function IUnknown_GetWindow Lib "shlwapi" Alias "#172" (ByVal pIUnk As IUnknown, ByVal hwnd As LongPtr) As Long 'definitely not my addition, necessary for this to work
Private Declare PtrSafe Function GetForegroundWindow Lib "user32" () As LongPtr 'probably not my addition, also needed
Private Declare PtrSafe Function SetWindowPos Lib "user32" (ByVal hwnd As LongPtr, ByVal hwndAfter As LongPtr, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal uflags As Long) As Long
Public Function isForeground(hwnd)
isForeground = (GetForegroundWindow() = hwnd)
End Function

Public Sub MoveUp(form)
Dim hwnd As LongLong
Const HWND_TOPMOST = (-1)
Const HWND_NOTOPMOST = (-2)
Const SWP_NOACTIVATE = &H10
Const SWP_NOMOVE = &H2
Const SWP_NOSIZE = &H1

Call IUnknown_GetWindow(form, VarPtr(hwnd))
Call SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOMOVE Or SWP_NOSIZE) 'make "always in front"
Call SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE Or SWP_NOMOVE Or SWP_NOSIZE) 'undo that, but this leaves it where last call moved it to
End Sub
 
Upvote 0
With Apologies for the stream of posts

This is actually good enough for me, but it might be useful to another to have a real answer

though, i'd like also to make it always enabled for input, even when not focused
 
Upvote 0

Forum statistics

Threads
1,224,811
Messages
6,181,080
Members
453,021
Latest member
Justyna P

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top