Author Topic: how to stay a window on top  (Read 5205 times)

Doodle

  • Newbie
  • *
  • Posts: 6
  • Karma: +1/-0
    • View Profile
Re: how to stay a window on top
« Reply #15 on: April 11, 2020, 12:19:29 pm »
Quote
Is 8 the right value for WS_TOPMOST ?

In my previous reply, I wrote:

Quote
For an example, please download the source code of DSSaver, and check one of the modules (preferable the Blank module, as that has the least additional code) on how it's done:
ftp://ftp.netlabs.org/pub/dssaver/dssaver_v20_srcbin.zip
Once unzipped, check the file Modules\Blank\Blank.c, search for lines containing "topmost", and you'll see how it's done in there.

Searching for lines containing "topmost" in that Blank.c file results these:

Code: [Select]
// Undocumented flag to make a window topmost:
#define WS_TOPMOST  0x00200000L

...

// Set WS_TOPMOST flag again!
WinSetWindowBits(hwnd, QWL_STYLE, WS_TOPMOST, WS_TOPMOST);

...

// Make window 'Always on top' because we'll be in real screensaver mode!
ulStyle = WS_VISIBLE | WS_TOPMOST;
hwndSaverWindow = WinCreateWindow(HWND_DESKTOP, SAVERWINDOW_CLASS, "Screen saver",
                                      ulStyle,
                                      0, 0,
                                      (int) WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN),
                                      (int) WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN),
                                      HWND_DESKTOP,
                                      HWND_TOP,
                                      0x9fff, // Some ID....
                                      NULL, NULL);


Hope this helps!

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 277
  • Karma: +2/-0
    • View Profile
Re: how to stay a window on top
« Reply #16 on: April 29, 2020, 11:00:01 pm »
Code: [Select]
#define WS_TOPMOST  0x00200000L

...
ulStyle = WS_VISIBLE | WS_TOPMOST;
hwndSaverWindow = WinCreateWindow(...ulStyle...)

Great, thank you Doodle. This code works. But it only works if I set the flag when creating the window, later with WinSetWindowBits it does not has an effect.

But now the window floats system wide. This is a very interesting and useful setting. I implement this lazarus-compatible in WDsibyl:
tForm.FormStyle = fsSystemStayOnTop

But I also want to implement the same, but only for a single application, so windows of other applications can hide my  "topmost" window:
tForm.FormStyle = fsStayOnTop

Is there also a flag or a way where I can achieve this?
« Last Edit: April 29, 2020, 11:11:46 pm by Martin Vieregg »

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 277
  • Karma: +2/-0
    • View Profile
Re: how to stay a window on top
« Reply #17 on: May 07, 2020, 11:38:01 pm »
Doodle,

I'm sorry for the false alarm, but all the code you have posted is working, even the code

Code: [Select]
WinSetWindowBits(hwnd, QWL_STYLE, WS_TOPMOST, WS_TOPMOST);
It seems that I did not use the correct frame handle. And I have to put the window on top again after this call, and then it stays on top system wide.

But I did not manage to turn it off again.

And I still did not manage to float on top only between my program windows and windows of other programs can hide my top window. WS_TOPMOST is system wide. I want to implement both options in the WDsibyl library.

Digi

  • Jr. Member
  • **
  • Posts: 52
  • Karma: +3/-0
  • http://os2.snc.ru/
    • View Profile
    • OS/2 ports and applications
Re: how to stay a window on top
« Reply #18 on: May 09, 2020, 05:21:58 pm »
And I still did not manage to float on top only between my program windows and windows of other programs can hide my top window. WS_TOPMOST is system wide.

As far as I remember, WXP / XPager uses a hook for these purposes ("Stay on top" option). Probably, standard methods for this are not provided.

Doodle

  • Newbie
  • *
  • Posts: 6
  • Karma: +1/-0
    • View Profile
Re: how to stay a window on top
« Reply #19 on: May 09, 2020, 05:39:11 pm »
Hi Martin,

I afraid that OS/2 does not have such a built-in windows style that you're seeking. The WS_TOPMOST (as you've already found out) has a system-wide effect. It will be on top of all other windows (until another gets WS_TOPMOST, or another WS_TOPMOST window gets moved on top, etc...).

If you want to have your window to be above all your windows, but not foreign windows, I think that you have to implement your own logic in all of your window procedures to handle the case when Z-order changes (WM_ADJUSTWINDOWPOS message, IIRC), and every time your window would get on top, set your "app-topmost" window to be on top.

Doodle

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 277
  • Karma: +2/-0
    • View Profile
Re: how to stay a window on top
« Reply #20 on: May 09, 2020, 06:33:57 pm »
Thank you Doodle for your post. But I wonder why a Dialog Window has the behaviour I would like to have. Dialog Windows always stay on top above the main program (standard) window. I thaught that all windows are internally the same for the operating system and only with different properties. So it seems that you cannot write a Dialog Window call with WinCreateWindow or WinCreateStandardWindow.

In WDsibyl, I have got a list of existing forms of an application in the main form. A form which changes the ZOrder to TOP should send a message to the main form of the application and the main form should send a message back to all other forms. If the other form has got the "StayOnTop" property set, it should get the ZOrder TOP again. This conecpt works without timer messages. I will report if I managed it.

