Visual Basic Development Bookmark and Share   
 Home > Visual Basic Interop and Upgrade > how to pass hwnd from VB6 code in VB.net library using Interop
 

how to pass hwnd from VB6 code in VB.net library using Interop

Ineed to pass a window handle (long) from VB6 client to a library written in VB.Net for some processing (using interop). I don't know how to make use of the hwnd from VB6 and get the correct window handle in .Net.

Please help!

btw, Im on VS 2008 SP1 and .Net framework 3.5 SP1

narsiCherukupalli  Monday, November 02, 2009 10:41 PM
Hi Narsi,

We can fix this issue by PInvoke calling MessageBox in VB.NET component to implement same effect as VB6 API calling. The following is my modification to your code snippet. I tested it. It should satisfy your requirement.

Public Shadows Function MessageBoxU(ByVal OwnerHandle As Integer, ByVal Prompt As String, ByVal Title As String, ByVal buttons As Integer) As Integer
Try
Dim iPtr As IntPtr
iPtr = New IntPtr(OwnerHandle)
MessageBox.Show(OwnerHandle.ToString())
MessageBox.Show(iPtr.ToString)
'MessageBox.Show(New CWindowWrapper(iPtr), Prompt, Title, buttons)
NativeMethods.MessageBoxW(iPtr, Prompt, Title, buttons)
Catch
MsgBox(Err.Description)
End Try
End Function

Partial Public Class NativeMethods

