Does anyone remember a program called Perfect Menu? It allowed you to attach shortcut taskbars to the right-click context menu in Windows. The company that developed it, for some reason, no longer sells or supports it. The last version was available 18 years ago. It runs in Windows 10, but it has a problem that prevents it from saving the settings. I'd like to find a way to re-create this program using Liberty BASIC, if it's possible.
My experience is limited, and I'm not looking for anyone to do it for me, but I thought it might be an interesting challenge for some folks here, and I'd really enjoy learning how. I suspect it may be as easy as a DLL call, but in my limited experience, I couldn't figure it out.
Anyone interested? ...Pretty please! Any hints or tips would be greatly appreciated.
P.S.: I also have an idea for reviving a really useful program called TreePad which died a similar fate recently.
Post by Chris Iverson on Dec 20, 2019 14:13:15 GMT -5
Do you have a link to the program? If it was available 18 years ago, and never updated since then, then I suspect I know what the issue is. (Although there are probably additional issues nowadays, anyway, like display scaling.)
As for doing it in LB, I have a couple of ideas on how it could be done, but it probably wouldn't be as responsive as that program likely is, since it would involve lots of manually searching the "currently open window" list. (All GUI display objects on Windows, including menus, are implemented as "windows". A menu opening up would appear as a new window being created.) You'd also have to keep searching the list to see if the menu you're currently "attached" to has been closed, so you can close your windows.
The "proper" way is to use a window creation hook, which notifies your program every time a window is created, but that requires a separate DLL to use properly. This is also an additional problem in that 32-bit DLLs can't be injected into 64-bit processes, and vice-versa, so you have the possibility of missing notifications. You could also do a CallWndProc hook, and filter it down to window creation messages for the popupmenu class, which would eliminate the 32/64-bit issue, but you'd still need a separate DLL for that. LB simply wouldn't have the ability to keep of with the flood of notifications that would generate.
I think an accessibility hook would also work, but that would also basically require a separate DLL since it needs to use COM to access the IAccessible interface. (It's possible to use COM directly from LB, but very wonky.)
Sorry if this is getting a bit off-topic. I'm genuinely interested in how Liberty BASIC handles DLLs, particularly in this specific situation.
In a vain attempt to try to lean something about DLLs, I found a program called DLL Export Viewer that lets you either load a DLL to list its internal functions or select a running program to list the DLLs it's using.
I was able to dig out the functions from the only included DLL in the Perfect Menu package (_mpdll.dll). They are as follows:
I have no idea what these mean or how they might work, but I do see some key words like "Mouse" and "hook". (I'm really showing my ignorance here.)
If I do a similar search of all DLLs accessed by the running program, I get a long list of DLLs that includes a number of usual suspects. But there are two entries listed for the running program. One is pmenu32.TMP0 and the other is the expected pmenu32.exe. The .TMPO appears to access fewer DLLs than the .EXE. Below are listed the DLLs for the .TMPO. After that, are listed the additional DLLs listed for the .EXE.
Post by Chris Iverson on Dec 21, 2019 20:43:39 GMT -5
Well, I was trying to confirm my guess, but if I can't get it to run, I won't be able to confirm it.
Still, at least I can make the guess public.
There's two ways a program can save settings. Files, or the registry.
Considering this was developed as a Windows 95/98 program, I doubt it uses the registry. It's more likely that it'll use something like an .ini file.
Most programs of that era either stored their settings as an INI file in the Windows folder, or stored it as an ini file in the program's folder. This worked fine on 95/98, because there was no security on the system at all. Anyone could do anything.
What I'm guessing is that it can't save the file properly because modern security configurations prevent general users from making system-wide changes. To confirm that guess, I was going to run the program as Administrator to see if it's able to access the file it needs, and then I was going to find the file itself, and modify the permissions on it to allow everyone to edit it.
Basically, my two suggestions are exactly that:
Run the program as Administrator. This can be considered a fix if you're willing to do that each time.
Find the config file, and grant "Write" or "Full Control" permissions on it to Everyone.
I appreciate your effort, though my concern is not about it's ability to save the settings. It's a moot issue, since I can't register it out of the 30 day trial.
You are correct about the .ini file. It does exactly that. But it also hides the registration info in the registry.
My motivating concern is how to replicate this function in Liberty BASIC. It's so far above my head I don't even know how to start. My guess is finding the right DLL functions. But that's the extent of my understanding so far.
Post by Chris Iverson on Dec 22, 2019 0:27:50 GMT -5
Well, the most basic version of this I can think of involves using a timer to constantly call the FindWindowA() API looking for any window with the class "#32768".
If you find an existing window of that class, that means a menu is open. You can use the handle returned by FindWindowA() in an API call like GetWindowRect() to find out where on the screen it is. Using that information, you can open up an LB window relative to where on the screen the menu is.
Even while the window is open, though, you'll want to keep the timer going, because once that menu stops being found, that means the menu has been closed, and you'll want to close your window as well.