Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Range check error

21 views
Skip to first unread message

Mike Lischke

unread,
Jan 15, 2006, 8:51:37 AM1/15/06
to
Hi all,

I wonder how IntPtr is declared? I can't find a declaration for it but I
need to explain an effect I found today. I have code like this:

var
BitmapHandle: TBITMAP;

BitmapHandle := HBITMAP(CLRBitmap.GetHbitmap);

This code throws a range check error whenever GetHbitmap returns a negative
value. Since GetHbitmap returns an IntPtr value and HBTIMAP is a long word
(Uint32) I thought this would be compatible. The only explanation I have
for the range check error is that IntPtr is actually an Int64 type.
However, I cannot cast IntPtr to UInt64 (compiler won't let do me) so I
have no way of bringing the IntPtr into a HBITMAP without risk of a range
check error.

Currently I have wrapped the code with conditional compiler stuff to switch
off range checking but a good solution is this not. Better ideas?

Mike
--
www.soft-gems.net

Rudy Velthuis [TeamB]

unread,
Jan 22, 2006, 5:11:13 PM1/22/06
to
At 14:51:37, 15.01.2006, Mike Lischke wrote:

> Hi all,
>
> I wonder how IntPtr is declared?

[Serializable, StructLayout(LayoutKind.Sequential)]
public struct IntPtr : ISerializable
{
private unsafe void* m_value;
public static readonly IntPtr Zero;
public IntPtr(int value);
public IntPtr(long value);
[CLSCompliant(false)]
public unsafe IntPtr(void* value);
private IntPtr(SerializationInfo info, StreamingContext context);
void ISerializable.GetObjectData(SerializationInfo info,
StreamingContext context);
public override bool Equals(object obj);
public override int GetHashCode();
public int ToInt32();
public long ToInt64();
public override string ToString();
public static explicit operator IntPtr(int value);
public static explicit operator IntPtr(long value);
[CLSCompliant(false)]
public static unsafe explicit operator IntPtr(void* value);
[CLSCompliant(false)]
public static unsafe explicit operator void*(IntPtr value);
public static explicit operator int(IntPtr value);
public static explicit operator long(IntPtr value);
public static bool operator ==(IntPtr value1, IntPtr value2);
public static bool operator !=(IntPtr value1, IntPtr value2);
public static int Size { get; }
[CLSCompliant(false)]
public unsafe void* ToPointer();
static IntPtr();
}

It is more or less the .NET equivalent of THandle (and/or Pointer).

--
Rudy Velthuis [TeamB] http://rvelthuis.de/

"Be tolerant of the human race. Your whole family belongs to it -- and
some of your spouse's family too." - Anonymous.

Rudy Velthuis [TeamB]

unread,
Jan 22, 2006, 5:36:26 PM1/22/06
to
At 14:51:37, 15.01.2006, Mike Lischke wrote:

> Hi all,
>
> I wonder how IntPtr is declared? I can't find a declaration for it but I
> need to explain an effect I found today. I have code like this:
>
> var
> BitmapHandle: TBITMAP;
>
> BitmapHandle := HBITMAP(CLRBitmap.GetHbitmap);

Huh? How can BitmapHandle be a TBitmap? Did you mean:

var
Bitmap: TBitmap;

Bitmap.Handle := HBITMAP(CLRBitmap.GetHBitmap);

> This code throws a range check error whenever GetHbitmap returns a
> negative value. Since GetHbitmap returns an IntPtr value and HBTIMAP is
> a long word (Uint32) I thought this would be compatible. The only
> explanation I have for the range check error is that IntPtr is actually
> an Int64 type. However, I cannot cast IntPtr to UInt64 (compiler won't
> let do me) so I have no way of bringing the IntPtr into a HBITMAP
> without risk of a range check error.

IntPtr should probably be cast to Integer, or to Pointer. Perhaps you can
cast that to a HBITMAP then?

Bitmap.Handle := HBITMAP(Integer(CLRBitmap.GetHBitmap));

Otherwise, you might need to use the Convert or Marshal classes to get it
into your HBITMAP.

The .NET help says:

<<
The IntPtr type is designed to be an integer whose size is
platform-specific. That is, an instance of this type is expected to be
32-bits on 32-bit hardware and operating systems, and 64-bits on 64-bit
hardware and operating systems.

The IntPtr type can be used by languages that support pointers, and as a
common means of referring to data between languages that do and do not
support pointers.

IntPtr objects can also be used to hold handles. For example, instances
of IntPtr are used extensively in the System.IO.FileStream class to hold
file handles.

The IntPtr type is CLS-compliant, while the UIntPtr type is not. Only the
IntPtr type is used in the common language runtime. The UIntPtr type is
provided mostly to maintain architectural symmetry with the IntPtr type.

This type implements the ISerializable interface.
>>

I also noticed this code in WinUtils.pas:

function ArrayToNativeBuf(Data: System.Array;
Buffer: IntPtr = nil): IntPtr;

This suggests that IntPtr is seen as a Pointer, or System.Object.

--
Rudy Velthuis [TeamB] http://rvelthuis.de/

"A printer consists of three main parts: the case, the jammed paper
tray and the blinking red light" -- unknown

Mike Lischke

unread,
Jan 23, 2006, 1:52:20 PM1/23/06
to
Rudy Velthuis [TeamB] wrote

>Huh? How can BitmapHandle be a TBitmap? Did you mean:
>
> var
> Bitmap: TBitmap;
>
> Bitmap.Handle := HBITMAP(CLRBitmap.GetHBitmap);

Sorry, no. It's a typo. Bitmap is actually a HBITMAP.

>IntPtr should probably be cast to Integer, or to Pointer. Perhaps you can
>cast that to a HBITMAP then?

I'm relatively sure I have tried all these combinations, but the compiler
won't let me do that. But I will try again, just to be sure.

> Bitmap.Handle := HBITMAP(Integer(CLRBitmap.GetHBitmap));
>
>Otherwise, you might need to use the Convert or Marshal classes to get it
>into your HBITMAP.

The funny thing is I found C# code where this is just casted and works. And
it *does* work, also in Delphi, I checked it. It is only the range check
error that drives me crazy.

>This suggests that IntPtr is seen as a Pointer, or System.Object.

Thank you for your help Rudy.

Mike
--
www.soft-gems.net

Marc Rohloff [TeamB]

unread,
Jan 23, 2006, 7:10:13 PM1/23/06
to
On 15 Jan 2006 06:51:37 -0700, Mike Lischke wrote:

> BitmapHandle := HBITMAP(CLRBitmap.GetHbitmap);
This is equivalent to calling CLRBitmap.GetHBitmap.ToInt32, since
HBitmap is defined as a longword (unsigned) that could be a problem.

I guess you could try CLRBitmap.GetHBitmap.ToInt64 and and out the
high order bits or use anInt32 to store the handle.

--
Marc Rohloff [TeamB]
marc rohloff -at- myrealbox -dot- com

0 new messages