'''Return Type: int
'''hWnd: HWND->HWND__*
'''lpText: LPCWSTR->WCHAR*
'''lpCaption: LPCWSTR->WCHAR*
'''uType: UINT->unsigned int
<System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint:="MessageBoxW")> _
Public Shared Function MessageBoxW(<System.Runtime.InteropServices.InAttribute()> ByVal hWnd As System.IntPtr, <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal lpText As String, <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal lpCaption As String, ByVal uType As UInteger) As Integer
End Function
End Class
Best regards,
Riquel
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
Riquel_Dong  Friday, November 06, 2009 5:57 AM

I should have checked for a unicode version of the API function call (MessageBoxIndirectW) which can be called directly from a VB 6.0 app.

http://www.vbforums.com/showthread.php?t=541220


Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Friday, November 06, 2009 1:20 PM
Maybe you could provide a little more detail as to what the .NET component needs to do with the hwnd. I don't see a problem with passing it from the VB 6.0 app to a .NET component function. Is it the interop process that you're not sure how to do?
Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 2:42 PM
Hi Paul
Thanks for the response. Here is what I am trying to do.

This is part of a project wherewe are adding Unicode support toa fairly complex VB6 application. We are doingInterop user controls to be used in VB6 forms. As part of this project we also have to wrap MessageBox function so that we can display unicode strings in the message box.

following are the two main objectives of thethe Wrapper function for MessageBox
a) to handle Unicode Strings
b) take Window handle as parameter so that the message box can be set for a particular window.

now, when calling this function from VB6 I can pass the window handle of any form that I want to this function as Integer but don't know how to properly convert it to "Iwin32Window" type so that MessageBox function can understand it.

Thanks again.
narsiCherukupalli  Tuesday, November 03, 2009 3:48 PM
See if the below link helps. It's written in C# but the example looks to be relatively simple and should be adaptable to Visual Basic:

http://ryanfarley.com/blog/archive/2004/03/23/465.aspx


Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 5:28 PM
Paul
I got this working by using a WrapperClass for IWin32Window. But I have a new problem now

When I pass the Window handle of an external window (not the VB6 Client from whereI call this function) the message box displaysmodally on that window and my VB6 Form also stuck behind that same Message box.

I don't want it to be Modal to my VB6 Form when I pass a handle to another window.

Please help! I'm posting the code here so you can reproduce it very easily

VB.Net 

Imports System.Windows.Forms

<ComClass(CTest.ClassId, CTest.InterfaceId, CTest.EventsId)> _
Public Class CTest

#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "75bce494-cfa8-46fd-8f2e-550aee2ebd47"
    Public Const InterfaceId As String = "8c003cc9-e226-4f9e-87c4-54619a2b9482"
    Public Const EventsId As String = "bbbf2e72-74f9-4514-8970-5a73ec62d421"
#End Region

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()
    End Sub

    Public Shadows Function MessageBoxU(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal OwnerHandle As Integer = 0) As Integer
        Try
            Dim iPtr As IntPtr
            Dim oWindWrapper As CWindowWrapper

            If OwnerHandle > 0 Then
                iPtr = New IntPtr(OwnerHandle)
                oWindWrapper = New CWindowWrapper(iPtr)


                Return MessageBox.Show(oWindWrapper, Prompt, Title)
            Else
                Return MessageBox.Show(Prompt, Title)
            End If

        Catch

        End Try


    End Function

End Class

Imports System.Windows.Forms

Class CWindowWrapper
    Implements IWin32Window

    Private _hwnd As IntPtr

    Public Sub New(ByVal handle As IntPtr)
        _hwnd = handle
    End Sub

    Public ReadOnly Property Handle() As IntPtr Implements IWin32Window.Handle
        Get
            Return _hwnd
        End Get
    End Property

End Class

-----------------------------------------------------------------
VB6 Client Code
On a form add these three controls
TextBox, CheckBox and Command Button
 and paste the following code

Option Explicit

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

Private Declare Function MessageBox Lib "user32" Alias "MessageBoxA" _
(ByVal hWnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long


Private Sub Command1_Click()
    Dim ot As New CTest
    Dim Whdl As Long
    
    'Text1.Text is any Window Caption
    Whdl = FindWindow(vbNullString, Text1.Text)
       
    If Check1.Value = vbChecked Then
        'use Win32 API
        MessageBox Whdl, "Hello on Window (" & Text1.Text & ")", "My Caption", vbInformation
    Else
        'use .Net MessageBox
        If Whdl > 0 Then
            ot.MessageBoxU "Hello on Window (" & Text1.Text & ")", "My Caption", Whdl
        Else
            ot.MessageBoxU "Window Not Found (" & Text1.Text & ")", "My Caption"
        End If
    End If
End Sub



narsiCherukupalli  Tuesday, November 03, 2009 5:32 PM

Example code converted to VB:

   MessageBox.Show(New WindowWrapper(hwnd), "Hello World!")

   Public Class WindowWrapper
        Implements System.Windows.Forms.IWin32Window
        Public Sub New(ByVal handle As IntPtr)
            _hwnd = handle
        End Sub

        Public ReadOnly Property Handle() As IntPtr Implements System.Windows.Forms.IWin32Window.Handle
            Get
                Return _hwnd
            End Get
        End Property

        Private _hwnd As IntPtr
    End Class

Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 5:36 PM
It is still modal to both the windows!

I am trying to make the Message box appear modally on lets say Windows Explorer window by passing its hwnd, when I click the button on my
VB6 Form. But somehow it makes the displayed message box Modal to both my VB6 Form and Windows Explorer window.

If I use the win32 MessageBox API it works correctly. After I click the button I can proceed to work with my VB6 Form. Messagebox is only Modal to windows explorer.


Modified VB.Net code (based on ur sample above)

Public Shadows Function MessageBoxU(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal OwnerHandle As Integer = 0) As Integer

Dim iPtr As IntPtr

iPtr =

New IntPtr(OwnerHandle)

MessageBox.Show(

New CWindowWrapper(iPtr), Prompt, Title)

End Function


Modified VB6 Code
Private Sub Command1_Click()
Dim ot As New CTest
Dim Whdl As Long

'Text1.Text is any Window Caption
Whdl = FindWindow(vbNullString, Text1.Text)

If Check1.Value = vbChecked Then
'use Win32 API
MessageBox Whdl, "Hello on Window (" & Text1.Text & ")", "My Caption", vbInformation
Else
'use .Net MessageBox
ot.MessageBoxU "Hello on Window (" & Text1.Text & ")", "My Caption", Whdl
End Sub
narsiCherukupalli  Tuesday, November 03, 2009 5:53 PM
The MessageBox method displays a modal window by design. I don't believe there is a parameter that will allow you to display a non-modal or mode-less window.

Can't you just use a Windows Form instead instead of a MessageBox?
Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 5:57 PM
I understand that Messagebox method is Modal and that is what I want it to be, but just to the Window whose handle I pass to it.

But it seems to become modal to both my VB6 Form (from where I call this method) and to the actual window whose handle I pass to this method.

narsiCherukupalli  Tuesday, November 03, 2009 6:06 PM
The MessageBox method is just a .NET wrapper for the MessageBox API function. I don't know why both the parent window and calling app are blocked but it could be a threading restriction with respect to VB 6.0. I would be curious to seewhether this would function differently under a .NET client.

I would use the API function callif it's providing the desired results. You could always create your own .NET MessageBox Class (wrapper)if you are looking for somethingthat is easier to use than the API.
Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 7:17 PM
I tried it using a .Net client, its the same behavious with MessageBox.Show method. It becomes Modal on both, the form that this method is called from and the window whose handle is passed.

Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

Private Sub Command1_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Command1.Click

Dim handle As Integer

handle = FindWindow(vbNullString,

"VB6 Test")

MessageBox.Show(

New WindowWrapper(New IntPtr(handle)), "My Message: " & TextBox1.Text, "My Caption - " & TextBox1.Text)

'MessageBox(handle, "My Message: " & TextBox1.Text, "My Caption - " & TextBox1.Text, vbInformation)

End Sub


--------------------------
If I use the MessageBox API it behaves correctly in this scenario also. But the API is not able to display Unicode Text, which is kind of why I am trying to use .Net Message Box in the first place.

Declare Function MessageBox Lib "user32" Alias "MessageBoxA" (ByVal hWnd As Integer, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Integer) As Integer

narsiCherukupalli  Tuesday, November 03, 2009 7:45 PM
Let me check to see if I can get an explanation for this behavior.

Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Tuesday, November 03, 2009 9:21 PM
Hi ï¼?br/>
Could you send your VB.NET project and VB6 project to me so that I can reproduce your scenario for further discussion? If you can, please send it via email(you can find it in my profile). Thanks.

Best regards,
Riquel
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
Riquel_Dong  Thursday, November 05, 2009 7:42 AM
Hi Riquel
I had just sent the Code to you in via email. subject line

Ref: "how to pass hwnd from VB6 code in VB.net library using Interop"

Hope you can see what I am doing wrong here.

Thank you in advance.
narsiCherukupalli  Thursday, November 05, 2009 4:05 PM
Hi Narsi,

We can fix this issue by PInvoke calling MessageBox in VB.NET component to implement same effect as VB6 API calling. The following is my modification to your code snippet. I tested it. It should satisfy your requirement.

Public Shadows Function MessageBoxU(ByVal OwnerHandle As Integer, ByVal Prompt As String, ByVal Title As String, ByVal buttons As Integer) As Integer
Try
Dim iPtr As IntPtr
iPtr = New IntPtr(OwnerHandle)
MessageBox.Show(OwnerHandle.ToString())
MessageBox.Show(iPtr.ToString)
'MessageBox.Show(New CWindowWrapper(iPtr), Prompt, Title, buttons)
NativeMethods.MessageBoxW(iPtr, Prompt, Title, buttons)
Catch
MsgBox(Err.Description)
End Try
End Function

Partial Public Class NativeMethods

'''Return Type: int
'''hWnd: HWND->HWND__*
'''lpText: LPCWSTR->WCHAR*
'''lpCaption: LPCWSTR->WCHAR*
'''uType: UINT->unsigned int
<System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint:="MessageBoxW")> _
Public Shared Function MessageBoxW(<System.Runtime.InteropServices.InAttribute()> ByVal hWnd As System.IntPtr, <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal lpText As String, <System.Runtime.InteropServices.InAttribute(), System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)> ByVal lpCaption As String, ByVal uType As UInteger) As Integer
End Function
End Class
Best regards,
Riquel
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
Riquel_Dong  Friday, November 06, 2009 5:57 AM

