Click here to Skip to main content
15,895,777 members
Articles / Desktop Programming / MFC

Import/Export Registry Sections as XML

Rate me:
Please Sign up or sign in to vote.
4.33/5 (16 votes)
21 Jan 20033 min read 167.9K   6.1K   73  
Export registry sections as XML to simplify registry diffs
This article details a tool aimed to import/export registry sections in XML format, to make registry diff easier in practice.
//
// Zhadum.cpp
//
// Copyright (c) 2001-2002 Mark H. P. Lord. All rights reserved.
// 
// This software is provided 'as-is', without any express or implied
// warranty.  In no event will the author(s) be held liable for any damages
// arising from the use of this software.
// 
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 
// 1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//

#include "stdafx.h"
#include <wingdi.h>
#include "Zhadum.h"
#include <assert.h>
#include <math.h>
#include <stdlib.h>

// Disable warning of conversion from LONG to x * (a Win64 portability warning
// given by VC7)
#pragma warning(disable:4312)
#pragma warning(disable:4311)

const char *dollarIdZhadum = "$Id: Zhadum.cpp,v 1.4 2002/10/21 23:31:52 mark Exp $";

//
// Win32 Defines
//

#define WS_EX_LAYERED           0x00080000

#define LWA_COLORKEY            0x00000001
#define LWA_ALPHA               0x00000002

#define ULW_COLORKEY            0x00000001
#define ULW_ALPHA               0x00000002
#define ULW_OPAQUE              0x00000004

#define AC_SRC_OVER                 0x00
#define AC_SRC_ALPHA                0x01

//
// Helpers
//

#define countof(x) (sizeof (x) / sizeof ((x)[0]))
#define minimum(a, b) ((a) < (b) ? (a) : (b))
#define maximum(a, b) ((a) > (b) ? (a) : (b))

#ifndef _WIN64
#define GetZhadumShadowDataFromHWnd(hwnd) (ZhadumShadowData *) GetWindowLong (hwnd, 0)
#define SetZhadumShadowDataForHWnd(hwnd, data) SetWindowLong (hwnd, 0, (LONG) data)
#else
#define GetZhadumShadowDataFromHWnd(hwnd) (ZhadumShadowData *) GetWindowLongPtr (hwnd, 0)
#define SetZhadumShadowDataForHWnd(hwnd, data) SetWindowLongPtr (hwnd, 0, (LONG_PTR) data)
#endif

#define is_atom(p) (((size_t) (p) & (~0xffff)) == 0)

//
// Z'Ha'Dum
//

// Types
struct ZhadumShadowData {
	HBITMAP bmp;
	bool vertical;
	int alpha;
};

typedef DWORD uint32;
typedef BYTE byte;

typedef BOOL (__stdcall *ZhadumSetLayeredWindowAttributesType) (HWND, COLORREF, BYTE, DWORD);
typedef BOOL (__stdcall *ZhadumUpdateLayeredWindowType) (HWND, HDC, POINT *, SIZE *, HDC, POINT *, COLORREF, BLENDFUNCTION *, DWORD);

// Constants
#define	ZHADUM_WM_SETALPHA (WM_USER + 1)
#define ZHADUM_WM_SETVERTICAL (WM_USER + 2)

#define MAX_ZHADUM_WNDS 128
#define MAX_ZHADUM_EXCLUSIONS 128

#if 1
	// Normal shadow size
	#define X_INDENT 2
	#define Y_INDENT 5
	#define X_SIZE 7
	#define Y_SIZE 7
	#define MAX_ALPHA 100
	#define MIN_ALPHA 0
#else
	// Chunkier shadows
	#define X_INDENT 4
	#define Y_INDENT 7
	#define X_SIZE 14
	#define Y_SIZE 14
	#define MAX_ALPHA 100
	#define MIN_ALPHA 0
#endif

static TCHAR zhadumShadowWndClassName[] = TEXT ("ZhadumShadow");

// Globals
static HINSTANCE zhadumHInst;
static HHOOK zhadumHook = NULL;

