Using variables dynamically named for a window

I've looked at other forum posts on dynamically named variables, but I can't figure out from them how to do what I want to do, so -- new post.

I have a macro (call it "make-changes" for simplicity) that takes note of certain characteristics of the front window, stores that info in global variables, and then resizes and otherwise alters the window so that I can do some tasks more conveniently. I have another macro ("revert-changes") that undoes those alterations, using the previously set global variables to restore the initial values.

(To be more specific, in case it matters somehow: I do a lot of complicated text editing in MS Word using Track Changes. I'm usually working in Draft view with windows narrow enough to see several at a time across my two monitors; but when I want to insert a comment, it's easier for me to do so in Print view with the window wide enough to see the entire text plus the comment area, and I also don't want tracked changes showing for this. So I have a first macro that notes the current window frame, whether Track Changes is active, whether tracked changes are showing, the current zoom and horizontal scroll percentages, and what the view type is; and then it enlarges the window, changes all the view options, and inserts a comment ready for me to type into. When I'm finished composing the comment I can trigger the second macro to restore the window to whatever size, position, view, etc. it was originally in. But these details probably don't matter; the principle is the thing.)

I can't use local variables for this, because "make-changes" and "revert-changes" are two different macros. I can't combine them into one macro that either makes or reverts changes depending on circumstances, for complex reasons having to do with my workflow.

My problem is that if I run the "make-changes" macro in one window, and then want to run it again in another window before I've run "revert-changes" on the first window, the second call to "make-changes" overwrites the global variables. So, since I can't associate the variables holding the initial values with a specific instance of the macro, I want to find a way to associate them with their window.

So I'm wondering if it's possible to create global variables whose name includes the name of the window they pertain to. When "make-changes" is triggered when the front window is named Main Document, it would set global variables named Main Document Frame, Main Document View Type, Main Document Changes Visible, and so on; when it's called when the window is named Bibliography, it would set global variables named Bibliography Frame, Bibliography View Type, Bibliography Changes Visible, and so on. And then when "revert-changes" is triggered, it would use the global variables containing the name of the front window.

For extra fun, I usually have two or three windows open on the same document, which means that the front window name may well look like "Main Document.docx - 1" or "Main Document.docx - 2". Is the dash going to cause problems if it's part of a variable name?

Is it possible to do this? Or is what I've got as good as it gets? (And it's pretty damn good; every time I run these macros, which is twenty to sixty times a day, I bless Peter's name :slight_smile: ) Thanks for any suggestions!

@Shoshanna Yes, it is possible to do what you want, though with the caveat that restoring window size and position isn't instantaneous the way it is with your current macros.

It's actually very easy to create dynamic variables, as you can see if I run this sample macro while working in the KM Editor:

Save Front Window Frame.kmmacros (1.1 KB)
image
Results
19%20AM

The real trick is making use of these dynamic variables, at least for window frames, since the Use Variable action doesn't let you use tokens in the same way:

image

The way I figured out to get around this was to loop through all the variables with the For Each action and the variables collection, then use a Switch/Case action to have the macro do what you want for each variable as appropriate. I don't know how your macros reference and set View Type or Changes Visible in Word, so I've only included actions to set the window frame here, but hopefully this should be enough to let you adopt your current macros to this dynamic version:

Revert Front Window Changes.kmmacros (3.1 KB)
image

Yes, it is possible.
However, that is not the design I would choose. :wink:

Here's a design pattern I use in several of my macros. If you think it might work for you, I'll provide more details:

  • Use a Global Variable that stores data in this format, with one line per each Item value you wish to store
    • <AppName>\t<WindowName>\t<ItemName>\t<ItemValue>
  • For example:
MS Word\tMain Document\tMain Document Frame\t1234,456,12,34
MS Word\tBibliography\tBibliography Frame\t9876,888,56,78

where "\t" represents the TAB character.

  • Then using KM Search Action and Replace Action with RegEx, you can easily Get, Set, Add, Delete the Items (lines) you want.

One macro I have that uses this pattern is my "Move and Set Window Size Per App & Win Name" macro. Here's some data:

APP_NAME,WINDOW_NAME,TOP,LEFT,WIDTH,HEIGHT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Acrobat,ALL,0,24,1088,1122
Atom,ALL,2053,23,1024,1125
Audacity,ALL,2048,24,1038,939
BBEdit,ALL,0,23,815,1125

In this case I am using the comma as a field delimited, but I recommend using the TAB. You may not need the "AppName" field.

Here is the KM Replace Action to change the data for a particular window:
image

Here is the KM Search Action to get the data for a particular window:
image

Then I use the data for this window to move & resize it:
image

Does this sound like something that would work for you?

2 Likes

Thanks, that's a clever trick! I think it would be computationally expensive, though. I'm going to pursue the tack JMichaelTX offered, but I do appreciate your suggestion!

1 Like

Holy moly, that is cool. It's a way of using a variable that hadn't ever occurred to me. Yes, I think that has definite possibilities, though I'll have to dig into regex syntax more than I've done till now... I'd be very glad to see the "more details" you offer!

My "make changes" macro will have to first delete any line in the global variable that already refers to the current front window. I can't put that in "revert changes", because sometimes I manually adjust the window further instead of using the revert macro. So "make changes" will delete any old line referring to the front window and then write a new line with current values. And "revert changes" will extract the relevant line from the global variable, parse that line to find the relevant values, and apply them to the window. Sounds simple enough. Now I just need to figure out how to implement it...

OK, let's start with my existing macro, which I have just uploaded:

MACRO: Move and Set Window Size Per App & Win Name

If you need help using the design pattern in that macro, feel free to ask. The more specific/focused the questions the better.

Heh, thank you -- but in the end it only took me two hours to get everything up and running on my own, before I even saw that you'd uploaded this! Mine is definitely more of a kludge than yours; I'm going to look closely at how you update the window list, because I had to hack it a bit and put in a separate step to get rid of blank lines left behind, which don't actually interfere with anything but which annoy me. But I figured out how to construct the regexes -- mostly -- and just finished running the set of related macros through a bunch of tests, and everything seems to be working just as I want it.

I'm also going to copy your cleanup routines; they're really nice.

3 Likes