DXVolumeControl / Volume Control for Vista

Posted by Julien on February 25th, 2007

After finishing the Volume Control widget, I wanted to have something I could actually use. Unfortunately, the current version of DesktopX does not support the new way of changing volume in Vista. Changing volume with the DX API only changes the volume for the DX application (or widget if you are running outside of DesktopX).

Enter DXVolumeControl, a plugin I wrote a month ago to control the master volume in Vista. I just updated it to allow control of muting state (and respond to it via a callback). I also added a peak value property (read-only) to get the playing sample peak value.

The Volume Control for Vista widget will have the following enhancements over the XP version:

  • Volume meter reacts to volume change from the mixer panel or another application
  • Muting state change is reflected on the widget
  • The volume overlay opacity changes with the audio peak value (looks really cool :-D )

Currently listening to Kubb - Wicked Soul

Volume Control

Posted by Julien on February 25th, 2007

When I did the DXMouseWheel plugin, it was to be used in a volume control widget. As far as I know, nobody has released one yet, so why not do it myself ?

I started from a speaker image shared by vica on DeviantArt in 2002 (he said it was ok to improve on it in the comments but I sent him an email just to be sure, and I’m waiting for his authorization). I then added a red glow for the mute state and a blue glow for the 10 different ON states.

Armed with the speaker image and the eleven overlays, I jumped into DesktopX and created new objects for the speaker, the overlays and the volume text.

The script was pretty simple. I added the DXMouseWheel plugin (of course :) ) and wrote the required code to respond to the mouse wheel and the middle button.

Less than two hours later (yep, I’m still slow when it comes to DX and VBScript), I have a nice little widget that allows to control the volume with the mouse wheel and mute it by pressing the middle button.

Coming to Wincustomize soon !

Getting closer to 1.0

Posted by Julien on February 23rd, 2007

Today I corrected a bunch of remaining issues with LogonSwitcher. The logon preview now shows the password box correctly, the main logon list has better looking borders, etc. I tested a little bit more under VPC to make sure it applies a full logon (not only a new background) I also added some new logons using nice images from Flickr (I’m using images under CC BY or CC BY-NC-SA, so it’s to distribute them).

It still need to be tested thoroughly, and that’s why I recruited two beta testers to get some feedback and to help me refine the UI. The poor ones don’t know what they are getting into :P

On another matter, I finally updated my project page, adding the remaining pages. I still need to write descriptions for some projects, but at least nobody is going to get a 404 error anymore.

Updating resources files with BMP and PNG files (with managed code)

Posted by Julien on February 23rd, 2007

This only concerns Bitmap resources (RT_BITMAP). Updating others type of resources is easier and doesn’t require specific code.

  • BMP files

Inserting BMP files is quite easy. You only have to remove the header and you are good to go.

int BMP_HEADER_BYTES = 14;
FileStream stream = new FileStream(file, 

                                   FileMode.Open,
                                   FileAccess.Read,
                                   FileShare.Read);

BinaryReader reader = new BinaryReader(stream);
byte[] data = reader.ReadBytes((int)reader.BaseStream.Length);

GCHandle gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr bitmap = Marshal.UnsafeAddrOfPinnedArrayElement(data, BMP_HEADER_BYTES);

uint size = (uint)(data.GetLength(0) - BMP_HEADER_BYTES);
UpdateResource(hDll, 2, resourceId, LANG_ENGLISH_ID, bitmap, size);

gcHandle.Free();
stream.Close();
  • PNG files

It’s a bit more difficult with PNG files. You must add a header before inserting the image data. You also need to rotate the image before inserting because of the bitmap is copied and read (alternatively, you can insert a negative height into the header, but I haven’t tested it).

Also note that we do not set the compression to BI_PNG (5) and the size of the image in the BITMAPINFO header.

[StructLayout(LayoutKind.Sequential)] 
class BITMAPINFO {
public int biSize;
public int biWidth;
public int biHeight;
public short biPlanes;
public short biBitCount;     
public int biCompression;     
public int biSizeImage;     
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public int biClrUsed;
public int biClrImportant; }

// Load file 
Bitmap pngFile = new Bitmap(file);
// Required due to the way bitmap is copied and read
pngFile.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData data = pngFile.LockBits(new Rectangle(0, 0,
                                                 pngFile.Width, pngFile.Height),
                                   ImageLockMode.ReadOnly,
                                   PixelFormat.Format32bppArgb); 

byte[] dataBuffer = new byte[data.Height * data.Stride]; 
Marshal.Copy(data.Scan0, dataBuffer, 0, data.Height * data.Stride); 
pngFile.UnlockBits(data);
// Setup Header 
BITMAPINFO header = new BITMAPINFO(); 
header.biSize = Marshal.SizeOf(typeof(BITMAPINFO));
header.biWidth = pngFile.Width; 
header.biHeight = pngFile.Height;
header.biPlanes = 1; 
header.biBitCount = 32; 

// Convert the structure to an array 
byte[] buffer = new byte[header.biSize];
GCHandle h = GCHandle.Alloc(buffer , GCHandleType.Pinned); 
Marshal.StructureToPtr(header, h.AddrOfPinnedObject(), false);
h.Free(); 

