Author Topic: Manipulating a PM window from another program  (Read 10437 times)

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 278
  • Karma: +2/-0
    • View Profile
Manipulating a PM window from another program
« 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.

Mathias

  • Full Member
  • ***
  • Posts: 196
  • Karma: +2/-0
  • using ArcaOS
    • View Profile
    • IRC
Re: Manipulating a PM window from another program
« Reply #1 on: February 17, 2020, 11:34:39 am »
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..

Laurence Pithie

  • Jr. Member
  • **
  • Posts: 62
  • Karma: +1/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #2 on: February 17, 2020, 02:18:13 pm »
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
Code: [Select]
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.


« Last Edit: February 17, 2020, 02:20:17 pm by Laurence Pithie »

Pete

  • Hero Member
  • *****
  • Posts: 1343
  • Karma: +11/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #3 on: February 17, 2020, 04:33:16 pm »
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

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 278
  • Karma: +2/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #4 on: February 17, 2020, 06:23:41 pm »
Quote
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:

Code: [Select]
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.
« Last Edit: February 18, 2020, 08:42:12 am by Martin Vieregg »

Laurence Pithie

  • Jr. Member
  • **
  • Posts: 62
  • Karma: +1/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #5 on: February 18, 2020, 02:34:14 pm »
To disable the close menu option in the system menu you can send  a MIA_DISABLED message to the system menu.

Code: [Select]
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.
« Last Edit: February 18, 2020, 02:47:03 pm by Laurence Pithie »

Rich Walsh

  • Sr. Member
  • ****
  • Posts: 359
  • Karma: +24/-0
  • ONU! (OS/2 is NOT Unix!)
    • View Profile
Re: Manipulating a PM window from another program
« Reply #6 on: February 18, 2020, 06:02:19 pm »
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
« Last Edit: February 19, 2020, 06:46:07 am by Rich Walsh »

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 278
  • Karma: +2/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #7 on: March 27, 2020, 10:23:17 am »
Quote
delete menuid SC_CLOSE from the System menu (FID_SYSMENU)

I did not manage this simple call.

I tried:

Code: [Select]
            hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
            //hwClose = WinWindowFromID(hw, SC_CLOSE);
            WinSendMsg (hw, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, 0), 0);

Where is the failure?

Rich Walsh

  • Sr. Member
  • ****
  • Posts: 359
  • Karma: +24/-0
  • ONU! (OS/2 is NOT Unix!)
    • View Profile
Re: Manipulating a PM window from another program
« Reply #8 on: March 27, 2020, 05:26:01 pm »
Code: [Select]
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

Code: [Select]
hw = WinWindowFromID(VIOhandle, FID_SYSMENU);
WinSendMsg (hw, MM_DELETEITEM, MPFROM2SHORT(SC_CLOSE, 1), 0);

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 278
  • Karma: +2/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #9 on: March 28, 2020, 11:54:39 pm »
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.

Laurence Pithie

  • Jr. Member
  • **
  • Posts: 62
  • Karma: +1/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #10 on: March 29, 2020, 09:25:21 am »
One solution would be to  subclass the frame window and process WM_CLOSE and WM_QUIT messages in the custom window procedure.

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 278
  • Karma: +2/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #11 on: March 29, 2020, 03:14:08 pm »
Quote
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.

Laurence Pithie

  • Jr. Member
  • **
  • Posts: 62
  • Karma: +1/-0
    • View Profile
Re: Manipulating a PM window from another program
« Reply #12 on: March 29, 2020, 03:40:13 pm »
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