views:

1589

answers:

3

I'm trying to call SendMessage with an uint parameter from Java, but I can't convert int to uint. I can't change the uint parameter in SendMessage because it is a windows function. Is there some way of doing this?

Background: I'm actually using Processing, and I'm following the following tutorials to access user32.dll: http://processing.org/hacks/hacks:jnative

and http://jnative.free.fr/SPIP-v1-8-3/article.php3?id_article=8

And I'm following this to call SendMessage http://www.codeproject.com/KB/cs/Monitor_management_guide.aspx

Here's my code, GetActiveWindow works fine, it's from the second link above.

 int SC_MONITORPOWER = 0xF170;
 int WM_SYSCOMMAND = 0x0112;
 int MONITOR_ON = -1;
 int MONITOR_OFF = 2;
 int MONITOR_STANDBY = 1;

HWND ValidHWND = org.xvolks.jnative.util.User32.GetActiveWindow(); 
org.xvolks.jnative.util.User32.SendMessage(ValidHWND, (UINT)WM_SYSCOMMAND, 
          (WPARAM)SC_MONITORPOWER, (LPARAM)MONITOR_STANDBY);

last line is where the error happens, it says the expected UINT in type User32 is not applicable to the LONG I provided. I can't modify SendMessage either

Here's the corresponding java file the call above invokes, the GetActiveWindow part works fine since it's from a tutorial. I'm trying to tailor Sendmessage to follow it, but I haven't figured it all out yet. However, I don't think it matters to the error I'm getting, since changing the parameters to SendMessage here doesn't change what the compiler expects. I've tried changing int Msg to uint Msg to long Msg, the compiler still expects uint from the code above.

public class Paul_s_User32 extends User32 {
public HANDLE GetActiveWindow() {
 JNative GetActiveWindow = new JNative(DLL_NAME, "GetActiveWindow");
 GetActiveWindow.setRetVal(Type.INT);
 GetActiveWindow.invoke();
 HWND handle = new HWND(GetActiveWindow.getRetValAsInt());
 GetActiveWindow.dispose();
 return handle;
}
public IntPtr SendMessage(IntPtr hWnd, int Msg, 
          IntPtr wParam, IntPtr lParam) {
 JNative SendMessage = new JNative(DLL_NAME, "SendMessage");
 //SendMessage.setRetVal(Type.long);
 SendMessage.invoke();

 SendMessage(ValidHWND, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_STANDBY);
}
A: 

Since Java does not have the notion of unsigned types, you have to use a long to represent an unsigned int. Check this site for examples on how to do this.

cartman
Thanks, but how do I pass a long when SendMessage expects an uint? I still can't type convert it to uint after changing it to a long. Sorry if the site answered it, I can't find it anywhere. Thanks again.
omikun
Oh, to clarify, I am not writing SendMessage, it's part of user32.dll. Is there a way to force SendMessage to accept a long in place of an uint?
omikun
cartman
omikun
cartman
+3  A: 

From a data perspective, a uint and an int are the same thing -- a 32 bit value. The only difference is how opcodes interpret the uppermost bit. When passing between Java and C, you're just passing 32 bits, so the sign is not relevant. The solution is to just declare the uint parameter as an int.

BTW, the issue of unsigned/signed is not significant here because the uMsg value for SendMessage is positive for all Microsoft messages, and for that matter, is more than likely positive for anything else you're likely to encounter.

jdigital
That's true as far as it goes. But to "setup" the unsigned int, you have to play tricks, like: int foo = (int)4294967295L; or int foo = 0xFF << 24 | 0xFF << 16 | 0xFF << 8 | 0xFF; (which is more convenient depends on the actual meaning of the bit sequence). You can't just do: int foo = 4294967295 And of course Java will still think foo is meant to refer to -1. The site cartman linked explains it more throughly.
Matthew Flaschen
The problem is SendMessage isn't a function I have control over. It's in user32.dll that's part of Windows.
omikun
+1  A: 

If you are using the org.xvolks.jnative package, all of the parameters (HWND, UINT, WPARAM, and LPARAM) are classes in org.xvolks.jnative.misc.basicStructures. So you should be able to do something like this (untested code):

import org.xvolks.jnative.misc.basicStructures.*;
...

User32.SendMessage(
    new HWND(ValidHWND),
    new UINT(WM_SYSCOMMAND), 
    new WPARAM(SC_MONITORPOWER),
    new LPARAM(MONITOR_STANDBY);

For your reference, here's the implementation of SendMessage in org.xvolks.jnative.util.User32. As you can see, the jnative code does not care at all about signed and unsigned. You might find it useful to grab the jnative source code.

public static LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) throws NativeException, IllegalAccessException
{
 JNative SendMessage = new JNative(DLL_NAME, "SendMessageA");
 SendMessage.setRetVal(Type.INT);
 int pos = 0;
 SendMessage.setParameter(pos++, hWnd.getValue());
 SendMessage.setParameter(pos++, Msg.getValue());
 SendMessage.setParameter(pos++, wParam.getValue());
 SendMessage.setParameter(pos++, lParam.getValue());
 SendMessage.invoke();
 pos = SendMessage.getRetValAsInt();
 SendMessage.dispose();
 return new LRESULT(pos);
}

And if you decide that you don't like JNative, you could take a look at Java Native Access (JNA).

jdigital
Wow thank you so much! My undergraduate education in CompE only consisted of C programming so all this OOP stuff really confuses me. But even so, the trouble was I used '(UINT)WM_SYSCOMMAND' instead of 'new UINT(WM_SYSCOMMAND);' which made all the difference. I'm still learning the difference between the two but thanks again! I would vote you up twice if I could. But since I only have 11 rep points so far, I can't even vote you up once.
omikun
Glad that you found this helpful. You can mark this as an answer and that's worth something too.BTW, not really sure I'd call this an OOP issue. There's a mismatch between Java and C and the author of JNative tried to come up with a clever way to handle this difference.
jdigital