// Write header + data 
MemoryStream memory = new MemoryStream(); 
memory.Write(buffer, 0, buffer.Length);
memory.Write(dataBuffer, 0, dataBuffer.Length);
byte[] imageData = memory.GetBuffer(); 
GCHandle gcHandle = GCHandle.Alloc(imageData, GCHandleType.Pinned); 
IntPtr firstCopyElement = Marshal.UnsafeAddrOfPinnedArrayElement(imageData, 0);

UpdateResource(hDll, 2, resourceId, LANG_ENGLISH_ID,                
	       firstCopyElement, (uint)imageData.GetLength(0));

gcHandle.Free(); 
memory.Close();

Updating bitmap resources (with png files)

Posted by Julien on February 20th, 2007

Today’s probably the worst day I’ve had for quite some time. I didn’t sleep well last night. I’ve been feeling dizzy since this morning. I haven’t had much appetite for breakfast or lunch. And yet, today I finally resolved the problem that’s been bugging me for at least two weeks. How ironic !

To replace the logon screen, LogonSwitcher is modifying several images in resource dlls (I’m preparing an article on that). Some of the images in those resources are stored as “Image” resources and others as “Bitmap” resources. The first kind is easy to replace. Just open the file, map the contents and copy the bits to the resource. Done ! But the latter is a little bit more complicated.

You can have store several formats in “Bitmap” resources. The two I’m using are BMP and PNG. BMP are easy, you just have to remove the header and copy the contents of the file to the resource. But with PNG files, that doesn’t work…

I’ve been trying to make it work for more than a week with no luck, trying several things… What doesn’t help is that I haven’t been able to find any documentation on that precise subject. There is a lot of info on updating resources, but nothing specifically for PNG files. Or at least I couldn’t find it.

Finally, the actual working solution is 23 lines long :( Gahhhhhhhh !

I learned way more that I would have liked about win32 resources, PE, DIB, bitmaps formats. Not that there is anything wrong with learning new things, but with pure win32 programming, the more you learn about it, the more you realize that you know almost nothing. And that’s discouraging.

PS: if that sounds like incoherent rambling, re-read the first paragraph :)

Apply and Export animation

Posted by Julien on February 20th, 2007

The animation on Apply & Export is now done.

Almost there…

More UI work and a few other things

Posted by Julien on February 20th, 2007

I finished the Details panel yesterday and corrected the open animation. There is still a small bug with the description that is not cleared when you select another logon and the new logon doesn’t have any description.

I also replaced the old scrollbar with a new one that is better integrated with the application. The extra aero border will hopefully go when I start handling WM_NCCALCSIZE correctly. The code is deactivated as it’s not working correctly yet.

I moved all the logic when applying a logon into it’s own thread, so that the application doesn’t freeze when you click Apply. The two buttons along with the textbox and the slider are disabled when applying a logon.

I wanted to have a nice animation when applying the logon. Right now, the main list fades to white but I still need to add the actual animation.

Export, Glass buttons & MS Samples

Posted by Julien on February 17th, 2007

I’m now using the VistaBridge dll to get the native windows dialogs. I removed my own helper class for TaskDialogs to use the one included in the VistaBridge dll. Turns out the MS samples are full of TODO’s… Fortunately, I only needed a few things that weren’t implemented (filters in particular), so I simply added them.

Here is the new export dialog:

Much better :)

It took a bit longer to get going than I though it would because of a problem with the common controls dll.

To get that dialog, you have to load version 6 and the version that get loaded by default is the old version. I thought I had it fixed earlier, but one of my dll was still loading an old version, with not so nice results down the line. 

I also worked a bit on the main UI. I am now using a new template for the buttons, done by Martin Grayson. I modified it a bit so that it looks good on a glass surface. It still needs a little bit of tweaking to be perfect, but it’s ok for now. 

 

It nicely glows on mouse over (and it’s transparent, of course).

Testing (in VPC): logon background working

Posted by Julien on February 15th, 2007

Corrected a bunch of problems with file and directory security today. The restore function (used when uninstalling or applying the default logon) is now working correctly.

Updated logon replacement functions. They are now working a little bit better.

Applying a logon with a background and branding images is now working. PNG files (in Bitmap section) are still resisting me, but not for long :)

Program for the next few days:

  • Move the apply function into a thread
  • Add an animation when applying a logon
  • Finish the details panel
  • Add the wait animation to the supported resources

WPF File Dialogs

Posted by Julien on February 13th, 2007

Arghhhhhh. What is that ? Are they kidding or what ? WPF is supposed to be the next generation API and the only thing they provide out of the box is that ?

  • Crappy Windows 95 era icons ? CHECK
  • “classic” style drop down boxes and buttons ? CHECK

What a shame really. On Vista this is so lame. I hope they provide something better in the next version of WPF ! Ah well, let’s pinvoke into the new Vista APIs then… 

Luckily, they are providing samples just for that. But why not include it then? Time & quality constraints aren’t really a good excuse when it comes to things used as much as a file dialog.