473,409 Members | 1,970 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

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

Invoking Win32 SendMessge

Most code on the net is wrong. This is SendMessage():
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
lParam);

All of those parameters are 32/64-bit in size depending on the
compiler, except for UINT which is a C int, which is always 32-bit,
even on a 64-bit machine, AFAIK. Most code on the net uses C# int (32-
bit) for all (or some) of these, when it should use IntPtr, which is
32/64-bit.

Now, I've seen code use HandleRef for the hWnd, instead of IntPtr, but
I cannot pass Control.Handle into a HandleRef, since it returns
IntPtr. So, should I stick with IntPtr? Or is HandleRef better?

Also, I want to do this:

const IntPtr SB_BOTTOM = 7;

But, C# doesn't allow me to make IntPtr constant, like I could do with
int! AND I cannot just store 7 into an IntPtr, since it's a type
conversion. Dammit. Is there another 32/64 integer data type that I
could use in place of IntPtr that IS allowed to be constant, which
acts like an int?

I am surprised at how annoying all of this is. No wonder people just
use int (and wait for their app to blow up on 64-bit).

Zytan

Mar 3 '07 #1
11 1973
Also, I see code like so (look at the DllImport part):

[DllImport("Kernel32.dll")]
public static extern void GetSystemTime(...);

But, NET Reflector shows me VB DLLs like so:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(...);

Is the extra ", CharSet = CharSet.Auto, SetLastError = true"
required? MSDN fails to explain this extra stuff.

Zytan

Mar 3 '07 #2
>Most code on the net uses C# int (32-
bit) for all (or some) of these, when it should use IntPtr, which is
32/64-bit.
Well some people don't care about 64-bit, and as long as you stay on
Win32 ints will work. Other people simply don't know how to write
proper P/Invoke declarations and use trial and error until they get
something that seemingly works. Or they start from old VB6 Declare
statements that often lack proper type info for the parameters.

>Now, I've seen code use HandleRef for the hWnd, instead of IntPtr, but
I cannot pass Control.Handle into a HandleRef, since it returns
IntPtr.
You can't use it directly, but you can create a new HandleRef when you
need it.

SendMessage(new HandleRef(yourControl, yourControl.Handle), ...

>So, should I stick with IntPtr? Or is HandleRef better?
You can use IntPtr if you know what you're doing. Nowadays, HandleRef
has sort of been superseded by SafeHandles which is an even better
wrapper type.

>Also, I want to do this:

const IntPtr SB_BOTTOM = 7;
Use int for the const, then cast it to IntPtr when you use it.

const int SB_BOTTOM = 7;

SendMessage(..., (IntPtr)SB_BOTTOM, ...

Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Mar 3 '07 #3
>Also, I see code like so (look at the DllImport part):

[DllImport("Kernel32.dll")]
public static extern void GetSystemTime(...);

But, NET Reflector shows me VB DLLs like so:

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(...);
>Is the extra ", CharSet = CharSet.Auto, SetLastError = true"
required? MSDN fails to explain this extra stuff.
It's not required, but recommended. It ensures that SendMessageW is
called instead of SendMessageA on NT-based systems. And since .NET and
most APIs use Unicode internally that's usually good for performance
reasons.

SetLastError=true only makes sense if you also use
Marshal.GetLastWin32Error to tell the reason for failure when a
function returns an error code.

Since GetSystemTime doesn't have a return value and doesn't deal with
text data, it's fine to leave out CharSet and SetLastError.
Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Mar 3 '07 #4
Also, I want to do this:
>
const IntPtr SB_BOTTOM = 7;

But, C# doesn't allow me to make IntPtr constant, like I could do with
int!
Is the reason for this beacuse IntPtr is a struct? I didn't realize
it was a struct until just now.

Zytan

Mar 3 '07 #5
Is the extra ", CharSet = CharSet.Auto, SetLastError = true"
required? MSDN fails to explain this extra stuff.

It's not required, but recommended. It ensures that SendMessageW is
called instead of SendMessageA on NT-based systems. And since .NET and
most APIs use Unicode internally that's usually good for performance
reasons.
It explains it here had I looked a bit more before posting:
http://msdn2.microsoft.com/en-us/library/7b93s42f.aspx
"CharSet.Auto: Platform invoke chooses between ANSI and Unicode
formats at run time, based on the target platform."

So, this is precisely what I want. I don't know how it knows how to
choose the right format, but what this, I can't see any reason to use
the other possibilities. This must be slower due to the extra checks
at run-time. CharSet.Ansi is default, so all the SendMessage imports
I've seen on the internet were calling SendMessageA!

MSDN shows a great example:

[DllImport("user32.dll")]
public static extern int MessageBoxA(int hWnd, String text,
String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Unicode)]
public static extern int MessageBoxW(int hWnd, String text,
String caption, uint type);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int MessageBox(int hWnd, String text,
String caption, uint type);
SetLastError=true only makes sense if you also use
Marshal.GetLastWin32Error to tell the reason for failure when a
function returns an error code.
Oh cool, thanks. It just passed the Win32 error into
Marshal.GetLastWin32Error? So, no harm done if I have it there and
don't use it. So, I might as well leave it there, in case in the
future I want to use it.
Since GetSystemTime doesn't have a return value and doesn't deal with
text data, it's fine to leave out CharSet and SetLastError.
Right.

Thanks, Mattias!

Oh, something that wasn't clear: I think you need this:
using System.Runtime.InteropServices;
to make all this work.

Zytan

Mar 3 '07 #6
Well some people don't care about 64-bit, and as long as you stay on
Win32 ints will work. Other people simply don't know how to write
proper P/Invoke declarations and use trial and error until they get
something that seemingly works. Or they start from old VB6 Declare
statements that often lack proper type info for the parameters.
Right.
You can use IntPtr if you know what you're doing. Nowadays, HandleRef
has sort of been superseded by SafeHandles which is an even better
wrapper type.
Well, yourControl.Handle returns IntPtr, and I know I just want to
pass this directly to SendMessage, so I think I'll stay with IntPtr
for now.
Use int for the const, then cast it to IntPtr when you use it.

const int SB_BOTTOM = 7;

SendMessage(..., (IntPtr)SB_BOTTOM, ...
I think I will do this. Either way is ugly. I wish a real non-struct
int_ptr / int3264 type existed, instead.

Thanks, Mattias

Zytan

Mar 3 '07 #7
"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@30g2000cwc.googlegro ups.com...
Most code on the net is wrong. This is SendMessage():
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
lParam);

All of those parameters are 32/64-bit in size depending on the
compiler, except for UINT which is a C int, which is always 32-bit,
even on a 64-bit machine, AFAIK. Most code on the net uses C# int (32-
bit) for all (or some) of these, when it should use IntPtr, which is
32/64-bit.

