Has anyone figured out a way to have a macro read and change the setting for "Keep Desktop Objects on Layer" which is found on the Objects docker, "Gear"/settings menu? I would love to be able to check and change this using VBA.
If I understand correctly, "Keep Desktop Objects on Layer" is an application preference. As an example, I see in the Windows Registry a key named KeepDesktopObjectsOnLayer under Computer\HKEY_CURRENT_USER\SOFTWARE\Corel\CorelDRAW\23.0\Draw\Application Preferences\VGDoc Pref Settings.
As an aside: I really, really wish that they had made that a document property instead of an application preference.
I think that there is something in the API for checking and changing application preferences. See Application.GetApplicationPreferenceValue method and Application.SetApplicationPreferenceValue method.
I have messed aroud a little bit trying to use those methods for other settings, but never achieved success. If you learn more about using those methods, then please share, as I would love to learn more about them.
Eskimo, I'm almost there. You're discovery of the Registry value for this setting was the key. After seeing that I thought, Hmm, I wonder if there is a way to edit Registry settings using VBA. Turns out, there is!
I wrote a quick macro that will read the Registry value for "KeepDesktopObjectsOnLayer" and then toggle it on or off based on what it finds. And it actually works. If you paste the script below into a module and step through the code using F8, you can see it do its thing. And if you have the Registry Editor open to this key and press F5 to refresh the window after running the script, you can see that it has changed the value.
Unfortunately, CorelDraw isn't aware that the setting was changed externally, so it remains the same. Closing CorelDraw will also overwrite the Registry value with whatever it was left as in the program.
So I'm wondering if you can figure out away to refresh/reload the application settings (or at least that value) with the update from the Registry. That will be the solution.
Here is my script:
Sub ToggleKeepDtObjOnLayer()'Toggle the CorelDraw application setting: Keep Desktop Objects on LayerOn Error GoTo OopsDim WS As ObjectDim RegKey As String, Value As Variant, sType As String'REG_SZ A string'REG_DWORD A Number An integer'REG_BINARY A binary value An integer'REG_EXPAND_SZ An expandable string (e.g., "%windir%\\calc.exe") A stringSet WS = VBA.CreateObject("WScript.Shell")RegKey = "HKEY_CURRENT_USER\SOFTWARE\Corel\CorelDRAW\23.0\Draw\Application Preferences\VGDoc Pref Settings\KeepDesktopObjectsOnLayer"If WS.RegRead(RegKey) = 0 ThenValue = 1ElseValue = 0End IfsType = "REG_SZ"WS.RegWrite RegKey, Value, sType
Done:Set WS = NothingExit Sub
Oops:MsgBox Err.Number & ": " & Err.DescriptionResume DoneResume 'For debuggingEnd Sub
The registry entry is probably just a place where CorelDraw saves setting after the program exits. And changing this value will not affect the current state.
CorelDraw certainly saves the setting in the Registry when it closes, but it must also read it from there when it opens. My hope is that I can find a way to make it read and update this one setting while already running without having to do the equivalent of reloading an entire Workspace full of settings.
Try this:
Application.FrameWork.Automation.InvokeItem "53861e80-f191-4a0f-beaf-99c4f20aee44"
I ran this code twice and each time it toggled the "KeepDesktopObjectsOnLayer" state
Shark - you're awesome, dude! One line of code does the trick. Where do you find those long strings and know what they do?
Here is my revised script allowing the user to change this setting via macro as needed.
Sub KeepDesktopObjectsOnLayer(bKeep As Boolean)'bKeep (True/False): Keep Desktop Objects on Layer (On/Off)On Error GoTo OopsDim WS As ObjectDim RegKey As String Set WS = VBA.CreateObject("WScript.Shell") RegKey = "HKEY_CURRENT_USER\SOFTWARE\Corel\CorelDRAW\23.0\Draw\Application Preferences\VGDoc Pref Settings\KeepDesktopObjectsOnLayer" If WS.RegRead(RegKey) <> bKeep Then 'If the setting does not match with the request, Application.FrameWork.Automation.InvokeItem "53861e80-f191-4a0f-beaf-99c4f20aee44" 'toggle the setting End If
Done: Set WS = Nothing Exit Sub
Oops: MsgBox Err.Number & ": " & Err.Description Resume Done Resume 'For debugging End Sub
shark, I'm having a problem with my macro. It will correctly perform the operation the first time it needs to change the setting.
If the user specifies True as the parameter and the setting is already True, it does nothing.If the user specifies False and the setting is True, the macro turns the setting off.
But on subsequent runs, the macro doesn't seem to be able to read the newly changed setting in the Registry, and so it is not able to perform as needed.
Do you know if there is a way to directly specify True or False when using your InvokeItem command rather than simply having it blindly toggle the setting?