471,627 Members | 1,250 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,627 software developers and data experts.

[API] Delegates and Parameters

I am trying to get an API (EnumResourceNamesW - kernel32) to pass a specific
parameter to the call-back function. The declaration I currently have for
EnumResourceNamesW is:

[
DllImport(
"kernel32.dll",
EntryPoint = "EnumResourceNamesW",
CharSet = CharSet.Unicode,
SetLastError = true
)
]
static extern bool EnumResourceNamesWithID(
IntPtr ModuleHandle,
uint Type,
EnumResNameDelegate EnumFunc,
IntPtr Param
);

I have a delegate as follows:

private delegate bool EnumResNameDelegate(
IntPtr ModuleHandle,
IntPtr Type,
IntPtr Name,
IntPtr Param
);

I want to pass an ArrayList to the EnumResourceNamesWithID and have it pass
that to the EnumResNameDelegate method. But, since Param is an IntPtr, I
can't. Is there a way to do what I am trying to accomplish?

Currently, I don't pass anything. I have a member variable in the class and
am using this var to store the values of the resources found. But I want to
do this w/o a member variable. Any suggestions/help?

Thanks,
Mythran

Dec 21 '05 #1
2 1571
Mythran,

First off, your declaration for your delegate and the API is wrong.
They should be:

[DllImport("kernel32.dll", EntryPoint="EnumResourceNamesW",
CharSet=CharSet.Unicode, SetLastError=true)]
static extern bool EnumResourceNamesWithID(
IntPtr hModule,
string lpszType,
EnumResNameProcDelegate lpEnumFunc,
IntPtr lParam);

public delegate bool EnumResNameProcDelegate(
IntPtr hModule
[MarshalAs(UnmanagedType.LPWStr)]
string lpszType,
[MarshalAs(UnmanagedType.LPWStr)]
string lpszName,
IntPtr lParam);

Note the changing of the lpszType parameter to a string.

Now, to pass the array list, you would use a GCHandle structure, like
so:

// Assume the arraylist is in a variable named al.
GCHandle handle = GCHandle.Alloc(al);

Then make the call to EnumResourceNamesWithID. Pass the GCHandle in the
lParam parameter. It might require a specific cast to IntPtr.

In your callback, you want to cast the IntPtr to a GCHandle, and then
get the Target property, like so:

// Get the handle.
GCHandle handle = (GCHandle) lParam;

// Get the array list.
ArrayList al = (ArrayList) handle.Target;

Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Mythran" <ki********@hotmail.comREMOVETRAIL> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
I am trying to get an API (EnumResourceNamesW - kernel32) to pass a
specific parameter to the call-back function. The declaration I currently
have for EnumResourceNamesW is:

[
DllImport(
"kernel32.dll",
EntryPoint = "EnumResourceNamesW",
CharSet = CharSet.Unicode,
SetLastError = true
)
]
static extern bool EnumResourceNamesWithID(
IntPtr ModuleHandle,
uint Type,
EnumResNameDelegate EnumFunc,
IntPtr Param
);

I have a delegate as follows:

private delegate bool EnumResNameDelegate(
IntPtr ModuleHandle,
IntPtr Type,
IntPtr Name,
IntPtr Param
);

I want to pass an ArrayList to the EnumResourceNamesWithID and have it
pass that to the EnumResNameDelegate method. But, since Param is an
IntPtr, I can't. Is there a way to do what I am trying to accomplish?

Currently, I don't pass anything. I have a member variable in the class
and am using this var to store the values of the resources found. But I
want to do this w/o a member variable. Any suggestions/help?

Thanks,
Mythran

Dec 21 '05 #2

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.com> wrote in
message news:%2****************@tk2msftngp13.phx.gbl...
Mythran,

First off, your declaration for your delegate and the API is wrong.
They should be:

[DllImport("kernel32.dll", EntryPoint="EnumResourceNamesW",
CharSet=CharSet.Unicode, SetLastError=true)]
static extern bool EnumResourceNamesWithID(
IntPtr hModule,
string lpszType,
EnumResNameProcDelegate lpEnumFunc,
IntPtr lParam);

public delegate bool EnumResNameProcDelegate(
IntPtr hModule
[MarshalAs(UnmanagedType.LPWStr)]
string lpszType,
[MarshalAs(UnmanagedType.LPWStr)]
string lpszName,
IntPtr lParam);

Note the changing of the lpszType parameter to a string.

Now, to pass the array list, you would use a GCHandle structure, like
so:

// Assume the arraylist is in a variable named al.
GCHandle handle = GCHandle.Alloc(al);

Then make the call to EnumResourceNamesWithID. Pass the GCHandle in
the lParam parameter. It might require a specific cast to IntPtr.

In your callback, you want to cast the IntPtr to a GCHandle, and then
get the Target property, like so:

// Get the handle.
GCHandle handle = (GCHandle) lParam;

// Get the array list.
ArrayList al = (ArrayList) handle.Target;

Hope this helps.


Mattias Sjogren stated in a message dated Feb 20 2003,

"You can't use string as the type for lpszType/lpszName parameters in
these callback delegates, becuase they often deal with integers cast
to LPTSTR values, that can't be converted to a string my the
marshaler. You have to use IntPtr instead, and then figure out
yourself if it's an integer or a string pointer."

I tried it with string types, but an exception was being thrown that stated
"Invalid access to memory location." By applying the fix for that from the
message Mattias wrote and including the GCHandle.Alloc method for allocating
the handle for the array list, I was able to get this working successfully!

Thank you very much :)

Mythran

Dec 21 '05 #3

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Natalia DeBow | last post: by
12 posts views Thread by ichor | last post: by
3 posts views Thread by Pavils Jurjans | last post: by
4 posts views Thread by Cedric Rogers | last post: by
4 posts views Thread by Anastasios Hatzis | last post: by
7 posts views Thread by Siegfried Heintze | last post: by
10 posts views Thread by Roger Frost | last post: by
9 posts views Thread by raylopez99 | last post: by
1 post views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.