1

I'm interested in the window title of the currently focused window. I now have this code which basically works:

#include <iostream>
#include <Windows.h>

using namespace std;


void CALLBACK myCallback(HWINEVENTHOOK hWinEventHook,
      DWORD event,
      HWND hwnd,
      LONG idObject,
      LONG idChild,
      DWORD idEventThread,
      DWORD dwmsEventTime) {
    int windowTitleLength = GetWindowTextLengthA(hwnd);
    const int bufferSize = windowTitleLength + 2;
    LPSTR windowTitleBuffer = new char[bufferSize];
    GetWindowTextA(hwnd, windowTitleBuffer, bufferSize);
    cout << "Title: " << windowTitleBuffer << endl;
    delete[] windowTitleBuffer;
}

void setup() {
    SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL, myCallback, 0, 0,
        WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
}

int main()
{
    bool bRet;
    MSG myMsg;
    setup();
    while (bRet = GetMessage(&myMsg, NULL, 0, 0) != 0)
    {
        if (bRet == -1) {
            cout << "ABANDON SHIP!" << endl;
        }
        cout << "Got a message!" << endl;
    }
}

And btw this is my attempt to achieve in c++ what I failed to achieve in nodejs here.

The window titles get printed as expected until I explicitly focus the terminal window of my little program. It prints it's own title then freezes. Focusing other windows does not print anything until I press Ctrl+C in my console then all the stored energy in my program's memory is released and starts working again.

Now I don't know why the callback is being called for my own program console window when I have specified WINEVENT_SKIPOWNPROCESS flag to SetWinEventHook. Maybe because the console is not really a window?

The second question I have about this code is the GetMessage function which gets called only once no matter how many events my program receives which doesn't make sense to me because I expect it to be called once for each event received.

Also, maybe as a consequence to the above, the while loop body never executes.

How to get this program to not choke on it's own events?

MadeOfAir
  • 2,933
  • 5
  • 31
  • 39
  • 5
    console is window, but it belong to another process, not your. so no mistake here – RbMm Dec 19 '18 at 14:37
  • 2
    Deadlock is a high probability here, I had no trouble getting one from the posted code on my machine. A program that listens for automation events needs to advertise that it is going to be nice to various components that can generate such events. You have to explicitly announce that you are going to pump a message loop to keep such components thread-safe. Add `CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);` to the setup() function. Not getting a lot of messages in a console mode app is expected, it is conhost.exe that maintains the console window – Hans Passant Dec 19 '18 at 15:04
  • I tried `CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)` but it didn't do it's magic. The program still locks up when I focus the console. – MadeOfAir Dec 19 '18 at 17:14
  • There is no use of COM objects in this code, so `CoInitialize/Ex()` is not necessary or useful. – Remy Lebeau Dec 19 '18 at 21:18
  • Do you have the same problem if you replace `GetWindowText/Length()` with [`GetConsoleTitle()`](https://learn.microsoft.com/en-us/windows/console/getconsoletitle) when the reported `HWND` is the same one returned by [`GetConsoleWindow()`](https://learn.microsoft.com/en-us/windows/console/getconsolewindow)? `if (hwnd == GetConsoleWindow()) { use GetConsoleTitle(); ... } else { use GetWindowText(); ...}` – Remy Lebeau Dec 19 '18 at 21:24
  • @RemyLebeau I'm not really interested in the console window title here so I just used if `(hwnd != GetConsoleWindow) {my.old.stuff}` and the issue remains. – MadeOfAir Dec 20 '18 at 12:51

0 Answers0