Do you have an idea how to turn off the system wide WS_TOPMOST flag after it has been set?




Doodle

  • Newbie
  • *
  • Posts: 6
  • Karma: +1/-0
    • View Profile
Re: how to stay a window on top
« Reply #21 on: May 09, 2020, 11:40:02 pm »
Quote
I wonder why a Dialog Window has the behaviour I would like to have. Dialog Windows always stay on top above the main program (standard) window.

The Dialog Windows are created with a different API (WinCreateDialog), and their window procedure has to follow different rules (return if a message was processed or not). If it's not processed, a default dialog window procedure of the OS/2 system will handle the message, and that already has this logic implemented, that when the dialog window gets activated and shown, it disables its owner window for the time the dialog window is active. If a window is disabled (see WinEnableWindow API), the user cannot interact with it, so you cannot click on the main window if you have a child dialog window active.

It's quite nicely described in the Presentation Manager Programming Guide:
ftp://bitsavers.informatik.uni-stuttgart.de/pdf/ibm/pc/os2/warp_ver_3/G25H-7103-00_OS2_WARP_V3_Presentation_Manager_Programming_Guide_The_Basics_Oct94.pdf

Focus on chapter 15-1 (Dialog Windows), most importantly on "modal" dialogs.


Quote
Do you have an idea how to turn off the system wide WS_TOPMOST flag after it has been set?

Sorry, I don't know. I never had to do that, but I always thought that removing the flag would be enough..

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 277
  • Karma: +2/-0
    • View Profile
Re: how to stay a window on top
« Reply #22 on: May 10, 2020, 08:11:52 pm »
Now I managed to implement all the functionality I wanted for the WDsibyl library:
tForm.Formstyle = fsSystemStayOnTop
tForm.Formstyle = fsStayOnTop

For turning on the TOPMOST functionality, I used
WinSetWindowBits(hwnd, QWL_STYLE, WS_TOPMOST, WS_TOPMOST);
Turning off:
WinSetWindowBits(hwnd, QWL_STYLE, 0, WS_TOPMOST);

If the window is not created while setting the property, the window is created with the WS_TOPMOST flag.

For "fsStayOnTop", I have fetched all events where other window go to HWND_TOP of  and in these cases, all the forms of the program which have got the fsStayOnTop property set are going to top after the window which has gone to top by the user. It works already fine.

I send now the changes to Rolf which collects the libary changes. I will send a message here if the new WDsibyl library is available.

Rich Walsh

  • Full Member
  • ***
  • Posts: 160
  • Karma: +7/-0
  • ONU! (OS/2 is NOT Unix!)
    • View Profile
Re: how to stay a window on top
« Reply #23 on: May 11, 2020, 03:15:01 pm »
I wonder why a Dialog Window has the behaviour I would like to have. Dialog Windows always stay on top above the main program (standard) window.

This is really sad. Hasn't anyone RTFM?

You're about to abuse a powerful - and possibly very annoying - feature (WS_TOPMOST) simply because neither you nor any of the other respondents knows one of the basics of PM programming: an owned window is always higher in the z-order than the frame window which owns it.

If a dialog is always on top of the window which created it, it's because the dialog is owned by that window. Change its owner to HWND_DESKTOP and the dialog will be free to go anywhere in the z-order. If you need a specific z-order for your windows, establish an ownership chain - don't use WS_TOPMOST.

BTW... there are times when WS_TOPMOST is called for. but it should always be at the user's discretion (i.e. he can turn it off).

Lars

  • Hero Member
  • *****
  • Posts: 957
  • Karma: +46/-0
    • View Profile
Re: how to stay a window on top
« Reply #24 on: May 12, 2020, 11:52:32 am »
I think you meant to say "parent-child relationship" instead of "ownership" but the explanation in the "Presentation Manager Programming Guide" is a bit blurry about z-ordering.
« Last Edit: May 12, 2020, 11:59:09 am by Lars »

Martin Vieregg

  • Sr. Member
  • ****
  • Posts: 277
  • Karma: +2/-0
    • View Profile
Re: how to stay a window on top
« Reply #25 on: May 12, 2020, 03:01:47 pm »
Rich,

the WS_TOPMOST setting is for the system wide float on top. This can be useful for very specific programs like a virtual desktop manager, a tool bar or a clock. In all these cases, the window which is allowed to float to system top should be small. It does not get the focus, of course. Because of the lack of knowing the existance of this hidden flag, for example the PMVdesk virtual desktop tool and others do floating via timer.

It was indeed not clear for me that the relationship of the child window defines the behaviour of the ZOrder. But in a lot of cases, a float or "rest" on top is not useful. For example, my WSedit editor has got a content tree window which should be placed on the desktop with the same rights as the main window.

So in the WDsibyl library, all windows are started without ownership and are listed in the Screen.Forms[] property. (A created tForm does not mean automatically that the window has been created on the OS-handle level. This is done in SetupShow.) One window is the Application.Mainform, but this only means that this window is started first when starting the application. I had problems with cleaning up the windows when creating a window with an owner. The current state is pehaps not "holy PM programming", but it works fine. I am not sure if I can turn off the relationship after creating a window with an owner. With the new FormStyle = wsStayOnTop property I can turn on and off this setting while the window exists.