How to make a window not always on top of another window? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

How to make a window not always on top of another window?

Post by Lefty777 » 24 Apr 2022, 16:09

So, here is my situation. I have an application with a poor design feature I am trying to bypass. The application includes a scheduling module which has a "feature" that is a source of frequent consternation. When the schedule window is open, one may double-click on an appointment to open an appointment window. Unfortunately, this locks the schedule window, which can no longer be accessed until appointment window is closed. The appointment window is a fairly simple window, but contains extra useful information and allows editing of the appointment details. I want to be able to have this appointment window open AND be able to switch to the underlying schedule WITHOUT first closing the appointment window.

The main problem I am having can be fixed fairly easily by using:

WinSet, Enable,, Schedule

This is great because the schedule is no longer disabled and if I slide the appointment window to the side I can 'see' the schedule and navigate around on it. However, the appointment window is still permanently on top of the schedule. Secondly, the appointment window's minimize button is 'grey-out' and does not allow minimizing by default. I used "WinSet, Style" to change this behavior and allow minimizing the window, but then I cannot easily restore the window as it is not part of the 'alt-tab' list. I played with all types of Winset styles and exstyles and found I could get fairly close to my goal if I simply set the appointment window styles to be the same as the schedule window. This adds the appointment window to the 'alt-tab' list and allows it to be minimized and restored easily so I can still access the schedule with this window open.

This is the test code I used that works to this degree:

Code: Select all

!F1::
WinSet, Enable,, Schedule

WinGet, Schedule_Win_Style, Style, Schedule
WinGet, Schedule_Win_ExStyle, ExStyle, Schedule

WinSet, Style, %Schedule_Win_Style%, Appointment
WinSet, ExStyle, %Schedule_Win_ExStyle%, Appointment

If (ErrorLevel=1) {
	MsgBox, Could not apply style!
} Else {
	MsgBox, Successfully applied style
}
So, the issue I am still having is that the appointment window is permanently above the schedule window if they are onscreen together. I would like to be able to click on the schedule and have it appear above the appointment window to switch between them. This is still not possible and I am forced to either keep moving the appointment window around on the screen to interact with the schedule, or fully minimize it. Is there a way to allow both windows to have the same ontop priority to switch between them easily?

Note:
WinSet, AlwaysOnTop,, Schedule
does not work at all for this situation. The always on top setting gets applied to BOTH windows with the appointment windows still always on top of the schedule. They appointment window is linked together with the schedule window. If I close the schedule window, the appointment window is automatically closed as well. Also if I minimize the schedule the appointment window also minimizes AND, somewhat strangely, disappears from the 'alt-tab' list.

I am fine with the dependent hierarchy of the appointment window to the schedule. I would just really like to be able to have the schedule window appear ABOVE the appointment window on screen.
Does anyone know how to accomplish this?
User avatar
boiler
Posts: 17387
Joined: 21 Dec 2014, 02:44

Re: How to make a window not always on top of another window?

Post by boiler » 25 Apr 2022, 03:17

It sounds like it may be a child window. Did you try removing the style 0x40000000?

I would just caution you about something, however. They may have set it up so you can’t interact with the main scheduling window while the appointment window is open for a very good reason. The code may assume that nothing else about that appointment that can be changed from the scheduling window while the appointment window is open, or else conflicts could occur and you could corrupt the database.

That’s just an example scenario, so don’t think just avoiding making those kind of changes to the appointment will keep everything kosher. I’ve disabled or hidden the main window when the popup window is open on applications I wrote for similar type of reasons. When you change things regarding how software operates, it can have significant unintended consequences, and anything that happens is at your own risk. You can do what you want, of course, but don’t be surprised if problems arise.
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

Re: How to make a window not always on top of another window?

Post by Lefty777 » 25 Apr 2022, 08:09

Thank you very much for your suggestion. I will try it and see it I can get it to work.

I understand your caution. I am certain the developer had a reason for disabling the schedule window when the appointment window is open and I plan to be cautious how I interact with it while the appointment child window is open. However, I fight this basic struggle everyday and it will dramatically increase productivity to simply be able to "view" the schedule while an appointment window is open. The main database is located on a central server and each change is committed to manually with "saves". I simply need to be able to leave an appointment window open for reference and be able to observe any schedule updates in real time.

I appreciate your suggestions
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

Re: How to make a window not always on top of another window?

Post by Lefty777 » 25 Apr 2022, 08:42

boiler wrote:
25 Apr 2022, 03:17
It sounds like it may be a child window. Did you try removing the style 0x40000000?
So trying to remove style 0x4000000 doesn't work. I think this applies to WS_CLIPSIBLINGS and it returns an error state when I attempt to do it. The documentation states of WS_CLIPSIBLINGS states "For a GUI window, WS_CLIPSIBLINGS is always enabled and cannot be disabled."

