Index: Fl_win32.cxx
===================================================================
--- Fl_win32.cxx	(revision 10387)
+++ Fl_win32.cxx	(working copy)
@@ -1711,12 +1711,17 @@
  * we register to avoid double registration. It has the added bonus 
  * of freeing everything on application close as well.
  */
+void unregisterclass(const char* classname);
 class NameList {
 public:
   NameList() { name = (char**)malloc(sizeof(char**)); NName = 1; nName = 0; }
   ~NameList() { 
     int i;
-    for (i=0; i<nName; i++) free(name[i]);
+    for (i=0; i<nName; i++)
+	{
+		unregisterclass(name[i]);
+		free(name[i]);
+	}
     if (name) free(name); 
   }
   void add_name(const char *n) {
@@ -1745,6 +1750,79 @@
 UINT fl_wake_msg = 0;
 int fl_disable_transient_for; // secret method of removing TRANSIENT_FOR
 
+
+#include "Psapi.h"
+#pragma comment( lib, "psapi.lib" )
+HMODULE GetModuleHandleByAddress(HANDLE hProc, LPVOID lpAddress)
+{
+	HANDLE hHeap = GetProcessHeap();
+	HMODULE * hmodules = NULL;
+	DWORD cb = 0;
+
+	for(;;)
+	{
+		DWORD cbNeeded = 0;
+
+		if(!EnumProcessModules(hProc, hmodules, cb, &cbNeeded))
+			return NULL;
+
+		if(cb >= cbNeeded)
+		{
+			cb = cbNeeded;
+			break;
+		}
+
+		PVOID p = HeapAlloc(hHeap, 0, cbNeeded);
+		HeapFree(hHeap, 0, hmodules);
+
+		if(p == NULL)
+			return NULL;
+
+		hmodules = (HMODULE *)p;
+		cb = cbNeeded;
+	}
+
+	DWORD i = 0;
+	DWORD ccModules = cb / sizeof(HMODULE);
+	HMODULE hm = NULL;
+
+	for(; i < ccModules; ++ i)
+	{
+		MODULEINFO modinfo;
+
+		if(!GetModuleInformation(hProc, hmodules[i], &modinfo, sizeof(modinfo)))
+			continue;
+
+		if(lpAddress < modinfo.lpBaseOfDll)
+			continue;
+
+		if((ULONG_PTR)lpAddress >= ((ULONG_PTR)modinfo.lpBaseOfDll + modinfo.SizeOfImage))
+			continue;
+
+		hm = (HMODULE)modinfo.lpBaseOfDll;
+		break;
+	}
+
+
+
+	if(i == ccModules && hm == NULL)
+		SetLastError(ERROR_MOD_NOT_FOUND);
+
+	HeapFree(hHeap, 0, hmodules);
+
+	return hm;
+}
+HMODULE GetCurrentModule()
+{
+	HMODULE hModule = GetModuleHandleByAddress(GetCurrentProcess(), &GetCurrentModule);
+
+	return hModule;
+}
+
+static char moduleName[100] = "";
+
+static NameList class_name_list;
+
 Fl_X* Fl_X::make(Fl_Window* w) {
   Fl_Group::current(0); // get rid of very common user bug: forgot end()
 
@@ -1758,25 +1836,31 @@
     return 0L;
   }
 
-  static NameList class_name_list;
+  if(!*moduleName)
+	  GetModuleFileNameA(GetCurrentModule(), moduleName, 100);
+
   static const char *first_class_name = 0L;
   const char *class_name = w->xclass();
   if (!class_name) class_name = first_class_name; // reuse first class name used
   if (!class_name) class_name = "FLTK"; // default to create a "FLTK" WNDCLASS
+
+  char long_class_name[200] = "";
+  sprintf_s(long_class_name, 200, "%s_%s", moduleName, class_name);
   if (!first_class_name) {
-    first_class_name = class_name;
+    first_class_name = long_class_name;
   }
 
-  wchar_t class_namew[100]; // (limited) buffer for Windows class name
+  wchar_t class_namew[200]; // (limited) buffer for Windows class name
 
   // convert UTF-8 class_name to wchar_t for RegisterClassExW and CreateWindowExW
 
-  fl_utf8toUtf16(class_name,
-		 (unsigned)strlen(class_name),		// in
+  fl_utf8toUtf16(long_class_name,
+		 (unsigned)strlen(long_class_name),		// in
 		 (unsigned short*)class_namew,		// out
 		 (unsigned)sizeof(class_namew)/sizeof(wchar_t));	// max. size
 
-  if (!class_name_list.has_name(class_name)) {
+  if (!class_name_list.has_name(long_class_name)) { 
+
     WNDCLASSEXW wcw;
     memset(&wcw, 0, sizeof(wcw));
     wcw.cbSize = sizeof(WNDCLASSEXW);
@@ -1799,7 +1883,7 @@
     wcw.lpszMenuName = NULL;
     wcw.lpszClassName = class_namew;
     RegisterClassExW(&wcw);
-    class_name_list.add_name(class_name);
+    class_name_list.add_name(long_class_name);
   }
 
   const wchar_t* message_namew = L"FLTK::ThreadWakeup";
@@ -2017,14 +2101,18 @@
   unsigned int elapsed = (unsigned int)(time * 1000);
 
   if ( !s_TimerWnd ) {
+    if(!*moduleName)
+      GetModuleFileNameA(GetCurrentModule(), moduleName, 100);
     const char* timer_class = "FLTimer";
+	char long_class_name[200] = "";
+	sprintf_s(long_class_name, 200, "%s_%s", moduleName, timer_class);
     WNDCLASSEX wc;
     memset(&wc, 0, sizeof(wc));
     wc.cbSize = sizeof (wc);
     wc.style = CS_CLASSDC;
     wc.lpfnWndProc = (WNDPROC)s_TimerProc;
     wc.hInstance = fl_display;
-    wc.lpszClassName = timer_class;
+    wc.lpszClassName = long_class_name;
     /*ATOM atom =*/ RegisterClassEx(&wc);
     // create a zero size window to handle timer events
     s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
@@ -2040,6 +2128,8 @@
 				  0, 0, 1, 1,
 				  NULL, NULL, fl_display, NULL);
     ShowWindow(s_TimerWnd, SW_SHOWNOACTIVATE);
+	if (!class_name_list.has_name(long_class_name))
+		class_name_list.add_name(long_class_name);
   }
 
   win32_timers[timer_id].callback = cb;
@@ -2049,6 +2139,51 @@
     SetTimer(s_TimerWnd, timer_id + 1, elapsed, NULL);
 }
 
+#define USER_ERROR 0x20000000
+
+BOOL CALLBACK HandleWindowClosing(HWND hwnd, LPARAM lParam)
+{
+	unsigned processID = 0;
+	if(processID == GetCurrentProcessId())
+	{
+		const char* const classNameToClose = (const char* const)lParam;
+		char className[200] = "";
+		GetClassName(hwnd, className, sizeof(className));
+		if(strcmp(className, classNameToClose) == 0)
+		{
+			BOOL ret = DestroyWindow(hwnd);
+			if(!ret)
+			{
+				SetLastError(GetLastError() | USER_ERROR);
+				return FALSE;
+			}
+		}
+	}
+
+	return TRUE;
+}
+
+void unregisterclass(const char* classname)
+{
+	if(classname)
+	{
+		HINSTANCE hInst = GetModuleHandle(NULL);
+		BOOL ret;
+		unsigned err = 0;
+		ret = UnregisterClassA(classname,  hInst);
+		if(!ret)
+		{
+			err = GetLastError();
+			if(err == ERROR_CLASS_HAS_WINDOWS)
+			{
+				EnumWindows(HandleWindowClosing, (LPARAM)(void*)classname);
+
+				ret = UnregisterClassA(classname,  hInst);
+			}
+		}
+	}
+}
+
 int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
 {
   for (int i = 0;  i < win32_timer_used;  ++i) {
