How do I know the Main Frame's size (Client area) from the MDI window?

,

So, there is nothing special. Main Frame, open the MDI child window.

I need to know (from the MDI child window) what width/height the Main Frame window has (I suppose Client area), so I can set the position I need for the MDI child window.

Any examples are welcome

That feature is in the resizing of my Super Stuff templates, but here’s a quick and dirty approach. First measure the client size in the frame:

R                               LIKE(RECT)
  CODE
  GetClientRect(0{PROP:ClientHandle}, R)
  FrameClientW = R.Right  - R.Left
  FrameClientH = R.Bottom - R.Top

FrameClientW and FrameClientH need to be non-threaded global LONGs, so the child thread can access them. Note that these are pixels not DLUs, so you turn on PROP:Pixels before setting the client size, then turn it off after.

1 Like

Hi,

Maybe the template Simplates By Mike Pasley - DisplayInfo Code Simplate could help you…

Flavio,
Thank you,
Would like to take a look, but https://www.logicentral.com/simplate.zip doesn’t exist. Do you have that template?

thank you, Mike, will take a look!

BTW, the approach I suggested measures the frame just once. If you wanted to handle frame resizing, then you must trap all of the events that can impact that. And if there are child windows open that are optimized for the earlier size, then they would all need to be told (via some type of interthread communication) to resize to the new client size.

That’s a fair bit of work, which is why it makes more sense to buy my templates. :wink:

4 Likes

Mike, I imagine this :slight_smile:
will think about! Thanks anyway

1 Like

Hi,

On the Icetips’s free downloads page there is another link:
https://www.icetips.com/par2downloads/simplat2.zip

1 Like

wow, great! will take a look, thx

If you add a non-threaded global reference variable and set it immediately after opening the frame you have direct access to all the properties of the window from every procedure in the app. This is true for any window on any thread as long as you have a non null reference to the window you want to query.

1 Like

That’s what I do. An alternative would be to store it in a System User Defined property. They are sort of super Implicit Variables that have no scope limit. That requires Clarion 10.

I think something like this would work (done on my phone).

FrameRefWnd  &WINDOW
FrameRefLong LONG,OVER(FrameRefWnd)

  OPEN(AppFrame)
  FrameRefWnd &= AppFrame
  SYSTEM { 'FrameRefWnd' } = FrameRefLong

Then you get to that Frame reference in any code:

FrameRef  &WINDOW
FrameWidth LONG

  FrameRef &= ( 0 + SYSTEM { 'FrameRefWnd' } )
  FrameWidth = FrameRef{PROP:Width}   !** pixels?

** As Mike notes you should work in Pixels or different fonts will have different DLUs and not work right.

I don’t think that would compile, but you could use ADDRESS(AppFrame) instead of OVER(FrameRef)

I just have a global AppFrame &Window
Which is easier to work with than Carls named property approach. But wouldnt work in modules with an empty member statement which Carls approach can do.

Isn’t that what I said??? :rofl:

Isn’t that what I said??? :rofl:

I’d tell you a chopped liver joke, but it might be offal. :slight_smile:

Correct that code will throw a compile error “OVER must name variable”.

The workaround is to put a GROUP around it and OVER that like the below code:

HubTestWndRefSystemRtn  ROUTINE
    DATA
FrameRefGrp  GROUP,PRE()  !w/o Group Error "OVER must name variable"
FrameRefWnd       &WINDOW
             END  
FrameRefLong LONG,OVER(FrameRefGrp)
    CODE 
    FrameRefWnd &= MainWindow
    SYSTEM { 'FrameRefWnd' } = FrameRefLong    
    Message('FrameRefLong=' & FrameRefLong & |
            '||Address()='& Address(MainWindow) & |          !Is &WINDOW = Address ?
            '||Size(FrameRefGrp)='& SIZE(FrameRefGrp) , |   !Is &Window 4 Bytes
            'HubTestWndRefSystemRtn')
    DO HubTestWndRefSystem_2_Rtn
    EXIT

That message showed:

    FrameRefLong = 6197488
    Address()    = 6197488
    Size(FrameRefGrp)=4

Which confirmed ADRESS(Window) is the same value and a &WINDOW reference is just the 4 byte address. So all my code can be reduced to one line.

    SYSTEM { 'FrameRefWnd' } = ADDRESS(MainWindow) 

I normally include 0 + {Prop} to assure the string is always converted to a number, not sure if its needed here.


I wrote the below code to show getting the User Property back into a &WINDOW Reference and using it:

HubTestWndRefSystem_2_Rtn  ROUTINE
    DATA
FrameRef  &WINDOW
FrameWidth LONG
    CODE 
    FrameRef &= ( 0 + SYSTEM { 'FrameRefWnd' } )
    FrameWidth = FrameRef{PROP:Width}   !** best to use pixels
    Message('FrameRef Text='& FrameRef{PROP:Text} & |
            '||FrameWidth='& FrameWidth & |
            '||SYSTEM FrameRefWnd='& SYSTEM{'FrameRefWnd'} ,|
             'HubTestWndRefSystem_2_Rtn')
    EXIT

To repeat the User Defined Property is like an Implicit Variable. It’s nice it can be accessed from any code in any class or any DLL with no export or import. It has an unlimited Scope. If you were going to use it in more than 2 places I would setup an Equate, which then has to be in scope.

SystemUsrProp:FrameRefWnd  EQUATE('FrameRefWnd')
    SYSTEM { SystemUsrProp:FrameRefWnd } = ADDRESS(MainWindow) 
1 Like