struct ZhadumWindowInfo {
	HWND hwnd;
	RECT rect;
	BOOL visible;
	HWND shadows[2];
};
static ZhadumWindowInfo zhadumWindows[MAX_ZHADUM_WNDS];
static int zhadumWindowCount = 0;

static BOOL zhadumRegisteredShadowClass = FALSE;

static ZhadumSetLayeredWindowAttributesType zhadumSetLayeredWindowAttributes;
static ZhadumUpdateLayeredWindowType zhadumUpdateLayeredWindow;

enum ZhadumExclusionType { 
	ZhadumExclusionType_Window,
	ZhadumExclusionType_Class,
	ZhadumExclusionType_Atom,
};
	
struct ZhadumExclusion {
	ZhadumExclusionType type;
	union {
		HWND hwnd;
		TCHAR *className;
		LPCTSTR atom;
	} u;
};

static ZhadumExclusion zhadumExclusions[MAX_ZHADUM_EXCLUSIONS];
static int zhadumExclusionCount = 0;

//
// Local Functions
//

static BOOL ZhadumInitialise () {
	HMODULE hmodule = GetModuleHandle (TEXT ("user32.dll"));
	
	if (zhadumSetLayeredWindowAttributes && zhadumUpdateLayeredWindow) {
		return TRUE;
	}

	zhadumSetLayeredWindowAttributes =
		(ZhadumSetLayeredWindowAttributesType) GetProcAddress (hmodule, "SetLayeredWindowAttributes");

	zhadumUpdateLayeredWindow =
		(ZhadumUpdateLayeredWindowType) GetProcAddress (hmodule, "UpdateLayeredWindow");
		
	if (! zhadumSetLayeredWindowAttributes || ! zhadumUpdateLayeredWindow) {
		return FALSE;
	}
	
	return TRUE;
}

static void FillU32 (uint32 *out, uint32 value, int count) {
	while (count--) {
		*out++ = value;
	}
}

static void FillPixels (uint32 *surf, int surfw, int surfh,
	int left, int top, int right, int bottom, uint32 value) {
	int w = right - left;

	assert (! (left < 0 || top < 0 || right > surfw || bottom > surfh || bottom < top || right < left));

	if (left < 0 || top < 0 || right > surfw || bottom > surfh || bottom < top || right < left) {
		return;
	}

	for (; top != bottom; ++top) {
		FillU32 (&surf[left + top * surfw], value, w);
	}
}

static void FillRoundedCorner (uint32 *surf, int cx, int cy, int cornersize,
	int left, int top, int right, int bottom, int dx, int dy) {
	if (left < 0 || top < 0 || right > cx || bottom > cy || bottom < top || right < left)
		return;
		
	uint32 *rowptr = surf + top;
	int cyminus1 = cornersize - 1;
	//double scale = sqrt (cyminus1*cyminus1 + cyminus1*cyminus1);
	double scale = cyminus1;
	int njinit = dx < 0 ? (cornersize-1) : 0;
	int ni = dy < 0 ? (cornersize-1) : 0;
	int nj;
	int i, j;
	uint32 value;
	for (i = top; i != bottom; ++i, rowptr += cx, ni += dy) {
		for (j = left, nj = njinit; j != right; ++j, nj += dx) {
			value = (uint32)floor (sqrt (ni*ni + nj*nj) * 255.0 / scale);
			if (value > 255)
				rowptr[j] = 0;
			else {
				value = 255-value;
				value = ((value * (MAX_ALPHA-MIN_ALPHA+1)) >> 8) + MIN_ALPHA;
				rowptr[j] = value << 24;
			}
		}
	}
}

