Skip to content

Commit dc0c453

Browse files
authored
Merge pull request #1242 from heldplayer/user32-callwindowproc
Add CallWindowProc to User32
2 parents 7cdc04b + 94c98c0 commit dc0c453

File tree

3 files changed

+84
-0
lines changed

3 files changed

+84
-0
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Features
1010
* [#1217](https://github.com/java-native-access/jna/pull/1217): Add mappings for AIX `Perfstat` library to `c.s.j.p.unix.aix` - [@dbwiddis](https://github.com/dbwiddis).
1111
* [#1231](https://github.com/java-native-access/jna/pull/1231): The test suite can now be executed on Windows using either ANSI or UNICODE win32 API by passing `-Dw32.ascii=true/false` to ant. Previously, UNICODE was always used. - [@T-Svensson](https://github.com/T-Svensson/)
1212
* [#1237](https://github.com/java-native-access/jna/pull/1237): *Experimental:* Add artifacts that make jna and jna-platform named modules (provide `module-info.class`). The new artifacts are named `jna-jpms.jar` and `jna-platform-jpms.jar` - [@matthiasblaesing](https://github.com/matthiasblaesing).
13+
* [#1242](https://github.com/java-native-access/jna/pull/1242): Add CallWindowProc to User32 - [@heldplayer](https://github.com/heldplayer).
1314

1415
Bug Fixes
1516
---------

contrib/platform/src/com/sun/jna/platform/win32/User32.java

+32
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,38 @@ HWND CreateWindowEx(int dwExStyle, String lpClassName,
16061606
*/
16071607
boolean GetClassInfoEx(HINSTANCE hinst, String lpszClass, WNDCLASSEX lpwcx);
16081608

1609+
/**
1610+
* Passes message information to the specified window procedure.
1611+
*
1612+
* @param lpPrevWndFunc
1613+
* The previous window procedure. If this value is obtained by calling
1614+
* the GetWindowLong function with the nIndex parameter set to GWL_WNDPROC
1615+
* or DWL_DLGPROC, it is actually either the address of a window or dialog
1616+
* box procedure, or a special internal value meaningful only to
1617+
* CallWindowProc.
1618+
*
1619+
* @param hWnd
1620+
* A handle to the window procedure to receive the message.
1621+
*
1622+
* @param Msg
1623+
* The message.
1624+
*
1625+
* @param wParam
1626+
* Additional message information. The content of this parameter
1627+
* depends on the value of the Msg parameter.
1628+
*
1629+
* @param lParam
1630+
* Additional message information. The content of this parameter
1631+
* depends on the value of the Msg parameter.
1632+
*
1633+
* @return The return value is the result of the message processing and depends on
1634+
* the message.
1635+
* <p>
1636+
* If the function fails, the return value is zero. To get extended
1637+
* error information, call {@link Kernel32#GetLastError}.
1638+
*/
1639+
LRESULT CallWindowProc(Pointer lpPrevWndFunc, HWND hWnd, int Msg, WPARAM wParam, LPARAM lParam);
1640+
16091641
/**
16101642
* Calls the default window procedure to provide default processing for any
16111643
* window messages that an application does not process. This function

contrib/platform/test/com/sun/jna/platform/win32/User32WindowMessagesTest.java

+51
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.junit.Test;
3232
import org.junit.runner.JUnitCore;
3333

34+
import com.sun.jna.CallbackReference;
3435
import com.sun.jna.Native;
3536
import com.sun.jna.Pointer;
3637
import com.sun.jna.Structure;
@@ -106,6 +107,24 @@ public void testWindowMesssages() {
106107
log("User Message sent to hooked proc " + hwndPing + ", result = " + result);
107108
assertEquals(0, result.intValue());
108109

110+
// DEMO 4 : subclass the window to return a different value when receiving MSG_SIMPLE_CODE
111+
// First make sure we remove the hook
112+
User32.INSTANCE.UnhookWindowsHookEx(hook);
113+
hook = null;
114+
115+
subclassProc(hwndPing);
116+
result = User32.INSTANCE.SendMessage(hwndPing, WinUser.WM_USER, new WPARAM(MSG_SIMPLE_CODE),
117+
new LPARAM(MSG_SIMPLE_VAL));
118+
log("User Message sent to subclassed " + hwndPing + ", result = " + result);
119+
assertEquals(0xC0FE, result.intValue());
120+
121+
// Then we check if this still works with a hooked proc as well
122+
hook = hookwinProc(hwndPing);
123+
result = User32.INSTANCE.SendMessage(hwndPing, WinUser.WM_USER, new WPARAM(MSG_HOOKED_CODE),
124+
new LPARAM(MSG_HOOKED_VAL));
125+
log("User Message sent to hooked and subclassed proc " + hwndPing + ", result = " + result);
126+
assertEquals(0, result.intValue());
127+
109128
// Waits e few moment before shutdown message.
110129
sleepCurrThread(3000);
111130

@@ -395,6 +414,38 @@ public LRESULT callback(int nCode, WPARAM wParam, LPARAM lParam) {
395414
return User32.INSTANCE.SetWindowsHookEx(WinUser.WH_CALLWNDPROC, hookProc, hInst, threadtoHook);
396415
}
397416

417+
private void subclassProc(HWND hwndToSubclass) {
418+
class SubClassedWindowProc implements WindowProc {
419+
private Pointer oldWindowProc;
420+
421+
@Override
422+
public LRESULT callback(HWND hwnd, int uMsg, WPARAM wParam, LPARAM lParam) {
423+
if (uMsg == WinUser.WM_USER) {
424+
log(hwnd + " - subclass received a WM_USER message with code : '" + wParam + "' and value : '" + lParam
425+
+ "'");
426+
427+
if (wParam.intValue() == MSG_SIMPLE_CODE) {
428+
// We also want to be sure the value is still the same passed
429+
assertEqualsForCallbackExecution(MSG_SIMPLE_VAL, lParam.intValue());
430+
431+
return new LRESULT(0xC0FE);
432+
}
433+
}
434+
if (this.oldWindowProc != null) {
435+
return User32.INSTANCE.CallWindowProc(this.oldWindowProc, hwnd, uMsg, wParam, lParam);
436+
} else {
437+
// In case the old pointer has not yet been set due to for example a race condition,
438+
// send the message to the default handler instead
439+
return User32.INSTANCE.DefWindowProc(hwnd, uMsg, wParam, lParam);
440+
}
441+
}
442+
}
443+
444+
SubClassedWindowProc subclass = new SubClassedWindowProc();
445+
subclass.oldWindowProc = User32.INSTANCE.SetWindowLongPtr(hwndToSubclass, WinUser.GWL_WNDPROC,
446+
CallbackReference.getFunctionPointer(subclass));
447+
}
448+
398449
/**
399450
* Gets the last error.
400451
*

0 commit comments

Comments
 (0)