Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


SetParent API

Posted on 1998-04-01
Medium Priority
Last Modified: 2008-02-01
Here's a fun one.  

We have a very large application that we need to partition out.  The application's interface is MDI.  The idea is to break each functional area out into smaller DLL's, where each DLL would (for the most part) correspond to a single screen (we have almost 200 screens).  The benefits of partitioning the application into DLLs provides us with better manageability, smaller EXE size and lower resource utilization.

Using VB5, each screen will be displayed modeless with the goal of the window being treated as an MDI child.  To accomplish this we are using the SetParent API call.  When the child screen is displayed, SetParent is invoked with the handle of the MDI parent form.

This works great - until we try to drag a window or click on its caption.  What happens next is the confusing part.  When we click on the title bar, the child form "jumps" to a lower-right offset.  We can drag the form around but the mouse pointer does not actually touch the child form’s title bar.  Once the mouse button is release, the child form "jumps" back to where it would be had everything worked correctly.

I have determined that the coordinate system of the MDI parent is not being assigned to the new child window.  Instead, the child window seems to retain the coordinate system of the desktop (the previous parent).

Does anyone know how to correct this behavior?

Incidentally, the Parent form does not need to be an MDI form.  You can duplicate this behavior with two normal forms, too.  Also, for testing, you do not need to create a DLL.  Simply create two forms in your project and use the following (pseudo)code.

Private Sub Form_Load()
End Sub

Private Sub Form_Load()
     Call SetParent(Form2.Hwnd, Form1.hWnd)
End Sub

Question by:zsi
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

Expert Comment

ID: 1460182
The SetParent function makes the target window parentless if the second parameter is Null. I'll bet you that Null is being passed in that call.

To test this, put a stop marker at the beginning of Form2.Load(), and check the value of Form1.hWnd. It may be zero, which means that you're attempting to use an invalid handle.

Try moving the setparent call up into Form1.Load(), like this:

Private Sub Form_Load()
  Call SetParent(Form2.hWnd, Form1.hWnd)
End Sub


Author Comment

ID: 1460183
Actually, I am calling SetParent from within the parent form.  Also, my code (and yours) contains an error: Form2.Load will not work.  It should be Form2.Show.  Sorry about that.

The actual code should read:
Private Sub Form_Load
   Call SetParent(Form2.hwnd, Form1.hwnd)
End Sub

No code is required in Form2.

Regarding the Null handle, there is no such thing.  When Windows creates a new window (or any other element for that matter) the very first thing that it does is allocates a memory handle.  Therefore, even if the SetParent call was being made in the child form, the .hWnd property would still not be null.

Expert Comment

ID: 1460184
Just a thought...

You could hook all events coming into the Child Forms in the App.  Then, instead of letting VB process these Forms normally when the caption is clicked or they are dragged, handle the behavior yourself.  That way, instead of working to fix odd behavior, you just prevent it altogether.

Just a thought...

LVL 39

Accepted Solution

abel earned 50 total points
ID: 1460185
I've had the same problem with an old VB-app which as compiled with VB3 and uses the function SetParent as well. I'm not going to provide you a "real" solution, but I will try to ease your search for it and I will provide a workaround.

My project contained several separate executables which needed to communicate with each other and act like a MDI form with childs for the end-user. To achieve that I did the same as you by using the SetParent API call. It worked well in Win16 and the first releases of Win32. At first the problem occurred on NT4 and only when "dragging of full windows" was on. When I turned that off (and you'll only see a wireframe when dragging a window), the problem disappeared.
On Win95 OSR2 it is also possible to drag full windows and the problem occurred again. After some research I began to think that it was a bug of Windows, and I still think that, although I never found a real prove.

To get rid of the problem I made a workaround. I used the following function:

I first retrieved the setting with SPI_GETDRAGFULLWINDOWS and if False, there was nothing to do, when True, I changed the setting. When my application was loosing focus I restored the setting. Again, when it was False before, there was nothing to do either.

It did the trick. Off course you won't be seeing fully dragged windows when in your application the user moves a child, but at the other hand, it looks better to the enduser (who probably won't even give it any thought). I know, it IS a workaround, but it's better then nothing. I'm sorry that I can't provide you a "real" solution for your problem, but maybe this'll do.

When you need some more info, just post a comment,

Regards, Abel

BTW: mattyboy, what did you do with your question "Refresh all maximized windows on desktop" (Q.10045126)? When I tried to read your comment, the question seemed to be deleted....

Author Comment

ID: 1460186
Hmm... Well, this has certainly gotten me closer than anything else I have found.  

I put the SET to FALSE command in the Form.Activate and the SET to TRUE in the ChildForm.Deactivate.  This way, I can toggle the settings back and forth so that only the child is dragged by the frame only.

Keeping in mind that it IS a workaround, one undesired effect is that you have to give the parent an opportunity to receive the system message that the setting has changed.  This means that instead of clicking and dragging directly on the parent's titlebar, you have to click in the parent's area (or titlebar), release the mouse, then click on the title bar to move it.

Also, setting SETDRAGFULLWINDOWS to True does not work - it has to be 1.

But, it gets the job done and solves the problem at an acceptable level.  

I guess this behavior is just one more to add to Microsoft's bug list.

Thanks for the help!

Featured Post


Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
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.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

671 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