changeset 466:c3dfa117b080

Added new code to make the menu handlers window local instead of global. According to the docs this will only work on Win2k/98 and above, so I added a WINNT_COMPAT define to allow Dynamic Windows to work on WinNT and Win95 without the new menu code. Also improved on this same fix for OS/2.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 08 Oct 2003 09:36:10 +0000
parents 4ff2c7210973
children ecf1df2edcee
files os2/dw.c win/dw.c
diffstat 2 files changed, 107 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/os2/dw.c	Thu Oct 02 07:51:26 2003 +0000
+++ b/os2/dw.c	Wed Oct 08 09:36:10 2003 +0000
@@ -2157,11 +2157,11 @@
 					int (* API clickfunc)(HWND, void *) = (int (* API)(HWND, void *))tmp->signalfunction;
 					ULONG command = COMMANDMSG(&msg)->cmd;
 
-					if(tmp->id)
+					if(tmp->id && command == tmp->id)
 					{
 						HWND menuowner = _menu_owner(tmp->window);
 
-						if((menuowner == hWnd || menuowner == NULLHANDLE) && command == tmp->id)
+						if(menuowner == hWnd || menuowner == NULLHANDLE)
 						{
 							result = clickfunc(tmp->window, tmp->data);
 							tmp = NULL;
--- a/win/dw.c	Thu Oct 02 07:51:26 2003 +0000
+++ b/win/dw.c	Wed Oct 08 09:36:10 2003 +0000
@@ -8,7 +8,11 @@
  *
  */
 #define _WIN32_IE 0x0500
+#ifdef WINNT_COMPAT
 #define WINVER 0x400
+#else
+#define WINVER 0x500
+#endif
 #include <windows.h>
 #include <windowsx.h>
 #include <commctrl.h>
@@ -204,7 +208,7 @@
 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
 {
 	char **argv;
-    int argc;
+	int argc;
 
 	DWInstance = hInstance;
 
@@ -275,9 +279,6 @@
 {
 	SignalHandler *new = malloc(sizeof(SignalHandler));
 
-	if(message == WM_COMMAND)
-		dw_signal_disconnect_by_window(window);
-
 	new->message = message;
 	new->window = window;
 	new->id = id;
@@ -294,6 +295,7 @@
 		{
 			if(tmp->message == message &&
 			   tmp->window == window &&
+			   tmp->id == id &&
 			   tmp->signalfunction == signalfunction)
 			{
 				tmp->data = data;
@@ -1342,6 +1344,35 @@
 	return -1;
 }
 
+#ifndef WINNT_COMPAT
+HMENU _get_owner(HMENU menu)
+{
+	MENUINFO mi;
+
+	mi.cbSize = sizeof(MENUINFO);
+	mi.fMask = MIM_MENUDATA;
+
+	if(GetMenuInfo(menu, &mi))
+		return (HMENU)mi.dwMenuData;
+	return (HMENU)0;
+}
+
+/* Find the desktop window handle */
+HMENU _menu_owner(HMENU handle)
+{
+	HMENU menuowner = 0, lastowner = _get_owner(handle);
+
+	/* Find the toplevel menu */
+	while((menuowner = _get_owner(lastowner)) != 0)
+	{
+		if(menuowner == (HMENU)1)
+			return lastowner;
+		lastowner = menuowner;
+	}
+	return (HMENU)0;
+}
+#endif
+
 /* The main window procedure for Dynamic Windows, all the resizing code is done here. */
 BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
 {
@@ -1664,7 +1695,19 @@
 								result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data);
 								tmp = NULL;
 							}
+						}
+#ifndef WINNT_COMPAT
+						else if(tmp->id && passthru == tmp->id)
+						{
+							HMENU hwndmenu = GetMenu(hWnd), menuowner = _menu_owner((HMENU)tmp->window);
+
+							if(menuowner == hwndmenu || !menuowner)
+							{
+								result = clickfunc(tmp->window, tmp->data);
+								tmp = NULL;
+							}
 						} /* Make sure it's the right window, and the right ID */
+#endif
 						else if(tmp->window < (HWND)65536 && command == tmp->window)
 						{
 							result = clickfunc(popup ? popup : tmp->window, tmp->data);
@@ -3835,6 +3878,18 @@
 
 	tmp = (HMENUI)CreateMenu();
 
+#ifndef WINNT_COMPAT
+	{
+		MENUINFO mi;
+
+		mi.cbSize = sizeof(MENUINFO);
+		mi.fMask = MIM_MENUDATA;
+		mi.dwMenuData = (ULONG_PTR)1;
+
+		SetMenuInfo((HMENU)tmp, &mi);
+	}
+#endif
+
 	dw_window_set_data(location, "_dw_menu", (void *)tmp);
 
 	SetMenu(location, (HMENU)tmp);
@@ -3874,6 +3929,9 @@
 {
 	MENUITEMINFO mii;
 	HMENU mymenu = (HMENU)menux;
+#ifndef WINNT_COMPAT
+	char buffer[15];
+#endif
 
 	if(IsWindow(menux) && !IsMenu(mymenu))
 		mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu");
@@ -3908,6 +3966,24 @@
 	mii.cch = strlen(title);
 
 	InsertMenuItem(mymenu, 65535, TRUE, &mii);
+
+#ifndef WINNT_COMPAT
+	sprintf(buffer, "_dw_id%d", id);
+	dw_window_set_data(DW_HWND_OBJECT, buffer, (void *)mymenu);
+
+	/* According to the docs this will only work on Win2k/98 and above */
+	if(submenu)
+	{
+		MENUINFO mi;
+
+		mi.cbSize = sizeof(MENUINFO);
+		mi.fMask = MIM_MENUDATA;
+		mi.dwMenuData = (ULONG_PTR)mymenu;
+
+		SetMenuInfo((HMENU)submenu, &mi);
+	}
+#endif
+
 	if(IsWindow(menux) && !IsMenu((HMENU)menux))
 		DrawMenuBar(menux);
 	return (HWND)id;
@@ -8128,7 +8204,7 @@
  */
 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
 {
-	ULONG message = 0L;
+	ULONG message = 0, id = 0;
 
 	if(window && signame && sigfunc)
 	{
@@ -8136,7 +8212,30 @@
 			window = _normalize_handle(window);
 
 		if((message = _findsigmessage(signame)) != 0)
-			_new_signal(message, window, 0, sigfunc, data);
+		{
+			/* Handle special case of the menu item */
+			if(message == WM_COMMAND && window < (HWND)65536)
+			{
+				char buffer[15];
+				HWND owner;
+
+				sprintf(buffer, "_dw_id%d", (int)window);
+				owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer);
+
+				if(owner)
+				{
+					id = (ULONG)window;
+					window = owner;
+					dw_window_set_data(DW_HWND_OBJECT, buffer, 0);
+				}
+				else
+				{
+					/* If it is a popup menu clear all entries */
+					dw_signal_disconnect_by_window(window);
+				}
+			}
+			_new_signal(message, window, id, sigfunc, data);
+		}
 	}
 }