1. Tracy Lamb
  2. PowerBuilder
  3. Thursday, 14 July 2022 16:39 PM UTC

Hi all,

I have a window with a listbox on the left, a datawindow on the right and a splitbar in between.  This is an MDI application.  I'm trying to get the popup menu to display where the user clicked the right mouse button.

I'm using the rbuttonup event.  Everything works fine, except the popup menu displays over the listbox, not the datawindow.  There is no rbuttonup code in the listbox.  Here's the code for rbuttonup event on the datawindow:

// Over-ride -
m_bt_rmb lm_popup

this.AcceptText()

// Create popup menu
lm_popup = create m_bt_rmb
lm_popup.of_SetParent (this)

// Popup menu
lm_popup.m_tableman.PopMenu (this.PointerX(),this.PointerY() )
destroy lm_popup

return 1

Not a show stopper, but probably needs to be fixed.  

TIA,

~~~Tracy

PB2021 Build 1509

Accepted Answer
Mark Goldsmith Accepted Answer Pending Moderation
  1. Thursday, 14 July 2022 17:19 PM UTC
  2. PowerBuilder
  3. # Permalink

Hi Tracy,

I'm using the RButtonDown event of the datawindow object using the X and Y position of the MDI frame and the menu always pops up wherever the mouse pointer is located at the time of right-clicking:

m_registrant.m_records.PopMenu(w_mdi_frame.pointerx(), w_mdi_frame.pointery())

While the above works I've coded it that way for illustrative purposes such that you can see what it's doing. More appropriately, you would code it such that it is more generic/ object-oriented and NOT hardcode the name of the MDI frame.

HTH...regards,

Mark

Comment
  1. Tracy Lamb
  2. Thursday, 14 July 2022 17:46 PM UTC
Thanks Mark...

This solution works. Not really object-oriented because I did hard-code the name of the MDI frame (It hasn't changed in 25 years)... not sure how to make it object-oriented without going through the whole routine of getting the parent window, then getting the frame. That's the way I did it in the legacy code for all of the RMB popup menus. Just seems like an awful lot of code to popup a simple menu.



lm_popup.m_tableman.PopMenu (w_benchtop_frame.PointerX(), w_benchtop_frame.PointerY())



Many Thanks,

~~~Tracy

  1. Helpful
  1. Miguel Leeuwe
  2. Thursday, 14 July 2022 18:20 PM UTC
Hi,

You'd probably have to assign you mdi window to some global variable when starting the application, like gw_frame in the PFC classes (if I remember well).

  1. Helpful
  1. Mark Goldsmith
  2. Thursday, 14 July 2022 18:31 PM UTC
You're very welcome Tracy and great to hear that worked for you! Yes, depending on how far down your objects are (especially if tab controls are involved) it may be a bit of traversing upward until you find the MDI window object and more trouble than it's worth if the need is rare. Otherwise, I might create a window instance variable (iw_my_mdi_frame) in the application object...or you could use a global variable of type window...and in the open event of your MDI window issue the following statement:



my_application_object.iw_my_mdi_frame = This



Then change the code in you RButtonDown event to:



m_registrant.m_records.PopMenu(my_application_object.iw_my_mdi_frame.pointerx(), my_application_object.iw_my_mdi_frame.pointery())



Regardless, glad you got it to work!
  1. Helpful
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 14 July 2022 19:25 PM UTC
  2. PowerBuilder
  3. # 1

Hi Tracy;

  Your marked Accepted Answer is wrong and will eventually not work correctly (and you are correct - not an OO solution). For example, the control could be being used within an SDI or MIMD style application. Also, an MDI application might have a visual control within a Popup or Response window that could be outside the MDI Frame window. In the above cases, the pop-up menu will not be within the application (or even on the correct monitor)!!!!!

My STD framework uses the following OO approach  ...

PopMenu ( lo_wn.PointerX ( ), lo_wn.PointerY ( ) )

   The above code is in every Visual Control's ancestor class on the RButtonDown event. The lo_win variable is a generic Window Pointer loaded from io_parent_wn pointer variable as set by the framework ancestor code. The "io_parent_wn" always points to the Parent Window address where that control resides (that includes any level of nesting within Tabe Pages, Tab Controls, User Objects, etc ... this is an action performed by the framework when any visual control is instantiated).

   The above code will work with any Application style, any level of nested controls, or any combination of instantiated window types where ever they reside (inside or outside the main App and/or its related monitors).

Food for thought.  ;-)

