/* Copyright (c) 2010 Daniel Doubrovkine, All Rights Reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package com.sun.jna.platform.win32;
import static com.sun.jna.platform.win32.User32.INSTANCE;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.DesktopWindow;
import com.sun.jna.platform.WindowUtils;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.WinDef.BOOL;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.DWORDByReference;
import com.sun.jna.platform.win32.WinDef.HDC;
import com.sun.jna.platform.win32.WinDef.HICON;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.POINT;
import com.sun.jna.platform.win32.WinDef.RECT;
import com.sun.jna.platform.win32.WinDef.UINT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinGDI.ICONINFO;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinUser.HMONITOR;
import com.sun.jna.platform.win32.WinUser.LASTINPUTINFO;
import com.sun.jna.platform.win32.WinUser.MONITORENUMPROC;
import com.sun.jna.platform.win32.WinUser.MONITORINFO;
import com.sun.jna.platform.win32.WinUser.MONITORINFOEX;
/**
* @author dblock[at]dblock[dot]org
*/
public class User32Test extends AbstractWin32TestSupport {
public static void main(String[] args) {
JUnitCore.runClasses(User32Test.class);
}
/**
* Iterates over all currently available Desktop windows and searches for
* the window with the associated process whose full PE file path ends with
* the specified string (case insensitive).
*
* @param filePathEnd
* The requested end of the process' full file path.
* @return Either the found window or {@code null} if nothing was found.
*/
private static DesktopWindow getWindowByProcessPath(final String filePathEnd) {
final List<DesktopWindow> allWindows = WindowUtils.getAllWindows(false);
for (final DesktopWindow wnd : allWindows) {
if (wnd.getFilePath().toLowerCase()
.endsWith(filePathEnd.toLowerCase())) {
return wnd;
}
}
return null;
}
@Test
public void testNoDuplicateMethodsNames() {
// see https://github.com/twall/jna/issues/482
Collection<String> dupSet = AbstractWin32TestSupport.detectDuplicateMethods(User32.class);
if (dupSet.size() > 0) {
for (String name : new String[] {
// has 2 overloads since the original API accepts both MONITORINFO and MONITORINFOEX
"GetMonitorInfo"
}) {
dupSet.remove(name);
}
}
assertTrue("Duplicate methods found: " + dupSet, dupSet.isEmpty());
}
@Test
public void testGetSystemMetrics() {
int cursorWidth = INSTANCE.GetSystemMetrics(WinUser.SM_CXCURSOR);
assertTrue(cursorWidth > 0);
}
@Test
public void testRegisterHotKey() {
int vk = KeyEvent.VK_D;
int id = 1;
assertTrue("RegisterHotKey failed", INSTANCE.RegisterHotKey(null, id, WinUser.MOD_CONTROL | WinUser.MOD_ALT, vk));
Robot robot = null;
try {
robot = new Robot();
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_ALT);
robot.keyPress(vk);
Thread.sleep(50);
robot.keyRelease(vk);
WinUser.MSG msg = waitForMessage(500);
assertNotNull(msg);
assertEquals(msg.wParam.intValue(), id);
assertTrue(INSTANCE.UnregisterHotKey(null, id));
robot.keyPress(vk);
Thread.sleep(10);
robot.keyRelease(vk);
msg = waitForMessage(500);
assertNull(msg);
} catch (AWTException e) {
e.printStackTrace();
fail();
} catch (InterruptedException e) {
e.printStackTrace();
fail();
} finally {
if (robot != null) {
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.keyRelease(KeyEvent.VK_ALT);
}
}
}
private WinUser.MSG waitForMessage(int timeout) {
WinUser.MSG msg = new WinUser.MSG();
try {
long time = System.currentTimeMillis();
while (true) {
while (INSTANCE.PeekMessage(msg, null, 0, 0, 1)) {
if (msg.message == WinUser.WM_HOTKEY) {
return msg;
}
}
if (System.currentTimeMillis() - time > timeout)
break;
Thread.sleep(50);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Test
public void testGetLastInputInfo() throws Exception {
LASTINPUTINFO plii = new LASTINPUTINFO();
assertEquals(plii.size(), plii.cbSize);
assertTrue(User32.INSTANCE.GetLastInputInfo(plii));
assertTrue(Kernel32.INSTANCE.GetTickCount() >= plii.dwTime);
assertTrue(plii.dwTime > 0);
}
@Test
public final void testRegisterWindowMessage() {
final int msg = User32.INSTANCE.RegisterWindowMessage("RM_UNITTEST");
assertTrue(msg >= 0xC000 && msg <= 0xFFFF);
}
@Test
public final void testMonitorFromPoint() {
int dwFlags = WinUser.MONITOR_DEFAULTTOPRIMARY;
POINT pt = new POINT(0, 0);
assertNotNull(User32.INSTANCE.MonitorFromPoint(pt, dwFlags));
}
@Test
public final void testMonitorFromRect() {
int dwFlags = WinUser.MONITOR_DEFAULTTOPRIMARY;
RECT lprc = new RECT();
assertNotNull(User32.INSTANCE.MonitorFromRect(lprc, dwFlags));
}
@Test
public final void testMonitorFromWindow() {
int dwFlags = WinUser.MONITOR_DEFAULTTOPRIMARY;
HWND hwnd = new HWND();
assertNotNull(User32.INSTANCE.MonitorFromWindow(hwnd, dwFlags));
}
@Test
public final void testGetMonitorInfo() {
HMONITOR hMon = User32.INSTANCE.MonitorFromWindow(User32.INSTANCE.GetDesktopWindow(), WinUser.MONITOR_DEFAULTTOPRIMARY);
assertTrue(User32.INSTANCE.GetMonitorInfo(hMon, new MONITORINFO()).booleanValue());
assertTrue(User32.INSTANCE.GetMonitorInfo(hMon, new MONITORINFOEX()).booleanValue());
}
@Test
public final void testEnumDisplayMonitors() {
assertTrue(User32.INSTANCE.EnumDisplayMonitors(null, null, new MONITORENUMPROC() {
@Override
public int apply(HMONITOR hMonitor, HDC hdc, RECT rect, LPARAM lparam)
{
return 1;
}
}, new LPARAM(0)).booleanValue());
}
@Test
public final void testAdjustWindowRect() {
RECT lpRect = new RECT();
lpRect.left = 100;
lpRect.top = 200;
lpRect.bottom = 300;
lpRect.right = 500;
assertTrue(User32.INSTANCE.AdjustWindowRect(lpRect, new DWORD(WinUser.WS_THICKFRAME), new BOOL(1)).booleanValue());
assertTrue(lpRect.left < 100);
assertTrue(lpRect.top < 200);
assertTrue(lpRect.bottom > 300);
assertTrue(lpRect.right > 500);
}
@Ignore("Locks the workstation")
@Test
public final void testLockWorkStation() {
assertTrue(User32.INSTANCE.LockWorkStation().booleanValue());
}
@Ignore("Shuts down the workstation")
@Test
public final void testExitWindows() {
assertTrue(User32.INSTANCE.ExitWindowsEx(new UINT(WinUser.EWX_LOGOFF), new DWORD(0x00030000)).booleanValue()); //This only tries to log off.
}
@Test
public void testGetIconInfo() throws Exception {
final ICONINFO iconInfo = new ICONINFO();
final HANDLE hImage = User32.INSTANCE.LoadImage(null, new File(
getClass().getResource("/res/test_icon.ico").toURI())
.getAbsolutePath(), WinUser.IMAGE_ICON, 0, 0,
WinUser.LR_LOADFROMFILE);
try {
// obtain test icon from classpath
if (!User32.INSTANCE.GetIconInfo(new HICON(hImage), iconInfo))
throw new Exception(
"Invocation of User32.GetIconInfo() failed: "
+ Kernel32Util.getLastErrorMessage());
iconInfo.read();
} finally {
if (iconInfo.hbmColor != null
&& iconInfo.hbmColor.getPointer() != Pointer.NULL)
GDI32.INSTANCE.DeleteObject(iconInfo.hbmColor);
if (iconInfo.hbmMask != null
&& iconInfo.hbmMask.getPointer() != Pointer.NULL)
GDI32.INSTANCE.DeleteObject(iconInfo.hbmMask);
}
}
@Test
public void testSendMessageTimeout() {
DesktopWindow explorerProc = getWindowByProcessPath("explorer.exe");
assertNotNull(explorerProc);
final DWORDByReference hIconNumber = new DWORDByReference();
LRESULT result = User32.INSTANCE
.SendMessageTimeout(explorerProc.getHWND(),
WinUser.WM_GETICON,
new WPARAM(WinUser.ICON_BIG),
new LPARAM(0),
WinUser.SMTO_ABORTIFHUNG, 500, hIconNumber);
assertNotEquals(0, result);
}
@Test
public void testGetClassLongPtr() {
if (System.getProperty("os.arch", "unknown").equalsIgnoreCase("amd64")) {
DesktopWindow explorerProc = getWindowByProcessPath("explorer.exe");
assertNotNull("Could not find explorer.exe process",
explorerProc);
ULONG_PTR result = User32.INSTANCE
.GetClassLongPtr(explorerProc.getHWND(),
WinUser.GCLP_HMODULE);
assertNotEquals(0, result.intValue());
} else {
System.err.println("GetClassLongPtr only supported on x64");
}
}
@Test
public void testGetDesktopWindow() {
HWND desktopWindow = User32.INSTANCE.GetDesktopWindow();
assertNotNull("Failed to get desktop window HWND", desktopWindow);
}
@Test
public void testPrintWindow() {
boolean pwResult = User32.INSTANCE.PrintWindow(null, null, 0);
assertFalse("PrintWindow result should be false", pwResult);
assertEquals("GetLastError should be ERROR_INVALID_WINDOW_HANDLE.", WinError.ERROR_INVALID_WINDOW_HANDLE, Native.getLastError());
}
@Test
public void testIsWindowEnabled() {
boolean iweResult = User32.INSTANCE.IsWindowEnabled(null);
assertFalse("IsWindowEnabled result should be false", iweResult);
assertEquals("GetLastError should be ERROR_INVALID_WINDOW_HANDLE.", WinError.ERROR_INVALID_WINDOW_HANDLE, Native.getLastError());
}
@Test
public void testIsWindow() {
boolean iwResult = User32.INSTANCE.IsWindow(null);
assertFalse("IsWindow result should be false", iwResult);
assertEquals("GetLastError should be ERROR_SUCCESS.", WinError.ERROR_SUCCESS, Native.getLastError());
}
@Test
public void testFindWindowEx() {
HWND result = User32.INSTANCE.FindWindowEx(null, null, null, null);
assertNotNull("FindWindowEx result should not be null", result);
assertEquals("GetLastError should be ERROR_SUCCESS.", WinError.ERROR_SUCCESS, Native.getLastError());
}
@Test
public void testGetAncestor() {
HWND desktopWindow = User32.INSTANCE.GetDesktopWindow();
assertNotNull("Failed to get desktop window HWND", desktopWindow);
HWND result = User32.INSTANCE.GetAncestor(desktopWindow, WinUser.GA_PARENT);
assertNull("GetAncestor result should be null", result);
assertEquals("GetLastError should be ERROR_SUCCESS.", WinError.ERROR_SUCCESS, Native.getLastError());
}
@Test
public void testGetCursorPos() {
POINT cursorPos = new POINT();
boolean result = User32.INSTANCE.GetCursorPos(cursorPos);
assertTrue("GetCursorPos should return true", result);
assertTrue("X coordinate in POINT should be >= 0", cursorPos.x >= 0);
assertTrue("Y coordinate in POINT should be >= 0", cursorPos.y >= 0);
}
@Test
public void testSetCursorPos() {
POINT cursorPos = new POINT();
boolean result = User32.INSTANCE.GetCursorPos(cursorPos);
assertTrue("GetCursorPos should return true", result);
assertTrue("X coordinate in POINT should be >= 0", cursorPos.x >= 0);
boolean scpResult = User32.INSTANCE.SetCursorPos(cursorPos.x - 20, cursorPos.y);
assertTrue("SetCursorPos should return true", scpResult);
POINT cursorPos2 = new POINT();
boolean result2 = User32.INSTANCE.GetCursorPos(cursorPos2);
assertTrue("GetCursorPos should return true", result2);
assertTrue("X coordinate in POINT should be original cursor position - 20", cursorPos2.x == cursorPos.x - 20);
}
@Test
public void testSetWinEventHook() {
HANDLE result = User32.INSTANCE.SetWinEventHook(0, 0, null, null, 0, 0, 0);
assertNull("SetWinEventHook result should be null", result);
assertEquals("GetLastError should be ERROR_INVALID_FILTER_PROC.", WinError.ERROR_INVALID_FILTER_PROC, Native.getLastError());
}
@Test
public void testUnhookWinEvent() {
boolean iwResult = User32.INSTANCE.UnhookWinEvent(null);
assertFalse("UnhookWinEvent result should be false", iwResult);
assertEquals("GetLastError should be ERROR_INVALID_HANDLE.", WinError.ERROR_INVALID_HANDLE, Native.getLastError());
}
@Test
public void testCopyIcon() {
HICON result = User32.INSTANCE.CopyIcon(null);
assertNull("CopyIcon result should be false", result);
assertEquals("GetLastError should be ERROR_INVALID_CURSOR_HANDLE.", WinError.ERROR_INVALID_CURSOR_HANDLE, Native.getLastError());
}
@Test
public void testGetClassLong() {
int result = User32.INSTANCE.GetClassLong(null, 0);
assertEquals("GetClassLong result should be 0", 0, result);
assertEquals("GetLastError should be ERROR_INVALID_WINDOW_HANDLE.", WinError.ERROR_INVALID_WINDOW_HANDLE, Native.getLastError());
}
@Test
public void testGetActiveWindow() {
HWND result = User32.INSTANCE.GetActiveWindow();
assertNull("GetActiveWindow result should be null", result);
assertEquals("GetLastError should be ERROR_SUCCESS.", WinError.ERROR_SUCCESS, Native.getLastError());
}
@Test
public void testSendMessage() {
DesktopWindow explorerProc = getWindowByProcessPath("explorer.exe");
assertNotNull(explorerProc);
LRESULT result = User32.INSTANCE
.SendMessage(explorerProc.getHWND(),
WinUser.WM_USER,
new WPARAM(124),
new LPARAM(12345));
assertNotEquals(0, result);
}
}