Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

StyleDialog - A transparent dialog class with an optional custom frame

0.00/5 (No votes)
3 Aug 2008 1  
StyleDialog may be used independently or in conjunction with the Style Toolkit.

Introduction

There are several transparent dialogs on CodeProject; however, none of them provide a generic dialog that allows you to paint on the transparent region. The reason for this is because Windows doesn’t effectively support transparent CWnd objects in the first place.

The image above shows StyleDialog being used with Style Toolkit[^] version 1.1. However, StyleDialog may be used with or without the toolkit, and with or without transparency.

Issues in Creating a Transparent Dialog

The key feature I needed for StyleDialog is the ability to use the transparent region. That means, you can draw on it, paint on it, and add controls to it.

Here are some of the typical methods used, and the associated drawbacks:

  • Return a HOLLOW_BRUSH in OnCtlColor – This works okay for controls, since the application controls the background. It also works for a dialog box as long as you don’t move it, which makes it relatively useless. It also causes child controls to stop receiving their OnCtlColor messages.
  • Use a Region – This solution works fairly well; however, you can’t use the transparent regions. Also, since you can’t anti-alias the border, the edges look a bit ragged.
  • Layered Windows – This is the only method that creates a true transparent window. This works fine for creating a fade effect, but since the transparency applies to the entire CWnd, you can’t have some things transparent and others opaque.
  • Layered CWnds – These solutions look and behave the best, but they aren’t generic, and you also can’t paint on the transparent regions.

StyleDialog Design Considerations

Other issues that are difficult to overcome are jitter when dragging the window, and maintaining the correct background when the application is not the active one.

To overcome these issues, StyleDialog imposes the following design rules:

  • Display an alternate background when not the active application. This overcomes the problem of the background changing underneath the application when it is visible but not active.
  • Display an alternate background when dragging the application. Actually, StyleDialog could display the correct background while dragging, but there is a jitter associated with layered windows that is undesirable.

StyleDialog achieves transparency by using an opaque layered window and taking advantage of the fact that it is maintained in an off-screen bitmap.

Using StyleDialog

Step 1 - Configure Usage in StyleDialog.h

// comment out this line if Style Toolkit is not used
#define USE_STYLE_TOOLKIT

// comment out this line if transparency is not supported 
#define USE_LAYERED_WINDOWS

Step 2 – Derive a Dialog from StyleDialog

Create a dialog based application with the wizard as usual. Replace all the instances of CDialog with StyleDialog. Note: Skip past CAboutDlg when doing the replace, unless you want it to also be a StyleDialog.

For child dialogs, just declare them as StyleDialog. See the demo program for examples.

Step 3 – Configure StyleDialog

Do the following before calling OnInitDialog or DoModal.

// configure StyleDialog before calling the init function
SetTransparent(TRUE);
SetControls(ALL_CONTROLS);
SetTitle(_T("Style Dialog Demo"));
  • SetTransparent enables transparency. It defaults to disabled since it will just waste bandwidth if it is not used.
  • SetControls tells StyleDialog which controls to use when there is a custom frame. This is described in more detail below. The default is no controls.
  • SetTitle is the title that will be displayed in the taskbar when a custom frame is used. The default is an empty string.

Step 4 – Add a style to the dialog [optional]

Load a style into the dialog with AddBackGroundStyle(style).

Minimal Implementation of StyleDialog

The image and code below is from the Dialog 3 button of the demo program.

Minimal.PNG

StyleDialog dlg(IDD_DIALOG3);
dlg.SetTransparent(TRUE);
dlg.SetTitle(_T("Standard Frame"));
dlg.DoModal();

This example uses the standard frame, and does not use the Style Toolkit. It is actually not necessary to set the title, but it will just say “Dialog” if you don’t.

Controlling the Alternate Background

If transparency is enabled, StyleDialog will display an alternate background when it is not the active application or when the window is being moved. The alternate background will be underneath anything that may have been painted on the transparent region.

By default, the alternate background will be a solid fill of the desktop background color. This can be overridden with one of the following:

  • SetOpaqueColor(clr) – Change the solid fill to another color.
  • AddOpaqueStyle(style) – Change the fill to a style.

The Dialog 2 button demonstrates the use of styles for the background.

SemiTransBack.PNG

This example uses a custom frame without controls, and a background style with a semi-transparent PNG image.

OpaqueBack.PNG

This shows the inactive state. It uses a fully opaque version of the same image for the opaque style.

Creating a Custom Frame

StyleDialog needs to know what the client rectangle’s size should be when creating a custom frame. This is needed for hit testing the title bar area, and for supporting the overridden function GetClientRect().

StyleDialog maintains an outer frame that can be retrieved with GetFrameRect and a client frame that can be retrieved with GetClientRect. Note that Windows does not perceive this as the client rectangle. There are cases when painting or erasing that you should use GetFrameRect or CDialog::GetClientRect to get the Windows definition of the client rectangle.

Method 1 – Use SetClientRect

Call GetFrameRect() to get the outer frame rect, adjust it for border and title bar sizes, then call SetClientRect().

Method 2 – Use the Resource Editor

Use the resource editor and create the client rectangle with a static control. This has the advantage of being able to adjust the title and border sizes as you design the dialog box. Use the static picture control, since it doesn’t have any offsets.

Set the ID of the control to one of SytleDialog’s keyword IDs – IDC_SC_CLIENT. When StyleDialog detects this ID in the resource.h file, it will automatically create the client rectangle.

There are also keyword IDs for the controls as seen in the image below.

ResourceLayout.png

If StyleDialog sees any of the control IDs, it will create StyleButtons for them and load them with the associated image. It will also create the expected functionality for each button.

Other Considerations

StyleDialog does not support maximize; in fact, it disables it. In principle, this could be supported, but I don’t have any intention of adding this feature in the future.

I didn’t really plan on supporting a transparent dialog with transparent child dialogs; however, it appears to work okay, and the demo program actually does this.

In order to not have a burn through effect when opening a child dialog, the transparency of the parent can be disabled, then re-enabled. However, there may be timing issues associated with turning on and off layered windows, so use this feature with caution.

Issues

  • Minimize and Restore when using a custom frame – If you click on the taskbar icon, StyleDialog will go to the proper active or inactive state, but it will not minimize and restore. I think this relates to the fact that the system menu does not have this functionality, and I hope to fix this in a future release.
  • VC6 users – StyleDialog will work as is if you comment out the layered window functionality. Layered windows will work on Win2K SP3 and newer, but you need to get newer versions of winuser.h, user32.lib, and user32.dll.

Revision History

  • Version 1.0 – August 3, 2008
  • Initial release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here