为什么* SetWindowLong(myForm.hWnd,GWL_HWNDPARENT,parentHwnd)*挂起?
我可以持续地执行这三个步骤来重现这个问题。
C#Windows应用程序(挂起)
private static void Main(string[] args)
{
Form form = new Form();
form.Show();
Interop.WaitWindow waitWindow = new Interop.WaitWindow();
waitWindow.ShowWindow(form.Handle.ToInt32(), Language.RISEnglish);
}
C#控制台应用程序(不挂起)
private static void Main(string[] args)
{
IntPtr handle = Process.GetCurrentProcess().MainWindowHandle;
Interop.WaitWindow waitWindow = new Interop.WaitWindow();
waitWindow.ShowWindow(handle.ToInt32(), Language.RISEnglish);
}
VB6代码段
Public Sub ShowWindow(ByVal parentHwnd As Long, ByVal language As Language)
SetWindowLong(myForm.hWnd, GWL_HWNDPARENT, parentHwnd) 'Hangs Here
CenterWindow (parentHwnd)
myForm.ShowRetrieving (language)
myForm.Show (vbModal)
End Sub
非常感谢您的帮助:)
修改
我知道不应该调用SetWIndowLong来更改父级,但是我试图理解为什么它只在使用.NET表单句柄时挂起。
EDIT2
我现在认为这个问题与SetWindowLong无关,而是实际的句柄本身。我还在调查,但似乎当我从.NET调用VB6代码时,它会创建一个RPC线程。我还不确定,但我觉得它与跨线程问题有关。
答案 0 :(得分:3)
我设法确切地知道发生了什么以及如何解决问题。我没有使用[STAThread]属性指定我的主入口点,因此它默认为MTA。这意味着当我调用VB6代码时,它创建了一个RPC回调线程,并没有编写对UI执行的主线程的调用。
Peter Mortensen写了一篇good explanation关于此事:
STA模型用于非线程安全的COM对象。那 意味着他们不处理自己的同步。常用的 这是一个UI组件。因此,如果另一个线程需要与之交互 对象(例如按下表单中的按钮)然后消息是 编组到STA线程上。窗户形成消息 系统就是一个例子。
答案 1 :(得分:2)
MSDN文档明确指出
您不能使用GWL_HWNDPARENT索引调用SetWindowLong来更改子窗口的父级。而是使用SetParent函数。
答案 2 :(得分:1)
你是在64位系统中运行吗?你的VB6应用程序是32位应用程序吗?如果您属于这种情况,它将解释为什么正在创建RPC调用,并且它将解释为什么您的非法黑客它无法正常工作。如果是这种情况,坏消息是现在有办法让它发挥作用。
您还应该知道.net控件may change during the lifetime of the control的底层窗口句柄。有关此问题的讨论,另请参阅SO中的this question。