15

I'm assuming, what I'm asking should actually be the default, but I'm experiencing some behavior I don't understand.

#include "stdafx.h"

using namespace std;

BOOL CALLBACK enumWindowsProc(
  __in  HWND hWnd,
  __in  LPARAM lParam
) {
  if( !::IsIconic( hWnd ) ) {
    return TRUE;
  }

  int length = ::GetWindowTextLength( hWnd );
  if( 0 == length ) return TRUE;

  TCHAR* buffer;
  buffer = new TCHAR[ length + 1 ];
  memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
  
  GetWindowText( hWnd, buffer, length + 1 );
  tstring windowTitle = tstring( buffer );
  delete[] buffer;

  wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;

  return TRUE;
}

int _tmain( int argc, _TCHAR* argv[] ) {
  wcout << TEXT( "Enumerating Windows..." ) << endl;
  BOOL enumeratingWindowsSucceeded = ::EnumWindows( enumWindowsProc, NULL );
  cin.get();
  return 0;
}

If I invoke that code, it will list all minimized windows: enter image description here

Now, I'm no longer interested in only the minimized windows, now I want all of them. So I remove the IsIconic check:

BOOL CALLBACK enumWindowsProc(
  __in  HWND hWnd,
  __in  LPARAM lParam
) {
  /*
  if( !::IsIconic( hWnd ) ) {
    return TRUE;
  }
  */

  int length = ::GetWindowTextLength( hWnd );
  if( 0 == length ) return TRUE;

  TCHAR* buffer;
  buffer = new TCHAR[ length + 1 ];
  memset( buffer, 0, ( length + 1 ) * sizeof( TCHAR ) );
  
  GetWindowText( hWnd, buffer, length + 1 );
  tstring windowTitle = tstring( buffer );
  delete[] buffer;

  wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;

  return TRUE;
}

Now I get all windows except the minimized ones (none of the previously listed window handles are listed this time): enter image description here

For completeness, this is the stdafx.h:

#pragma once

#include "targetver.h"


#include <iostream>
#include <map>
#include <string>

namespace std {
  #if defined _UNICODE || defined UNICODE
    typedef wstring tstring;
  #else
    typedef string tstring;
  #endif
}

#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <psapi.h>

What am I doing wrong?

Community
  • 1
  • 1
Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138

4 Answers4

12

Here is a callback function that lists all open windows:

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

static BOOL CALLBACK enumWindowCallback(HWND hWnd, LPARAM lparam) {
    int length = GetWindowTextLength(hWnd);
    char* buffer = new char[length + 1];
    GetWindowText(hWnd, buffer, length + 1);
    std::string windowTitle(buffer);
    delete[] buffer;

    // List visible windows with a non-empty title
    if (IsWindowVisible(hWnd) && length != 0) {
        std::cout << hWnd << ":  " << windowTitle << std::endl;
    }
    return TRUE;
}

int main() {
    std::cout << "Enmumerating windows..." << std::endl;
    EnumWindows(enumWindowCallback, NULL);
    std::cin.ignore();
    return 0;
}

If you want to check if the window is minimized, you can use IsIconic().

See Also:

worbel
  • 6,509
  • 13
  • 53
  • 63
Stevoisiak
  • 23,794
  • 27
  • 122
  • 225
10

Well, wcout.flush() never works, however wcout.clear() fixes your code, at least for me.

wcout << hWnd << TEXT( ": " ) << windowTitle << std::endl;
wcout.clear();
return TRUE;

And I know that this question is already one year old, however it's never too late to answer.

FrogTheFrog
  • 1,548
  • 19
  • 32
  • You're right, this works. However, after looking up the documentation for `ios::clear`, I'm a bit confused in regards to *why* it works. – Oliver Salzburg Jul 01 '13 at 11:30
3

It's (as I assumed) not a problem with EnumWindows at all. The problem is with the output stream.

While debugging, I noticed that enumWindowsProc is called just fine for every window, but that some iterations are simply not generating output.

For the time being, I switched to using _tprintf, but I don't understand what the problem with the original code is. Calling wcout.flush() had no desirable effect either.

Oliver Salzburg
  • 21,652
  • 20
  • 93
  • 138
  • Did you try stepping through your code? If you do, you may notice that there is still a code path where your callback function returns without printing anything. – Raymond Chen Apr 20 '12 at 14:16
  • Yes, after replacing the `wcout << ...` part with `_tprintf` everything works as expected. I must be using the stream incorrectly or something else is causing me this problem. – Oliver Salzburg Apr 20 '12 at 14:29
  • Using a debugger to examine the data in windowTitle for some of the "missed" windows might help you figure out the common denominator which should provide a hint as to the cause. – Harry Johnston Apr 22 '12 at 00:08
0

Documentation of Windows (dunno its accuracy) says that EnumWindows only enumerates top level windows. If you wish to enumerate child windows, you need to use EnumChildWindows function where you have to pass handle of parent window