问题
A window handle sometimes of type int
and other times of type IntPtr
int
example:
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId);
IntPtr
example:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);
I don't seem to be able to convert/cast from one to the other.
When I try this.ProcessID = GetWindowThreadProcessId(windowHandle.ToInt32(),0)
I get an error cannot implicitly convert from uint to int
回答1:
The SendMessage
signature is
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
or this
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, StringBuilder lParam);
Don't exchange int
and IntPtr
. They are nearly equivalent only at 32 bits (equal in size). At 64 bits an IntPtr
is nearly equivalent to a long
(equal in size)
The GetWindowThreadProcessId
signature is
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
or
static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
In this case, a ref
or a out
to "something" are managed references to something, so they are internally converted to IntPtr
when passed to Native API. So out uint
is, from the point of view of the Native API, equivalent to IntPtr
.
Explanation: what is important is that the "length" of the parameters is the correct one. int
and uint
are equal for the called API. And a 32bit IntPtr
is the same too.
Note that some types (like bool
and char
) have special handling by the marshaler.
You shouldn't EVER convert an int
to an IntPtr
. Keep it as an IntPtr
and live happy. If you have to make some math operations not supported by IntPtr
, use long
(it's 64 bits, so until we will have Windows 128, there won't be any problem :-) ).
IntPtr p = ...
long l = (long)p;
p = (IntPtr)l;
回答2:
I think that error cannot implicitly convert from uint to int
refers to =
statement. The field this.ProcessID
is int
, but GetWindowThreadProcessId
returns uint
.
Try this
this.ProcessID = unchecked((int)GetWindowThreadProcessId(windowHandle.ToInt32(),0))
回答3:
I was getting "Arithmetic operation resulted in an overflow", whenever I was:
IntPtr handler = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
if (handler.ToInt32() == 0) //throws Exception
instead of that:
IntPtr handler = OpenSCManager(null, null, SC_MANAGER_CREATE_SERVICE);
if (handler == IntPtr.Zero) //OK
来源:https://stackoverflow.com/questions/18173211/how-to-convert-intptr-to-int