static void ZhadumShadowWindowUpdate (HWND hwnd) {
	ZhadumShadowData *data = GetZhadumShadowDataFromHWnd (hwnd);

	if (data->bmp) {
		DeleteObject (data->bmp);
	}

	SIZE sz;
	RECT rwnd;
	GetWindowRect (hwnd, &rwnd);
	sz.cx = rwnd.right - rwnd.left;
	sz.cy = rwnd.bottom - rwnd.top;

	if (! sz.cx || ! sz.cy) {
		data->bmp = NULL;
		return;
	}

	// We have to use a DIB section for 16-bit video mode support	
	BITMAPINFO bitmapInfo;
	bitmapInfo.bmiHeader.biSize = sizeof (bitmapInfo.bmiHeader);
	bitmapInfo.bmiHeader.biWidth = sz.cx;
	bitmapInfo.bmiHeader.biHeight = -(int)sz.cy;
	bitmapInfo.bmiHeader.biPlanes = 1;
	bitmapInfo.bmiHeader.biBitCount = 32;
	bitmapInfo.bmiHeader.biCompression = BI_RGB;
	bitmapInfo.bmiHeader.biSizeImage = sz.cx * sz.cy * 4;
	bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
	bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
	bitmapInfo.bmiHeader.biClrUsed = 0;
	bitmapInfo.bmiHeader.biClrImportant = 0;
	
	HDC hdc = GetDC (NULL);
	VOID *bits;
	data->bmp = CreateDIBSection (hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
	ReleaseDC (NULL, hdc);
	if (! data->bmp) {
		//ZhadumDisplayWinError (GetLastError (), TEXT ("CreateBitmap"));
		return;
	}

	int area = sz.cx * sz.cy;
	int i;

	uint32 *pixels = (uint32 *) bits;
	uint32 *pixelptr = pixels;

	if (! data->vertical) {
		FillRoundedCorner (pixelptr, sz.cx, sz.cy, sz.cy, 
							0, 0, sz.cy, sz.cy, -1, 1);

		uint32 *rowptr = pixelptr;
		int maxx = minimum (sz.cx, sz.cy);
		for (i = 0; i != sz.cy; ++i, rowptr += sz.cx) {
			FillPixels (pixelptr, sz.cx, sz.cy, maxx, i, sz.cx, i + 1, rowptr[maxx-1]);
		}

		FillRoundedCorner (pixelptr, sz.cx, sz.cy, sz.cy, 
							sz.cx - sz.cy, 0, sz.cx, sz.cy, 1, 1);
	}
	else {	
		FillRoundedCorner (pixelptr, sz.cx, sz.cy, sz.cx,
							0, 0, sz.cx, sz.cx, 1, -1);
							
		int maxy = minimum (sz.cx, sz.cy);
		uint32 *rowptr = pixelptr + (maxy - 1) * sz.cx;
		for (i = 0; i != sz.cx; ++i) {
			FillPixels (pixelptr, sz.cx, sz.cy, i, maxy, i + 1, sz.cy, rowptr[i]);
		}
	}
	
	if (data->alpha != 255) {
		int alpha;
		if (data->alpha == 0) {
			alpha = 1;
		}
		else {
			alpha = data->alpha;
		}
		
		byte *alphaptr = (byte *) pixels;
		byte *alphaend = alphaptr + area * 4;
		alphaptr += 3;
		alphaend += 3;
		for (; alphaptr != alphaend; alphaptr += 4) {
			*alphaptr = (byte) ((int) (*alphaptr) * alpha / 255);
		}
	}

	hdc = ::GetDC (NULL);
	HDC hdctemp = CreateCompatibleDC (hdc);
	SetLayout (hdctemp, LAYOUT_BITMAPORIENTATIONPRESERVED);
	HGDIOBJ oldbmp = SelectObject (hdctemp, data->bmp);
	
	POINT ptwnd;
	ptwnd.x = rwnd.left;
	ptwnd.y = rwnd.top;
	
	POINT ptzero = { 0, 0 };
	BLENDFUNCTION blend;
	memset (&blend, 0, sizeof (blend));
	blend.BlendOp = AC_SRC_OVER;
	blend.BlendFlags = 0;
	blend.SourceConstantAlpha = 255;
	blend.AlphaFormat = AC_SRC_ALPHA;
	if (zhadumUpdateLayeredWindow) {
		(*zhadumUpdateLayeredWindow) (hwnd, hdc, &ptwnd, &sz, hdctemp, &ptzero, 0, &blend, ULW_ALPHA);
	}

	SelectObject (hdctemp, oldbmp);
	DeleteDC (hdctemp);
	::ReleaseDC (NULL, hdc);
}

// Our window procedure for our shadow windows
static LRESULT CALLBACK ZhadumShadowWndProc (HWND hwnd, UINT msg, WPARAM wparam,
		LPARAM lparam) {
	ZhadumShadowData *data;
	
	switch (msg) {
		case WM_CREATE: {
			data = (ZhadumShadowData *) calloc (sizeof (ZhadumShadowData), 1);
			if (! data) {
				return -1;
			}
			
			SetZhadumShadowDataForHWnd (hwnd, data);
			
			data->alpha = 255;
			data->vertical = false;
			break;
		}
		
		case WM_DESTROY: {
			data = GetZhadumShadowDataFromHWnd (hwnd);
			if (data) {
				if (data->bmp) {
					DeleteObject (data->bmp);
				}
				free (data);
			}
			break;
		}
		
		case WM_PAINT: {
			ValidateRect (hwnd, NULL);
			return 0;
		}
		
		case WM_NCHITTEST: {
			return HTTRANSPARENT;
		}

		case WM_SIZE: {
			ZhadumShadowWindowUpdate (hwnd);
			break;
		}

		case ZHADUM_WM_SETVERTICAL: {
			ZhadumShadowData *data = GetZhadumShadowDataFromHWnd (hwnd);
			
			data->vertical = wparam != 0;			
			return 0;
		}
		
		case ZHADUM_WM_SETALPHA: {
			ZhadumShadowData *data = GetZhadumShadowDataFromHWnd (hwnd);
			
			int alpha = (int) wparam;
			if (alpha != data->alpha) {
				data->alpha = alpha;
				ZhadumShadowWindowUpdate (hwnd);
			}
			return 0;
		}
	}
	
	return DefWindowProc (hwnd, msg, wparam, lparam);
}

// Register the shadow window's window class, if it's not already been done
static BOOL ZhadumRegisterShadowClass () {
	if (! zhadumRegisteredShadowClass) {
		WNDCLASSEX wc;
		wc.cbSize = sizeof (wc);
		wc.cbClsExtra = 0;
		wc.cbWndExtra = sizeof (ZhadumShadowData *);
		wc.hbrBackground = NULL;
		wc.hCursor = LoadCursor (NULL, IDC_ARROW);
		wc.hIcon = NULL;
		wc.hIconSm = NULL;
		wc.hInstance = zhadumHInst;
		wc.lpfnWndProc = (WNDPROC) ZhadumShadowWndProc;
		wc.lpszClassName = zhadumShadowWndClassName;
		wc.lpszMenuName = NULL;
		wc.style = 0;
		
		if (RegisterClassEx (&wc)) {
			zhadumRegisteredShadowClass = TRUE;
		}
		
		return zhadumRegisteredShadowClass;
	}
	else {	
		return TRUE;
	}
}

// Update the specified window's shadows. If isvisible is specified it should
// be zero if the window is being hidden or > zero if the window is being
// shown
static void ZhadumUpdateWindow (HWND hwnd, int isvisible = -1) {
	ZhadumWindowInfo *p = zhadumWindows;
	ZhadumWindowInfo *e = p + zhadumWindowCount;
	for (; p != e; ++p) {
		if (p->hwnd == hwnd) {
			break;
		}
	}
	
	if (p == e) {
		// Window's not being shadowed, so quit
		return;
	}
	
	int i;

	if (isvisible >= 0) {
		// "isvisible" was passed to us, so we received a WM_SHOWWINDOW or some
		// other indication that the window's visibility is changing
	
		if (! isvisible) {
			// We should be invisible
			if (p->visible) {
				// We're currently visibile
				p->visible = FALSE;
				
				// Destroy the shadow windows
				for (i = 0; i != 2; ++i) {
					if (p->shadows[i]) {
						DestroyWindow (p->shadows[i]);
					}
				}
				
				memset (p->shadows, 0, sizeof (HWND) * 2);
				return;
			}
			else {
				// No problem, already invisible
				return;
			}
		}
		else {
			// We should be visible
			if (! p->visible) {
				// We're not, so we're going to need the shadow window class
				if (! ZhadumRegisterShadowClass ()) {
					return;
				}

				// Update visible flag now
				p->visible = TRUE;
				
				// Make the shadow windows
				for (i = 0; i != 2; ++i) {
					p->shadows[i] = CreateWindowEx (WS_EX_LAYERED | WS_EX_TRANSPARENT, 
							zhadumShadowWndClassName, NULL,
							WS_POPUP | WS_DISABLED,
							0, 0, 0, 0, hwnd, NULL, zhadumHInst, NULL);
					SendMessage (p->shadows[i], ZHADUM_WM_SETVERTICAL, i, 0);
					ShowWindow (p->shadows[i], SW_SHOWNA);
				}
				
				// Reset the rectangle to force it to update as necessary
				memset (&p->rect, 0, sizeof (p->rect));
			}
		}
	}
	
	// If we reach here then either our visibility state didn't change or we've
	// just become visible
	if (! p->visible) {
		return;
	}

	// Get the window's current location
	RECT rect;
	GetWindowRect (hwnd, &rect);
	
	// Compare the current rectangles to the rectangle the shadows were last set
	// to.
	if (p->rect.left == rect.left && p->rect.top == rect.top 
            && p->rect.right == rect.right && p->rect.bottom == rect.bottom) {
        // No change, quit now
		return;
	}
	
	// Shadows need to follow the window
	p->rect = rect;

	SetWindowPos (p->shadows[0], NULL, rect.left+X_INDENT, rect.bottom,
			rect.right - rect.left + X_SIZE - X_INDENT, Y_SIZE, SWP_NOZORDER | SWP_NOACTIVATE);
	SetWindowPos (p->shadows[1], NULL, rect.right, rect.top+Y_INDENT, X_SIZE, 
			rect.bottom-rect.top-Y_INDENT, SWP_NOZORDER | SWP_NOACTIVATE);
}

// Add a window to the list of windows to be shadowed
static void ZhadumAddWindow (HWND hwnd) {
	ZhadumWindowInfo *p = zhadumWindows;
	ZhadumWindowInfo *e = p + zhadumWindowCount;
	for (; p != e; ++p) {
		if (p->hwnd == hwnd) {
			return;
		}
	}
	
	if (e != zhadumWindows + countof (zhadumWindows)) {
		// There's room
		memset (e, 0, sizeof (*e));
		e->hwnd = hwnd;
		++zhadumWindowCount;
	}
}

// Remove a window from the list of windows to be shadowed
static void ZhadumRemoveWindow (HWND hwnd) {
	ZhadumWindowInfo *p = zhadumWindows;
	ZhadumWindowInfo *e = p + zhadumWindowCount;
	for (; p != e; ++p) {
		if (p->hwnd == hwnd) {
			// Remove the shadows, if they exist
			for (int i = 0; i != 2; ++i) {
				if (p->shadows[i]) {
					DestroyWindow (p->shadows[i]);
				}
			}
			
			// Shrink the list
			if (p + 1 < e) {
				memmove (p, p + 1, (e - (p + 1)) * sizeof (ZhadumWindowInfo));
				return;
			}
			
			--zhadumWindowCount;
		}
	}
}

// Should we shadow a window?
static BOOL ZhadumShouldShadow (HWND hwnd, LPCREATESTRUCT cs) {
	// Child windows are a no no
	if ((cs->style & (WS_POPUP | WS_CHILD | WS_OVERLAPPED)) == WS_CHILD) {
		return FALSE;
	}
	
	// Check for us first
	if (! is_atom (cs->lpszClass)) {
		if (lstrcmp (cs->lpszClass, zhadumShadowWndClassName) == 0) {
			return FALSE;
		}
	}
	
	// Scan the exclusions
	ZhadumExclusion *p = zhadumExclusions;
	ZhadumExclusion *e = zhadumExclusions + zhadumExclusionCount;
	for (; p != e; ++p) {
		switch (p->type) {
			case ZhadumExclusionType_Window:
				if (hwnd == p->u.hwnd) {
					return FALSE;
				}
				break;
				
			case ZhadumExclusionType_Atom:
				if (cs->lpszClass == p->u.atom) {
					return FALSE;
				}
				break;
				
			case ZhadumExclusionType_Class:
				if (! is_atom (cs->lpszClass) 
						&& 0 == lstrcmp (cs->lpszClass, p->u.className)) {
					return FALSE;
				}
				break;
		}
	}
	
	return TRUE;
}

// Our hook procedure. We're only interested in certain messages.
static LRESULT CALLBACK ZhadumHookProc (int code, WPARAM wparam, LPARAM lparam) {
    HWND hwnd;
    
	switch (((CWPRETSTRUCT *) lparam)->message) {
		case WM_CREATE: {
			// Window being created. If it's suitable for shadowing (i.e.,
			// it's not a child window and it's not disabled) then add it
			// to the list of windows to shadow.
			// We catch shadows this way because they're always disabled.
			LPCREATESTRUCT cs = (LPCREATESTRUCT) ((CWPRETSTRUCT *) lparam)->lParam;
			if (ZhadumShouldShadow (((CWPRETSTRUCT *) lparam)->hwnd, cs)) {
				ZhadumAddWindow (((CWPRETSTRUCT *) lparam)->hwnd);
			}
			break;
		}
			
		case WM_DESTROY:
			// A window is being destroyed. Remove it from the shadowed window
			// list, if it's there.
			ZhadumRemoveWindow (((CWPRETSTRUCT *) lparam)->hwnd);
			break;
			
		case WM_SIZE:
		case WM_MOVE:
		case WM_MOVING:
		case WM_SIZING:
        case WM_ACTIVATE:
			// The window has moved or resized so we should adjust the shadows
            hwnd = ((CWPRETSTRUCT *) lparam)->hwnd;
			ZhadumUpdateWindow (hwnd, 
                    (GetWindowLong (hwnd, GWL_STYLE) & WS_VISIBLE) ? 1 : 0);
			break;

		case WM_SHOWWINDOW:
			// The window is being shown or hidden, update the shadows accordingly
			ZhadumUpdateWindow (((CWPRETSTRUCT *) lparam)->hwnd, 
					((CWPRETSTRUCT *) lparam)->wParam ? 1 : 0);
			break;
	}
	
	return CallNextHookEx (zhadumHook, code, wparam, lparam);
}

// Add an exclusion to the list
static BOOL ZhadumAddExclusion (const ZhadumExclusion *exclusion) {
	if (zhadumExclusionCount == MAX_ZHADUM_EXCLUSIONS) {
		return FALSE;
	}
	
	zhadumExclusions[zhadumExclusionCount++] = *exclusion;
	
	return TRUE;
}

// Free a single ZhadumExclusion
static void ZhadumFreeExclusion (ZhadumExclusion *exclusion) {
	if (exclusion->type == ZhadumExclusionType_Class) {
		free (exclusion->u.className);
	}
	
	exclusion->type = ZhadumExclusionType_Window;
}

// Free all exclusions
static void ZhadumFreeExclusions () {
	ZhadumExclusion *p = zhadumExclusions;
	ZhadumExclusion *e = zhadumExclusions + zhadumExclusionCount;
	for (; p != e; ++p) {
		ZhadumFreeExclusion (p);
	}
	
	zhadumExclusionCount = 0;
}

//
// Global Functions
//

// Exclude the specified window from window shadows. Returns FALSE if there
// are too many exclusions in place.
BOOL WINAPI ZhadumExcludeWindow (HWND hwnd) {
	ZhadumExclusion excl;
	
	ZhadumRemoveWindow (hwnd);
	
	excl.type = ZhadumExclusionType_Window;
	excl.u.hwnd = hwnd;
	return ZhadumAddExclusion (&excl);
}

// Remove the exclusion on the specified window. This won't create shadows
// but it will allow any future windows with the same HWND to have shadows.
// You no longer have to call this, it's handled internally.
void WINAPI ZhadumUnexcludeWindow (HWND hwnd) {
	ZhadumExclusion *p = zhadumExclusions;
	ZhadumExclusion *e = zhadumExclusions + zhadumExclusionCount;
	for (; p != e; ++p) {
		if (p->type == ZhadumExclusionType_Window 
				&& p->u.hwnd == hwnd) {
			memmove (p, p + 1, (e - (p + 1)) * sizeof (ZhadumExclusion));
			return;
		}
	}
}

// Exclude the specified WNDCLASS (can be an internal class, e.g. WC_DIALOG).
// Returns FALSE if there are too many exclusions in place.
BOOL WINAPI ZhadumExcludeClass (LPCTSTR classname) {
	ZhadumExclusion excl;
	
	if (! is_atom (classname)) {
		excl.type = ZhadumExclusionType_Atom;
		int size = (lstrlen (classname) + 1) * sizeof (TCHAR);
		excl.u.className = (TCHAR *) malloc (size);
		if (! excl.u.className) {
			return FALSE;
		}
		memcpy (excl.u.className, classname, size);
		if (! ZhadumAddExclusion (&excl)) {
			free (excl.u.className);
			return FALSE;
		}
		else {
			return TRUE;
		}
	}
	else {
		excl.type = ZhadumExclusionType_Atom;
		excl.u.atom = classname;
		return ZhadumAddExclusion (&excl);
	}
}

// Set the alpha of the shadows belonging to the specified window.
void WINAPI ZhadumSetWindowShadowAlpha (HWND hwnd, BYTE alpha) {
	ZhadumWindowInfo *p = zhadumWindows;
	ZhadumWindowInfo *e = p + zhadumWindowCount;
	for (; p != e; ++p) {
		if (p->hwnd == hwnd) {
			for (int i = 0; i != 2; ++i) {
				if (p->shadows[i]) {
					SendMessage (p->shadows[i], ZHADUM_WM_SETALPHA, (WPARAM) alpha, 0);
				}
			}
		}
	}
}

// Begins automatically applying window shadows to our popup windows
BOOL WINAPI ZhadumBegin (HINSTANCE hinst) {
	if (zhadumHook != NULL) {
		// Hook already installed
		return TRUE;
	}

	// Remember this
	zhadumHInst = hinst;

	// Make sure shadows are available
	if (! ZhadumInitialise ()) {
		return FALSE;
	}

	// Exclude menus
	ZhadumExcludeClass ((LPCTSTR) 32768);
	
	// Set a Windows CALLWNDPROCRECT hook, which will get called whenever
	// a window procedure returns. We inspect the messages and work on the
	// ones we're interested in.
	zhadumHook = SetWindowsHookEx (WH_CALLWNDPROCRET, ZhadumHookProc, GetModuleHandle (NULL), GetCurrentThreadId ());
	
	// Return boolean indicating success
	return zhadumHook != NULL ? TRUE : FALSE;
}

// Stop auto-shadowing
void WINAPI ZhadumEnd () {
	if (zhadumHook != NULL) {
		UnhookWindowsHookEx (zhadumHook);
		zhadumHook = NULL;
	}
	
	// Remove all the window entries from the list
	ZhadumWindowInfo *p = zhadumWindows;
	ZhadumWindowInfo *e = p + zhadumWindowCount;
	zhadumWindowCount = 0;
	for (; p != e; ++p) {
		for (int i = 0; i != 2; ++i) {
			if (p->shadows[i]) {
				DestroyWindow (p->shadows[i]);
			}
		}
	}
	
	// Remove all the exclusions
	ZhadumFreeExclusions ();
}

void WINAPI ZhadumDisplayWinError (DWORD err, LPCTSTR title) {
	TCHAR buf[128];
	FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			err,
			0,
			buf,
			countof (buf),
			NULL);
	MessageBox (NULL, buf, title, MB_OK | MB_ICONSTOP);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


Written By
France France
Addicted to reverse engineering. At work, I am developing business intelligence software in a team of smart people (independent software vendor).

Need a fast Excel generation component? Try xlsgen.

Comments and Discussions