Question

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);
}
Was it helpful?

Solution

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).

OTHER TIPS

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top