Windows API: Programmatically moving the Windows IME Input box possible? - c

Question
On Windows, if a program does not use one of the native APIs to produce a GUI, then Windows IME shows a tiny Textbox in the upper left corner to input IME strings, as is the case with Japanese.
Can this textbox be moved programmatically via the Windows API? I just want it moved roughly where the text input happens, so it's not so jarring having to look in the upper left corner all the time. Can someone point me in the right direction, what to read where to search?
Details
I have an OpenGL Program with a simple Immediate-Mode GUI Toolkit on top. As such this program does not interface with the OS's GUI capabilities in any meaningful way to provide OS native behaviour or accessibility functions. For my use-case, similar to many video games, this is fine. If I have textboxes inside the program however, inputting text via Windows or Google IME is an awful experience and I would like to improve it. I am not looking to integrate with Windows any more that this, just moving the IME Textbox roughly to the correct position of the "in program" textbox. It is compiled with MinGW64 and I already used Win32 API functions like changing the program's window and taskbar icon. Is this a possibility via the Win32 api?

The following code works in moving the IME position from default to current cursor position:
if (msg.message == WM_IME_STARTCOMPOSITION) { // msg is windows message
HIMC imc = ImmGetContext(msg.hwnd);
COMPOSITIONFORM cf;
cf.dwStyle = CFS_FORCE_POSITION;
POINT ptPos;
bool ret = GetCursorPos(&ptPos);
if (ret)
{
cf.ptCurrentPos.x = ptPos.x;
cf.ptCurrentPos.y = ptPos.y;
}
ImmSetCompositionWindow(imc, &cf);
ImmReleaseContext(msg.hwnd, imc);
}
WM_IME_STARTCOMPOSITION is a message type which windows sends to application when it starts IME. In your application when you peek or process windows messages try to catch for WM_IME_STARTCOMPOSITION and then force set the IME composition window position.

Related

WS_EX_LAYERED window chroma key (LWA_COLORKEY) doesn't work in Windows 7 with Aero Glass enabled