Regards ... Chris

Comment
  1. Mark Goldsmith
  2. Thursday, 14 July 2022 23:37 PM UTC
Hi Chris...thanks for your interesting and insightful thoughts, as usual. Under the assumption that Tracy is using a framework, be it your STD or the PFC, completely agree that should the parent window address already be available (assuming it's the ParentWindow's X and Y coordinates you should be trying to obtain, see below) then that's the way to go...why re-invent the wheel!



Assuming one is not using a framework, there are likely a number of ways to accomplish this, including what I provided. In the case of pop-up windows this, I believe, can be addressed by providing the ParentWindow value with the Open() function, especially in the case of SDI applications (even more so when opening a second popup which may become the child of the first popup). I think this is likely not an issue in an MDI application since the MDI frame is the active window, irrespective of whether or not there is an active sheet, and so the MDI frame would be the popups parent. Not certain of this, just going by my recollection. So I'm not sure that when you say "...an MDI application might have a visual control within a Popup or Response window that could be outside the MDI Frame window. In the above cases, the pop-up menu will not be within the application (or even on the correct monitor)!!!!!" I don't believe that applies to a pop-up window if using the MDI frame's pointerX() and pointerY() and I have yet to experience this...that's not to say there are no circumstances under which this could occur, I just haven't experienced it yet.



As for Response windows in an MDI frame, while you can move the window around and "outside" the MDI frame (and to a different monitor), the parent window of the Response window is still the MDI frame. That being said, obtaining the pointerX() and pointerY() of the MDI frame from within a Response window will give you coordinates relative to the MDI frame (and potentially one or more negative values if the Response window was moved to a second monitor), and you are absolutely right that issuing a PopMenu command as previously indicated will pop-up the menu in an unexpected location and not where the mouse was when you right-clicked. For a Response window you must use the pointerX() and pointerY() of the Response window and not of the MDI frame in order to have the menu show up where you right-clicked.



So, I think it's best to know definitively what will happen when using PopMenu with SDI -> PopUp window, SDI -> Response window, MDI -> PopUp window, MDI -> Response window in order to code it correctly and, making sure that you're obtaining the correct pointerX() and pointerY() coordinates, that being the MDI frame or the ParentWindow. Said another way, it's not just being able to identify the ParentWindow of an object/ nested objects, it's about knowing when to use the coordinates of that ParentWindow versus the coordinates of the MDI frame when using a PopMenu command.



I welcome additional thoughts and corrections from you or anyone else and always willing to stand corrected. Thanks Chris.
  1. Helpful
  1. Chris Pollach @Appeon
  2. Friday, 15 July 2022 00:24 AM UTC
Hi Mark ... She is using the PFC. So IMHO, the way forward would be to utilize the PFE extension layer to implement the same approach as what I have in the STD Framework. The STD Framework also handles dynamic pop-up menu classes & different user languages as well. So it's very flexible vs all hard coded (thus inflexible). ;-)
  1. Helpful
There are no comments made yet.
Olan Knight Accepted Answer Pending Moderation
  1. Thursday, 14 July 2022 16:53 PM UTC
  2. PowerBuilder
  3. # 2

You'd think this would work, right?
Well, I have the exact same situation. I ended up adding values by trial and error to the pointers until the end result was what I liked.

Example:

ll_x = this.PointerX()
ll_y = this.PointerY()
// Test this, the popup is in the wrong spot.


ll_x = this.PointerX() + 250
ll_y = this.PointerY() + 175
// Test this, it pops up where it should.


Klunky, but it works.

Comment
  1. Tracy Lamb
  2. Thursday, 14 July 2022 17:32 PM UTC
Thanks Olan,

I did this and it works...

lm_popup.m_tableman.PopMenu (this.PointerX() + lb_1.Width, this.PointerY() + 350)



As I was testing the best value to add to PointerY value, Mark replied. Mark's solution is better... I don't have to get a handle to the parent then the frame... see my comment to his response.

  1. Helpful 1
  1. John Fauss
  2. Thursday, 14 July 2022 18:52 PM UTC
I'm glad Mark was able to help you. The problem with using PointerX() and PointerY() in he RButtonUp event is that the user may move the mouse position between the RButtonDown and RButtonUp events. By capturing the mouse position in the RButtonDown event, you know this is the position where the user initiated the click action.
  1. Helpful 1
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.