Highlighted
Absent Member.
Absent Member.
1298 views

[archive] Keeping floating windows together

[Migrated content. Thread originally posted on 13 December 2004]

I am looking for a way to keep floating windows together. In other words, if the user chooses to move a window, I want to move other windows programatically at that time (to the same place that the user moves the window).

After researching the manual set and contacting support, it doesn't seem like there is an event that occurs when a window is moved or a way to keep windows together without using subwindows. I cannot use subwindows for a variety of reasons. So, I started looking for a Windows API solution.

I found some VB code that looks to accomplish what I want by calling the Windows API (shown below). I'm currently working through this to see if this works, but so far I haven't been able to get it to work. Does anyone know a better way to accomplish this? Has anyone done something like this before? Any help would be appreciated.

Thanks,
Rob


Public OldWindowProc As Long
Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, lParam As WINDOWPOS) As Long
Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Const GWL_WNDPROC = (-4)

Type WINDOWPOS
hwnd As Long
hWndInsertAfter As Long
x As Long
y As Long
cx As Long
cy As Long
flags As Long
End Type
' Process messages.
Public Function NewWindowProc(ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, lParam As WINDOWPOS) As Long
Const WM_NCDESTROY = &H82
Const WM_WINDOWPOSCHANGING = &H46

' If we're being destroyed,
' restore the original WindowProc.
If msg = WM_NCDESTROY Then
SetWindowLong _
hwnd, GWL_WNDPROC, _
OldWindowProc
Else
' See if the window is moving.
If msg = WM_WINDOWPOSCHANGING Then
' The window is moving. Keep the others with it.
Form2.Move Form1.Left + Form1.Width, Form1.Top - 360
Form3.Move Form1.Left - Form3.Width, Form1.Top - 360
End If
End If

' Continue normal processing. VERY IMPORTANT!
NewWindowProc = CallWindowProc( _
OldWindowProc, hwnd, msg, wParam, _
lParam)
End Function
0 Likes
7 Replies
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

You cannot use this technique, because it depends on callback functionality, which is not supported by COBOL.
You could do it, if you made your a callback function using C or Delphi and either linked this or used it from a DLL.

This does however sum up to a lot of work.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

Thanks, Gisle. That makes me feel a little bit better. After attending your class, I was hoping to be able to understand how to do this stuff, but couldn't figure out the recursion (or callback) that was involved here.

Do you know of any other way that I can accomplish this with COBOL?

Thanks,
Rob
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

Here's a thought Rob, haven't tried it myself. If you have a thread running in the background, perhaps that thread could inquire the active windows position on a timed basis and then if a move is detected, reposition the other windows. Window handles may have to be external though. Not sure.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

Dan's proposal here is an option.

You could enumerate windows' belonging to your process, inquire their position and move them around relatively to your own window. However, as you yourself point out, the problem is to get the message when your window moves. It *is* possible to get messages from COBOL, problem is, when you are calling the Windows API, you are stopping all other threads in the runtime. THe reason for this is because the threading in ACUCOBOL-GT is local to the COBOL application and not a system thread. There is a sound reason for this, and that reason is named: Portability.
As with most techniques though, there are ups and downs with this, as you can see.
You could check message bail out, stay idle for a little and check again. That would make things work, but still.
Honestly, I'd consider this so much api that I would not consider it unless having a bit of experience with the API. Heading onto this as your first serious task on your own is a bit heavy.
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

Honestly, I'd consider this so much api that I would not consider it unless having a bit of experience with the API. Heading onto this as your first serious task on your own is a bit heavy.


Gisle,

I agree. Thanks for your input on this. Also, Thanks to you, Dan. Hope all is well in Norway and New York (probably cold in both places, however it's 27 in Alabama today). 🙂

Rob
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

In light of all this, does anyone know of an easy way to prevent a window from being moved by the user? Then, we don't have to move the other windows. Some examples I've seen respond to the event and fail. Since we can't get an event easily, this doesn't seem like an option.

Any ideas?

Thanks,
Rob
0 Likes
Highlighted
Absent Member.
Absent Member.

RE: [archive] Keeping floating windows together

I couldn't help it, but had to give this another thought.

When I was out running yesterday (running is an excellent way of getting your mind set onto something), I figured there is a solution that does not require reprogramming.

As Dan suggested spawn off a separate thread, then, inside here, do like the following pseudo code:

Call GetWindowRect on your main window to get its original placement.
Make a factor for the offset of sub windows.
LOOP-START
Make the thread go idle, experiment to find an ideal amount of time, a good start could be half a second.
Check if the thread is requested to end. If so, bail out.
Call GetWindowRect on the main window again, see if it has changed from the original placement. If not, go back to LOOP-START
Iterate through all sub windows.
Call GetWindowRect for each sub window to get current position.
Use the offset factor to calculate new positions.
Reposition them relatively using MoveWindow.
Go back to LOOP-START.

GetWindowRect will return you the absolute screen coordinate of a window.
MoveWindow will move your window using the provided start xy coordinate and the size and height of the window.

You find these functions in user32.dll.

The one catch with this method is that you may experience a short delay (depends on how long you let the thread go idle), if you had been able to catch the message WM_WINDOWPOSCHANGED, this would have been accomplished straight forward.
The benefit of this approach is that it will not hang your other threads significantly, there will be a slight halt of the execution while the particular API functions are called, but that is not likely to be noticed.
0 Likes
The opinions expressed above are the personal opinions of the authors, not of Micro Focus. By using this site, you accept the Terms of Use and Rules of Participation. Certain versions of content ("Material") accessible here may contain branding from Hewlett-Packard Company (now HP Inc.) and Hewlett Packard Enterprise Company. As of September 1, 2017, the Material is now offered by Micro Focus, a separately owned and operated company. Any reference to the HP and Hewlett Packard Enterprise/HPE marks is historical in nature, and the HP and Hewlett Packard Enterprise/HPE marks are the property of their respective owners.