?
Solved

Make window child to my MDI

Posted on 2005-03-01
17
Medium Priority
?
325 Views
Last Modified: 2008-03-10
Is it possible to make a window (outside of my application) a child to my own MDIForm?  Like if I have:

Window = FindWindow("windowClass", vbNullString)

Could I turn Window into a child to my MDI Form?
0
Comment
Question by:learning_t0_pr0gram
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 11
  • 5
17 Comments
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13434165
And instead of starting a new Question, could someone tell me what Seek does?

Seek #1, 25

I'll give 10 pts to whoever tells me what it does.
0
 
LVL 37

Assisted Solution

by:Harisha M G
Harisha M G earned 80 total points
ID: 13434271
Hi learning_t0_pr0gram,
    I believe you cannot make other applications child to your own MDI form.
    Seek will give the current position of insertion.

MS help...

Returns a Long specifying the current read/write position within a file opened using the Open statement.


Seek(filenumber)

The required filenumber argument is an Integer containing a valid file number.


Seek returns a value between 1 and 2,147,483,647 (equivalent to 2^31 – 1), inclusive.

The following describes the return values for each file access mode.

Mode    
    Return Value

Random    
    Number of the next record read or written.

Binary, Output, Append, Input    
    Byte position at which the next operation takes place. The first byte in a file is at position 1, the second byte is at position 2, and so on.
   
Bye
---
Harish
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 320 total points
ID: 13434541
You can try the SetParent() API:
http://www.mentalis.org/apilist/SetParent.shtml

Private Declare Function SetParent Lib "user32" Alias "SetParent" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long

Private Sub foo()
    Dim Window As Long
    Window = FindWindow("windowClass", vbNullString)
    If Window <> 0 Then
        SetParent Window, Me.hwnd
    End If
End Sub
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13434626
Ahh, I knew it was possible :P

I'm still trying to learn all of the API's.

Thanks IM.
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13435112
Hey IM.  If you see this do you know how to tell if the Child window has closed?  For some reason it doesn't find the window anymore once it's added as a Child to my MDI form.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13436056
Hmm....have to think about that one a little...

When you add it using SetParent() it isn't really an MDI child and isn't really its own form anymore either.  We can't subclass it to tell when it has closed because it isn't part of our process.  We may have to use some kind of timer and periodically enumerate the child windows of your main form...

I'll see what I can come up with.
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13436431
Anything that works will be good.  I see it can find the window using FindWindowEx(Me.hWnd, ....) but i'm still having trouble keeping track of all the windows and looping through etc to see if they're closed or not.  I'd like an easier way if there is one.  The question is already closed so you don't have to give further help unless you want to.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13439235
>> I see it can find the window using FindWindowEx(Me.hWnd, ....)

That is exactly the route I was thinking of doing first.  Use a recursive subroutine to descend into the child windows.  Each time you open a form, you can use FindWindow() to get the hWnd and then store it in a collection.  You can use any value you want as the key for the hWnd.  Call the recursive routine from the timer and update your collection accordingly.  When you go to open the form, you should first check the collection using the key to see if the form is already open.

Alternatively, we can use various ShellAndWait() algorithms to monitor the processes we have spawned.  You can make a boolean value for each child window that you spawn and then toggle it back when you know it is closed.  Here is a basic shell and wait algorithm:

    Option Explicit

    Private Const SYNCHRONIZE = &H100000
    Private Const WAIT_TIMEOUT = &H102

    Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
                ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
    Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
                ByVal dwMilliseconds As Long) As Long
    Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

    Private Sub Command1_Click()
        ShellAndWait "calc.exe"
        MsgBox "Done"
    End Sub

    Private Sub ShellAndWait(ByVal cmd As String)
        Dim lPid As Long
        Dim lHnd As Long

        lPid = Shell(cmd, vbNormalFocus)
        If lPid <> 0 Then
            lHnd = OpenProcess(SYNCHRONIZE, 0, lPid)
            If lHnd <> 0 Then
                Do
                    DoEvents ' keep application responsive
                    Sleep 50 ' keep CPU usage from ramping to 100%
                Loop Until WaitForSingleObject(lHnd, 0) <> WAIT_TIMEOUT
                CloseHandle (lHnd)
            End If
        End If
    End Sub

We would need to modify it so it wouldn't be a "holding" routine.  Instead, we add the PID from the Shell() command into a collection.  At the same time we add the name of a boolean variable into another collection.  A Timer control routine can iterate the collection and use OpenProcess() and CloseHandle() on each one checking to see if the process is still open.  If it is not, we can use the CallByName() function along with the corresponding variable name from the second collection to toggle the correct variable (I'll show you how to do that if you don't know how).

