Skip to content

Commit f9e5f5b

Browse files
committed
Set user interface language for current thread
- Bind SetThreadUILanguage, SetThreadPreferredUILanguages and GetThreadUILanguage in c.s.j.p.win32.Kernel32 - test is written - update CHANGES.md - remove unused imports in Kernel32.java
1 parent e96f301 commit f9e5f5b

File tree

5 files changed

+121
-2
lines changed

5 files changed

+121
-2
lines changed

CHANGES.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Next Release (5.14.0)
77

88
Features
99
--------
10+
* [#1514](https://github.com/java-native-access/jna/pull/1514): Add `SetThreadUILanguage`, `SetThreadPreferredUILanguages` and `GetThreadUILanguage` in `c.s.j.p.win32.Kernel32` - [@overpathz](https://github.com/overpathz).
1011

1112
Bug Fixes
1213
---------

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

+73-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626
import com.sun.jna.LastErrorException;
2727
import com.sun.jna.Native;
2828
import com.sun.jna.Pointer;
29-
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
30-
import com.sun.jna.platform.win32.WinNT.HANDLE;
3129
import com.sun.jna.ptr.IntByReference;
3230
import com.sun.jna.ptr.PointerByReference;
3331
import com.sun.jna.win32.StdCallLibrary;
@@ -4387,4 +4385,77 @@ Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize,
43874385
* </p>
43884386
*/
43894387
boolean VirtualUnlock(Pointer lpAddress, SIZE_T dwSize);
4388+
4389+
/**
4390+
* Sets the user interface language for the current thread.
4391+
*
4392+
* <p>
4393+
* Windows Vista and later: This function cannot clear the thread preferred UI languages list. Your MUI application
4394+
* should call SetThreadPreferredUILanguages to clear the language list.
4395+
* </p>
4396+
* <p>
4397+
* Windows XP: This function is limited to allowing the operating system to identify and set a value that is safe
4398+
* to use on the Windows console.
4399+
* </p>
4400+
*
4401+
* <p><strong>Remarks</strong></p>
4402+
* <p>
4403+
* When a thread is created, the thread user interface language setting is empty and the user interface for
4404+
* the thread is displayed in the user-selected language. This function enables the application to change
4405+
* the user interface language for the current running thread.
4406+
* </p>
4407+
* <p>
4408+
* Windows Vista and later: Calling this function and specifying 0 for the language identifier is identical
4409+
* to calling SetThreadPreferredUILanguages with the MUI_CONSOLE_FILTER flag set. If the application specifies
4410+
* a valid nonzero language identifier, the function sets a particular user interface language for the thread.
4411+
* </p>
4412+
*
4413+
* @param LangId Language identifier for the user interface language for the thread.
4414+
*
4415+
* @return Returns the input language identifier if successful.
4416+
* If the input identifier is nonzero, the function returns that value.
4417+
* If the language identifier is 0, the function always succeeds and returns
4418+
* the identifier of the language that best supports the Windows console.
4419+
*
4420+
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-setthreaduilanguage">SetThreadUILanguage</a>
4421+
*/
4422+
int SetThreadUILanguage(int LangId);
4423+
4424+
/**
4425+
* Sets the thread preferred UI languages for the current thread.
4426+
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/intl/user-interface-language-management">User Interface Language Management</a>
4427+
*
4428+
* @param dwFlags Flags identifying format and filtering for the languages to set.
4429+
*
4430+
* <p>
4431+
* The following format flags specify the language format to use for the thread preferred UI languages.
4432+
* The flags are mutually exclusive, and the default is MUI_LANGUAGE_NAME.
4433+
* </p>
4434+
* <p>
4435+
* We recommend that you use MUI_LANGUAGE_NAME instead of MUI_LANGUAGE_ID.
4436+
* </p>
4437+
*
4438+
* @param pwszLanguagesBuffer Pointer to a double null-terminated multi-string buffer that contains an ordered,
4439+
* null-delimited list, in the format specified by dwFlags.
4440+
* <p>
4441+
* To clear the thread preferred UI languages list, an application sets this parameter to a null string or an empty
4442+
* double null-terminated string. If an application clears a language list, it should specify either a format flag
4443+
* or 0 for the dwFlags parameter.
4444+
* </p>
4445+
*
4446+
* @param pulNumLanguages Pointer to the number of languages that the function has set in the thread preferred UI languages list.
4447+
* When the application specifies one of the filtering flags, the function must set this parameter to NULL.
4448+
*
4449+
* @return Returns {@code true} if the function succeeds or {@code false} otherwise.
4450+
*/
4451+
boolean SetThreadPreferredUILanguages(int dwFlags, String[] pwszLanguagesBuffer, IntByReference pulNumLanguages);
4452+
4453+
/**
4454+
* Returns the language identifier of the first user interface language for the current thread.
4455+
*
4456+
* @return Returns the identifier for a language explicitly associated with the thread by SetThreadUILanguage or
4457+
* SetThreadPreferredUILanguages. Alternatively, if no language has been explicitly associated with the
4458+
* current thread, the identifier can indicate a user or system user interface language.
4459+
*/
4460+
int GetThreadUILanguage();
43904461
}

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

