Home All Groups Group Topic Archive Search About

Form Z order across the divide

Author
31 Jul 2010 8:46 PM
BeeJ
I want to stack forms in a certain order.
Z pos - Form
0     - Main App Form
1     -   Image Form (launched from Main Form, sits on top of Main App
Form)
2     -     Small Image Form #1
2     -     Small Image Form #2.
Note that Z2 only means above Z1 and Small Image Form #1 can be above
or below #2 (not mandatory).
Now the way I would do this is to use the following in the Main App
Form.  This works.  Hope I got the following code right.

    fImage.Show , Me      ' on top of main
    fSmallImage1.Show  , fImage
    fSmallImage2.Show  , fImage

But, unfortunately, this not the new architecture.

fSmallImage1 and fSmallImage2 are now each contained in ActiveX EXEs.
One ActiveX EXE for each fSmallImageN.
I have a class that all works except for setting the owner of the
fSmallImage form.

So I am not sure if this can be done this way or a different way needs
to be applied, but right now I am trying to pass the fImage as an
object to the ActiveX EXE to use in the fSmallImage1.Show , fImage.
problem is, I get an out of stack space when I try to execute the sub
to pass the fImage object to the ActiveX EXE.  It all compiles to EXEs
and all other interfaces to the ActiveX EXE work.

1) So, is this Marshalling (just trying to learn terminology here)?
2) Can I pass an object like this? (does not look like it)
3) what other method should I use to accomplish what I need?
4) maybe pass the hwnd and use
        SetWindowPos hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE Or
SWP_NOMOVE  ?
But this does not specify a Z order.  Or does it by sequence?
Can I get multiple fSmallImage1 and fSmallImage2 etc (there are more)
to lay on top of fImage.  Do I assume that if they are SetWindowPos in
the order 1,2 ... n then n is on top of 2 which is on top of 1 which is
on top of fImage.
This would mean passing hWnd from the Main app to the ActiveX EXEs.
Since the ActiveX EXE is out of process, would this work?
I could spend several days trying to code something but hoping someone
will tell me the path to take so my coding efforts will be going in the
right direction.

Author
31 Jul 2010 8:57 PM
BeeJ
When I said I needed to pass the fImage form I was suggesting use of
This sub in the ActiveX EXE.

Public Function SetOwner(ByVal hwndToUse, ByVal hwndOfOwner) As Long

    SetOwner = SetWindowLong(hwndToUse, GWL_HWNDPARENT, hwndOfOwner)

End Function 'SetOwner

Does this also set the Z Order?
Author
31 Jul 2010 9:44 PM
ralph
On Sat, 31 Jul 2010 13:57:19 -0700, BeeJ <nospam@nowhere.com> wrote:

>When I said I needed to pass the fImage form I was suggesting use of
>This sub in the ActiveX EXE.
>
>Public Function SetOwner(ByVal hwndToUse, ByVal hwndOfOwner) As Long
>
>    SetOwner = SetWindowLong(hwndToUse, GWL_HWNDPARENT, hwndOfOwner)
>
>End Function 'SetOwner
>
>Does this also set the Z Order?
>

[With the usual reservations - as in I'm not exactly sure what you're
trying to do... <g>]

Normally clients manage the display/presentation and servers just
supply services. It looks like you are trying to force or control the
wrong player.

1) The easiest way to communicate instructions to an ActiveX
component/exe is to have the service provide a 'config' interface
(class) or simply add the additional instructions to the existing
Interface.

2) As Z-Order is pretty much only valid for (and should be controlled
by) the client, create an object to wrap these facilities. Something
like
    a) Send the ActiveX information on how to construct and create an
object. (If needed)
    b) Retrieve the object
    c) Sort display as needed.
    d) Return the object/clean-up

-ralph
Author
1 Aug 2010 3:40 AM
David Youngblood
"BeeJ" <nospam@nowhere.com> wrote in message
news:i322na$cqk$1@speranza.aioe.org...
> When I said I needed to pass the fImage form I was suggesting use of
> This sub in the ActiveX EXE.
>
> Public Function SetOwner(ByVal hwndToUse, ByVal hwndOfOwner) As Long
>    SetOwner = SetWindowLong(hwndToUse, GWL_HWNDPARENT, hwndOfOwner)
> End Function 'SetOwner
>
> Does this also set the Z Order?

