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. - Proposed As Answer byRiquel_DongModeratorFriday, November 06, 2009 5:59 AM
- Marked As Answer bynarsiCherukupalli Friday, November 06, 2009 2:23 PM
-
| | 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) - Marked As Answer bynarsiCherukupalli Friday, November 06, 2009 2:23 PM
-
| | 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. - Proposed As Answer byRiquel_DongModeratorFriday, November 06, 2009 5:59 AM
- Marked As Answer bynarsiCherukupalli Friday, November 06, 2009 2:23 PM
-
| | 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) - Marked As Answer bynarsiCherukupalli Friday, November 06, 2009 2:23 PM
-
| | 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 |
|