Get all macros from Microsoft Word (using automation) - c++

I'm writing a C++ MFC program which automate MS Word using their interfaces.
From my app I was able to open MS Word, open macro window but I need to retrieve all macros from a combobox and add them in my app and so later on user can choose which macro he wants to apply to some document.
Can retrieving be done with GetProperty method? If it can you can show me an example?

You can use Document.VBProject to get access to the VBA code (to get to the macros in the document). Here is how to do it in word using VBA/C#. You can just rewrite that code using C++.
Note that MFC is not the easiest way to work with word automation, but you can do it using MFC as well. There is more than one approach available when you do automation with MFC. You may do this with MFC-only-way (i.e. in style from 90x, using object wrappers), or use e.g. #import directive.
GetProperty is basically a generic method, which can be to get some properties of the object it is applied to, i.e. it is not specific for macros.
Note also that end-user must have "Trust programmatic access to VBA project" enabled to allow your code to get the macros (this is a checkbox in word security settings, turned OFF by default). May be a show-stopper.

Related

How to prevent the running of auto macros when starting ms word in c++ automation

I'm generating thumbnails for office files using c++. I open and save the files using automation similar to this: https://support.microsoft.com/en-us/kb/179494. Since there are many files, this takes a lot of time and the program should run through the night.
Everything works fine, except when a file contains an auto start macro, which doesn't even exist.
Sub AutoOpen()
Application.Run ("stupidMacroWhichDoesntExist")
End Sub
In this case, the Loop stops, and an error message appears that the macro couldn't be executed.
Off Course, I have set the macro settings in the trust center to -> disable all macros without notification
The error message still appears
In Excel, I can prevent this with:
objExcelApp.SetEnableEvents(false);
Unfortunately, the word application in c++ doesn't have a SetEnableEvents method. I have googled a lot and found a lot of VB Code to prevent this. Mostly it was something like:
objWord.WordBasic.DisableAutoMacros 1
But I haven't found anything in c++
I'm very thankful for your help.
I believe you're looking for:
WordApplication.AutomationSecurity = msoAutomationSecurityForceDisable
The Trust Center setting doesn't apply to documents being opened using automation. This property and its MsoAutomationSecurity enumeration correspond to that setting in the object model.
FWIW the WordBasic approach should also be possible using C++. I don't know C++ syntax, but with C# I'd need to use PInvoke (GetType().InvokeMember) to communicate directly with the IDispatch (I think that's the right term).
I have solved it. I'm backing up the actual macro (vbaData.xml and vbaProject.bin in the word folder), put a dummy macro into the word file, open it via automation and save it to generate the thumbnail. After that, I put back the backed up macro into the word file.
Since the dummy macro does nothing I am safe that nothing will be executed, whatever is programmed in the original macro.

Using a dialog box to graphically retrieve user input

I am not new in C++ but this is my first time developing a Win32 program. It has to be graphical and so I have been attempting to get user input using an input/dialog box with no success.
I have read this topic on MSDN and found it helpful, but I get an error about IDD_PASSWORD and IDE_PASSWORD not being defined. Declaring them in resource.h and giving arbitrary values (like 110, 111) yields no results. Other attempts I have tried to modify the auto-generated about box, which also yields no results after modification, I noticed that if i change the value of IDD_ABOUTBOX in resource.h from 103, this also does not work. I also tried using the .rc under Resource View, but still no results.
So I'd like to know if the resource box templates have predefined constant numbers that i have to use, if so where because I searched that too or if there is another way to obtain user input in a windowed application. I just want to obtain an integer, that's all.
There is nothing magic in the numbers assigned to resources. The numbers are what the code actually uses to identify the resources. Visual Studio just allows you to assign symbolic names to those numbers through the use of C macros (i.e., #define) to make your code easier to read. These values are all defined in the file resource.h by convention, and although you can modify that file manually, you usually should not do so—let the Visual Studio Resource Editor handle that for you.
The problem you're running into is that you actually have to create those resources first before the numbers will mean anything. When you create a new Win32 project, Visual Studio will automatically create an about box dialog and give it the symbolic ID IDD_ABOUTBOX. However, there is no such IDD_PASSWORD dialog created by default in a new project, and there isn't one built into Windows.
You can create this dialog yourself using the Dialog Editor (part of Visual Studio's Resource Editor), which is pretty easy to do as it allows you to drag controls around on the dialog where WYSIWYG. When you add a new dialog box to your project's resources, you will be given the option to name it anything you like. You can use IDD_PASSWORD if you want, or any other name. A numeric ID will be assigned automatically based on an algorithm; generally the lowest available number is used.
The article you linked to is assuming that you have already added a dialog to your project with the symbolic name IDD_PASSWORD (which is probably a mistake on the part of the author). All it shows you is how to display that dialog once it exists as part of your project's resources.
It's going to be somewhat difficult to learn Win32 programming just by reading the MSDN documentation. I strongly suggest getting a book that explains it more clearly and in a more logical order. The canonical text is Charles Petzold's Programming Windows, 5th Edition. Note that you will need to make sure you get the 5th edition, as the newer editions digress from their Win32 roots and start talking about completely unrelated things like C# and Silverlight.
If you absolutely must learn by trial-and-error and MSDN, start reading about dialog box resources here.

C++ - Writing to a specific output window pane in VS2010

I'm trying to write to a custom Output Window Pane, but the only examples that I can find for writing to the output window automatically write to the Debug pane.
I've gotten as far as creating a custom pane with a VS add-in in C#, and writing text to it when VS2010 starts up. I'm working in a C++ project, and I'm just wondering how I can write to my custom pane from anywhere in code. I'd like to do it with as little overhead as possible, because I am working in a larger code base that I don't want to have to heavily modify.
Thanks
The Debug pane shows results of OutputDebugString calls (either direct, or by Debug.WriteLine / Trace.WriteLine) (it serves the same purpose as dbgview.exe from SysInternals). This is default behavior of the IDE. I think, that writing to custom pane may require implementing your own extension for Visual Studio.
As a workaround, you may use dbgview, define specific prefixes (as [MODULE-A]: , [MODULE-B]: etc.) and set filters to highlight occurences of specific words. Note, that dbgview will work properly only if you run your program without the IDE.

VC++ 10 MFC: What is the correct way to do localization

I am a .NET guy who is having to do some work on an MFC app. The app is a VS2008 MFC executable which I have converted to VS2010. The original developers did localisation by specifying the name of a .txt file with key value pairs in it on the applications command line. Installed shortcuts to the executable specify a different .txt file depending on which country the app is being installed in. This of course does not work if you just run the .exe directly. This seems like a weird way to do things to me.
I want to do this the propper MFC way, but I am having difficulty finding definitive answers on Google. My understanding is that the String Table in the .rc file should be used for this localisation? Is this the current best practice for MFC?
With respect to the String Table I have read that the practice is to create multiple string tables each for a different language. How do MFC applications choose which language to use? Is it based on the machines current language settings or can I control this (it may be that we want the language to be specified by the Wix .msi installer we are also building)?
I have also read that embedding all resource inside an MFC application has fallen out of favor and that now you should compile seperate resource .dlls? Is this is true ill investigate how to do it...
Finally, do I have to do something special to get MFC to support Unicode or is MFC Unicode by default?
Thanks
The idea is that all localizable items should be stored in resources. Standard UI objects such as menus and dialogs are automatically stored in there (resources) for you but items such as string literals (eg: error messages, messagebox prompts,...) should be pulled from source code to the string table. This short codeproject article of mine demonstrates how to easily pull strings from the string table in your code.
Note: You should have only one string table in your resource script (.rc).
From there on, you can translate your resources and create resource DLLs (aka satellite DLLs). The idea is that you keep a different copy of the .rc file(s) for each language. Each translation is compiled into a codeless DLL that acts as a container for the resources.
This other codeproject article of mine lets you easily load resource DLLs according to system settings or user preferences: The code looks among your resource DLLs which available language best matches user settings (based on user's UI language and regional settings). The code also lets you easily build a menu with all available languages. That way, your user can override the default choice.
DISCLAIMER: My ad follows. Feel free to skip :-)
Regarding the translation of resources, the management of translations and the creation of resource DLLs, you may want to check out appTranslator.
END OF AD :-)
Regarding Unicode, MFC ships with ANSI and Unicode versions of the code. It's up to you to choose if you want to build an ANSI or a Unicode app: Just make your pick in the first page of project settings. Of course, if you are startgin from scratch, you should definitely go Unicode. But if legacy reasons force you to stay ANSI/MBCS, don't worry to much: It won't prevent you from localizing your app.
Years ago when I had to work with multiple languages in MFC, we used separate resource DLLs. All you need do is make one call to switch which handle the resource functions would use and all was automatic from that point forward.
You need to do more than just change the strings. Dialogs in particular will have strings inside of them, and you may need to change the layout if those strings become too long after translation.

How to implement "record macro"-like functionality similar to Microsoft Excel?

How to implement "record macro" like that in Microsoft Excel? As far as I know, I can embed a scripting interpreter(eg. javascript) and make c++ objects visible to scripts, similar to the DOM in a web browser.
My question is how do you record user actions and then generate the corresponding javascript code? In Excel we can record a macro and it will generated the appropriate VBA code.
Does someone know how to implement this feature in C++ or in other languages?
PS: Can be any language/platform -- I just want an idea of how to do it.
One way to do it is have dual event handlers for each menu item / button click.
As the standard event handlers fire, your secondary macro-builder events fire.
As the macro event builders fire you record a list of actions performed
e.g.
ActiveDocument->Save.
ActiveDocument->SaveAs.
ActiveDocument->Print.
Find (AllDocument,"ThisText").SelectFirst
Edit.Cut
Find().SelectNext
You can then translate those actions into your desired scripting language.
Hope this helps.
Have a look at the Command Pattern. Each action in the program can be represented by a Command object. So when you're recording a macro, you both perform the command and store it in a list. When you want to play back the macro, you simply run through the list you created, performing every command again.
You don't necessarily even need to use distinct objects, though it will probably be easier in the long run. As an example, Emacs has keyboard macros that simply record every keystroke, then simulates those keystrokes when you play the macro back.