1. Christopher Craft
  2. PowerBuilder
  3. Wednesday, 2 June 2021 03:49 AM UTC

So after all these years I thought I was the only one that struggled with trying to get response windows to always be centered within the application no matter what monitor it is on but I am not! Looks like there are many posts out there ( Popup window position VS frame window position (appeon.com)Multiple monitor support? (appeon.com) ...).

I have implemented the ribbonbar and theme with our application (along with some other objects on the frame) and I am back to trying to get these windows to center correctly. I saw the link to Chris P's STD Framework which supposedly works perfectly but I cannot find that section of code. I also saw a note from Michael Kramer saying he found a way and was going to post it but I cannot find that either.

I am trying not to resort to a bunch of API calls because this should be doable with PB itself. I thought the simple 'Center' checkbox option was suppose to do all that for me but that has never worked.  I have also tried all the WorkSpace calls as well as using the Frames X/Y positions but it just gets confused when the monitors are a different size.

Why is this so difficult? What is the magic code to get this to always work properly?!

Thanks again,

Chris Craft

Accepted Answer
Christopher Craft Accepted Answer Pending Moderation
  1. Wednesday, 2 June 2021 15:12 PM UTC
  2. PowerBuilder
  3. # Permalink

Well, after reading your feedback and the Microsoft document I thought I was on to something until...

Background: I have 2 types of response windows. Window 'A' is inherited from Window and set to a Response type window.  Window 'B' is inherited from one of my base class windows where the window type is Main but then changed to a Response type.

I always use the Frame to center my response windows. This is the code in the Open event of both response windows:

this.X = ((App.GetFrame().Width / 2) - (this.Width / 2)) + App.GetFrame().X
this.Y = ((App.GetFrame().Height / 2) - (this.Height / 2)) + App.GetFrame().Y

This works perfectly on all monitors for window 'A' but window 'B' will display off the screen if the application is running on the smaller monitor. This made me wonder if the X/Y coordinates are different depending on the window but they were not. I ended up grabbing the X/Y coordinate of window 'A' which displays perfectly on the smaller monitor and hard-coded those exact numbers for window 'B' and guess what? Window 'B' still displayed off the screen! 

So now I am completely confused! The only difference between 'A' and 'B' is the inherited piece and there is no code in that inherited window which sizes, positions, etc.

Thanks again,

Chris Craft

Comment
  1. John Fauss
  2. Wednesday, 2 June 2021 15:59 PM UTC
What PowerScript function do you use to open window "B"...Open() or OpenSheet()? Also, at what point is the window type of window "B" changed from Main! to Response! - In the Window Painter (design time) or in code (execution time)?
  1. Helpful
  1. Christopher Craft
  2. Wednesday, 2 June 2021 16:38 PM UTC
