Friday, February 01, 2008

Workaround: Mouse Sensitivity Settings Lost after Laptop Re-dock

Issue: After undocking and then re-docking my Thinkpad T60 laptop (running Windows XP), my custom sensitivity settings for my external Logitech mouse (an MX500) are lost; in particular, the mouse cursor acceleration effect is gone, and the base speed of the movement of the mouse cursor increases significantly.

(Since I run dual high-resolution monitors, I find it very useful and comfortable to set the base mouse cursor speed to a low setting to allow easy precision pointing, and to also enable fairly high acceleration to allow me to move the mouse cursor long distances on my large screen area without having to move the physical mouse a correspondingly long distance on my desk. Moving the mouse on my machine and expecting to have the cursor respond according to these settings, but instead getting high-speed, no-acceleration cursor movement, feels very jarring.)

Also, after re-docking, the custom Logitech-provided mouse controls (the "Logitech MouseWare Control Center") in the Mouse applet in the Windows XP Control Panel are gone. Instead, running the Mouse applet just brings up the basic Windows mouse applet.

Workaround: Running the program logi_mwx.exe (which I found located on my local machine at C:\Windows, and, per msconfig.exe, runs at system startup time) restores the custom Logitech mouse control panel applet and my custom mouse speed and acceleration settings.

Of course, rebooting the machine is also an effective workaround! (The drawback to rebooting, of course, being the necessity of waiting for the reboot, and then re-opening any applications and documents that were in use prior to the reboot.)

As an aside, the same symptoms occur whenever the Microsoft Virtual PC 2007 Console is the active (foreground) application on my machine, even when no virtual PC image is actually running. If anyone knows a better workaround for this issue than "keep Virtual PC as the foreground app as little as possible", please comment! :-)

Friday, January 04, 2008

Mapping "Find Next/Previous" to F3/Shift+F3 in MS Word

Earlier today, after years of using Microsoft Word, I finally decided that I'd had enough of reopening the Find dialog every time I want to do a "Find Next" or "Find Previous" – that is, to have Word search up or down from the current caret position to find the next (or previous) instance of the string that I had most recently searched for via the Find dialog.

