Can't change console application window title with virtual terminal sequences - c++

I read this article by Microsoft about using of console virtual terminal sequences.
I followed this sequence to change the window title:
ESC ] 2 ; <string> BEL
I also tried:
ESC ] 0 ; <string> BEL
But it doesn't change the title.
This is my code:
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
int main()
{
// https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
// Set output mode to handle virtual terminal sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
DWORD dwMode = 0;
if (!GetConsoleMode(hOut, &dwMode))
{
return GetLastError();
}
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hOut, dwMode))
{
return GetLastError();
}
// Try some Set Graphics Rendition (SGR) terminal escape sequences
wprintf(L"hello");
wprintf(L"\x1b]2;titel\x07");
return 0;
}
It doesn't change the console window title.

The Microsoft document suggests:
Note that these sequences are OSC “Operating system command” sequences, and not a CSI like many of the other sequences listed, and as such starts with “\x1b]”, not “\x1b[”. As OSC sequences, they are ended with a String Terminator represented as and transmitted with ESC \ (0x1B 0x5C). BEL (0x7) may be used instead as the terminator, but the longer form is preferred.
It wouldn't be the first time MS didn't implement something. Try Esc \ - it's worked for me.
That said, I have noticed during debugging that the window title doesn't change immediately and since you terminate the program right after the sequence, you might not be seeing the effect.

Related

How to handle pasted text correctly via GetConsoleInput()?

In Windows console, we can use GetConsoleInput() to get raw keyboard (and more) input. I want to use it to implement a custom function that read keystrokes with possible CTRL, SHIFT, ALT status. A simplified version of the function is
// for demo only, no error checking ...
struct ret {
wchar_t ch; // 2-byte UTF-16 in Windows
DWORD control_keys;
};
ret getch() {
HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD buf;
DWORD cnt;
for (;;) {
ReadConsoleInput(in, &buf, 1, &cnt);
if (buf.EventType != KEY_EVENT)
continue;
const KEY_EVENT_RECORD& rec = buf.Event.KeyEvent;
if (!rec.bKeyDown)
continue;
if (!rec.uChar.UnicodeChar)
continue;
return { rec.uChar.UnicodeChar,rec.dwControlKeyState };
}
}
It works fine, except that when I try to paste character not representable in 2 bytes in UTF-16, the UnicodeChar field is 0 when bKeyDown==true, and the UnicodeChar field is the pasted content when bKeyDown==false. Can anyone tell why it is the case and suggest possible workarounds?
Here is some demo code and result.

I use the function "FillConsoleOutputCharacter" but the application stoped working

I want to make a console application, so i searched for Windows API, and get this code, but it stoped working when i run it, what should i do?
Source code:
#include "windows.h"
#include "stdio.h"
#include <conio.h> //console i/o
int main()
{
HANDLE hOut;
// 获取标准输出设备句柄
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
// 窗口信息
CONSOLE_SCREEN_BUFFER_INFO bInfo;
// 获取窗口信息
GetConsoleScreenBufferInfo(hOut, &bInfo );
printf("\n\nThe soul selects her own society,\n");
printf("Then shuts the door;\n");
printf("On her devine majority\n");
printf("Obtrude no more.\n\n");
_getch();
COORD pos = {0, 0};
// 向窗口中填充字符以获得清屏的效果
FillConsoleOutputCharacter(hOut, ' ', bInfo.dwSize.X * bInfo.dwSize.Y, pos, NULL);
// 关闭标准输出设备句柄
CloseHandle(hOut);
return 0;
}
Could someone tell me how to solve? PLZPLZ!!
You are passing NULL to the lpNumberOfCharsWritten parameter of FillConsoleOutputCharacter(), but the documentation says:
lpNumberOfCharsWritten [out]
A pointer to a variable that receives the number of characters actually written to the console screen buffer.
It does not say that NULL is valid for that parameter. So give it what it wants - a pointer to a variable, eg:
DWORD dwNumWritten;
FillConsoleOutputCharacter(hOut, ' ', bInfo.dwSize.X * bInfo.dwSize.Y, pos, &dwNumWritten);

get_accChildCount returns 0 when it shouldn't

I'm trying to enumerate tabs of IE from an extension and from a standalone application. For one of the MSAA nodes get_accChildCount returns 0 when called from extension, while it should return 1 according to inspect and a call from standalone application.
The problem was described previously at StackOverflow, yet it was solved via a hack that doesn't work for me. /clr and /MT are incompatible.
Also there was a topic on MSDN with the same issue. There's no single answer there.
If you run IE with administrator privileges, it works properly.
API Monitor shows several thousand calls in a minimal example, and it's unclear which of these are related. The minimal example is attached below.
What are the undocumented cases when get_accChildCount returns wrong child count?
What other method could I use to activate the tab by URL in most versions of IE?
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <atltypes.h>
#include <atlsafe.h>
#include <io.h>
#include <fcntl.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/format.hpp>
#include <fstream>
using namespace std;
CComPtr<IAccessible> get_acc_by_hwnd(HWND hwnd) {
CComPtr<IAccessible> ret;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &ret);
if (FAILED(hr) || !ret) {
wcout << L"Accessible::Accessible invalid hwnd" << endl;
}
return ret;
}
std::vector<CComPtr<IAccessible>> get_acc_children(CComPtr<IAccessible> acc) {
std::vector<CComPtr<IAccessible>> ret;
long count;
if (FAILED(acc->get_accChildCount(&count))) return ret;
long count_obtained = 0;
if (!count) return ret;
std::vector<CComVariant> accessors(count);
if (FAILED(::AccessibleChildren(acc, 0, count, &*accessors.begin(), &count_obtained))) return ret;
accessors.resize(count_obtained);
for (auto vtChild : accessors) {
if (vtChild.vt != VT_DISPATCH) continue;
CComQIPtr<IAccessible> pChild = vtChild.pdispVal;
if (pChild) ret.push_back(pChild);
}
return ret;
}
bool is_client(CComPtr<IAccessible> acc) {
CComVariant var;
HRESULT hr = acc->get_accRole(CComVariant(CHILDID_SELF), &var);
return SUCCEEDED(hr) && var.vt == VT_I4 && var.lVal == 0xA;
}
std::wstring get_descr(CComPtr<IAccessible> acc) {
CComBSTR str;
HRESULT hr = acc->get_accDescription(CComVariant(CHILDID_SELF), &str);
return SUCCEEDED(hr) && str ? std::wstring(str) : L"";
}
int main() {
::CoInitialize(nullptr);
_setmode(_fileno(stdout), _O_U16TEXT);
// put HWND of the window that contains tab labels
// it's hardcoded to minimize quantity of API calls
HWND hwnd = reinterpret_cast<HWND>(0x002D0696);
CComPtr<IAccessible> iaccessible;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &iaccessible);
if (FAILED(hr) || !iaccessible) {
wcout << L"AccessibleBrowser::activate_tab " L"failed to get IAccessible for IE" << endl;
return EXIT_FAILURE;
}
wstring const sentinel = L"\r\n";
for (auto child : get_acc_children(iaccessible)) if (is_client(child)) {
for (auto child1 : get_acc_children(child)) { // fails here in extension
for (auto child2 : get_acc_children(child1)) {
std::wstring descr = get_descr(child2);
auto pos = descr.find(sentinel);
if (pos == string::npos) continue;
auto tab_url = descr.substr(pos + sentinel.size());
wcout << tab_url << endl;
}
}
}
}
I poked at your program for a while without having much to show for it. Perhaps I realized too late that it was not supposed to reproduce the problem :( I can only provide some possibly helpful hints to get you to look under the right kind of rock.
yet it was solved via a hack that doesn't work for me
These programmers made a simple mistake, they forgot to call CoInitialize/Ex(). A very common oversight. Using the /clr build option works around that mistake because it is now the CLR that calls it. You can easily repro this mishap, just comment out the CoInitialize() call. Unfortunately it works for a while without any loud errors being produced, but you do get 0 for certain accobjects. You'll notice your program no longer finds the tabs.
Not so sure I can cleanly explain this, certain COM-style object models don't actually use the COM infrastructure. DirectX is the best example, we can add UIAutomation to that list. I assume it will silently fail like this when the client app's component is COM-based. Unclear if it is, DirectUIHWnd is quite undocumented.
So stop looking for that as a workaround, you did not forget to call CoInitialize() and it will be taken care of by IE before it activates your extension.
If you run IE with administrator privileges, it works properly.
That's a better rock. Many programmers run VS elevated all the time, the roles might be reversed in the case of UIA. Do keep in mind that your extension runs in a sandbox inside IE. No real idea how elevating IE affects this. One thing you cannot do from code running in the low-integrity sandbox is poke at UI components owned by a code that runs in a higher integrity mode. Google "disable IE enhanced protected mode" and follow the guideline to see what effect that has on your addin.

can't get current keyboard layout

I have tried GetKeyboardLayoutName() and GetKeyboardLayout() for getting the current keyboard layout, but they both give me the default layout and changing the layout doesn't affect the output!
while(1)
{
Sleep(5);
for(int i = 8; i < 191; i++)
{
if(GetAsyncKeyState(i)&1 ==1)
{
TCHAR szKeyboard[KL_NAMELENGTH];
GetKeyboardLayoutName(szKeyboard);
if(GetAsyncKeyState(i)&1 ==1)
{
TCHAR szKeyboard[KL_NAMELENGTH];
GetKeyboardLayoutName(szKeyboard);
cout << szKeyboard << endl ;
}
}
}
}
It always gives me "00000409" when the default layout is set to English, while I expect it to be "00000429" when I change the layout to Farsi.
My first question here, I used to find all my answers by just searching. But right now I'm driving crazy after hours of searching around and getting nothing...
one thing that you need to notice is that ::GetKeyboardLayout (..) gets the lang for the passed thread identifer as a param.
each input thread can have different input locale lang.
for instance if you put lets IE in the foreground and press Alt+Shift the lang changes to UK. ( you can see it in the taskbar )
now if you will Alt+Tab to another window ( which will be in foregorund ) you will see that lang dont have to stay UK.
so what you need to check is what is the thread id you are passing.
look at this code it will get you the lang for the current active window:
GUITHREADINFO Gti;
::ZeroMemory ( &Gti,sizeof(GUITHREADINFO));
Gti.cbSize = sizeof( GUITHREADINFO );
::GetGUIThreadInfo(0,&Gti);
DWORD dwThread = ::GetWindowThreadProcessId(Gti.hwndActive,0);
HKL lang = ::GetKeyboardLayout(dwThread);
to use GUITHREADINFO you need to define WINVER 0x500.
put this in the stdafx.h before all the include.
#ifdef WINVER
#undef WINVER
#endif
#define WINVER 0x500
source: GetKeyboardLayout not returning correct language ID (WINXP)
The following code is simple and works fine. If you write a command line program, the GetKeyboardLayout API does't work in windows cmd or powershell, you can test it in babun(an open source windows shell).
#include <Windows.h>
int getInputMethod() {
HWND hwnd = GetForegroundWindow();
if (hwnd) {
DWORD threadID = GetWindowThreadProcessId(hwnd, NULL);
HKL currentLayout = GetKeyboardLayout(threadID);
unsigned int x = (unsigned int)currentLayout & 0x0000FFFF;
return ((int)x);
}
return 0;
}

How do I turn off or ignore key repeat for my curses application?

So I recently found curses (specifically PDcurses) and I'm just getting into it. Right now I'm trying to write a little space shooter type game with it and it's worked fine so far for rendering and getting menu type input, but now when I go into the game, I've noticed that key repeat is pretty bad for action games. I need to be able to hold the key and move my avatar every single frame that the key is down. I know how to do this with a normal Win32 application, but I don't have a window and therefore I don't have a wndproc and I can't control the messages the console recieves :/
I don't expect this is something for curses to handle, though if it can that would be awesome, I was really just looking for a work-around that plays nicely with curses.
I have tried cbreak(), nodelay() and raw() to no avail.
Additional info:
Microsoft Visual Studio 2010 Ultimate
PDcurses 3.4, from prebuilt binaries
Windows 7 x64 Ultimate
This is far from a complete solution, and I don't know how it'll interact with PDCurses, but it's an attempt:
In summary, grab the console's handle with GetStdHandle(), configure it for raw reading with SetConsoleMode(), and then read keys one at a time with ReadConsoleInput(). I use a std::set to keep track of the currently pressed keys and so ignore repeats.
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
#include <cassert>
#include <set>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
BOOL success;
success=GetConsoleMode(h, &mode);
assert(success);
mode &= ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT);
mode |= ENABLE_WINDOW_INPUT;
success=SetConsoleMode(h, mode);
assert(success);
INPUT_RECORD buffer[10];
std::set<WORD> keys_down;
while (true)
{
DWORD count=0;
success=ReadConsoleInput(h, buffer, 10, &count);
if (!success)
{
continue;
}
for (size_t i=0;i<count;++i)
{
switch (buffer[i].EventType)
{
case KEY_EVENT:
{
WORD keycode=buffer[i].Event.KeyEvent.wVirtualKeyCode;
if (buffer[i].Event.KeyEvent.bKeyDown)
{
if (keys_down.find(keycode)==keys_down.end())
{
std::cout<<"Key down: "<<keycode<<std::endl;
keys_down.insert(keycode);
}
}
else
{
if (keys_down.find(keycode)!=keys_down.end())
{
std::cout<<"Key up:"<<keycode<<std::endl;
keys_down.erase(keycode);
}
}
break;
}
default:
break;
}
}
}
}