Yes and no. It sets the owner of a window, but you may need to 'force' an
update to the ZOrder for it to be shown. The below example changes the owner
of Notepad (if running), Me.ZOrder forces an update. If called from the
Form_Load, ZOrder isn't needed.


Private Declare Function FindWindow Lib "user32" _
    Alias "FindWindowA" ( _
    ByVal lpClassName As String, _
    ByVal lpWindowName As String) As Long

Private Declare Function SetWindowLong Lib "user32" _
    Alias "SetWindowLongA" ( _
    ByVal hwnd As Long, _
    ByVal nIndex As Long, _
    ByVal dwNewLong As Long) As Long

Private Const GWL_HWNDPARENT = (-8)
Private hwndOldOwner As Long

Private Sub Command1_Click()

    Dim h As Long

    h = FindWindow("Notepad", vbNullString)
    If h Then
        hwndOldOwner = SetWindowLong(h, GWL_HWNDPARENT, Me.hwnd)
    End If
    Me.ZOrder

End Sub
Author
31 Jul 2010 9:19 PM
Nobody
I don't think you can set the parent or owner to another process. See the
remarks section of SetParent() API function. So what you can ideally do is
move the form to the standard EXE, or use SetWindowPos tricks, but this
would cause some flickering when the user switches to another application,
like when you activate Notepad which would be obscured by your inactive top
most window until you remove the top most flag(from Deactivate event), so
Notepad would flicker during the switch.
Author
31 Jul 2010 9:30 PM
BeeJ
Nobody used his keyboard to write :
> I don't think you can set the parent or owner to another process. See the
> remarks section of SetParent() API function. So what you can ideally do is
> move the form to the standard EXE, or use SetWindowPos tricks, but this would
> cause some flickering when the user switches to another application, like
> when you activate Notepad which would be obscured by your inactive top most
> window until you remove the top most flag(from Deactivate event), so Notepad
> would flicker during the switch.

Sort of what I got too.
May be OK since the user will not be messing with forms, just viewing
them, so there should be no flicker during normal viewing.

So is SetWindowPos like vbSystemModal for a MsgBox?
Author
31 Jul 2010 9:42 PM
Nobody
"BeeJ" <nospam@nowhere.com> wrote in message
news:i324m7$f5f$1@speranza.aioe.org...
> So is SetWindowPos like vbSystemModal for a MsgBox?
>

Yes, like Task Manager.
Author
31 Jul 2010 9:53 PM
BeeJ
dug this out

' Declare Function SetWindowPos Lib "user32.dll" (ByVal hwnd As Long,
ByVal hWndInsertAfter As Long, _
                ByVal x As Long, ByVal y As Long, _
                ByVal cx As Long, ByVal cy As Long, _
                ByVal wFlags As Long) As Long
'
' hwnd              The handle of the window to move.
' hWndInsertAfter   Either the handle of the window to position this
window behind,
'  Or exactly one of the following flags stating where in the Z-order
to put the window:
'   HWND_BOTTOM = 1     Put the window at the bottom of the Z-order.
'   HWND_NOTOPMOST = -2 Put the window below all topmost windows and
above all non-topmost windows.
'   HWND_TOP = 0        Put the window at the top of the Z-order.
'   HWND_TOPMOST = -1   Make the window topmost (above all other
windows) permanently.
'   x                   The x coordinate of where to put the upper-left
corner of the window.
'   y                   The y coordinate of where to put the upper-left
corner of the window.
'   cx                  The x coordinate of where to put the
lower-right corner of the window.
'   cy                  The y coordinate of where to put the
lower-right corner of the window.
'   wFlags              Zero or more of the following flags stating how
to move the window:
'       SWP_DRAWFRAME = &H20    Same as SWP_FRAMECHANGED.
'       SWP_FRAMECHANGED = &H20 Fully redraw the window in its new
position.
'       SWP_HIDEWINDOW = &H80   Hide the window from the screen.
'       SWP_NOACTIVATE = &H10   Do not make the window active after
moving it unless it was already the active window.
'       SWP_NOCOPYBITS = &H100  Do not redraw anything drawn on the
window after it is moved.
'       SWP_NOMOVE = &H2        Do not move the window.
'       SWP_NOSIZE = &H1        Do not resize the window.
'       SWP_NOREDRAW = &H8      Do not remove the image of the window
in its former position, effectively leaving a ghost image on the
screen.
'       SWP_NOZORDER = &H4      Do not change the window's position in
the Z-order.
'       SWP_SHOWWINDOW = &H40   Show the window if it is hidden.
'
Author
1 Aug 2010 1:58 PM
MikeD
Show quote Hide quote
"BeeJ" <nospam@nowhere.com> wrote in message
news:i3222h$c23$1@speranza.aioe.org...
> I want to stack forms in a certain order.
> Z pos - Form
> 0     - Main App Form
> 1     -   Image Form (launched from Main Form, sits on top of Main App
> Form)
> 2     -     Small Image Form #1
> 2     -     Small Image Form #2.
> Note that Z2 only means above Z1 and Small Image Form #1 can be above or
> below #2 (not mandatory).
> Now the way I would do this is to use the following in the Main App Form.
> This works.  Hope I got the following code right.
>
>    fImage.Show , Me      ' on top of main
>    fSmallImage1.Show  , fImage
>    fSmallImage2.Show  , fImage
>
> But, unfortunately, this not the new architecture.
>
> fSmallImage1 and fSmallImage2 are now each contained in ActiveX EXEs.
> One ActiveX EXE for each fSmallImageN.

