I ran into a reproducible bug which doesn't really make sense to me. Hopefully someone knows more about the internals of keyboard input under Windows (I'm using Windows 7) and can point me in the right direction on how to solve it. As it stands now I don't really know where I should start to look.
My application creates a global keyboard hook, using the MouseKeyboardActivityMonitor library. This was working fine for me, but I quickly received bug reports from people using different keyboard input languages. When they write letters with accents, e.g. ë and ê, they show up as ¨¨e and ^^e respectively. This bug is also reported on the library's website, but hasn't been resolved yet.
To try to reproduce the bug I set up an alternate input language 'Dutch (Belgium)' next to my existing 'English (United States)'. After some toying around I discovered the following:
The bug doesn't occurs when the application which installs the hook has focus, and language is set to 'English (United States)'. Writing in any other application (e.g. notepad) and using 'Dutch (Belgium)' to write the special characters work. The bug does occur when the application which installs the hook has focus, and language is set to 'Dutch (Belgium)'.
I am looking for any clue as how the two are related. Perhaps I need to introduce some extra checks in the keyboard hook library? The source code of the keyboard hook is available on line.
It seems that the input language is not updated in your application. Looking at the source code of the library that you are using, it seems that they use this call to get the correct keyboard layout:
internal static extern uint GetKeyboardLayout( int dwLayout );
The documentation of this method however emphasises:
The input locale identifier is a broader concept than a keyboard
layout, since it can also encompass a speech-to-text converter, an
Input Method Editor (IME), or any other form of input. Since the
keyboard layout can be dynamically changed, applications that cache
information about the current keyboard layout should process the
WM_INPUTLANGCHANGE message to be informed of changes in the input
language.
However, based on a quick glance at the code, the library does not seem to respond to this WM_INPUTLANGCHANGE message, which might cause this behaviour
Also, here is a useful link to an explanation how the Keyboard is handled by Windows
Related
It seems to me that English texts will get better hyphenation if the system language in macOS is set to English. Thing is, it is hard to be sure, and restarting with a new system language is cumbersome, so I haven't tested this thoroughly, but I'm reasonable sure that I've only seen "somet-hing" and similar when my system was set to Swedish.
This is on macOS Big Sur, in an NSTextView with hyphenation switched on by setting hyphenationFactor to 1 on an NSParagraphStyle object in an NSAttributedString. It is not a web view. The application is not localized, so the app language is English even when the system is set to Swedish. Setting NSAccessibilityLanguageTextAttribute to "en-US" seems to have no effect.
I'd like to know if anyone can confirm this, and if so, can anything be done about it?
From the documentation of hyphenationFactor:
This property detects the user-selected language by examining the first item in preferredLanguages.
+[NSLocale preferredLanguages] is called once from -[NSAttributedString lineBreakByHyphenatingBeforeIndex:withinRange:] but before that the language is read from NSUserDefaults with key NSHyphenationLanguage. Setting the language with
[NSUserDefaults.standardUserDefaults setObject:#"en" forKey:#"NSHyphenationLanguage"]
seems to work but it is undocumented, so use it at your own risk.
As yolu may have noticed, MS introduced a modern kind of 'theming' in Windows 10 regarding the basic OS elements like start menu and taskbar. With newer versions, you can choose a 'light' theme as an alternative to the default black theme.
I was wondering if there is an API or hook to elegantly and (more importantly) efficiently check live for theme changes (Did not find anything in the MS docs regarding this, but often enough these gems are pretty hidden there IMHO).
Specific problem: When you have a desktop application with a system tray icon, chances are high that you designed it to be bright. Nearly all of the modern Windows icons feature such a style (simple and white, yielding good readability on the black taskbar). Now you can provide a different version in a darker style for the light theme, but how to notice when to apply this on the fly?
I'm aware of the registry key under HCU (Software/Microsoft/Windows/CurrentVersion/Themes/Personalize) which is what I'm utilizing right now. However, blindly checking for change every x milliseconds seems pretty awkward.
If no such thing is available, I'm also happy to hear some ideas for more efficient implementations of such a check.
Method 1: Use RegNotifyChangeKeyValue
Notifies the caller about changes to the attributes or contents of a
specified registry key.
Methon 2: Use WM_SETTINGCHANGE
Applications should send WM_SETTINGCHANGE to all top-level windows when they make changes to system parameters. (This message cannot be sent directly to a window.) To send the WM_SETTINGCHANGE message to all top-level windows, use the SendMessageTimeout function with the hwnd parameter set to HWND_BROADCAST.
I tend to use the second method, I have tried, and have been able to work successfully.
Minimum code example:
case WM_SETTINGCHANGE:
{
if (!lstrcmp(LPCTSTR(lParam), L"ImmersiveColorSet"))
{
//theme has been changed
}
}
My custom Windows shell context menu handler works like a charm, for all Windows versions from XP to 7, but on Windows 8, 8.1 and 10, installing it breaks the Win+X menu (sometimes called "Power user menu", or "Quick Access menu", or "WinX menu"): when hitting Win+X, the menu is displayed as expected, but its items do not work anymore (nothing happens when I click on them), except for the last four items at the bottom which still work as expected ("Search", "Run", "Shut down/Sign out", "Desktop"):
I quickly found out on Google that it was a well known issue for a great number of shell extensions that were not "compatible" with Windows 8/10. But sadly, I only found application users talking about this issue and its "solutions", and no developer talking about this. And the two "solutions" proposed by these users were:
Unregistering this shell extension
Uninstalling the app that registered this shell extension (which leads to solution 1...)
See for example this, this, or this to read people talking about this issue.
Note: my shell extension is applied for the * file type, which means all files.
Several days later, I found the cause of this issue in the shell extension source code, so I thought it would help other developers to share it on StackOverflow, as a self-answered question (I didn't find this question). See answer above.
I first looked at the shell extension sample code provided by Microsoft (which doesn't cause this issue), compared it with my code, and progressively replaced parts of my code with Microsoft's code and testing it after each replacement.
I found out that what prevents power-user menu to work is what you return in method InvokeCommand() from IContextMenu interface: if your extension cannot handle the given verb, it shall always return E_FAIL so that Windows tries with other implementations of IContextMenu (see Microsoft documentation for more details). It seems that when a power-user menu item was clicked, Windows first called my extension (* file type), then since it didn't return E_FAIL for this unknown verb, Windows thought that my shell extension has processed this event, so it didn't process it through the nominal power-user menu callback.
By the way, three things seem very weird to me:
Why does Windows even try to process this power-user menu event with a shell file extension? Is this menu coded using the same design/mechanism as any other Explorer's file contextual menu?
Why does this bug didn't produce more side-effects yet? I mean this should have broken the whole shell extension system right from the beginning, no?
Why do so many applications has this bug? (meaning why so many applications do not return E_FAIL as expected?). It's been a while now that I've written this code, I can't really remember where it comes from, but I guess it comes from a Microsoft sample or any Microsoft employee tutorial (far too Microsoft-oriented to be coded by yourself). If it's the case, that may answer the question why so many shell extensions cause this issue...
I would be interested if someone has some ideas to share about this subject!
By the way, I hope my post can help other developers. When looking at the new Microsoft example that works like a charm, I was first afraid having to rewrite all my shell extension from their sample without knowing what was wrong in my code!
I have a coworker who needs to have multiple versions of LabVIEW on his computer. He has a bad habit of opening LV2010 code in LV2013. LabVIEW doesn't warn that you are about to change all of the code to a new version of LabVIEW, and this breaks the code running on a test system on the production floor.
Here is my question: does anyone know of any kind of hack or legitimate method of changing the windows title bar for a single application? I would like to be able to change the color of the title bar only on LabVIEW 2013 from blue to red or something.
If this isn't possible, does anyone have an idea of how to distinguish one application from another that looks almost identical?
Thanks for any advice you have to give.
Well, the good news is that LabVIEW 2014 on will have the version number in their icon. That doesn't help your situation much, though. I'm not sure about changing the title bar, but I think I can help with your second question.
The icons for those versions are indistinguishable, however, the mass compile LabVIEW does when you open a project from an older version is a dead giveaway. You know LabVIEW is performing a mass compile if, while the project is loading, "Compiling:" appears where "Loading:" normally does. Close out of LabVIEW without saving and open the right version of LabVIEW. If he still goofs, there's always reverting in whatever version control software you're (hopefully) using, and you can always save back to older versions in LabVIEW itself.
I currently have four (older) versions installed to support projects that are under warranty. One trick I've found to be helpful is to put a .txt document in the same directory I save my .lvproj with the LabVIEW version as the title. For example, if the code is written in LabVIEW 2012 I include a text document called LV2012.txt in my _Project folder. Not a foolproof plan, but it has definitely made me double check my open version of LabVIEW before double-clicking.
I would suggest to use get VI version property described here: http://digital.ni.com/public.nsf/allkb/0C72D335AA87DD6486256FC40069C17F
Than using version information change you title bar text or transparency(I am not sure about color) or other FP component using VI ref property node.
I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.