comparison win/dw.c @ 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 12ba7e744560
children ecf1df2edcee
comparison
equal deleted inserted replaced
465:4ff2c7210973 466:c3dfa117b080
6 * (C) 2000-2003 Brian Smith <dbsoft@technologist.com> 6 * (C) 2000-2003 Brian Smith <dbsoft@technologist.com>
7 * (C) 2003 Mark Hessling <m.hessling@qut.edu.au> 7 * (C) 2003 Mark Hessling <m.hessling@qut.edu.au>
8 * 8 *
9 */ 9 */
10 #define _WIN32_IE 0x0500 10 #define _WIN32_IE 0x0500
11 #ifdef WINNT_COMPAT
11 #define WINVER 0x400 12 #define WINVER 0x400
13 #else
14 #define WINVER 0x500
15 #endif
12 #include <windows.h> 16 #include <windows.h>
13 #include <windowsx.h> 17 #include <windowsx.h>
14 #include <commctrl.h> 18 #include <commctrl.h>
15 #include <shlwapi.h> 19 #include <shlwapi.h>
16 #include <shlobj.h> 20 #include <shlobj.h>
202 206
203 /* Ok this is a really big hack but what the hell ;) */ 207 /* Ok this is a really big hack but what the hell ;) */
204 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 208 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
205 { 209 {
206 char **argv; 210 char **argv;
207 int argc; 211 int argc;
208 212
209 DWInstance = hInstance; 213 DWInstance = hInstance;
210 214
211 argv = _convertargs(&argc, lpCmdLine); 215 argv = _convertargs(&argc, lpCmdLine);
212 216
273 */ 277 */
274 void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data) 278 void _new_signal(ULONG message, HWND window, int id, void *signalfunction, void *data)
275 { 279 {
276 SignalHandler *new = malloc(sizeof(SignalHandler)); 280 SignalHandler *new = malloc(sizeof(SignalHandler));
277 281
278 if(message == WM_COMMAND)
279 dw_signal_disconnect_by_window(window);
280
281 new->message = message; 282 new->message = message;
282 new->window = window; 283 new->window = window;
283 new->id = id; 284 new->id = id;
284 new->signalfunction = signalfunction; 285 new->signalfunction = signalfunction;
285 new->data = data; 286 new->data = data;
292 SignalHandler *prev = NULL, *tmp = Root; 293 SignalHandler *prev = NULL, *tmp = Root;
293 while(tmp) 294 while(tmp)
294 { 295 {
295 if(tmp->message == message && 296 if(tmp->message == message &&
296 tmp->window == window && 297 tmp->window == window &&
298 tmp->id == id &&
297 tmp->signalfunction == signalfunction) 299 tmp->signalfunction == signalfunction)
298 { 300 {
299 tmp->data = data; 301 tmp->data = data;
300 free(new); 302 free(new);
301 return; 303 return;
1340 return pos; 1342 return pos;
1341 } 1343 }
1342 return -1; 1344 return -1;
1343 } 1345 }
1344 1346
1347 #ifndef WINNT_COMPAT
1348 HMENU _get_owner(HMENU menu)
1349 {
1350 MENUINFO mi;
1351
1352 mi.cbSize = sizeof(MENUINFO);
1353 mi.fMask = MIM_MENUDATA;
1354
1355 if(GetMenuInfo(menu, &mi))
1356 return (HMENU)mi.dwMenuData;
1357 return (HMENU)0;
1358 }
1359
1360 /* Find the desktop window handle */
1361 HMENU _menu_owner(HMENU handle)
1362 {
1363 HMENU menuowner = 0, lastowner = _get_owner(handle);
1364
1365 /* Find the toplevel menu */
1366 while((menuowner = _get_owner(lastowner)) != 0)
1367 {
1368 if(menuowner == (HMENU)1)
1369 return lastowner;
1370 lastowner = menuowner;
1371 }
1372 return (HMENU)0;
1373 }
1374 #endif
1375
1345 /* The main window procedure for Dynamic Windows, all the resizing code is done here. */ 1376 /* The main window procedure for Dynamic Windows, all the resizing code is done here. */
1346 BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2) 1377 BOOL CALLBACK _wndproc(HWND hWnd, UINT msg, WPARAM mp1, LPARAM mp2)
1347 { 1378 {
1348 int result = -1; 1379 int result = -1;
1349 static int command_active = 0; 1380 static int command_active = 0;
1662 if(tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2) 1693 if(tmp->message == LBN_SELCHANGE && tmp->window == (HWND)mp2)
1663 { 1694 {
1664 result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data); 1695 result = listboxselectfunc(tmp->window, dw_listbox_selected(tmp->window), tmp->data);
1665 tmp = NULL; 1696 tmp = NULL;
1666 } 1697 }
1698 }
1699 #ifndef WINNT_COMPAT
1700 else if(tmp->id && passthru == tmp->id)
1701 {
1702 HMENU hwndmenu = GetMenu(hWnd), menuowner = _menu_owner((HMENU)tmp->window);
1703
1704 if(menuowner == hwndmenu || !menuowner)
1705 {
1706 result = clickfunc(tmp->window, tmp->data);
1707 tmp = NULL;
1708 }
1667 } /* Make sure it's the right window, and the right ID */ 1709 } /* Make sure it's the right window, and the right ID */
1710 #endif
1668 else if(tmp->window < (HWND)65536 && command == tmp->window) 1711 else if(tmp->window < (HWND)65536 && command == tmp->window)
1669 { 1712 {
1670 result = clickfunc(popup ? popup : tmp->window, tmp->data); 1713 result = clickfunc(popup ? popup : tmp->window, tmp->data);
1671 tmp = NULL; 1714 tmp = NULL;
1672 } 1715 }
3833 { 3876 {
3834 HMENUI tmp; 3877 HMENUI tmp;
3835 3878
3836 tmp = (HMENUI)CreateMenu(); 3879 tmp = (HMENUI)CreateMenu();
3837 3880
3881 #ifndef WINNT_COMPAT
3882 {
3883 MENUINFO mi;
3884
3885 mi.cbSize = sizeof(MENUINFO);
3886 mi.fMask = MIM_MENUDATA;
3887 mi.dwMenuData = (ULONG_PTR)1;
3888
3889 SetMenuInfo((HMENU)tmp, &mi);
3890 }
3891 #endif
3892
3838 dw_window_set_data(location, "_dw_menu", (void *)tmp); 3893 dw_window_set_data(location, "_dw_menu", (void *)tmp);
3839 3894
3840 SetMenu(location, (HMENU)tmp); 3895 SetMenu(location, (HMENU)tmp);
3841 return location; 3896 return location;
3842 } 3897 }
3872 */ 3927 */
3873 HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu) 3928 HWND API dw_menu_append_item(HMENUI menux, char *title, ULONG id, ULONG flags, int end, int check, HMENUI submenu)
3874 { 3929 {
3875 MENUITEMINFO mii; 3930 MENUITEMINFO mii;
3876 HMENU mymenu = (HMENU)menux; 3931 HMENU mymenu = (HMENU)menux;
3932 #ifndef WINNT_COMPAT
3933 char buffer[15];
3934 #endif
3877 3935
3878 if(IsWindow(menux) && !IsMenu(mymenu)) 3936 if(IsWindow(menux) && !IsMenu(mymenu))
3879 mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu"); 3937 mymenu = (HMENU)dw_window_get_data(menux, "_dw_menu");
3880 3938
3881 mii.cbSize = sizeof(MENUITEMINFO); 3939 mii.cbSize = sizeof(MENUITEMINFO);
3906 mii.hSubMenu = 0; 3964 mii.hSubMenu = 0;
3907 mii.dwTypeData = title; 3965 mii.dwTypeData = title;
3908 mii.cch = strlen(title); 3966 mii.cch = strlen(title);
3909 3967
3910 InsertMenuItem(mymenu, 65535, TRUE, &mii); 3968 InsertMenuItem(mymenu, 65535, TRUE, &mii);
3969
3970 #ifndef WINNT_COMPAT
3971 sprintf(buffer, "_dw_id%d", id);
3972 dw_window_set_data(DW_HWND_OBJECT, buffer, (void *)mymenu);
3973
3974 /* According to the docs this will only work on Win2k/98 and above */
3975 if(submenu)
3976 {
3977 MENUINFO mi;
3978
3979 mi.cbSize = sizeof(MENUINFO);
3980 mi.fMask = MIM_MENUDATA;
3981 mi.dwMenuData = (ULONG_PTR)mymenu;
3982
3983 SetMenuInfo((HMENU)submenu, &mi);
3984 }
3985 #endif
3986
3911 if(IsWindow(menux) && !IsMenu((HMENU)menux)) 3987 if(IsWindow(menux) && !IsMenu((HMENU)menux))
3912 DrawMenuBar(menux); 3988 DrawMenuBar(menux);
3913 return (HWND)id; 3989 return (HWND)id;
3914 } 3990 }
3915 3991
8126 * sigfunc: The pointer to the function to be used as the callback. 8202 * sigfunc: The pointer to the function to be used as the callback.
8127 * data: User data to be passed to the handler function. 8203 * data: User data to be passed to the handler function.
8128 */ 8204 */
8129 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data) 8205 void API dw_signal_connect(HWND window, char *signame, void *sigfunc, void *data)
8130 { 8206 {
8131 ULONG message = 0L; 8207 ULONG message = 0, id = 0;
8132 8208
8133 if(window && signame && sigfunc) 8209 if(window && signame && sigfunc)
8134 { 8210 {
8135 if(stricmp(signame, DW_SIGNAL_SET_FOCUS) == 0) 8211 if(stricmp(signame, DW_SIGNAL_SET_FOCUS) == 0)
8136 window = _normalize_handle(window); 8212 window = _normalize_handle(window);
8137 8213
8138 if((message = _findsigmessage(signame)) != 0) 8214 if((message = _findsigmessage(signame)) != 0)
8139 _new_signal(message, window, 0, sigfunc, data); 8215 {
8216 /* Handle special case of the menu item */
8217 if(message == WM_COMMAND && window < (HWND)65536)
8218 {
8219 char buffer[15];
8220 HWND owner;
8221
8222 sprintf(buffer, "_dw_id%d", (int)window);
8223 owner = (HWND)dw_window_get_data(DW_HWND_OBJECT, buffer);
8224
8225 if(owner)
8226 {
8227 id = (ULONG)window;
8228 window = owner;
8229 dw_window_set_data(DW_HWND_OBJECT, buffer, 0);
8230 }
8231 else
8232 {
8233 /* If it is a popup menu clear all entries */
8234 dw_signal_disconnect_by_window(window);
8235 }
8236 }
8237 _new_signal(message, window, id, sigfunc, data);
8238 }
8140 } 8239 }
8141 } 8240 }
8142 8241
8143 /* 8242 /*
8144 * Removes callbacks for a given window with given name. 8243 * Removes callbacks for a given window with given name.