Now, I've seen code use HandleRef for the hWnd, instead of IntPtr, but
I cannot pass Control.Handle into a HandleRef, since it returns
IntPtr. So, should I stick with IntPtr? Or is HandleRef better?

Also, I want to do this:

const IntPtr SB_BOTTOM = 7;
Why do you want this to be an IntPtr (machine dependent integer)?
I suppose you want to use this as a Msg parameter value, but Msg is Int32 on both 32 and 64
bit, so an IntPtr is wrong and will blow on 64 bit.

Willy.

Mar 3 '07 #8
Also, I want to do this:
const IntPtr SB_BOTTOM = 7;

Why do you want this to be an IntPtr (machine dependent integer)?
I suppose you want to use this as a Msg parameter value, but Msg is Int32 on both 32 and 64
bit, so an IntPtr is wrong and will blow on 64 bit.
Actually, WM_VSCROLL is the message, which is only 32-bit. I caught
this myself, but never thought to repost here with the correction.
SB_BOTTOM is WPARAM which is 32/64-bit.

But, you made me think of something else:

I want to use IntPtr for 4 of the 5 parameters/return value, since 4
of the 5 should be 32/64-bit depending on the compilation (32/64-
bit). But, that's for a single source that can be compiled both in 32
and 64-bit. Doesn't both compilations need to refer to two
*different* SendMessage? Thus, using IntPtr is wrong if compiling on
64-bit but still linking to the 32-bit SendMessage. I think maybe I
am confusing myself.

Zytan

Mar 5 '07 #9
"Zytan" <zy**********@yahoo.comwrote in message
news:11*********************@8g2000cwh.googlegroup s.com...
Also, I want to do this:
const IntPtr SB_BOTTOM = 7;

Why do you want this to be an IntPtr (machine dependent integer)?
I suppose you want to use this as a Msg parameter value, but Msg is Int32 on both 32 and
64
bit, so an IntPtr is wrong and will blow on 64 bit.

Actually, WM_VSCROLL is the message, which is only 32-bit. I caught
this myself, but never thought to repost here with the correction.
SB_BOTTOM is WPARAM which is 32/64-bit.
Ok.
const int WM_VSCROLL = 0x115;
const int sb_bottom = 7;
IntPtr SB_BOTTOM = new IntPtr(sb_bottom);
....
SendMessage(wHandle, WM_VSCROLL, SB_BOTTOM, ...);
But, you made me think of something else:

I want to use IntPtr for 4 of the 5 parameters/return value, since 4
of the 5 should be 32/64-bit depending on the compilation (32/64-
bit). But, that's for a single source that can be compiled both in 32
and 64-bit. Doesn't both compilations need to refer to two
*different* SendMessage? Thus, using IntPtr is wrong if compiling on
64-bit but still linking to the 32-bit SendMessage. I think maybe I
am confusing myself.

Zytan

