Introduction
How often do you edit a series of code fragments that are redundant? Where you will repeat the same
steps over and over, adding the same formatting around a simple list of items, or making the
same changes to each function in your file? Visual Studio's IDE contains a feature that will
allow you to easily convert this repetitive task into a simple quick process. The feature is
called Quick Macros.
This is a feature that I was not aware of how to use until I saw another keyboard savvy developer
use it. I am writing this article to make sure that everyone on CodeProject is aware of
this feature as well.
Process
The Quick Macro is found under the Tools menu. In order to use the Quick Macro you
will first need to record a macro (CTRL + SHIFT + R), then play it back (CTRL + SHIFT + P).
The keyboard commands listed are the defaults for the Visual Studio IDE.
Record Quick Macro
The most important thing is to properly record the macro in order to make it work repeatedly
without any intervention on your part. This will allow you to play back the macro as fast as you
can type (CTRL + SHIFT + P).
In order to record the macro you must:
- Decide the common set of operations that need to be applied to each item.
- Decide the best plan of action to accomplish your task.
- Start recording by selecting Tools | Record Quick Macro or (CTRL + SHIFT + R).
- Enter all of the editor operations that you want to repeat in your quick macro.
- Stop recording by selecting Tools | Record Quick Macro or (CTRL + SHIFT + R).
What sort of things can you do with the quick macro? Basically anything that you can do with the keyboard.
It is very helpful if you know all of the commands to help you navigate in your editor with the keyboard.
I have found that I am able to use the most basic keyboard commands in order to accomplish some very creative
macros:
- Arrow Keys.
- Home (odd number of times): Moves the cursor to the beginning of the indented text on the current line.
- Home (even number of times): Moves the cursor to the beginning of the line.
- SHIFT + Arrows: Select characters or lines.
- SHIFT + HOME: Select from current position to the beginning of the line.
- SHIFT + END: Select from current position to the end of the line.
- CTRL + X or SHIFT + DELETE: Cut selected text.
- CTRL + C or CTRL + INSERT: Copy selected text.
- CTRL + V or SHIFT + INSERT: Paste selected text.
- CTRL + SHIFT + Arrow: Select complete words on the current line.
- CTRL + F: Bring up the find dialog and start a search.
- F3: Search for the next instance of the previous search.
I am sure there are others that I use, but these are the most common, and I am able to accomplish most tasks
with these keyboard commands.
Play Quick Macro
Playing back the macro is the easiest part. After all of the hard work that has been used to create
the macro, you can sit back and type (CTRL + SHIFT + P) as many times as you need until your
repetitive task is complete.
Examples
Here are a few examples to show where I have found this feature is useful, and step by step
explanations on how to use this feature.
Example 1
Say you have created an enumeration with a different number of elements. Then you want to create a switch
statement that contains a handler for each of these enumerations. For only a few items this would be a simple
task, however if you have 10 items or more, this just becomes tedious.
enum QuickMacro
{
ITEM1 = 1,
ITEM2,
ITEM3,
ITEMN
};
Given this example, I would copy the ITEM list to be inside of the switch statement before you start
recording the macro.
switch(value)
{
ITEM1 = 1,
ITEM2,
ITEM3,
ITEMN
}
Place your cursor at the beginning of the first ITEM and start recording (CTRL + SHIFT + R).
- Type "case ".
- Hold (CTRL + SHIFT) and move the cursor to the right, this will select the entire variable ITEM1.
- Move the cursor to the right with the right arrow key and now you will be at the end of the variable ITEM1.
- Type ":" + return + "{" + return + tab + "break;" + return + backspace + "}".
- Type (SHIFT + END) + Delete, this will erase the rest of the text at the end of this line.
- Move the cursor down one line, and hit HOME to move the cursor to
the beginning of the text for the next variable.
Stop recording with (CTRL + SHIFT + R). At this point your text will look like this:
switch(value)
{
case ITEM1 :
{
break;
}
ITEM2,
ITEM3,
ITEMN
}
Play back the Quick Macro with (CTRL + SHIFT + P) until all of the items have case handlers.
This is the final result.
switch(value)
{
case ITEM1 :
{
break;
}
case ITEM2:
{
break;
}
case ITEM3:
{
break;
}
case ITEMN:
{
break;
}
}
Example 2
The second example requires copying, pasting and searching for text. This is a set of function pointer variable declarations that
will be created from the original type definitions for the function pointers.
typedef HDC (*pGetDC)(HWND hWnd);
typedef HDC (*pGetDCEx)(HWND hWnd);
typedef HDC (*pGetWindowDC)(HWND hWnd);
typedef HWND (*CreateWindow)(LPCTSTR lpClassName, LPCTSTR lpWindowName, ...);
- Copy the
typedef
listing to where the member variables will be pasted.
- Move the cursor to the first line of the
typedef
s.
- If the text was preformatted we could simply move the cursor over to
the beginning of the function pointer. However
the text is not preformatted so we will need to search for
the beginning of the pointer name. Notice how there is
a * before each name.
Use the * to find the beginning of the pointer name. Type (CTRL + F) + * + return.
- (SHIFT + HOME + HOME) + Delete + Delete. This will delete all of the text
before the pointer name including the *.
The text will now look like this:
pGetDC)(HWND hWnd);
typedef HDC (*pGetDCEx)(HWND hWnd);
typedef HDC (*pGetWindowDC)(HWND hWnd);
typedef HWND (*CreateWindow)(LPCTSTR lpClassName, LPCTSTR lpWindowName, ...);
...
- The next goal is to copy the name of the function pointer. We could select each of the 6 characters for the
current pointer, however, not all of the pointers names are 6 characters long. Therefore we will need to do another
search. Type (CTRL + F) + ")", This will find the end of the pointer name.
- Type (SHIFT + HOME) + (CTRL + C) This will copy the name of the variable to the clipboard.
- Move the cursor to the right once. This will move the cursor to the end of the variable name. Then
Type (SHIFT + END) + Delete. This will delete all of the text after the pointer name.
- Type tab + tab + tab + "m_". This will add formatting and the beginning of the variable name.
- Paste the name of the variable with (CTRL + V) and type ";".
- Move the cursor to the next line and the beginning the text by hitting the HOME key.
End the recording session with (CTRL + SHIFT + R). Now play back the macro as many times that is needed with
(CTRL + SHIFT + P). This is what the text will look like after playing back the macro
(after formatting).
pGetDC m_pGetDC;
pGetDCEx m_pGetDCEx;
pGetWindowDC m_pGetWindowDC;
CreateWindow m_CreateWindow;
...
Limitations
The only limitations that I have found so far is when I would like to increment an index or some other number
on each new line. What I have done in this situation is used a default number like one, and then incremented
by hand afterwards.
Conclusion
This is a nice feature that has one specific use, making repetitive editing tasks simpler.
I think this feature is very convenient when you find the right place to use it. In some cases
it may be faster and easier to simply type out the repetitive changes. However, this is a
feature that I have gotten better at using over the years. So the more you practice with it hopefully the
better you will become with it as well!
I am a software architect and I have been developing software for nearly two decades. Over the years I have learned to value maintainable solutions first. This has allowed me to adapt my projects to meet the challenges that inevitably appear during development. I use the most beneficial short-term achievements to drive the software I develop towards a long-term vision.
C++ is my strongest language. However, I have also used x86 ASM, ARM ASM, C, C#, JAVA, Python, and JavaScript to solve programming problems. I have worked in a variety of industries throughout my career, which include:
• Manufacturing
• Consumer Products
• Virtualization
• Computer Infrastructure Management
• DoD Contracting
My experience spans these hardware types and operating systems:
• Desktop
o Windows (Full-stack: GUI, Application, Service, Kernel Driver)
o Linux (Application, Daemon)
• Mobile Devices
o Windows CE / Windows Phone
o Linux
• Embedded Devices
o VxWorks (RTOS)
o Greenhills Linux
o Embedded Windows XP
I am a Mentor and frequent contributor to CodeProject.com with tutorial articles that teach others about the inner workings of the Windows APIs.
I am the creator of an open source project on GitHub called
Alchemy[
^], which is an open-source compile-time data serialization library.
I maintain my own repository and blog at
CodeOfTheDamned.com/[
^], because code maintenance does not have to be a living hell.