Skip to content

Commit 2e96df4

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
1 parent e96f301 commit 2e96df4

File tree

4 files changed

+146
-2
lines changed

4 files changed

+146
-2
lines changed

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

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
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;
29+
import com.sun.jna.StringArray;
3130
import com.sun.jna.ptr.IntByReference;
3231
import com.sun.jna.ptr.PointerByReference;
3332
import com.sun.jna.win32.StdCallLibrary;
@@ -4387,4 +4386,76 @@ Pointer VirtualAllocEx(HANDLE hProcess, Pointer lpAddress, SIZE_T dwSize,
43874386
* </p>
43884387
*/
43894388
boolean VirtualUnlock(Pointer lpAddress, SIZE_T dwSize);
4389+
4390+
/**
4391+
* Sets the user interface language for the current thread.
4392+
*
4393+
* <p>
4394+
* Windows Vista and later: This function cannot clear the thread preferred UI languages list. Your MUI application
4395+
* should call SetThreadPreferredUILanguages to clear the language list.
4396+
* </p>
4397+
* <p>
4398+
* Windows XP: This function is limited to allowing the operating system to identify and set a value that is safe
4399+
* to use on the Windows console.
4400+
* </p>
4401+
*
4402+
* @param LangId Language identifier for the user interface language for the thread.
4403+
*
4404+
* @return Returns the input language identifier if successful.
4405+
* If the input identifier is nonzero, the function returns that value.
4406+
* If the language identifier is 0, the function always succeeds and returns
4407+
* the identifier of the language that best supports the Windows console.
4408+
*
4409+
* <p>
4410+
* When a thread is created, the thread user interface language setting is empty and the user interface for
4411+
* the thread is displayed in the user-selected language. This function enables the application to change
4412+
* the user interface language for the current running thread.
4413+
* </p>
4414+
* <p>
4415+
* Windows Vista and later: Calling this function and specifying 0 for the language identifier is identical
4416+
* to calling SetThreadPreferredUILanguages with the MUI_CONSOLE_FILTER flag set. If the application specifies
4417+
* a valid nonzero language identifier, the function sets a particular user interface language for the thread.
4418+
* </p>
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 TRUE if the function succeeds or FALSE otherwise.
4450+
*/
4451+
boolean SetThreadPreferredUILanguages(DWORD dwFlags, StringArray pwszLanguagesBuffer, ULONGByReference 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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.sun.jna.Memory;
3737
import com.sun.jna.Native;
3838
import com.sun.jna.Pointer;
39+
import com.sun.jna.StringArray;
3940
import com.sun.jna.platform.win32.WinNT.HANDLE;
4041
import com.sun.jna.platform.win32.WinNT.HANDLEByReference;
4142
import com.sun.jna.platform.win32.WinNT.HRESULT;
@@ -299,6 +300,31 @@ public static String getLastErrorMessage(int primaryLangId, int sublangId) {
299300
.GetLastError(), primaryLangId, sublangId);
300301
}
301302

303+
/**
304+
* Sets the user interface language for the current thread using primary and sub-language identifiers.
305+
*
306+
* @param langId Language identifier.
307+
*
308+
* @return Returns the input language identifier if successful.
309+
*/
310+
public static int setThreadUILanguage(int langId) {
311+
return Kernel32.INSTANCE.SetThreadUILanguage(langId);
312+
}
313+
314+
/**
315+
* Sets the thread preferred UI languages for the current thread.
316+
*
317+
* @param languages String array of preferred languages to set.
318+
*
319+
* @return Returns TRUE if the function succeeds or FALSE otherwise.
320+
*/
321+
public static boolean setThreadPreferredUILanguages(String[] languages) {
322+
DWORD dwFlags = new DWORD(0);
323+
StringArray pwszLanguagesBuffer = new StringArray(languages);
324+
ULONGByReference pulNumLanguages = new ULONGByReference(new ULONG(languages.length));
325+
return Kernel32.INSTANCE.SetThreadPreferredUILanguages(dwFlags, pwszLanguagesBuffer, pulNumLanguages);
326+
}
327+
302328
/**
303329
* Return the path designated for temporary files.
304330
*

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@
6363
import com.sun.jna.NativeMappedConverter;
6464
import com.sun.jna.Platform;
6565
import com.sun.jna.Pointer;
66+
import com.sun.jna.StringArray;
67+
6668
import com.sun.jna.platform.win32.BaseTSD.SIZE_T;
6769
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
6870
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTRByReference;
@@ -2099,4 +2101,33 @@ public void testVirtualLockUnlock() {
20992101
// Unlocking an unlocked region should fail
21002102
assertFalse(Kernel32.INSTANCE.VirtualUnlock(mem, new SIZE_T(4096)));
21012103
}
2104+
2105+
public void testSetThreadUILanguage() {
2106+
int langId = 0x0409; // English (United States)
2107+
int result = Kernel32.INSTANCE.SetThreadUILanguage(langId);
2108+
if (result == 0) {
2109+
int errorCode = Kernel32.INSTANCE.GetLastError();
2110+
fail("SetThreadUILanguage failed with error code " + errorCode);
2111+
}
2112+
assertEquals(langId, result);
2113+
}
2114+
2115+
public void testSetThreadPreferredUILanguages() {
2116+
WinDef.DWORD dwFlags = new WinDef.DWORD(0);
2117+
StringArray pwszLanguagesBuffer = (StringArray) StringArray.NULL;
2118+
WinDef.ULONGByReference pulNumLanguages = new WinDef.ULONGByReference();
2119+
boolean result = Kernel32.INSTANCE.SetThreadPreferredUILanguages(dwFlags, pwszLanguagesBuffer, pulNumLanguages);
2120+
assertTrue(result);
2121+
}
2122+
2123+
public void testGetThreadUILanguage() {
2124+
int langId = 0x0409; // English (United States)
2125+
int result = Kernel32.INSTANCE.SetThreadUILanguage(langId);
2126+
if (result == 0) {
2127+
int errorCode = Kernel32.INSTANCE.GetLastError();
2128+
fail("SetThreadUILanguage failed with error code " + errorCode);
2129+
}
2130+
int uiLangId = Kernel32.INSTANCE.GetThreadUILanguage();
2131+
assertEquals(langId, uiLangId);
2132+
}
21022133
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,22 @@ public void testFormatMessageFromErrorCodeWithNonEnglishLocale() {
171171
}
172172
}
173173

174+
public void testSetThreadUILanguage() {
175+
int langId = 0x0409; // English (United States)
176+
int result = Kernel32Util.setThreadUILanguage(langId);
177+
if (result == 0) {
178+
int errorCode = Kernel32.INSTANCE.GetLastError();
179+
fail("SetThreadUILanguage failed with error code " + errorCode);
180+
}
181+
assertEquals(langId, result);
182+
}
183+
184+
public void testSetThreadPreferredUILanguages() {
185+
String[] languages = {};
186+
boolean result = Kernel32Util.setThreadPreferredUILanguages(languages);
187+
assertTrue(result);
188+
}
189+
174190
public void testGetTempPath() {
175191
assertTrue(Kernel32Util.getTempPath().length() > 0);
176192
}

0 commit comments

Comments
 (0)