I'm trying to make a DirectX8 application (Game Maker) chroma keyed using layered windows (WS_EX_LAYERED extended style flags, and LWA_COLORKEY method) for transparency and correct hit testing on a borderless window. However, out of all platforms I've tested it on, Windows 7 fails but specifically only when Aero Glass is turned on. The effect works for apparently one frame, and then stops working - the chroma key then comes out to the screen and the window is a full rectangle, including mouse hit testing. Turning off Aero Glass in advanced appearance, or changing to a Basic or Classic theme fixes the issue, but that's undesirable.
__declspec(dllexport) double __cdecl __gm82core_setchromakey(double enable, double color) {
if (enable>=0.5) {
SetWindowLong(window_handle,GWL_EXSTYLE,GetWindowLong(window_handle,GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(window_handle,((DWORD)color)&0x00ffffff,0xff,LWA_COLORKEY);
} else {
SetWindowLong(window_handle,GWL_EXSTYLE,GetWindowLong(window_handle,GWL_EXSTYLE) & ~WS_EX_LAYERED);
}
return 0;
}
broken effect in Win7 with Aero Glass enabled
(The variable types are all double because the develoment platform (Game Maker) only allows for doubles to be passed to native code)
I've read that there are issues using colors that have the same value on multiple channels like white or yellow for chroma key, and tried using colors such as rgb (253,254,255) or (201,202,203), to similar results.
I've read that chroma keying apparently broke in Windows 7 RC1, and we can just assume that wasn't fixed for RTM due to the experienced behavior.
I've read that in Win 7 and earlier, child windows cannot be chroma keyed, and I've attempted to remove the window's parent using SetParent(), to similar results (and introducing other issues in the process), despite the window's parent being disabled and invisible when the application is launched in borderless mode.
The effect works fine until the window is updated, and then never again, which is an issue as the program has animated controls.
Was verified to work in various versions of Win 10 dated as far back as 1903:
effect working as intended in Win10
I've used an alternate method using DWM direct compositing using a 32 bit ARGB surface format, which allows per-pixel alpha transparency in all platforms, however does not allow for mouse hit testing, which is undesirable for this application due to its free-form window.
Even though the effect works properly in Win10, I'd like to support Win7 as well since that's a common target for the extension package this code is from.

Why this BitBlt example doesn't work anymore?

I'm currently getting back to some Windows Programming using Petzold's book (5th edition).
I compiled the following example using BitBlt and it doesn't work as it is supposed to.
It should copy the Window's icon of (CxSource, CySource) size and replicate it on the whole window's surface.
What happens, in reality, using Windows 7 is that the bitmap below the window gets sourced and copied into the drawing surface i.e. hdcClient.
I don't understand why it behaves like this knowing that it's clear the DC passed to BitBlt is hdcWindow, which refers to a device context obtained via a GetWindowDC(hwnd) of the current application.
I first thought it was due to the fact the transparency mode is enabled by default, but deactivating it doesn't change anything. BitBlt seems to always take the surface below the application Window!
I don't get it! :)
Anyone knows why it works that way and how to fix it?
Making screenshots with BitBlt() did not exactly get any easier since the addition of the DWM (Desktop Window Manager, aka Aero). Petzold's sample code suffers from a subtle timing issue, it is making the screenshot too soon. It does so while Aero is still busy animating the frame, fading it into view. So you see what is behind the window, possibly already partly faded depending on how quickly the first WM_PAINT message is generated.
You can easily fix it by disabling the effect:
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
And after the CreateWindow() call:
BOOL disabled = TRUE;
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, &disabled, sizeof(disabled));
Another tricky detail is that the first BitBlt matters, the DWM returns a cached copy afterwards that is not correctly invalidated by the animation.
This gets grittier when you need a screenshot of a window that belongs to another process. But that was already an issue before Aero, you had to wait long enough to ensure that the window was fully painted. Notable perhaps is the perf of BitBlt(), it gets bogged-down noticeably by having to do job of composing the final image from the window back-buffers. Lots of questions about that at SO, without happy answers.
It is not supposed to copy the windows icon, it is supposed to copy the windows titlebar part where the icon is located.
There are some issues with this (now 20 year old code):
GetSystemMetrics values cannot be used for window related dimensions anymore since GetSystemMetrics returns the classic sizes, not the Visual Style sizes.
Depending on the Windows version, the DWM might define the window size as something larger than your window (where it draws the window shadow and other effects).
Your example works OK on XP:
(There is a small problem because the titlebar is not square (unlike Windows 98/2000 that this example was designed for) so you see a issue in the top left where it is just white. I also modified the example slightly so it varies the HDC source location)
On a modern version of Windows it seems like the DWM or something is not able to properly emulate a simple window DC and parts of the shadow/border/effects area is part of the DC:
I don't know how to fix this but the example is pretty useless anyway, if you want to draw the window icon you should draw the HICON with DrawIconEx. If you want to draw custom non-client area stuff then you need to find more recent examples, not something that only supports the classic theme.

How to verify font created by Windows?

I'm using the ChooseFont system dialog to populate a LOGFONT structure that is passed to CreateFontIndirect and the resulting font handle is selected into the device context and used. But it doesn't resemble the requested font in any way (well, OK, similar character sets, but otherwise not the same). Here's an image of the screen showing the ChooseFont dialog selecting an old DOS-style VGA font and in the background (behind the ChooseFont dialog) shows the font that I got when I selected the values shown in the dialog:
Notice that the Sample in the dialog and what Windows puts on the screen when the created font is selected into the DC are quite different. This doesn't happen for ALL fonts, only some of them, which is why I'm trying to correct and/or detect this.
I've tried getting the LOGFONT for the new font from the DC using (GetCurrentObject and GetObject) and it is identical to my request, except that the lfQuality has changed to NONANTIALIASED_QUALITY from anything else I've tried setting it to.
I have a kinda two part question:
How can I force Windows to use the font I've selected. Obviously there is a way, or it wouldn't look right in the ChooseFont dialog, either.
If no one can answer #1, how can I reliably find out that Windows has selected a totally wrong font, when asking Windows for the font info about the created font when selected into the device context doesn't work?
EDIT: July 8
If this helps at all, my basic calling sequence is:
LOGFONT lf;
CHOOSEFONT cf;
HFONT hf;
cf.lpLogFont = &lf; // plus other necessary stuff
ChooseFont( &cf );
hf = CreateFontIndirect( &lf );
SelectObject( hdc, hf );
ExtTextOut( hdc, ... );
Then, when I use the font, it doesn't always match what I requested. At all. (I just tried using Arial Monospaced MT and was rewarded with Courier -- Lucida Console would be a better substitute, at least it doesn't have serifs!) I don't do ANYTHING to the DC other than call GetDC(). I don't call any GDI setup/configuration functions, either, so I'm in whatever default mode one gets with a standard Windows program written in C to the WIN32API.
I've discovered that the Windows version of PuTTY shows the correct fonts while my program doesn't, but I have not yet been able to find anything different between the functions/parameters it uses to handle font creation and the way I do it. I'll keep looking though. Thanks to anyone who's given my question any thought, with or without suggestions. :-)

