|
Hi Daniel,
See if something like this would work for you:
BOOL RegGetPreferredUILanguages(const PSID p, std::vector<std::wstring>& out_vector)
{
LPWSTR szSid = nullptr;
BOOL bRet = FALSE;
if (ConvertSidToStringSidW(p, &szSid))
{
HKEY k;
constexpr DWORD size = 256;
WCHAR buffer[size];
wsprintf(buffer, L"%s\\Control Panel\\Desktop", szSid);
LSTATUS status = RegOpenKeyW(HKEY_USERS, buffer, &k);
if (ERROR_SUCCESS == status)
{
DWORD dwNeeded = 0;
std::vector<WCHAR> multi_sz;
RegGetValue(k, nullptr, L"PreferredUILanguages", RRF_RT_REG_MULTI_SZ, nullptr, nullptr, &dwNeeded);
multi_sz.resize(dwNeeded / sizeof(WCHAR));
if (ERROR_SUCCESS == RegGetValue(k, nullptr, L"PreferredUILanguages", RRF_RT_REG_MULTI_SZ | RRF_ZEROONFAILURE, nullptr, &multi_sz[0], &dwNeeded))
{
std::wistringstream ss(std::wstring(multi_sz.begin(), multi_sz.end()));
std::wstring lang;
while (std::getline(ss, lang, L'\0'))
{
if(lang.length())
out_vector.push_back(lang);
}
bRet = TRUE;
}
RegCloseKey(k);
}
LocalFree(szSid);
}
return bRet;
}
You would use it something like this:
std::vector<std::wstring> langs;
RegGetPreferredUILanguages(pData->Sid, langs);
UINT index = 1;
for (auto lang : langs)
{
wprintf(L"User Preferred UI Language at index %u is: %s \n", index++, lang.c_str());
}
My understanding is that the first entry is the current preferred UI language.
I have some additional comments:
1.) If you are doing this in a corporate environment then you might want to check for the domain/machine policy[^] first. The security policy is located in the registry at HKLM\Software\Policies\Microsoft\MUI\Settings and you would need to honor that.
2.) You will need to use a multi-tiered fallback. The HKCU\Control Panel\Desktop\PreferredUILanguages key will not exist if the user has not setup MUI and a default language. I believe you need fallback in this order:
* HKCU\Control Panel\Desktop\PreferredUILanguages (User prference) **might not be present**
* HKCU\Control Panel\Control Panel\International\Locale (User default) **always present**
* HKLM\SYSTEM\CurrentControlSet\Control\MUI\Settings\PreferredUILanguages (MUI default) **might not be present**
* HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language\Default **always present**
* HKLM\SYSTEM\CurrentControlSet\Control\Nls\Language\InstallLanguage **always present**
The MUI keys are only present if the user has enabled MUI and installed multiple language packs. You can convert from LCID to locale with the LCIDToLocaleName function[^]. And use the LocaleNameToLCID function[^] for the reverse.
Here is how you would use them: (with the provided sample code)
constexpr DWORD s = 256;
WCHAR buffer[s] = {0};
WCHAR name[LOCALE_NAME_MAX_LENGTH] = {0};
if (RegGetInternationaliations(pData->Sid, L"Locale", buffer, s))
{
wprintf(L"Default User Hex locale: %s\n", buffer);
DWORD id = wcstol(buffer, NULL, 16);
wprintf(L"Default User Dec locale: %u\n", id);
LCIDToLocaleName(id, name, LOCALE_NAME_MAX_LENGTH, LOCALE_ALLOW_NEUTRAL_NAMES);
wprintf(L"Default User Locale Name: %s\n", name);
}
Let me know if this works out for you.
Best Wishes,
-David Delaune
|
|
|
|
|
Hi David,
Thank you very much for this lucid explanation of the MUI Registry info. and how to extract it. I'm sure that I'll be able to build something that serves from this.
Whatever you did in the past or are doing at the moment, you have obviously mastered an arcane part of Windows programming. Thanks again.
Best Wishes,
Daniel Pfeffer
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
David,
Thank you again for this solution. It works perfectly, and enabled me to answer a client's request.
This is a work project, so I can't for obvious reasons, share it with you, but if Legal at work permits, would you mind my using my version of the code as a basis for a short CodeProject article?
I would, of course, give you full credit for this solution.
Thanks again,
Daniel
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
Hello Daniel,
I apologize for the slow response. I haven't been on codeproject.com in a few weeks.
All of the sample code that I have written here in this forum is now in the public domain. You may use, modify and share it without restriction. Attribution is unnecessary. Keep in mind that it is a code sample and there is no guarantee of completeness or accuracy.
It looks like I am going to be mostly unavailable for the next few weeks. So I might not have much time for internet forums.. I should have more time in November.
Looking at the above code do see a potential political issue for your geo region. Make sure that you understand what "neutral names" implies with the LOCALE_ALLOW_NEUTRAL_NAMES flag. Or just remove it.
I also see a potential divide-by-zero surrounding the DWORD dwNeeded where the length comes from the registry, might want to add a if(dwNeeded) around that. It's an imperfect code sample, so you might want to polish it up a bit.
Best Wishes,
-David Delaune
|
|
|
|
|
Dear David,
Thanks for the release to public domain, for the warning of incompleteness, and especially for the warning re potential political issues - I never even considered the last... As I work for a multi-national (Western Digital), I wouldn't want my work banned in certain countries...
Best Regards,
Daniel Pfeffer
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
I am developing a service for a client, and must display a system-modal message box from the service. I would like my message box to look similar to other notifications displayed by the system (e.g. low power notifications, Windows Update notifications, etc.)
I can display an message box from the service in the standard Windows format. Is there an API to display windows in this format, or must I write it myself?
Thanks.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
There is no System Modal anymore, so you will have to find some other way of doing what you want. Take a look at Security Blackout Window[^] which may be of use, or provide ideas.
|
|
|
|
|
Thanks, this looks like what I need.
Freedom is the freedom to say that two plus two make four. If that is granted, all else follows.
-- 6079 Smith W.
|
|
|
|
|
When I search on the Internet, I find millions of web pages explaining how to check if a .exe-file is running, from within a .bat-file. However, I can't find a single page explaining what to do if you have several .exe-files with identical names and you only want to check an .exe-file that resides in a specific folder. Can anybody please help me, what's the way to detect if the file C:\MyProject\bin\release\MyApplication.exe is running, but at the same time completely ignore C:\MyProject\bin\debug\MyApplication.exe?
|
|
|
|
|
|
Victor Nijegorodov wrote: BTW, what do you mean by "... from within a .bat-file."? I want to do it in bat-file language (the language you type in the command prompt C:\Windows\System32\cmd.exe)
|
|
|
|
|
@echo off
set "workdir=C:\MyProject\bin\release"
set "workdir=%workdir:\=\\%"
setlocal enableDelayedExpansion
for /f "usebackq tokens=* delims=" %%a in (`
wmic process where 'CommandLine like "%%!workdir!%%" and not CommandLine like "%%RuntimeBroker%%"' get CommandLine^,ProcessId /format:value
`) do (
for /f "tokens=* delims=" %%G in ("%%a") do (
if "%%G" neq "" (
rem echo %%G
set "%%G"
rem echo !ProcessId!
goto :TheApplicationIsRunning
)
)
)
echo The application is not running
exit /B
:TheApplicationIsRunning
echo The application is running
exit /B
|
|
|
|
|
|
|
Congrats!
|
|
|
|
|
|
That's a lot of magic
If prefer to write my own.
Bastard Programmer from Hell
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Greetings to everyone. On my Windows 10 PC, I use Avast AV for an extra layer of protection on Windows Defender. But with the installation of Avast AV, the Avast Secure browser was installed. I don't really use it, so if I uninstall Avast Secure Browser, will it cause any problems with Avast AV on my PC? Please, give me some suggestions about this. Any kind of reply would be greatly appreciated.
|
|
|
|
|
In playing around with some basic GDI stuff, I had the need to draw an object in the middle of the main window and then when a button is clicked, draw that object progressively closer to some corner (in my code below, the object moves to the lower right corner, but ultimately I'd like it to move to any corner). So my question is: how to calculate those new X/Y coordinates with each button click?
The initial X/Y coordinates are calculated in response to WM_SIZE like:
case WM_SIZE:
nScreenWidth = LOWORD(lParam);
nScreenHeight = HIWORD(lParam);
nX = (nScreenWidth - nObjectWidth) / 2;
nY = (nScreenHeight - nObjectHeight) / 2;
break; When the button is clicked, new X/Y coordinates are "calculated" like:
case WM_COMMAND:
if (LOWORD(wParam) == ID_BUTTON)
{
nX += 20;
nY += 10;
InvalidateRect(hWnd, NULL, TRUE);
}
break; The object is drawn in response to WM_PAINT like:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break; You can count on one hand how many GDI projects I've done in the past (and have fingers left over) so I'm walking in somewhat uncharted territory for me. As a visual aide, if you envision a straight line drawn from the middle of the screen to one of its corners, each pixel of that line is on an X/Y coordinate. What would that calculation look like?
Thank you.
DC
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
modified 11-Jan-21 15:00pm.
|
|
|
|
|
David Crow wrote: What would that calculation look like? I don't think it is a straightforward calculation as you would need to move more pixels in the horizontal direction than the vertical (assuming landscape view). If you use GDI+ it is slightly easier as you can use float values for the points and Windows does the smoothing. But I am not 100% clear as to the actual problem. And incidentally, as far as handling messages and repainting, your code all looks correct.
|
|
|
|
|
I started reading about Bresenham's line drawing algorithm last night but haven't had time yet to put anything in place.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"You can easily judge the character of a man by how he treats those who can do nothing for him." - James D. Miles
|
|
|
|
|
Sixty years ago my brain might have been able to handle that. 
|
|
|
|
|
Here is a very simple method of moving the box:
You need to start by calculating the value of the slope ratio between horizontal and vertical size of the Window's client area. You need this as a floating point value as it will be used to calculate positions further on.
Declare a static float value named slopeRatio , and add the following code to either the initialisation (e.g. WM_CREATE), or whenever the Window is resized (WM_SIZE).
RECT rcClient;
GetClientRect(hWnd, &rcClient);
float horiz = (float)rcClient.right; float vert = (float)rcClient.bottom; slopeRatio = horiz / vert;
Then when you need to calculate the new X and Y positions of your drawing (after the button press) do the following:
currentX += 30; tempY = (float)currentX / slopeRatio;
currentY = (int)tempY;
InvalidateRect(hWnd, nullptr, TRUE);
|
|
|
|
|
Does anyone here have to maintain Labview Projects? If so what are thoughts and concerns?
|
|
|
|
|
This[^] looks to be a great place for you to get started.
|
|
|
|
|