This seems to apply to sibling windows relative to each other? I am still testing different settings to figure out if I can get it to work, but maybe there is a style relating parent/child clipping or overlap?
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

Re: How to make a window not always on top of another window?

Post by Lefty777 » 25 Apr 2022, 09:07

Sorry, I left off a 0 :facepalm: . So I have tried it with -0x40000000 to remove WS_CHILD, but still no dice
doubledave22
Posts: 343
Joined: 08 Jun 2019, 17:36

Re: How to make a window not always on top of another window?

Post by doubledave22 » 25 Apr 2022, 09:26

If you can apply styles to this window can we not just winmove it out of the way?
datavectors
Posts: 6
Joined: 25 Apr 2022, 05:56

Re: How to make a window not always on top of another window?

Post by datavectors » 25 Apr 2022, 09:55

I am a newcomer learning how to use AHK although I use Ubuntu a lot. Windows is a bit dormant.
Now reading this I would try Actiona https://jmgr.net/ and place one of your windows
into a Virtual Workspace .. or just toggle between views.

I am just starting to think through how to get Actiona and AHK to co-work together.
Sometimes either one or other might be chosen.
Sometimes both.
e.g. Actiona has image processing features,
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

Re: How to make a window not always on top of another window?

Post by Lefty777 » 28 Apr 2022, 12:34

doubledave22 wrote:
25 Apr 2022, 09:26
If you can apply styles to this window can we not just winmove it out of the way?
I could for sure, but it doesn't fully accomplish what I am looking to do.
Lefty777
Posts: 25
Joined: 04 Apr 2022, 23:16

Re: How to make a window not always on top of another window?  Topic is solved

Post by Lefty777 » 28 Apr 2022, 13:32

I figured out how to do it. I thought I would post it here in case anyone else has the same question.

I used both Winspector and Spy++ to get window properties for the target application.
(Winspector is no longer updated and only captures 32-bit WM_ Messages but is still convenient for finding and identifying window elements and properties. Spy++ is part of Microsoft Visual Studio. It has two run files: 'Spyxx.exe' is 32-bit and 'Spyxx_amd64.exe' is the 64-bit version needed to capture WM_Messages of most modern applications. Spy++ is an awesome tool and can be downloaded separately on this page. Spy++ can do everything Winspector can, but it is a little harder to locate and identify the different window elements.)

The windows were not in a parent/child relationship, but the appointment window was 'owned' by the schedule window. This explained its behavior according to Microsoft documentation--

Owned window:
  • An owned window is always above its owner in the z-order.
  • The system automatically destroys an owned window when its owner is destroyed.
  • An owned window is hidden when its owner is minimized.
The documentation also states that "After creating an owned window, an application cannot transfer ownership of the window to another window."
So, it looked like it was not possible to change...

However, I then found this thread which stated how to do it!

So the working code for my application is:

Code: Select all

^F1::
WinSet, Enable,, Schedule	;Unlocks the schedule window
WinSet, Style, +0x00020000L, Appointment	;Add WS_MINIMIZEBOX to allow minimizing the appointment window
WinSet, ExStyle, +0x00040000L, Appointment	;Add WS_EX_APPWINDOW which adds the appointment window to the 'alt-tab' list
WinGet, Appointment_hwnd, ID, Appointment
SetOwner(Appointment_hwnd, 0)	;Removes ownership of appointment window
Return

SetOwner(hwnd, newOwner) {
    static GWL_HWNDPARENT := -8
    if A_PtrSize = 8
        DllCall("SetWindowLongPtr", "ptr", hwnd, "int", GWL_HWNDPARENT, "ptr", newOwner)
    else
        DllCall("SetWindowLong", "int", hwnd, "int", GWL_HWNDPARENT, "int", newOwner)
}
Works like a charm!

Note: I changed the default function of the target application. By removing the ownership of the window and/or allowing the locked window to be accessed, it may have some unforeseen consequences in the stability of the application or database. There is a good discussion of this on StackOverflow linked here. I will continue to test it and be cautious...

However, it seems to be working fine! The appointment window still closes automatically when the schedule window closes (which is optimal). I assume this is because they are both running on the same thread, which is killed when the schedule window is closed. (I get a quick flash of a message window which disappears before it displays anything if the schedule window is closed before the appointment window.) My current belief is that the original developers of the application made the appointment window owned by the schedule window to help manage its opening/closing behavior and WPF management, but noting that its always on top behavior relating to the schedule would confuse/annoy users, they simply locked the schedule window!
Post Reply

Return to “Ask for Help (v1)”