views:

217

answers:

4
public partial class Form1 : Form
{
  [DllImport("coredll.dll")]
  static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  const int GWL_WNDPROC = -4;

  public delegate int WindProc(IntPtr hWnd, uint msg, long Wparam, long lparam);

    public Form1()
    {
        InitializeComponent();

        WindProc SampleProc = new WindProc (SubclassWndProc);

        SetWindowLong(this .Handle , GWL_WNDPROC,
            SampleProc.Method .MethodHandle.Value.ToInt32());

    }

public int SubclassWndProc(IntPtr  hwnd, uint  msg, long  Wparam, long  lparam)
{
    return 1;
}

Here is the sample which i was trying to take the window procedure of a form, this is how i do in C++ i get the windwproc easlily if i try the same in C# .net 3.5 i am unable to get the window proc,, after calling SetWindowLong API application hangs and it pops up some dont send report... i have read this is the way to get the window proc.. please let me know were i am making mistake...

+3  A: 

SampleProc.Method .MethodHandle.Value.ToInt32()

Just use SampleProc. If that fails, try marshalling it to a FunctionPointer.

leppie
no i cant give simply SampleProc it wont work,i have no idea about marshalling it to a FunctionPointer.. please tell me in detail.. it would be helpfull
Shadow
Why wont it work? Please tell me. I have used many a delegate exactly like I said.
leppie
i dont no, but this will be the error i am gettingerror CS1503: Argument '3': cannot convert from 'UnsafeCodeSample.Form1.WindProc' to 'int'
Shadow
Hey Leppie... how to achive marshalling it to a FunctionPointer i dont have much idea about marshalling.. if you know send me some sample example or snippet of it.
Shadow
Lippie it worked.. i just marshalled to function pointer its so simple "Marshal .GetFunctionPointerForDelegate (SampleProc)" :-). Thank U so much.. Thanks lot for answer
Shadow
A: 

I think you need to declare your delegate instance at the form level, like this:

public partial class Form1 : Form
{
    [DllImport("coredll.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    const int GWL_WNDPROC = -4;
    public delegate int WindProc(IntPtr hWnd, uint msg, 
        long Wparam, long lparam);
    private WindProc _SampleProc;
    public Form1()
    {
        InitializeComponent();
        _SampleProc = new WindProc(SubclassWndProc);
        SetWindowLong(this.Handle, GWL_WNDPROC,
            _SampleProc.Method.MethodHandle.Value.ToInt32());

    }
    public int SubclassWndProc(IntPtr  hwnd, uint  msg, 
        long  Wparam, long  lparam)
    {
        return 1;
    }

Your original delegate instance was being declared in the form's constructor, where it immediately went out of scope (and thus wasn't around anymore to be called back to).

There might be other problems with your sample, too.

MusiGenesis
Either way, the delegate will require an instance. You need to declare the delegate instance as static.
leppie
@leppie: I don't think the delegate instance needs to be static.
MusiGenesis
No yaar.. i tried it didnt work.. please let me know were i am making mistake.. if it works big headache gets resolved please help..
Shadow
@MusiGenesis: We will see about that! :) Will test it sometime.
leppie
@Leppie static instance of deligate also gives same problem..i dont no why :-(.. any way please let me know the problem..
Shadow
@leppie: bring it! :)
MusiGenesis
@Grablt: can you include the link to where you got this sample code from? The online samples I found for SetWindowLong don't use it by passing in a delegate.
MusiGenesis
@MusiGenesis, it worked .. i just marshalled to function pointer its so simple "Marshal .GetFunctionPointerForDelegate (SampleProc)" :-).Thank U so much..
Shadow
@Grablt: You're probably going to run into a rare, intermittent problem with your code anyway. Your delegate instance, since it's a form-level variable, will stick around for the life of your form. However, the .Net garbage collector *may* move it in memory, which will screw up the method call from Windows and produce the same problem. The way around this is to create a form-level GCHandle and "pin" the delegate instance - this will prevent it from being moved.
MusiGenesis
@MusiGenesi :what you said is right.. for that what i am doing is i am taking "oldwindowproc" to one intptr variable using "GetWindowLong" method, then i am using "CallWindowProc" method to call the default window proc and in this am passing the "oldwindproc" address.. and will pass all the messages.. when the form is getting closed am resetting the oldwindow proc.. i think its fine or will it cause any side effects
Shadow
+1  A: 

The delegate instance does not need to be static. No idea why you think it should.

ctacke
A: 

You are working with the compact framework, right? Are you doing everything from the same process?

I have experienced this kind of trouble myself, if the process where the window is created is not the same process as the message stems from. However I actively used SendMessage to send a message. If I did this from a different process, I got the "send error report" page. I now have found out, that if the SendMessage comes from the same process, things work fine.

In the above you could probably replace process with thread, although i am no sure.

Marcel
Um, no. The answer was already given and accepted. He was incorrectly using a delegate.
ctacke