Let me know if you want to see the modifed shell and wait algorithm.

~IM
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13442369
Well right now I have this:

Private Sub Get_All_IM_Windows(ByVal Win As Long)
Dim LastWin As Long, a As Long
Win = GetWindow(Win, GW_HWNDFIRST)
LastWin = GetWindow(Win, GW_HWNDLAST)
Do
    Win = GetWindow(Win, GW_HWNDNEXT) 'next window
    If GetClass(Win) = "AIM_IMessage" Then
        AIM_WINDOWS.Add Win
    End If
    DoEvents
Loop Until Win = LastWin Or Win = 0
End Sub

This adds all open AIM windows's handles to my collection (AIM_WINDOWS).  So AIM_WINDOWS already contains each window I have in my MDIForm.  When it adds an AIM window to my MDI form, it adds the Username of the person to a ListBox.  What I want to do is remove the name from the ListBox when the window isn't found anymore.  All Index's should be the same.  username with index 0 in the listbox should be the same as index 1 in the collection, 1 in the listbox would be 2 in the collection, etc.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13442495
Then you would need two different collections.  One to hold the AIM handles you initially find and another that gets updated each time you call Get_All_IM_Windows() from your polling routine.

Then you can iterate the first collection and see if those values are still present in the updated collection.  As you iterate the first collection, if the value is not in the second collection then remove it from the first collection and the listbox (AIM window has been closed).  If the value from the first collection is in the second collection then only remove it from the second collection (AIM window still open).  When you are done iterating the first collection, anything left in the second collection is a new AIM window that needs to be added to your first collection and your listbox.

Hope that made sense....
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13443349
I do get what you're saying.  I appreciate all your help.  I will see if I can do what you suggested when I get home.  It sounds like it might work.
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13454388
For some reason I can't get it to work.  This is the first time i've known how to do something but couldn't make it work right.  My coding to do it keeps building up and up and it still won't work.  Have a look:

Private Sub Check_All_IM_Windows()
Dim Win As Long, x As Long, y As Long
Win = FindWindowEx(Me.hWnd, 0, "AIM_IMessage", vbNullString)
Set AIM_HANDLES = Nothing
'###### Add all Child Windows to AIM_HANDLES
Do
    If GetClass(Win) = "AIM_IMessage" Then
        AIM_HANDLES.Add Win
    End If
    Win = GetWindow(Win, GW_HWNDNEXT) 'next window
    DoEvents
Loop Until Win = 0

For x = 1 To AIM_WINDOWS.Count
NextX:
    For y = 1 To AIM_HANDLES.Count
        If AIM_HANDLES.Item(y) = AIM_WINDOWS.Item(x) Then
            AIM_WINDOWS.Remove x
            If x <= AIM_WINDOWS.Count Then GoTo NextX Else GoTo Re_Add
        End If
    Next
    Form1.List1.RemoveItem (x - 1)
    AIM_WINDOWS.Remove x
Next

Re_Add:

For x = 1 To AIM_HANDLES.Count
    AIM_WINDOWS.Add AIM_HANDLES.Item(x)
Next
End Sub

As you can see it got pretty sloppy when I kept trying new things.  It's pretty easy to follow.  It DOES detect when I close a window, but it keeps removing Index 0 in the Listbox.  Can't figure out why.  I'm probably just mis-reading something, dunno.  Any Idea?
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13473998
Is that a no? :(
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13474057
Hi learning_t0_pr0gram,

I haven't forgotten you.  =)

Just been real busy sorry.  I'll see what I can do...
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13474143
Oh ok.  I'll get you some points for all your help anyway.  I haven't had much time to answer questions on the site so my points are low but i'll answer a few and get you some.
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13571478
Oh man.  I kind of gave up on this a few days ago and then decided to give it one more thought.  I was going the wrong way about it, it was so simple!

Private Sub Check_All_IM_Windows()
Dim x As Long
For x = 1 To AIM_WINDOWS.Count
    If GetClass(AIM_WINDOWS.Item(x)) = "" Then
        AIM_WINDOWS.Remove x
        Form1.List1.RemoveItem x - 1
        x = x - 1
    End If
Next
End Sub
0
 
LVL 4

Author Comment

by:learning_t0_pr0gram
ID: 13572275
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses
Course of the Month13 days, 8 hours left to enroll

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question