+12
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,18 @@ public static String getLastErrorMessage(int primaryLangId, int sublangId) {
299299
.GetLastError(), primaryLangId, sublangId);
300300
}
301301

302+
/**
303+
* Sets the thread preferred UI languages for the current thread.
304+
*
305+
* @param languages String array of preferred languages to set.
306+
*
307+
* @return Returns TRUE if the function succeeds or FALSE otherwise.
308+
*/
309+
public static boolean setThreadPreferredUILanguages(String[] languages) {
310+
IntByReference pulNumLanguages = new IntByReference(languages.length);
311+
return Kernel32.INSTANCE.SetThreadPreferredUILanguages(0, languages, pulNumLanguages);
312+
}
313+
302314
/**
303315
* Return the path designated for temporary files.
304316
*

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

+29
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import com.sun.jna.NativeMappedConverter;
6464
import com.sun.jna.Platform;
6565
import com.sun.jna.Pointer;
66+
6667
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
6768
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
6869
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTRByReference;
@@ -2099,4 +2100,32 @@ public void testVirtualLockUnlock() {
20992100
// Unlocking an unlocked region should fail
21002101
assertFalse(Kernel32.INSTANCE.VirtualUnlock(mem, new SIZE_T(4096)));
21012102
}
2103+
2104+
public void testSetThreadUILanguage() {
2105+
int langId = 0x0409; // English (United States)
2106+
int result = Kernel32.INSTANCE.SetThreadUILanguage(langId);
2107+
if (result == 0) {
2108+
int errorCode = Kernel32.INSTANCE.GetLastError();
2109+
fail("SetThreadUILanguage failed with error code " + errorCode);
2110+
}
2111+
assertEquals(langId, result);
2112+
}
2113+
2114+
public void testSetThreadPreferredUILanguages() {
2115+
String[] languages = {};
2116+
IntByReference pulNumLanguages = new IntByReference(languages.length);
2117+
boolean result = Kernel32.INSTANCE.SetThreadPreferredUILanguages(0, languages, pulNumLanguages);
2118+
assertTrue(result);
2119+
}
2120+
2121+
public void testGetThreadUILanguage() {
2122+
int langId = 0x0409; // English (United States)
2123+
int result = Kernel32.INSTANCE.SetThreadUILanguage(langId);
2124+
if (result == 0) {
2125+
int errorCode = Kernel32.INSTANCE.GetLastError();
2126+
fail("SetThreadUILanguage failed with error code " + errorCode);
2127+
}
2128+
int uiLangId = Kernel32.INSTANCE.GetThreadUILanguage();
2129+
assertEquals(langId, uiLangId);
2130+
}
21022131
}

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

+6
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,12 @@ public void testFormatMessageFromErrorCodeWithNonEnglishLocale() {
171171
}
172172
}
173173

174+
public void testSetThreadPreferredUILanguages() {
175+
String[] languages = {};
176+
boolean result = Kernel32Util.setThreadPreferredUILanguages(languages);
177+
assertTrue(result);
178+
}
179+
174180
public void testGetTempPath() {
175181
assertTrue(Kernel32Util.getTempPath().length() > 0);
176182
}

0 commit comments

Comments
 (0)