strange subclassing problem

S

SQACSharp

I have to following class :

using System;
using System.Windows.Forms;

namespace Test
{
public class SubclassWindow : NativeWindow
{
[System.Security.Permissions.PermissionSet
(System.Security.Permissions.SecurityAction.Demand, Name =
"FullTrust")]
protected override void WndProc(ref Message m)
{
if (m.Msg==666)
MessageBox.Show("blablabla!");
}
IntPtr ObjectHandle;
public new void AssignHandle(IntPtr handle)
{
ObjectHandle=handle;
Control ctl = Control.FromHandle(handle);
MessageBox.Show("Assign handle for control :"+ctl.Name);
base.AssignHandle(handle);
}
public new void ReleaseHandle()
{
Control ctl = Control.FromHandle(ObjectHandle);
MessageBox.Show("Release handle for control :"+ctl.Name);
base.ReleaseHandle();
}
}
}

Drop 2 buttons in a form with the following code and click events :

SubclassWindow wr;
private void button1_Click(object sender, System.EventArgs e) //
assign handle button
{
wr=new SubclassWindow();
wr.AssignHandle(button2.Handle); //we pass the button2
handle...juste for the test
}
private void button2_Click(object sender, System.EventArgs e) //
release handle button
{
wr.ReleaseHandle();
}

After clicking button1 (assign) and button2 (release) the next time I
try to click the button1 there is an error in the messagebox because
ctl.Name is null?????? What is wrong when releasing the handle?

Any explanation? workaround? How an this be possible???????

Thanks!

Mike
 
S

SQACSharp

Yeah my subject is not relevant with my example ;o)

Ok I post here because i'm trying to figure out a bug in my
application which look like the same as my stripped example.

I'm doing a macro recording tool for unmanaged/managed application.
For unmanaged application I simply use something similar to my example
but i'm trapping tons of msg to report the appropriate action in my
"script"
For managed application I use another class (no nativewindow
inherits) and it work. It simple add and remove events to the object
to listen to the object.

My goal was to "combine/merge" the code of both class in a class that
inherits from nativewindow. This way I can manage controls in a
native and an unmanaged point of view. Some managed class use
unmanaged windows and this could make thing a lot easier for me. But
after releasing the handle of a managed control the access to the
control is lost for some reasons. **Control.FromHandle just stop
working**. I want to manage "managed" control in a nativewindow
class because I want to use the Keyboard and mouse management that is
already developped in my "native subclassing" class.

When executing my code it look like the release come from somewhere
else like a different thread since the messagebox is not appearing on
top of the application like the "Assign" messagebox. Is there a way
to "invoke" that control in a different way if it's in a different
thread or unavailable for some reasons because of the use of the
NativeWindow class? Never releasing the handle is the only solution I
have for now but this can't be a solution :(

Mike
 
S

SQACSharp

After hours working on this the only workaround found is to add a Start
() and Stop() fonction and not calling the releaseHandle at all :

bool Recording=false;
public void Start()
{
Recording=true;
}
public void Stop()
{
Recording=false;
}

and in WndProc it start with
If (!Recording)
return;

At least I get the expected results but I don't want to live with
unreleased stopped process in the tested application :( There must
be a way to call ReleaseHandle and still behing able to access to the
net control after
 
S

SQACSharp

Found the explanation from another newsgroup :

Control.FromHandle() actually returns NativeWindow.FromHandle(handle)
to get the reference. So if we called
ReleaseHandle method, the handle is removed from the internal window
hooked
table, then the NativeWindow.FromHandle can not get any NativeWindow
object
from the internal window hooked table, so the null is return.

The code of FromHandleInternal in NativeWindow class look like this :
internal static Control FromHandleInternal(IntPtr handle)
{
NativeWindow window1 = NativeWindow.FromHandle(handle);
while ((window1 != null) && !(window1 is
Control.ControlNativeWindow))
{
window1 = window1.PreviousWindow;
}
if (window1 is Control.ControlNativeWindow)
{
return ((Control.ControlNativeWindow) window1).GetControl
();
}
return null;
}

So this behavior is by design ...there is a lot of threads about "a
bug" in releaseHandle but nobody proposes a Workaround or an idea to
make it work. Now I'm looking for a way to "ReCreate" manually the
control in nativeWindow class after releasing the handle.

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top