Friday, January 16, 2009

Playing with Windows 7

I've been playing with Windows 7 for about a week now. Like Andrew MacNeill, I installed it on a Virtual PC and also like Andrew, I got a BSOD when I tried to install Virtual Machine Additions (and in fact had to restore Windows 7 to a previous restore point to get it to work again). Fortunately, I remembered GIYF ("Google is your friend") and quickly found that Virtual PC SP1 was needed for Windows 7. After upgrading to SP1, I had no problems installing Virtual Machine Additions (which VPC can be a PITA to deal with if you don't).

I have a few other glitches right now, but they are all "Windows 7 on VPC" issues rather than Windows 7 issues:

  • No Aero Glass or related features (like the new Aero Peek). Come to think of it, I don't get Aero Glass when running Vista in a VPC either.
  • No sound.
  • Dragging a file from my main system to the VPC window gives an error. Copying a file from a shared folder on my main system to the VPC also has problems.

There are lots of cool things about Windows 7; Tim Sneath has blogged about some of them. The new taskbar and the concept of libraries will likely take some getting used to, but so far it feels like Vista with more fit-and-finish things taken care of.

Wednesday, January 14, 2009

PEM Editor is a Must-Have Tool

Jim Nelson has done a ton of work on the PEM Editor, the new name for the former Edit Property/Method replacement dialog project on VFPX that Marcia Akins originally created. He's made this into an incredible tool that I used about a hundred times a day. It completely replaces the native Edit Property/Method, New Property, and New Method dialogs, and in fact can even replace the Properties and Document View windows to some extent. Because it's modeless, resizable, and dockable, you never have to close it if you don't want to. Its customizable color coding and filtering abilities make working with forms and classes a lot easier. This is simply one of those must-have tools.

If you haven't already installed it, do yourself a favor and download it today. Installing it is as simple as DO PEMEditor.APP. From then on, you'll wonder what you ever did without it.


Changing the Color and Orientation of Images

Recently, I needed to change the color of an image. I have a container that includes an image and depending on the user's color choices, the container's background color might change. That means certain colors in the image must also change so the image blends in with the container properly, and rather than creating a number of images with pre-defined colors, I wanted to change the colors programmatically. One other wrinkle: because the orientation of the container might also change under some circumstances, I also wanted to rotate the image.

Fortunately, the VFPX GDIPlusX project makes this a snap and thanks to a recent blog posting by Cesar, it didn't take too long to figure out what to do. The following code reads the color of the upper left pixel in the image whose file name is in the lcImageFile variable and converts that color to the one specified in This.BackColor. It also rotates the image if it's wide and short but the container is narrow and tall. It then writes the new image directly to the PictureVal property of the imgImage object so there's no additional disk I/O.

* Create the GDIPlusX objects if necessary.

if type('_screen.System.Name') <> 'O'
do System.APP
endif type('_screen.System.Name') <> 'O'
with _screen.System.Drawing

* Load the image.

loBmp = .Bitmap.FromFile(lcImageFile)

* Get the color of the upper left pixel.

loColor = loBmp.GetPixel(0, 0)

* Create a color map and tell it to convert from the color of
* the pixel to our background color.

loColorMap = .Imaging.ColorMap.New()
loColorMap.OldColor = loColor
loColorMap.NewColor = .Color.FromRGB(This.BackColor)

* Create an attributes object and make it use the color map.

loAttr = .Imaging.ImageAttributes.New()

* Create a new image and draw the old image onto it using the new
* color mapping.

loDestBmp = .Bitmap.New(loBmp.Width, loBmp.Height, ;
loGfx = .Graphics.FromImage(loDestBmp)
loRect = loBmp.GetBounds()
loGfx.DrawImage(loBmp, loRect, loRect, .GraphicsUnit.Pixel, loAttr)

* Flip the image if its orientation doesn't match ours.

if This.Width > This.Height and loBmp.Height > loBmp.Width
endif This.Height > This.Width ...

* Write the image directly to the PictureVal property of our image
* object.

loDestBmp.Save(This.imgImage, .Imaging.ImageFormat.Bmp)