OS2 World Community Forum
OS/2, eCS & ArcaOS - Technical => Programming => Topic started by: Martin Vieregg on February 17, 2020, 10:23:52 am
-
For my commandline frontend, I need to manipulate the VIO window where cmd.exe runs. I have got the window handle. I want to remove buttons in the window title, because the user should neither close the window, nor minimize or maximize. I assume I have to use a WinSetWindow* call and I can use the constant WS_MAXIMIZEBOX for example. But I did not find any documentation, I only found one for Windows in the Internet. Any hints are appreciated.
-
Unfortunately I cannot help on topic, but a side note: Please keep the shortcuts (close, minimise, maximise) in mind. Removing the buttons alone might not be enough.
I'm not that far into developing on OS/2 to know, but could be that if the buttons are gone, the shortcuts won't work either? - Not sure. - Just as a reminder..
-
To disable a window use the WinEnableWindow call with the handle of the window you wish to disable as the first parameter and FALSE as the second parametert. To get the window handle of the control windows use WinWindowFromID with the Frame window handle as the first parameter and the window id of the control window as the second parameter. So to disable and hide the minimize and maximize control window you would use
hwnd = WinWindowFromID(hwndParent, FID_MINMAX);
WinEnableWindow(hwnd, FALSE);
WinShowWindow(hwnd, FALSE);
The identifier for the system menu is FID_SYSMENU.
To remove the windows instead of disabling and hiding them then call WinDestroyWindow.
However, given that the VIO window has standard input and standard output redirected(If you're interested in stderror you could redirect that as well) it's not really going to be showing anything of interest so it would be simpler to simply hide the entire window. To prevent the user from closing it from the window list you'd need to get the Switch entry handle for the window and then remove it from the switch list using WinQuerySwitchHandle and WinRemoveSwitchEntry.
-
Hi Martin
Possibly a parameter in DosStartSession - looking at the example in cp1.inf (os2 toolkit) I see the following within the example given :-
/* Open the session VISIBLE and MAXIMIZED */
SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
Regards
Pete
-
SData.PgmControl = SSF_CONTROL_VISIBLE | SSF_CONTROL_MAXIMIZE;
PgmControl defines the window state when starting the window with DosStartSession. It would be started visible and maximized in this case. I want to manipulate the "maximize" button in the title bar. Laurence is right. I remember now that long time ago I already programmed it for my 4allCalc calulator, but meanwhile I do not practise regulary OS/2 API programming anymore. Any button has got a window handle, and with this window handle, you can do all the things you want.
Laurences code principally works, but WinEnableWindow FALSE makes the buttons non-functional, but they are normally shown. WinShowWindow FALSE deletes the buttons, but now there's a "hole" which is no more redrawn. The titlebar width is unchanged. The first trial, I made a programming failure and it did not work. I have to recalulate the correct width of the titlebar so it "fits" the holes. The correct titlebar width is the client width minus the width of the sysmenu button. This code works:
hw = WinWindowFromID(VIOhandle, FID_MINMAX);
WinEnableWindow(hw, FALSE); //turns off Min/Max functionality, but buttons are still shown
WinShowWindow(hw, FALSE); //do not show Min/Max buttons
//enlarge the titlebar width to fit the "holes"
hwtb = WinWindowFromID(VIOhandle, FID_TITLEBAR); WinQueryWindowPos (hw, &swp);
tbHeight = swp.cy;
hw = WinWindowFromID(VIOhandle, FID_CLIENT); WinQueryWindowPos (hw, &swp);
clWidth = swp.cx;
hw = WinWindowFromID(VIOhandle, FID_SYSMENU); WinQueryWindowPos (hw, &swp);
sysWidth = swp.cx;
ZOrderHWND = 0;
vLeft = 0; vBottom = 0; flOptions = SWP_SIZE;
WinSetWindowPos (hwtb, 0, vLeft, vBottom, clWidth-sysWidth, tbHeight, flOptions);
Because I need the System Menu of the VIO window, I cannot delete the System Menu and the user has got access to CLOSE which I do not want. Is it possible to disable the close functionality (also in the switch list) ? If not, I will restart the session automatically.
-
To disable the close menu option in the system menu you can send a MIA_DISABLED message to the system menu.
hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
WinSendMsg(hw, MM_SETITEMATTR,
MPFROM2SHORT(SC_CLOSE, TRUE),
MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
However, you still need to handle keyboard shortcuts like ctl-F4 as well. I would suggest subclassing the VIO window (WinSubclassWindow) and handling WM_CLOSE and WM_SIZE messages sent to the VIO window in a custom window procedure. That would allow you to do anything from simply ignoring the WM_CLOSE message to customized close procedures. You can also control which frame controls are created if you do this using a WmCreateFrameControls call in the WM_CREATE processing rather than deleting the frame control windows.
-
The correct way to do this:
* delete menuid SC_CLOSE from the System menu (FID_SYSMENU); this will also remove the Close button from the MinMax button (FID_MINMAX)
* delete menuids SC_MAXIMIZE and SC_RESTORE from both the System menu and the MinMax button
* delete menuids SC_MAXIMIZE and SC_RESTORE from the MinMax button, and SC_MAXIMIZE from the System menu
* do NOT remove the Minimize button. It is the user's right to clear his screen if desired - even if it may have negative consequences in some *few* situations.
Edit: leave "Restore" on the System menu for use when the window is minimized
-
delete menuid SC_CLOSE from the System menu (FID_SYSMENU)
I did not manage this simple call.
I tried:
hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
//hwClose = WinWindowFromID(hw, SC_CLOSE);
WinSendMsg (hw, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, 0), 0);
Where is the failure?
-
hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
WinSendMsg (hw, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, 0), 0);
Where is the failure?
SC_CLOSE appears on a submenu of FID_SYSMENU. Therefore, the correct call is
hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
WinSendMsg (hw, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, 1), 0);
-
Ah, yes, thank you Rich. I tried it already with the mp parameter value "1" but did not recognize that the "Close" entry indeed vanished.
But a double click to the System Menu Button still closes the session which I hoped to prevent, because I do not want that the user closes this session directly. A close closes cmd.exe and helper, and the helper should close a lot of stuff if cmd.exe has terminated.
It is not really problematic, because meanwhile I built a mechanism where MeShell automatically restarts the helper+cmd session and re-initializes all the pipe, semaphore and shared memory stuff. But I wonder if it would be possible or not.
-
One solution would be to subclass the frame window and process WM_CLOSE and WM_QUIT messages in the custom window procedure.
-
One solution would be to subclass the frame window and process WM_CLOSE and WM_QUIT messages in the custom window procedure.
The window is the original PM VIO window where cmd.exe runs. I have no access to the code. It is as-is. I can only post messages to handles.
-
Pass the window handle of the Vio window as the first parameter of the WinSubClassWindow call with a pointer to the custom window procedure as the second parameter. Pass any messages that you don't explicitly process to the original window procedure (which is the return value from the WinSubClassWindow call) in a similar fashion to the way you pass messages you don't process to the standard window procedure in window classes you create in your own code. Because you can only subclass windows started in the same session you need ti issue this call from the helper app. There's a discussion on calling PM from AVIO here.
http://www.edm2.com/index.php/Calling_PM_from_AVIO_Applications (http://www.edm2.com/index.php/Calling_PM_from_AVIO_Applications)