Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I programmed a WinForm in .net by C# to opens VB6 exe in TabControl,
now all of Windows exe file like Notpad.exe or ... opens success in TabControl but VB6 does not open correctly in WinForm, it does not obey Parent/Child legal.
Now please help me, it is very important and neseccery for me.

In Addation:
1-in The Program used Procces class to start program and also used SetParent() for define Parent/Child legal.
2- I Used Telerik PageView to open windows in separated tabs.


code:

C#
// Global Var ---------------
public string TabName;
public const int GWL_STYLE = -16;
public const uint WS_VISIBLE = 0x10000000;
// ---------------------------

private void radButtonElement3_Click(object sender, EventArgs e)
        {
         //Creeate New Tab in Telerik PageView
            TabName = radButtonElement3.Text;
            Telerik.WinControls.UI.RadPageViewPage Tab = new Telerik.WinControls.UI.RadPageViewPage(TabName);
            radPageView1.Pages.Add(Tab);
            radPageView1.SelectedPage = Tab;


            IntPtr appWin;
            appWin = IntPtr.Zero;

            string exeName = Application.StartupPath + "\\" + "VB6.exe";

            Process p = null;
            try
            {

                // Start the process
                p = System.Diagnostics.Process.Start(exeName);
             

                // Wait for process to be created and enter idle condition
                p.WaitForInputIdle();

                // Get the main handle
                appWin = p.MainWindowHandle;               
                
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error");
            }
                                
           
            //set new Handel 
            IntPtr _newHandler = radPageView1.Pages[(radPageView1.Pages.Count) - 1].Handle;

            SetParent(p.MainWindowHandle, _newHandler);
            SetWindowLong(_newHandler, GWL_STYLE, WS_VISIBLE);
            MoveWindow(_newHandler, 0, 0, radPageView1.Pages[0].Size.Width, radPageView1.Pages[0].Size.Height, true);
        
        }


// define user32.dll ---------------------------------------
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
             CharSet = CharSet.Unicode, ExactSpelling = true,
             CallingConvention = CallingConvention.StdCall)]
        private static extern long GetWindowThreadProcessId(long hWnd, long lpdwProcessId);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll")]
        public static extern int GetClassLong(IntPtr hWnd, int index);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern long SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

        [DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
        private static extern long GetWindowLong(IntPtr hwnd, int nIndex);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongA", SetLastError = true)]
        private static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long x, long y, long cx, long cy, long wFlags);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);

        [DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
        private static extern bool PostMessage(IntPtr hwnd, uint Msg, long wParam, long lParam);
Posted
Updated 2-Aug-16 7:27am
v2
Comments
Philippe Mori 2-Aug-16 9:21am    
Please, use a code block for your code. No one like to read unformatted code.
vahid211 2-Aug-16 13:30pm    
tanks for your attention
[no name] 2-Aug-16 9:49am    
I experienced such problems several times. Don't ask me why, but put a Thread.Sleep(200) _after_ p.WaitForInputIdle() solved it each time. I know, not a nice solution... and yes I assume you checked with Debugger for p.MainWindowHandle is valid...
vahid211 2-Aug-16 13:32pm    
hi
I did it, but the problem does not resolved.
other solution?
[no name] 2-Aug-16 14:52pm    
No, sorry no other idea. But I found someting in your code... you use _newHandler....which I think should be p.MainWindowHandle:
SetWindowLong(_newHandler, GWL_STYLE, WS_VISIBLE);
MoveWindow(_newHandler, 0, 0, radPageView1.Pages[0].Size.Width, radPageView1.Pages[0].Size.Height, true);

1 solution

It does not really make sense to have parent/child relationship between distinct applications. And obviously, Windows is not designed to handle such scenarios. And it might be even worst with VB or .NET in the mix as each technology has its way of handling and dispatching events...

You might want to convert you VB code to create Active/X (COM) controls that can then be embedded inside a form or user control.

Or better yet, would be to convert the VB6 code to either VB.NET or C# code or replace those controls by some more modern controls designed for .NET.

If you cannot afford to do that, then I think you should still use standalone windows. Maybe, you could simply adjust the position of the VB6 main windows so that it appears at the appropriate area and display your application as activated when the VB6 application is active.

You would then need custom code to handle move and activation so that both applications appears as if they were one application. Even then, it might be problematic if one of the application stop responding or crashes...

A better alternative might be to reuse code from the VB6 EXE but redo the UI using .NET.
 
Share this answer
 
Comments
[no name] 2-Aug-16 10:06am    
Just a few thoughts:
Whether it makes sense or not I can not judge.
But "And obviously, Windows is not designed to handle such scenarios" I think is a very bold statement. What other than a window is the windows desktop (HWND WINAPI GetDesktopWindow(void))?
Philippe Mori 2-Aug-16 10:56am    
The common rule is that each application (or top-level windows) has its own UI thread... The Windows desktop is a "special" windows as it belong to all applications in a sense and at the same time does not belong to any application (for example, your application won't receive a paint event if the desktop is redrawn).
Some links that might be useful:
Thread affinity of user interface objects, part 1: Window handles
Running WPF Application with Multiple UI Threads
Who would ever write a multi-threaded GUI program?
vahid211 2-Aug-16 15:11pm    
Dear Philippe Mori
Thanks for your answer, but I sure it is possible,
actually we have about 300 vb6 form exe that we want manage thire links by Telerik Ribbon bar menu in .net to call vb6 exe s and opening every link in new TabPage on Tab Control, just it.
Philippe Mori 2-Aug-16 16:00pm    
Well, even if it might somehow works, it is an abuse of the system.

The fact that it does not works as you expect means that Windows or .NET was not designed with those cases in mind so you are essentially using undocumented features which might make it harder for Windows team (or .NET team) to improve their code as changes might break some applications in unexpected ways.

By the way, why would you put controls in an EXE? I think it would make much more sense to put those controls inside a DLL and use them as Active/X controls. That way, the UI from VB controls would be in the same thread as the main application UI thread and you won't have to fight against the system.

vahid211 3-Aug-16 4:44am    
Dear Philippe Mori
how can we make DLL and use Active/X controls ?
please suggest some article that learning clearly this topic.

BR,

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900