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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C#
  4. Passing an int array by refеrence to a shell function - how?

Passing an int array by refеrence to a shell function - how?

Scheduled Pinned Locked Moved C#
comlinuxdata-structureshelptutorial
12 Posts 2 Posters 0 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.
  • I iliyang

    Hello, I'm trying to send the HDM_GETORDERARRAY message to my ListView. The problem is that it requires a pointer to an array to write the indicies in. And I don't know how to pass an array of integers, so that I can read what's been written in it. Any suggestions? Thanks in advance!

    J Offline
    J Offline
    jjansen
    wrote on last edited by
    #2

    I assume your already familiar with using unmanaged code (Introp calls etc.) Try this: int[] MyArrayOfInts = ... fixed(int* p_MyArrayOfInts = MyArrayOfInts) { ThatFunction(p_MyArrayOfInts); } Good luck.

    I 1 Reply Last reply
    0
    • J jjansen

      I assume your already familiar with using unmanaged code (Introp calls etc.) Try this: int[] MyArrayOfInts = ... fixed(int* p_MyArrayOfInts = MyArrayOfInts) { ThatFunction(p_MyArrayOfInts); } Good luck.

      I Offline
      I Offline
      iliyang
      wrote on last edited by
      #3

      OK, but the function prototype is: protected static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam) that is, I have to pass an integer, not an interger pointer...

      J 1 Reply Last reply
      0
      • I iliyang

        OK, but the function prototype is: protected static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, ref int lParam) that is, I have to pass an integer, not an interger pointer...

        J Offline
        J Offline
        jjansen
        wrote on last edited by
        #4

        iliyang wrote: that is, I have to pass an integer, not an interger pointer... The syntax is: lResult = SendMessage( // returns LRESULT in lResult (HWND) hWndControl, // handle to destination control (UINT) HDM_GETORDERARRAY, // message ID (WPARAM) wParam, // = (WPARAM) (int) iSize; (LPARAM) lParam // = (LPARAM) (LPINT) lpiArray; ); where lpiArray is: Pointer to an array of integers that receive the index values for items in the header. So you do have to pass an array (even if the array is only one element long). The pointer in the code of my previous post is merely a pointer to the FIRST integer in a row. From there the app can access the next integer, and the next, and so on. It will assume there are iSize integers in a row, starting at the address that is the pointer.

        I 1 Reply Last reply
        0
        • J jjansen

          iliyang wrote: that is, I have to pass an integer, not an interger pointer... The syntax is: lResult = SendMessage( // returns LRESULT in lResult (HWND) hWndControl, // handle to destination control (UINT) HDM_GETORDERARRAY, // message ID (WPARAM) wParam, // = (WPARAM) (int) iSize; (LPARAM) lParam // = (LPARAM) (LPINT) lpiArray; ); where lpiArray is: Pointer to an array of integers that receive the index values for items in the header. So you do have to pass an array (even if the array is only one element long). The pointer in the code of my previous post is merely a pointer to the FIRST integer in a row. From there the app can access the next integer, and the next, and so on. It will assume there are iSize integers in a row, starting at the address that is the pointer.

          I Offline
          I Offline
          iliyang
          wrote on last edited by
          #5

          OK, 10x a lot! It worked finde when I called the function like this: int[] MyArrayOfInts = ... fixed(int* p_MyArrayOfInts = MyArrayOfInts) { ThatFunction(*p_MyArrayOfInts); // not: ThatFunction(p_MyArrayOfInts); }

          J 1 Reply Last reply
          0
          • I iliyang

            OK, 10x a lot! It worked finde when I called the function like this: int[] MyArrayOfInts = ... fixed(int* p_MyArrayOfInts = MyArrayOfInts) { ThatFunction(*p_MyArrayOfInts); // not: ThatFunction(p_MyArrayOfInts); }

            J Offline
            J Offline
            jjansen
            wrote on last edited by
            #6

            Huh? :confused: That's not a pointer to an array you're putting in the function but the value of the first array element. Anyhow, I was going to recommend an alternative method. The Interop-call to SendMessage should look something like this: [DllImport("user32.dll"] public static extern int SendMessage(IntPtr hwnd, uint wMsg, IntPtr wParam, IntPtr lParam); You can get an IntPtr to your array using Marshal.Copy(Int[] source, int startIndex, IntPtr destination, int length). I've never used Marshal.Copy before, so if you're decide to try it this way let me know how it turns out.

            I 1 Reply Last reply
            0
            • J jjansen

              Huh? :confused: That's not a pointer to an array you're putting in the function but the value of the first array element. Anyhow, I was going to recommend an alternative method. The Interop-call to SendMessage should look something like this: [DllImport("user32.dll"] public static extern int SendMessage(IntPtr hwnd, uint wMsg, IntPtr wParam, IntPtr lParam); You can get an IntPtr to your array using Marshal.Copy(Int[] source, int startIndex, IntPtr destination, int length). I've never used Marshal.Copy before, so if you're decide to try it this way let me know how it turns out.

              I Offline
              I Offline
              iliyang
              wrote on last edited by
              #7

              Yes, I know that I'm passing the first element of the array, but I just tried and it worked fine :) The second method (with the IntPtr) I found ealier but I didn't know how to obtain an IntPtr object. I suppose with the IntPtr is better too. But how should I get an IntPtr object to copy the array into?

              J 1 Reply Last reply
              0
              • I iliyang

                Yes, I know that I'm passing the first element of the array, but I just tried and it worked fine :) The second method (with the IntPtr) I found ealier but I didn't know how to obtain an IntPtr object. I suppose with the IntPtr is better too. But how should I get an IntPtr object to copy the array into?

                J Offline
                J Offline
                jjansen
                wrote on last edited by
                #8

                Just make one: int[] MyArray = ... IntPtr MyPointer = IntPtr.Zero; // make and initialize Marshal.Copy(MyArray, 0, MyPointer, MyArray.Length); (Note: Don't confuse the marshal-call with the overload Marshal.Copy(IntPtr, int[], int, int) .)

                I 1 Reply Last reply
                0
                • J jjansen

                  Just make one: int[] MyArray = ... IntPtr MyPointer = IntPtr.Zero; // make and initialize Marshal.Copy(MyArray, 0, MyPointer, MyArray.Length); (Note: Don't confuse the marshal-call with the overload Marshal.Copy(IntPtr, int[], int, int) .)

                  I Offline
                  I Offline
                  iliyang
                  wrote on last edited by
                  #9

                  Nope, Marshal.Copy throws a NullReference exception when passing a null (0) IntPtr object. So for now, the "mystical" solution works the best :rolleyes:

                  J 1 Reply Last reply
                  0
                  • I iliyang

                    Nope, Marshal.Copy throws a NullReference exception when passing a null (0) IntPtr object. So for now, the "mystical" solution works the best :rolleyes:

                    J Offline
                    J Offline
                    jjansen
                    wrote on last edited by
                    #10

                    You're right, my mistake. I wrongly assumed that the Copy method returns a pointer to the array. On second thought this isn't what Copy does at all. Instead you have to allocate some space yourself using Marshal.AllocHGlobal with the appropriate number of bytes. This gives you a valid IntPtr. int Nr = ...; // number of elements in array int[] MyArray = new int[Nr]; IntPtr MyPtr = Marshal.AllocHGlobal(Nr * sizeof(int)) Then call SendMessage with MyPtr. Next use the Copy(IntPtr MyPtr, int[] MyArray, 0, MyArray.Length) method. Finally use Marshal.FreeHAlloc.

                    I 1 Reply Last reply
                    0
                    • J jjansen

                      You're right, my mistake. I wrongly assumed that the Copy method returns a pointer to the array. On second thought this isn't what Copy does at all. Instead you have to allocate some space yourself using Marshal.AllocHGlobal with the appropriate number of bytes. This gives you a valid IntPtr. int Nr = ...; // number of elements in array int[] MyArray = new int[Nr]; IntPtr MyPtr = Marshal.AllocHGlobal(Nr * sizeof(int)) Then call SendMessage with MyPtr. Next use the Copy(IntPtr MyPtr, int[] MyArray, 0, MyArray.Length) method. Finally use Marshal.FreeHAlloc.

                      I Offline
                      I Offline
                      iliyang
                      wrote on last edited by
                      #11

                      Well, this time works but the values returned are messed. But, you know, this does work fine: _columnOrder = new int[this.Columns.Count]; int size = 0; IntPtr pHeader = SendMessage(this.Handle, (int) Win32.Consts.LVM_GETHEADER, 0, ref size); SendMessage(pHeader, (int) Win32.Consts.HDM_GETORDERARRAY, _columnOrder.Length, ref _columnOrder[0]); See the ref _columnOrder[0] in the second SendMessage call ;)

                      J 1 Reply Last reply
                      0
                      • I iliyang

                        Well, this time works but the values returned are messed. But, you know, this does work fine: _columnOrder = new int[this.Columns.Count]; int size = 0; IntPtr pHeader = SendMessage(this.Handle, (int) Win32.Consts.LVM_GETHEADER, 0, ref size); SendMessage(pHeader, (int) Win32.Consts.HDM_GETORDERARRAY, _columnOrder.Length, ref _columnOrder[0]); See the ref _columnOrder[0] in the second SendMessage call ;)

                        J Offline
                        J Offline
                        jjansen
                        wrote on last edited by
                        #12

                        OK, good luck with your project.

                        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