Both windows are set at design time and I use OpenWithParm() on window 'A' and Open() on window 'B' BUT...you caused a thought which solved my problem! The OpenWithParm does not pass in a parent window but the Open is. I changed it to not pass the parent (I didn't need it) and poof...it shows in the correct spot!



Thank you all for your help!
  1. Helpful
  1. John Fauss
  2. Wednesday, 2 June 2021 17:50 PM UTC
That's great news, Chris - Congratulations!
  1. Helpful
There are no comments made yet.
Ivan Mesarc Accepted Answer Pending Moderation
  1. Wednesday, 2 June 2021 13:06 PM UTC
  2. PowerBuilder
  3. # 1

This is code we use to center Response, PopUp windows and appears in same monitor as Parent window:

External functions declaration:

FUNCTION Integer GetSystemMetrics (Integer nIndex) LIBRARY "user32.dll"
FUNCTION UnsignedLong MonitorFromWindow (Long hwnd, Long dwFlags) LIBRARY "user32"
FUNCTION UnsignedLong GetMonitorInfo (long hMonitor, ref tagmonitorinfo moninfo) LIBRARY "user32" ALIAS FOR "GetMonitorInfoA"

structures :

type rect from structure
   long left
   long top
   long right
   long bottom
end type

type tagmonitorinfo from structure
   long cbsize
   rect rcmonitor
   rect rcwork
   long dwflags
end type

function Of_CenterWindow(window a_w) return boolean :

Window lw_p

constant integer SM_CMONITORS = 80
constant integer MONITOR_DEFAULTTONULL = 0
constant integer MONITOR_DEFAULTTOPRIMARY = 1
constant integer MONITOR_DEFAULTTONEAREST = 2

lw_p = a_w.ParentWindow()

IF IsValid(lw_p) THEN
   IF GetSystemMetrics(SM_CMONITORS)> 1 THEN
      tagmonitorinfo tmi
      UnsignedLong m
      m = MonitorFromWindow(Handle(lw_p), MONITOR_DEFAULTTONEAREST)
      IF m > 0 THEN
         tmi.cbSize = 72 // size in bytes of TAGMONITORINFO
         GetMonitorInfo(m, tmi);
         a_w.Y = PixelsToUnits(tmi.rcWork.top + (tmi.rcWork.bottom - tmi.rcWork.top) / 2, YPixelsToUnits!) - a_w.Height / 2
         a_w.X = PixelsToUnits(tmi.rcWork.left + (tmi.rcWork.right - tmi.rcWork.left) / 2, XPixelsToUnits!) - a_w.Width / 2

         RETURN 1
      END IF
   END IF
END IF

RETURN 0

open event of window :

CHOOSE CASE THIS.WindowType
   CASE Response!, PopUp!
      IF THIS.Center THEN
         THIS.Center = FALSE
         IF of_CenterWindow(THIS) = 1 THEN
         ELSE
            THIS.Center = TRUE
         END IF
      END IF
END CHOOSE

Center property for Response, PopUp window is set to TRUE.

Inspired by great Réal Gagnon :

https://www.rgagnon.com/pbdetails/powerbuilder-display-on-the-second-monitor.html

Ivan

 

Comment
  1. John Fauss
  2. Wednesday, 2 June 2021 13:32 PM UTC
Hi, Ivan - A minor correction, if I may: The memory size of the monitorinfo / tagmonitorinfo structure is 40 bytes, not 72. Setting the cbSize member's value to 40 or greater works, but strictly speaking the correct length is 40.
  1. Helpful
There are no comments made yet.
René Ullrich Accepted Answer Pending Moderation
  1. Wednesday, 2 June 2021 05:26 AM UTC
  2. PowerBuilder
  3. # 2

Hi Chris,

I agree with you that powerbuilder should have better support for multiple monitors.

But I also solved another problem with multiple monitors and so I know that the problem is not trivial.

You can get some information about Multiple Display Monitors here: https://docs.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen

There you can find this picture that already shows, that there are different problems to solve: Monitors may be positioned different (left-right, top-bottom and also at free positions), Primary Monitor may be at different positions so position values may also be negative, Virtual Screen may contain areas that are not visual, Application window may be at not only one monitor, monitors may have different size, ...

illustration showing a three boxes representing monitors arranged within a box representing the virtual screen

Regards,

René

Comment
  1. Christopher Craft
  2. Wednesday, 2 June 2021 13:32 PM UTC
Thank you René, that explains why my window would become positioned in an un-seeable area which made no sense to me. I will take a look at the document.



Chris

  1. Helpful
  1. Chris Pollach @Appeon
  2. Wednesday, 2 June 2021 14:18 PM UTC
Hi René ... good points!

My STD Frameworks though do not care as the framework's approach is to track the main App's "Controller" window. This window is basically "in charge" of all other open windows and tracks wherever the App user moves it to. It is also in charge of keeping all the other subordinate windows in line and within the confines of the "Controller" Window's *current* monitor. Thus, all Windows - regardless of their type and opening mechanism - follow what & where the Controller window places them. ;-)
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.