Take screenshot of desktop when Windows is locked (Win+L)

I want to take a screenshot of desktop while Windows is locked (with Win+L). Standard methods make a black screen, with code of pixel:
COLORREF color = GetPixel(hdc, x, y);
equal -1. Neither a user mode program nor a service could capture a useful image. Any ideas?
GetPixel and BitBlt won't work when the desktop isn't physically displayed on the monitor.
You may have some luck capturing individual windows with PrintWindow. However, not all applications respond to PrintWindow calls the same way, so you may see glitches and/or blackness. You'll also need to capture each window individually.

Pinyin Character entry on a touchscreen keyboard

The app I'm developing requires that it be deployed in China, which means that it needs to have Pinyin and Chinese character handling. I'm told that the way that our customers handle character entry is like so:
Enter in the pinyin character, like 'zhang'
As they enter the characters, a list of possible Chinese (Mandarin?) characters are presented to the user, like:
The user will then select '1' to enter the family name that is roughly translated to 'zhang'
How can I hook such programs (I believe one is called 'mspy.exe', from Microsoft, which I'm lead to believe comes with Microsoft versions of XP) into a WPF text box? Right now, the user can enter text either by using their keyboard or by using an on-screen keyboard, so I will probably need to capture the event of a keypress from either source and feed it to some OS event or to MSPY.exe or some similar program.
Or is there some other way to enter pinyin and have it converted to Mandarin? Is there a program other than MSPY I should look at?
EDIT: For those of you who think that this should 'just work', it does not. Chinese character entry will work just fine if entering text into notepad or the start->run menu or whatever, but it will not work in WPF. That's the key to this question: how do I enable WPF entry? There's the Google Pinyin and Sogou pinyin, but the websites are in Mandarin or Chinese or something similar and I don't read the language.
In all likelihood the system will handle this automagically if a Chinese input method is selected by the user. Trying to implement your own system for dealing with Chinese text is probably a bad idea.
Be sure to test it on a Chinese version of XP before deploying, of course, but with any amount of decent design in WPF, and XP as a whole, at all; it should Just Work.
Not really an answer to your question, but as far as I know, this is handled by the operating system, and I'm not sure that application really have that much control over it.
Here's a guide on how you enable pin yin Chinese character entry in Windows XP:
http://www.biblioscape.com/tips/tip_020318.htm
My application works with chinese input, and it is using WPF, i don't get what you want to ask.
You can input chinese text in a WPF textbox using sogou pinyin, or microsoft pinyin. Tested in xp and win7
It is just because your ime is setted to input in english.
Press shift once briefly if using sogou pinyin and you will see the hanzi of "yi" become "zhong"
At that point you will be able to type in chinese ;-)
Also, there are IME property on textboxes, select to have it On, otherwise the IME will be in "english mode"

Resources