Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. pass a Size object to sendmessage

pass a Size object to sendmessage

Scheduled Pinned Locked Moved C#
graphicshelptutorialquestion
9 Posts 2 Posters 1 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    manchukuo
    wrote on last edited by
    #1

    Hello i have this problem. I need to send a message from a child window to a parent window using sendmessage but i can't make it work to send the Size object to my lParam parameter and i don't know how to cast it when catching it in the parent window so i get the valid Size object i send can someone tell me how? i am getting Cannot convert type 'System.Drawing.Size' to 'int' when calling sendmessage i don't know how to pass it there, thanks

    D 1 Reply Last reply
    0
    • M manchukuo

      Hello i have this problem. I need to send a message from a child window to a parent window using sendmessage but i can't make it work to send the Size object to my lParam parameter and i don't know how to cast it when catching it in the parent window so i get the valid Size object i send can someone tell me how? i am getting Cannot convert type 'System.Drawing.Size' to 'int' when calling sendmessage i don't know how to pass it there, thanks

      D Offline
      D Offline
      DaveyM69
      wrote on last edited by
      #2

      manchukuo wrote:

      Cannot convert type 'System.Drawing.Size' to 'int'

      Why have you declared lParam as an int. This will possibly fail on a 64Bit system as it expects an IntPtr which is 8 bytes on X64 and 4 bytes on X86. You could declare the SendMessage function in this case with lParam as ref Size.

      Dave
      Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
      BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

      M 1 Reply Last reply
      0
      • D DaveyM69

        manchukuo wrote:

        Cannot convert type 'System.Drawing.Size' to 'int'

        Why have you declared lParam as an int. This will possibly fail on a 64Bit system as it expects an IntPtr which is 8 bytes on X64 and 4 bytes on X86. You could declare the SendMessage function in this case with lParam as ref Size.

        Dave
        Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
        BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

        M Offline
        M Offline
        manchukuo
        wrote on last edited by
        #3

        ok i change from this [DllImport("user32.dll")] public static extern int SendMessage( IntPtr hWnd, int Msg, int wParam, int lParam); to this [DllImport("user32.dll")] public static extern int SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); but now i am getting errors in wparam where i am passing a int, how can i pass the int now and about the part to declare as ref Size i can't because i might use another type in there in the future

        D 1 Reply Last reply
        0
        • M manchukuo

          ok i change from this [DllImport("user32.dll")] public static extern int SendMessage( IntPtr hWnd, int Msg, int wParam, int lParam); to this [DllImport("user32.dll")] public static extern int SendMessage( IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam); but now i am getting errors in wparam where i am passing a int, how can i pass the int now and about the part to declare as ref Size i can't because i might use another type in there in the future

          D Offline
          D Offline
          DaveyM69
          wrote on last edited by
          #4

          You should NOT pass an int directly as I explained - an int is 4 bytes but on a 64 bit system the function requires 8 bytes. If you really need to pass a value directly you should create an IntPtr from it:

          new IntPtr(yourInt)

          By the way, the return value should also be an IntPtr. Don't forget you can overload the method, so long as the size of the parameters are correct it won't fail.

          // NativeMethods.cs

          using System;
          using System.Drawing;
          using System.Runtime.InteropServices;

          internal static class NativeMethods
          {
          // http://msdn.microsoft.com/en-us/library/ms644950(v=vs.85).aspx
          /*
          LRESULT WINAPI SendMessage(
          __in HWND hWnd,
          __in UINT Msg,
          __in WPARAM wParam,
          __in LPARAM lParam
          );*/
          [DllImport("User32.dll", SetLastError = true)]
          public static extern IntPtr SendMessage(
          IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
          [DllImport("User32.dll", SetLastError = true)]
          public static extern IntPtr SendMessage(
          IntPtr hWnd, int Msg, IntPtr wParam, ref Size lParam);
          }

          Now you need to work out how to get the size back out once you receive the message, and you may need to pin the Size parameter in memory so it doesn't get moved or go out of scope and get collected...

          Dave
          Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
          BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

          M 1 Reply Last reply
          0
          • D DaveyM69

            You should NOT pass an int directly as I explained - an int is 4 bytes but on a 64 bit system the function requires 8 bytes. If you really need to pass a value directly you should create an IntPtr from it:

            new IntPtr(yourInt)

            By the way, the return value should also be an IntPtr. Don't forget you can overload the method, so long as the size of the parameters are correct it won't fail.

            // NativeMethods.cs

            using System;
            using System.Drawing;
            using System.Runtime.InteropServices;

            internal static class NativeMethods
            {
            // http://msdn.microsoft.com/en-us/library/ms644950(v=vs.85).aspx
            /*
            LRESULT WINAPI SendMessage(
            __in HWND hWnd,
            __in UINT Msg,
            __in WPARAM wParam,
            __in LPARAM lParam
            );*/
            [DllImport("User32.dll", SetLastError = true)]
            public static extern IntPtr SendMessage(
            IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
            [DllImport("User32.dll", SetLastError = true)]
            public static extern IntPtr SendMessage(
            IntPtr hWnd, int Msg, IntPtr wParam, ref Size lParam);
            }

            Now you need to work out how to get the size back out once you receive the message, and you may need to pin the Size parameter in memory so it doesn't get moved or go out of scope and get collected...

            Dave
            Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
            BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

            M Offline
            M Offline
            manchukuo
            wrote on last edited by
            #5

            ok it worked like a charm thank you soo much :laugh:, just a question, isn't there a general way so it could only be one declaration and be able to pass any object?

            modified on Friday, May 6, 2011 2:44 PM

            D 3 Replies Last reply
            0
            • M manchukuo

              ok it worked like a charm thank you soo much :laugh:, just a question, isn't there a general way so it could only be one declaration and be able to pass any object?

              modified on Friday, May 6, 2011 2:44 PM

              D Offline
              D Offline
              DaveyM69
              wrote on last edited by
              #6

              That is the purpose of an IntPtr. When passing data using unmanaged memory a portion of that memory should be allocated to holding the data. The pointer to that memory location is then passed to the function. On the receiving side of the message the pointer is retrieved and the data read at that location then the memory freed. There are several ways to do this, the easiest is a combination of the BitConverter and Marshal classes. Something like this will convert your Size to/from an IntPtr:

              public static IntPtr SizeToPointer(Size size)
              {
                  byte\[\] bytes = new byte\[8\];
                  Array.Copy(BitConverter.GetBytes(size.Width), 0, bytes, 0, 4);
                  Array.Copy(BitConverter.GetBytes(size.Height), 0, bytes, 4, 4);
                  IntPtr result = Marshal.AllocHGlobal(8);
                  Marshal.Copy(bytes, 0, result, 8);
                  return result;
              }
              public static Size PointerToSize(IntPtr pointer)
              {
                  byte\[\] bytes = new byte\[8\];
                  Marshal.Copy(pointer, bytes, 0, 8);
                  Size result = new Size(BitConverter.ToInt32(bytes, 0), BitConverter.ToInt32(bytes, 4));
                  Marshal.FreeHGlobal(pointer);
                  return result;
              }
              

              It is very important that the memory is freed! I have done this in the PointerToSize function. If this is not called then the memory will leak. [Edit] I have just tested this with two forms. With both forms shown, this in form1:

              NativeMethods.SendMessage(
              form2.Handle, 100, IntPtr.Zero, NativeMethods.SizeToPointer(
              new Size(123, 456)));

              and this in form2

              protected override void WndProc(ref Message m)
              {
              if (m.Msg == 100)
              {
              Size size = NativeMethods.PointerToSize(m.LParam);
              MessageBox.Show(size.ToString());
              }
              base.WndProc(ref m);
              }

              The 100 was just a random number I chose for the message - it will be important to use numbers that Windows doesn't already use! [/Edit] [Edit2] Check this[^] out to make sure you don't clash your message numbers. [/Edit2]

              Dave
              Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (

              1 Reply Last reply
              0
              • M manchukuo

                ok it worked like a charm thank you soo much :laugh:, just a question, isn't there a general way so it could only be one declaration and be able to pass any object?

                modified on Friday, May 6, 2011 2:44 PM

                D Offline
                D Offline
                DaveyM69
                wrote on last edited by
                #7

                If you're not happy with all the conversions to/from byte[] then it can be done instead with a class decorated with the StructLayoutAttribute. You can wrap the size in a custom wrapper class and use two other methods of the Marshal class which makes life a bit simpler. Each field in the class must be a blittable[^] type.

                public static IntPtr ConvertSizeToPointer(Size size)
                {
                    SizeWrapper wrapper = new SizeWrapper(size);
                    IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(wrapper));
                    Marshal.StructureToPtr(wrapper, result, true);
                    return result;
                }
                public static Size ConvertPointerToSize(IntPtr pointer)
                {
                    SizeWrapper sizeWrapper = new SizeWrapper();
                    Marshal.PtrToStructure(pointer, sizeWrapper);
                    Marshal.FreeHGlobal(pointer);
                    return sizeWrapper.Size;
                }
                
                \[StructLayout(LayoutKind.Sequential)\]
                internal class SizeWrapper
                {
                    private int height;
                    private int width;
                
                    public SizeWrapper()
                    { }
                    public SizeWrapper(Size size)
                    {
                        this.width = size.Width;
                        this.height = size.Height;
                    }
                
                    public int Height
                    {
                        get { return height; }
                    }
                    public Size Size
                    {
                        get { return new Size(width, height); }
                    }
                    public int Width
                    {
                        get { return width; }
                    }
                }
                

                Dave
                Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                1 Reply Last reply
                0
                • M manchukuo

                  ok it worked like a charm thank you soo much :laugh:, just a question, isn't there a general way so it could only be one declaration and be able to pass any object?

                  modified on Friday, May 6, 2011 2:44 PM

                  D Offline
                  D Offline
                  DaveyM69
                  wrote on last edited by
                  #8

                  manchukuo wrote:

                  one declaration and be able to pass any object

                  I've been thinking about this a little more as it seemed an obvious candidate for generics. This seems to work...

                  // NativeMethods.cs

                  using System;
                  using System.Drawing;
                  using System.Runtime.InteropServices;

                  internal static class NativeMethods
                  {
                  // http://msdn.microsoft.com/en-us/library/ms644950(v=vs.85).aspx
                  /*
                  LRESULT WINAPI SendMessage(
                  __in HWND hWnd,
                  __in UINT Msg,
                  __in WPARAM wParam,
                  __in LPARAM lParam
                  );*/
                  [DllImport("User32.dll", SetLastError = true)]
                  public static extern IntPtr SendMessage(
                  IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

                  \[DllImport("User32.dll", SetLastError = true)\]
                  public static extern IntPtr SendMessage(
                      IntPtr hWnd, int Msg, IntPtr wParam, GCHandle lParam);
                  
                  /// <summary>
                  /// Creates a pinned GCHandle from the supplied object of the specified type.
                  /// </summary>
                  /// <typeparam name="T">Type of object to pin.</typeparam>
                  /// <param name="obj">The object to pin.</param>
                  /// <returns>A pinned GCHandle.</returns>
                  public static GCHandle CreateGCHandle<T>(T obj)
                  {
                      return GCHandle.Alloc(obj, GCHandleType.Pinned);
                  }
                  /// <summary>
                  /// Gets the target of the pinned GCHandle and frees the handle.
                  /// </summary>
                  /// <typeparam name="T">Type of the pinned object.</typeparam>
                  /// <param name="pointer">The GCHandle as an IntPtr.</param>
                  /// <returns>The pinned object.</returns>
                  public static T GetFromPointer<T>(IntPtr pointer)
                  {
                      GCHandle gcHandle = GCHandle.FromIntPtr(pointer);
                      T result = (T)gcHandle.Target;
                      gcHandle.Free();
                      return result;
                  }
                  

                  }

                  Dave
                  Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                  BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                  M 1 Reply Last reply
                  0
                  • D DaveyM69

                    manchukuo wrote:

                    one declaration and be able to pass any object

                    I've been thinking about this a little more as it seemed an obvious candidate for generics. This seems to work...

                    // NativeMethods.cs

                    using System;
                    using System.Drawing;
                    using System.Runtime.InteropServices;

                    internal static class NativeMethods
                    {
                    // http://msdn.microsoft.com/en-us/library/ms644950(v=vs.85).aspx
                    /*
                    LRESULT WINAPI SendMessage(
                    __in HWND hWnd,
                    __in UINT Msg,
                    __in WPARAM wParam,
                    __in LPARAM lParam
                    );*/
                    [DllImport("User32.dll", SetLastError = true)]
                    public static extern IntPtr SendMessage(
                    IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

                    \[DllImport("User32.dll", SetLastError = true)\]
                    public static extern IntPtr SendMessage(
                        IntPtr hWnd, int Msg, IntPtr wParam, GCHandle lParam);
                    
                    /// <summary>
                    /// Creates a pinned GCHandle from the supplied object of the specified type.
                    /// </summary>
                    /// <typeparam name="T">Type of object to pin.</typeparam>
                    /// <param name="obj">The object to pin.</param>
                    /// <returns>A pinned GCHandle.</returns>
                    public static GCHandle CreateGCHandle<T>(T obj)
                    {
                        return GCHandle.Alloc(obj, GCHandleType.Pinned);
                    }
                    /// <summary>
                    /// Gets the target of the pinned GCHandle and frees the handle.
                    /// </summary>
                    /// <typeparam name="T">Type of the pinned object.</typeparam>
                    /// <param name="pointer">The GCHandle as an IntPtr.</param>
                    /// <returns>The pinned object.</returns>
                    public static T GetFromPointer<T>(IntPtr pointer)
                    {
                        GCHandle gcHandle = GCHandle.FromIntPtr(pointer);
                        T result = (T)gcHandle.Target;
                        gcHandle.Free();
                        return result;
                    }
                    

                    }

                    Dave
                    Binging is like googling, it just feels dirtier. Please take your VB.NET out of our nice case sensitive forum. Astonish us. Be exceptional. (Pete O'Hanlon)
                    BTW, in software, hope and pray is not a viable strategy. (Luc Pattyn)

                    M Offline
                    M Offline
                    manchukuo
                    wrote on last edited by
                    #9

                    Thanks this has though me a lot,thanks for your time :cool:

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups