Here are two methods of doing that. The first is from the PMHINTS file, and the second is from Gpf. PMHINTS takes the approach of removing SC_CLOSE and the nearby separator. The Gpf solution takes the approach of deleting everything that it doesn't explicitly want. I've extended it to, among other things, conditionally delete the "Window List" menu item as well.
The deletion problems get messier in application menus when there are multiple separaters in different pull-downs. That is when assigning the separators an id really pays off.
Both examples are 16-bit OS/2 1.x code.
PMHINTS:
VOID DelClose(HWND hwnd) { HWND hSysMenu, hSysSubMenu; MENUITEM SysMenu; SHORT idItem, idSep, idSysMenu; hSysMenu = WinWindowFromID(WinQueryWindow(hwnd, QW_PARENT, FALSE), FID_SYSMENU); idSysMenu = SHORT1FROMMR(WinSendMsg(hSysMenu, MM_ITEMIDFROMPOSITION, NULL, NULL)); WinSendMsg(hSysMenu, MM_QUERYITEM, MPFROM2SHORT(idSysMenu, FALSE), MPFROMP(&SysMenu)); hSysSubMenu = SysMenu.hwndSubMenu; idItem = SHORT1FROMMR(WinSendMsg(hSysSubMenu, MM_ITEMPOSITIONFROMID, MPFROM2SHORT(SC_CLOSE, FALSE), NULL)); if (idItem != MIT_ERROR) { idSep = idItem + 1; // Get separator ID idSep = SHORT1FROMMR(WinSendMsg(hSysSubMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(idSep), NULL)); WinSendMsg(hSysMenu, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, TRUE), MPFROMSHORT(NULL)); WinSendMsg(hSysSubMenu, MM_DELETEITEM, MPFROM2SHORT(idSep, FALSE), NULL); } }
Derived from Gpf, adapted for a client, with some of my changes expurgated (so it won't compile as is):
/***** * * UtilDlgSysMenu * * Remove unavailable items from system menu of dialog box. * * History: * 8/31/92 gts Adapted from Gpf's GpfSetDialogBoxSysMenu * with slight modifications. * *****/ void _export UtilDlgSysMenu ( /* Remove unwanted system menu items */ HWND hwndFrame) /* I - Handle to dialog window */ { HWND hwndSubMenu; /* sys menu pull-down handle */ MENUITEM miTemp; /* menu item template */ SHORT sItemId; /* system menu item ID */ SHORT sItemIndex; /* system menu item index */ MRESULT mresult; /********************************************************************/ /* Get the handle of the system menu pull-down. */ /********************************************************************/ hwndSubMenu = WinWindowFromID( hwndFrame, FID_SYSMENU ); WinSendMsg( hwndSubMenu, MM_QUERYITEM, MPFROM2SHORT( SC_SYSMENU, FALSE ), MPFROMP( (PSZ)&miTemp ) ); hwndSubMenu = miTemp.hwndSubMenu; /********************************************************************/ /* Remove all items from the system menu pull-down that are no */ /* longer wanted. */ /********************************************************************/ mresult = WinSendMsg( hwndSubMenu, MM_QUERYITEMCOUNT, MPFROMSHORT(0), MPFROMSHORT(0) ); sItemIndex = SHORT1FROMMR(mresult); for (sItemId = 0; sItemIndex != -1; sItemIndex--) { mresult = WinSendMsg( hwndSubMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(sItemIndex), MPFROMSHORT(0) ); sItemId = SHORT1FROMMR(mresult); if ( sItemId != MIT_ERROR &&sItemId != SC_MOVE &&sItemId != SC_CLOSE &&(sItemId != SC_TASKMANAGER || (flFlags & MAXONLY)) ) // <- application controls { WinSendMsg( hwndSubMenu, MM_DELETEITEM, MPFROM2SHORT(sItemId,FALSE), MPFROMSHORT(0) ); } } }
Credit: Guy Scharf