I should have checked for a unicode version of the API function call (MessageBoxIndirectW) which can be called directly from a VB 6.0 app.

http://www.vbforums.com/showthread.php?t=541220


Paul ~~~~ Microsoft MVP (Visual Basic)
Paul P Clement IV  Friday, November 06, 2009 1:20 PM

Riquel
This worked! Thank you so much for your help. The solution Paul gave below is also good and works for me. Now I have a choice!

Thank you for your help, I appreciate it very much.

Narsi

narsiCherukupalli  Friday, November 06, 2009 2:20 PM

Paul
This worked! Thank you so much for your help.Riquel's solution above is also works. Now I have a choice!

Thank you for your help, I appreciate it very much.

Narsi

narsiCherukupalli  Friday, November 06, 2009 2:21 PM

You can use google to search for other answers

Custom Search

More Threads

• Error installing Interop Forms toolkit 2.0
• Sporadic error occuring while calling a COM DLL inside of ASP.NET / VB.NET App
• Opening Modeless VB.Net Form from VB6 using Interop
• Generating wrapper classes for one project only
• Interop Forms Toolkit - Tools menu
• Communication between VB6.0 and Asp.net applications
• vb6 conversion
• call unmanaged activex method with pointer type
• Accessing InteropUserControl Object in vb6
• .Net MDI Parent form in VB6 process using the Interop Forms Toolkit