Why? Are these going to be shared among multiple applications?  If not,
there's probably no reason to have them in ActiveX anything. And why did you
chose ActiveX EXE?

> I have a class that all works except for setting the owner of the
> fSmallImage form.
>

Gonna be difficult (or at least more complex) since being ActiveX EXEs, they
are a different process. Even ActiveX DLLs wouldn't be so bad since they run
in the same process as the main app (or whatever's loading the DLL).

It sounds like everything was functioning as you wanted it before.  So why
did you change things?  Not everything needs to be in its own separate
component.

--
Mike
Author
3 Aug 2010 6:48 PM
BeeJ
It happens that MikeD formulated :
Show quoteHide quote
>
> "BeeJ" <nospam@nowhere.com> wrote in message
> news:i3222h$c23$1@speranza.aioe.org...
>> I want to stack forms in a certain order.
>> Z pos - Form
>> 0     - Main App Form
>> 1     -   Image Form (launched from Main Form, sits on top of Main App
>> Form)
>> 2     -     Small Image Form #1
>> 2     -     Small Image Form #2.
>> Note that Z2 only means above Z1 and Small Image Form #1 can be above or
>> below #2 (not mandatory).
>> Now the way I would do this is to use the following in the Main App Form.
>> This works.  Hope I got the following code right.
>>
>>    fImage.Show , Me      ' on top of main
>>    fSmallImage1.Show  , fImage
>>    fSmallImage2.Show  , fImage
>>
>> But, unfortunately, this not the new architecture.
>>
>> fSmallImage1 and fSmallImage2 are now each contained in ActiveX EXEs.
>> One ActiveX EXE for each fSmallImageN.
>
> Why? Are these going to be shared among multiple applications?  If not,
> there's probably no reason to have them in ActiveX anything. And why did you
> chose ActiveX EXE?
>
>> I have a class that all works except for setting the owner of the
>> fSmallImage form.
>>
>
> Gonna be difficult (or at least more complex) since being ActiveX EXEs, they
> are a different process. Even ActiveX DLLs wouldn't be so bad since they run
> in the same process as the main app (or whatever's loading the DLL).
>
> It sounds like everything was functioning as you wanted it before.  So why
> did you change things?  Not everything needs to be in its own separate
> component.

For one thing it is an excellent self-tutorial.
Since no one else seems to be able to help with ActiveX EXE in any
significant way.
The main app has many timing operations going on and the ActiveX
components now carry that to a new thread.
It also helps me see what is going on by isolating certain timing
operations to ActiveX EXEs.
So maybe in the future I can bring them all back if I can figure out
how to make all the timing considerations work together in the main
app.
I have six distinct ActiveX apps.  Two of them are instantiated
multiple times.  All are isolated on there own thread and that allows
me to see what is going on.  One of the ActiveX EXEs is a debug app
that all other app can pass debugging messages to.  That all works. 
All the ActiveX EXEs are working but I still have some timing issues I
am trying to understand. e.g. using a loop to delay or use
CreateWaitableTimer to delay.   The loop method is not consistent so I
am going to try CreateWaitableTimer and see if the WIN OS can do a
better job.
Yes, a real-time OS would help but I am stuck with Window XP and on.