Visual Studio comes with this functionality by default, mapped to F3 for Find Next and Shift+F3 for Find Previous. Some other applications including Firefox and Notepad2 (Florian Balmer's excellent lightweight Notepad-like text editor) support these keyboard shortcuts as well. (Regular old notepad.exe supports F3, but not Shift+F3.) I'm very accustomed to using F3/Shift+F3, so I set out to get my copy of Word to support these.

(Update 4/28/2009: Jeff Cogswell commented with a much better solution to this problem that doesn't involve writing a custom macro, as detailed in this post -- see the comments on this post below for his solution!)

A search revealed that Microsoft Word supports a "Find Again" function, mapped by default to Shift+F4 and to Ctrl+Alt+y, but that isn't what I was looking for; I wanted to be able to easily search in either direction without having to open up the Find dialog and alter the setting of the search direction option.

So I ended up writing a couple of simple VBA functions using Word 2003's integrated Visual Basic Editor to do what I was looking for:

Sub FindNext()
  
   DoFind True

End Sub

Sub FindPrevious() DoFind False End Sub
Sub DoFind(findDirection As Boolean) 'Save the initial Find direction in order to restore it when we're done, 'so that we don't alter the current "Find Up" setting in the regular Find dialog. Dim initialFindDirection As Boolean initialFindDirection = Selection.Find.Forward 'Do the Find in the requested direction. Selection.Find.Forward = findDirection Selection.Find.Execute 'Restore the initial Find direction. Selection.Find.Forward = initialFindDirection End Sub

I determined that the Selection.Find.Execute statement was the key to getting Word to repeat a Find operation by using the Tools | Macro | Record New Macro functionality to record a macro of the built-in Ctrl+Alt+y "Find Again" shortcut, and then inspecting the resulting generated code in the VBA editor. Using the editor's intellisense functionality, it was simple to determine that the Selection.Find.Forward property was what controls the direction of the Find.

At first, I just wrote the FindNext and FindPrevious methods, setting Selection.Find.Forward to the appropriate value, and then calling Selection.Find.Execute. When testing those methods, though, I noticed that the setting of the Find direction carried over to be the new initial value for the Find dialog; i.e. after running the FindPrevious method, the next time the Find dialog was used, it would be set to find in the Up direction by default. I added the DoFind method to handle this issue, by temporarily setting Find.Forward to the necessary value, doing the Find, and then setting Find.Forward back to its original value.

To use these FindNext and FindPrevious functions yourself in Word 2003, paste the code above into the VBA editor (Tools | Macro | Visual Basic Editor), and save them. Then, map the F3 and Shift+F3 keys (or other keys of your choice) to FindNext and FindPrevious respectively by using the Customize Keyboard dialog (Tools | Customize, then click the Keyboard button at the bottom of the Customize dialog).

I would imagine that these functions should be similarly usable under Word 2007 as well, but since 2007's menu system and customization interface have changed, there are likely to be some changes to the steps necessary to enter the functions and map them to the F3 and Shift+F3 keys.

Monday, December 24, 2007

C#/Java/C++: Combining a variable assignment and evaluation

Pop Quiz! C#/Java/C++/Javascript/(probably others, too!) programmers, off the top of your head, what's the result of evaluating a variable assignment? In other words, to take a specific example, what is the output of this Java code snippet:

int n;
System.out.println(n = 50);
(Feel free to substitute in Console.Out.WriteLine (C#) or good old printf (C++) for the System.out.println in that snippet, depending on your language of choice.)

The answer is: 50. In Java and the other languages mentioned, the result of the evaluation of a variable assignment is the value being assigned.

I just came across this construct myself for the first time while I recently was doing a code review of a colleague's Java code. Somehow, prior to that code review, I had managed to go for over a decade of developing in these various languages without running across this!

The reason I hasn't run across this before may have to do with code readability. Doing two different things at once (in this case, a combined variable assignment and evaluation) often isn't very good for code readability (and therefore for ease of maintainability); in the general case, then, it probably makes the most sense for the variable assignment and evaluation to just be separated into two separate lines of code.

However, as my colleague's code demonstrated, combining an assignment with an evaluation can be useful when setting up a loop where the same statement is executed to assign a value to the loop variable both before the loop starts, and on each subsequent iteration of the loop. For example, here's a Java example of reading data from an input file a line at a time, using a java.io.BufferedReader:

String inputLine;
while ((inputLine = bufferedReader.readLine()) != null)
{
    // Do something with inputLine...
}

The while statement in this case combines the assignment of the variable inputLine to the line of text read from the BufferedReader, with the check to stop looping when inputLine is null.

In the past, I've written the same logic in this manner:

String inputLine = bufferedReader.readLine();
while (inputLine != null)
{
    // Do something with inputLine...

    inputLine = bufferedReader.readLine();
}

I had always been kind of annoyed over the need to repeat the assignment (inputLine = bufferedReader.readLine()) in two different places.

For writing loops like this in the future, I'll have to think more about whether the gain in code brevity (and debatably, in elegance) from using the former approach (the combined assignment/evaluation in the while statement) is worth the potential cost for future maintainers in the readability of the code.

Wednesday, December 12, 2007

Java: Displaying negative percentage values in red and in parentheses

Recently, I was looking to write some code in Java for a financial application that would output percentage-format numbers, rounded to two decimal places, with negative numbers being displayed in parentheses and in red color. This was an internal application which only needed to work in the US/English locale.

For example, given the values 0.12345 and -0.12345, the formatted output needed to be, respectively:

12.35%
(12.35%)

Since for this application the output only needs to be formatted in the default locale, it can be done with one of the constructors of the Java DecimalFormat class. If the output will be displayed in a web browser (and only in a web browser), the HTML to display the red color for negative values can be embedded in the string passed to the NumberFormat constructors as well:

NumberFormat redNegativePercentTwoDecimalsFormat = new java.text.DecimalFormat(
  "0.00%;'<span style=\"color:#FF0000\">'(0.00%)'</span>'");

The created NumberFormat instance can then be used to output values in our desired format:

System.out.println(redNegativePercentTwoDecimalsFormat.format(0.12345f));
System.out.println(redNegativePercentTwoDecimalsFormat.format(-0.12345f));

Which produces the desired output (when viewed in a web browser):

12.35%
(12.35%)

Monday, December 03, 2007

Finding album art quickly

Here's a quick series of steps that can be taken to find album art for an album (music CD) to paste into Windows Media Player or iTunes:
  • Open up Google Image Search. (Follow that link, or go to the Google.com main homepage and click the "Images" link there.)
  • From Google Image Search, search on the album name. (If the album name is something generic, try entering both the album and artist name in the search field.)
  • Click on one of the image results where the image size is a square and isn't tiny (e.g. 200x200).
  • If the image isn't immediately visible on the page that comes up (or even before the page finishes loading, if you don't want to wait), click the "See full-size image" link that Google puts at the top of the page.
  • Right-click the image and select the Copy option from the context menu that appears to put the image on your clipboard.
I found these steps useful when setting up my small music library in iTunes for the first time recently, having purchased my first iPod. These steps worked for even some of the non-mainstream CDs in my collection, such as Michigan Marching Band CDs and Black Mages CDs.