Introduction
There are many articles that demonstrate how you can use the new layering
features of Windows 2000 or Windows XP to create applications that are
translucent. This article adds to that and shows how you can use the same
features to turn any application transparent even if you do not
have sources for it.
Using this "WinTrans" application you will be able to select any currently
running application and turn it transparent by dragging and dropping the wand
(icon at the top-left corner) on the title bar of that application. You can
also control the transparency using the slider. "WinTrans" has an interface very
much like SPY and also demonstrates the usage of Win32 APIs to locate a window
under the mouse pointer and extract details like the class associated with it,
the caption of the window, etc.
"WinTrans" comes in handy if you want to work on a maximized window and at
the same time keep a watch on some other application running in the
background.
Background
In Windows 2000 and Windows XP a new function named
SetLayeredWindowAttributes
has been added to User32.dll.
To use this function an application needs to set the
WS_EX_LAYERED (0x00080000)
bit in the window style either while
creating it or later using the SetWindowLong
function. Once this
bit is set any application can call this function passing a handle to a window
and make either the whole window or a particular color on the window transparent.
This function takes the following arguments.
HWND hWnd:
Handle to the window
COLORREF col:
Color to be made transparent
BYTE bAlpha:
If this value is 0 the window becomes completely
transparent and if it is 255 it becomes opaque
DWORD dwFlags:
If this flag is 1 then only the color col
is made transparent. If it is 2 then the whole window
becomes transparent as dictated by the bAlpha
value
Using the code
We begin by defining the following member variables of the main dialog
class in WinTransDlg.h
bool m_bTracking;
HWND m_hCurrWnd;
HCURSOR m_hCursor;
We also define a function pointer that points to the
SetLayeredWindowAttributes
function. This function is defined in
the User32.dll.
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr,
BYTE bAlpha, DWORD dwFlags);
lpfn g_pSetLayeredWindowAttributes;
In the OnInitDialog
event handler for the dialog we get the
address of the SetLayeredWindowAttributes
function and store it
in g_pSetLayeredWindowAttributes
. We also load the wand cursor
and store the handle in m_hCursor
BOOL CWinTransDlg::OnInitDialog()
{
....
HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32,
"SetLayeredWindowAttributes");
if (g_pSetLayeredWindowAttributes == NULL)
AfxMessageBox (
"Layering is not supported in this version of Windows",
MB_ICONEXCLAMATION);
HINSTANCE hInstResource = AfxFindResourceHandle(
MAKEINTRESOURCE(IDC_WAND), RT_GROUP_CURSOR);
m_hCursor = ::LoadCursor( hInstResource, MAKEINTRESOURCE(IDC_WAND) );
...
}
We then define handler for the WM_LBUTTONDOWN
, WM_LBUTTONUP
and
WM_MOUSEMOVE
events. For the handler for WM_LBUTTONDOWN
we do the following
void CWinTransDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
...
SetCapture();
m_hCurrWnd = NULL;
m_bTracking = true;
::SetCursor(m_hCursor);
...
}
For mouse move event handler the following code is used
void CWinTransDlg::OnMouseMove(UINT nFlags, CPoint point)
{
...
if (m_bTracking)
{
...
ClientToScreen(&point);
...
m_hCurrWnd = ::WindowFromPoint(point);
...
...
}
...
}
As long as the left mouse button is clicked anywhere inside the main dialog
and is not released the mouse pointer will change into the wand and the details
of the window beneath the pointer will be displayed on the WinTrans dialog
When the button is released the event handler for WM_LBUTTONUP
is called.
void CWinTransDlg::OnLButtonUp(UINT nFlags, CPoint point)
{
...
ReleaseCapture();
m_bTracking = false;
if (g_pSetLayeredWindowAttributes && m_hCurrWnd != m_hWnd)
{
::SetWindowLong(m_hCurrWnd, GWL_EXSTYLE,
GetWindowLong(m_hCurrWnd,
GWL_EXSTYLE) ^ WS_EX_LAYERED);
g_pSetLayeredWindowAttributes(m_hCurrWnd, 0,
(BYTE)m_slider.GetPos(), LWA_ALPHA);
::RedrawWindow(m_hCurrWnd, NULL, NULL,
RDW_ERASE | RDW_INVALIDATE |
RDW_FRAME | RDW_ALLCHILDREN);
}
...
}
Points of Interest
This application works correctly only when the wand is dropped on the title
bar of another application or on the body of a dialog based application. If for
example the wand is dropped on the body of notepad it will not work
To remove the transparent effect you can simply drag-n-drop the wand again
on that application. Since in OnLButtonUp
we toggle the WS_EX_LAYERED
bit
the transparency effect will also be toggled
TransWand does not work on the command window
History
- v1.0 This is the initial version.
- v1.1 Added Undo All button and check box to clear the transparency effect on
all windows when WinTrans is closed