Managed code compiled as anycpu(platform:anycpu - is default) will automatically run in a 32
bit process on a 32 bit OS, and as a 64 bit process on 64 bit.
Managed code compiled as 32 bit (platform:x86), will always run as 32bit irrespective the OS
version.
Managed code compiled as 64 bit (platform:x64 or itanium), will run as 64, and this only on
X64 or IA64.
A 32 bit process will automatically get the 32 bit version of user32.dll loaded by the OS
loader, while a 64 bit version will load the 64 bit version, a 32 and 64 bit code mix isn't
possible in the same process, this means that you need to declare all machine dependent
int's as IntPtr to be portable between 32 and 64 bit, the rest is taken care of by the OS.

Willy.


Mar 5 '07 #10
Managed code compiled as anycpu(platform:anycpu - is default) will automatically run in a 32
bit process on a 32 bit OS, and as a 64 bit process on 64 bit.
Managed code compiled as 32 bit (platform:x86), will always run as 32bit irrespective the OS
version.
Managed code compiled as 64 bit (platform:x64 or itanium), will run as 64, and this only on
X64 or IA64.
A 32 bit process will automatically get the 32 bit version of user32.dll loaded by the OS
loader, while a 64 bit version will load the 64 bit version, a 32 and 64 bit code mix isn't
possible in the same process, this means that you need to declare all machine dependent
int's as IntPtr to be portable between 32 and 64 bit, the rest is taken care of by the OS.
Thanks, Willy. Just to be clear, the default compilation in VC# 2005
(Express) is platform:anycpu, which means it will chage IntPtr to the
proper size at runtime? Also, IntPtr is always the proper thing to
use, just as INT_PTR is in VC++, so that it will work if compiled on
32-bit, or compiled on 64-bit, or compiled as 32/64-bit
(platform:anycpu)?

Zytan

Mar 5 '07 #11
"Zytan" <zy**********@yahoo.comwrote in message
news:11**********************@c51g2000cwc.googlegr oups.com...
>Managed code compiled as anycpu(platform:anycpu - is default) will automatically run in a
32
bit process on a 32 bit OS, and as a 64 bit process on 64 bit.
Managed code compiled as 32 bit (platform:x86), will always run as 32bit irrespective the
OS
version.
Managed code compiled as 64 bit (platform:x64 or itanium), will run as 64, and this only
on
X64 or IA64.
A 32 bit process will automatically get the 32 bit version of user32.dll loaded by the OS
loader, while a 64 bit version will load the 64 bit version, a 32 and 64 bit code mix
isn't
possible in the same process, this means that you need to declare all machine dependent
int's as IntPtr to be portable between 32 and 64 bit, the rest is taken care of by the
OS.

Thanks, Willy. Just to be clear, the default compilation in VC# 2005
(Express) is platform:anycpu, which means it will chage IntPtr to the
proper size at runtime? Also, IntPtr is always the proper thing to
use, just as INT_PTR is in VC++, so that it will work if compiled on
32-bit, or compiled on 64-bit, or compiled as 32/64-bit
(platform:anycpu)?

Zytan

Yep, it's always the proper thing to use where machine dependent integers are expected.
These include pointer types like HANDLE and HWND but also opaque types like WPARAM, LPARAM,
LRESULT etc..

Willy.

Mar 5 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Prasad | last post by:
We are invoking a SQL DTS component (lets call it Comp1) built by us in another component (Comp2).Comp1 was built by creating the DTS package using the SQL DTS wizard and then saving it as a VB...
7
by: ~neil~ | last post by:
hello I'm fairly new to the language, and my problem is I'm trying to write a program to run a command from the DOS prompt "C:>". I don't know all the functions in "C", however there are a few...
3
by: Nidhee Pathak via .NET 247 | last post by:
Hi, I am trying to run an exe present on the remote machine using the ManagementClass object. I connect to the remote machine using ObjectManagementScope class, but i am not being able to run the...
25
by: MuZZy | last post by:
Hi, I'm currently rewriting some functionality which was using multithredaing for retrieving datasets from database and updating a grid control. I found that the grids (Infragistics UltraGrid,...
2
by: shanmani | last post by:
Hi, I am developing a .NET application which will invoke the methods from different COM / .NET DLLs. While invoking methods from .NET DLLs, I am encountering the following error. I have also...
0
by: balaji krishna | last post by:
Hi, I need to handle the return set from COBOL stored procedure from my invoking Java program. I do not know, how many rows the stored proc SQL fetches.I have declared the cursor in that proc, but i...
3
by: Monkeyfun | last post by:
Hi, I have a CAN controller from which I need to read packets whenever one is received. With the CAN controller came a WIN32 (non clr) library. When a CAN packet is received the library must...
2
by: =?Utf-8?B?SmltIE93ZW4=?= | last post by:
Hi John, Hopefully this post will find its way back to you - or perhaps be answered by someone else. As I mentioned in my last post on the earlier portion of this thread, changing the...
0
by: Dobedani | last post by:
Dear All, For some time now, I have been working with the ctypes module on Windows. First I got my hands on a library developed with Delphi 7. That library is exporting plain functions....
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

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.