Verstaendnisproblem!, mit "EnumChildWindows + EnumChildProc" ...



  • hi ich suche schon einige zeit nach einen verstaendnisvollen C++ Quelltext fuer EnumChildWindows() aber alles was ich finde is VB-zeugs...
    ich möchte mir alle ChildWindow-Handels, bzw ID's auflisten lassen.

    und zwar will ich fuer diesen zweck erstmal ein API-Prog schreiben mit diversen Buttons, EBOXES, LBs ect., wenn diese Anwendung laeuft moechte ich ein Konsolen Prog starten, das erst mal mit FindWindow() den handel zum fenster findet. und dann soll in der konsole untereinander alle childwindows aufgelistet werden....

    nur weiss ich nicht wie man mit EnumChildWindos + EnumChildProc umgeht. haettet ihr vieleicht ein Beispielcode oder koenntet mir mit codeschnippseln erklären wie man es macht?

    Danke.
    Gruß Tobi



  • Zufällig hab ich da was vorbereitet...

    #include <windows.h>
    #include <stdio.h>
    
    struct tWinList
    { HWND hwnd;
      int cnt;
      long processid;
      long threadid;
      RECT wr;
      char wtext[80];
    };
    struct tWinListBase
    { struct tWinList *wl;
      int cnt;
    };
    struct tWinListBase WinListBase;
    
    int useparms(int a, ...)
    {
      return a;
    }
    
    char *fbprint(char *format, ...)
    {
      static char buf[1000];
    
      vsnprintf(buf, sizeof(buf), format, (&format)+1);
      return (char *)buf;
    }
    
    long TextOutStr(HDC hdc, int x, int y, char *s)
    {
      return TextOut(hdc, x, y, s, strlen(s));
    }
    
    int ReturnValue = 19;
    
    int ChildCounter;
    
    int _stdcall enumchildproc(HWND hwnd, long lParam)
    {
      ChildCounter++;
      return 1;
    }
    
    int _stdcall enumwindowsproc(HWND hwnd, long lParam)
    {
      struct tWinListBase *wlb;
      unsigned long processid;
      long threadid;
      RECT wr;
      char wtext[80];
    
      wlb = (struct tWinListBase *)lParam;
      wlb->wl = (struct tWinList *)realloc(wlb->wl, (wlb->cnt+1)*sizeof(struct tWinList));
      memset(wlb->wl+wlb->cnt, 0, sizeof(struct tWinList));
      wlb->wl[wlb->cnt].hwnd = hwnd;
      wlb->cnt++;
    
      ChildCounter = 0;
      EnumChildWindows(hwnd, enumchildproc, 0);
      wlb->wl[wlb->cnt-1].cnt = ChildCounter;
    
      threadid = GetWindowThreadProcessId(hwnd, &processid);
      wlb->wl[wlb->cnt-1].processid = processid;
      wlb->wl[wlb->cnt-1].threadid = threadid;
    
      GetWindowRect(hwnd, &wr);
      memmove(&(wlb->wl[wlb->cnt-1].wr), &wr, sizeof(RECT));
    
      GetWindowText(hwnd, wtext, sizeof(wtext));
      strcpy(wlb->wl[wlb->cnt-1].wtext, wtext);
      return 1;
    }
    
    void DoEnumWindows(void)
    {
      free(WinListBase.wl);
      memset(&WinListBase, 0, sizeof(struct tWinListBase));
      ReturnValue = EnumWindows(enumwindowsproc, (long)&WinListBase);
    }
    
    long _stdcall WndProc(HWND hwnd, unsigned int message, unsigned int wParam, long lParam)
    {
      HDC hdc;
      PAINTSTRUCT ps;
      int KEYDOWN_nVirtKey;
      int i;
    
      switch(message)
        { case WM_PAINT:
              hdc = BeginPaint(hwnd, &ps);
              TextOutStr(hdc, 10, 10, fbprint("ReturnValue %i", ReturnValue));
              TextOutStr(hdc, 10, 30, fbprint("WinListBase.cnt %i", WinListBase.cnt));
              for (i = 0; i < WinListBase.cnt; i++)
                  TextOutStr(hdc, 10, 50+i*20,
                             fbprint("%u %04X %u th %04X pr %04X %i %i %i %i \"%s\"",
                          i, WinListBase.wl[i].hwnd,
                             WinListBase.wl[i].cnt,
                             WinListBase.wl[i].threadid,
                             WinListBase.wl[i].processid,
                             WinListBase.wl[i].wr.left,
                             WinListBase.wl[i].wr.top,
                             WinListBase.wl[i].wr.right,
                             WinListBase.wl[i].wr.bottom,
                             WinListBase.wl[i].wtext));
              EndPaint(hwnd, &ps);
              return 0;
          case WM_KEYDOWN:
              KEYDOWN_nVirtKey = wParam;
              if (KEYDOWN_nVirtKey == VK_RETURN)
                { DoEnumWindows();
                  InvalidateRect(hwnd, 0, TRUE);
                  UpdateWindow(hwnd);
                }
              return 0;
          case WM_DESTROY:
              free(WinListBase.wl);
              PostQuitMessage(0);
        }
      return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                                              char *szCmdLine, int iCmdShow)
    {
      HWND hwnd;
      MSG msg;
      WNDCLASS wc;
      char *cln = "mbclass";
    
      memset(&wc, 0, sizeof(WNDCLASS));
      wc.style         = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
      wc.lpfnWndProc   = WndProc;
      wc.hInstance     = hInstance;
      wc.hIcon         = LoadIcon(0, IDI_INFORMATION);
      wc.hCursor       = LoadCursor(0, IDC_ARROW);
      wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
      wc.lpszClassName = cln;
    
      RegisterClass(&wc);
      hwnd = CreateWindow(cln, "Titel", WS_OVERLAPPEDWINDOW,
                                        CW_USEDEFAULT, CW_USEDEFAULT,
                                        CW_USEDEFAULT, CW_USEDEFAULT,
                                        0, 0, hInstance, 0);
      ShowWindow(hwnd, iCmdShow);
      UpdateWindow(hwnd);
    
      useparms(0, hPrevInstance, szCmdLine);
      while(GetMessage(&msg, 0, 0, 0))
        { TranslateMessage(&msg);
          DispatchMessage(&msg);
        }
    
      return msg.wParam;
    }
    


  • aehm jaaa? und wie, was passiert da jetzt? ich steig da irgendwie net ganz durch


  • Mod

    Das geht weitaus einfacher mit der Fubktion GetWindow (GW_CHILD, GW_NEXT)!



  • ja und wie?



  • Win32 Programmer's Reference

    Guggst Du hier: http://www.codingcrew.de/programmierung/win32hlp.php


  • Mod

    T0bi schrieb:

    ja und wie?

    In dem man anfängt zum Beispiel die Doku zu lesen:

    for (HWND hWnd=::GetWindow(hWndParent,GW_CHILD); hWnd; hWnd = ::GetWindow(hWnd,GW_HWNDNEXT))
    {
    ...
    }
    


  • also ich habe des jetzt mal so versucht wies der martin vorgeschlagen hat, und er erkännt schon mal das ich 9Childs habe, doch will ich mir den text noch ausgeben lassen den das jeweilige child besitzt.
    Hier mein Ansatz

    int main( int argc, char* argv[] ) {
    
        HWND hWnd;
        string sWindow;             // searched window
        string Window_text;         // childwindows text
        char *szBuffer;
        int iLength = 0;
        int i = 1;
    
        cout << "\n Please enter here the windowname, witch one you want: ";
        cin >> sWindow;
        cout << endl;
        cin.sync();
    
            hWnd = FindWindow( 0, sWindow.c_str() );
                if( !( hWnd ) ) {
    
                    textcolor( LIGHTRED );
                    cprintf( "\n Error, couldn't found window.\n" );
                    getchar();
                    return 0;
                }
                else {
    
                    textcolor( LIGHTGREEN );
                    cprintf( "\n Ok, the window could found.\n" );
                }
    
        for( hWnd = GetWindow( hWnd, GW_CHILD ); hWnd;
             hWnd = GetWindow( hWnd, GW_HWNDNEXT ) ) {
    
            iLength = GetWindowTextLength( hWnd );
            Window_text = GetWindowText( hWnd, szBuffer, iLength );
    
            cout << "\n Childwindow[ " << i << " ]  -  " << *szBuffer;
            i++;
        }
        getchar();
        return 0;
    }
    

    doch jedes mal listet er mir nur "Y" auf statt, Butto01 ... wieso???

    [EDIT] Ok... wenn ich statt pointer nen array nehm gehts... hmm

    Gruß Tobi



  • Wenn du mit einem Pointer arbeitest und sogar schon die Länge in iLength ermittelst, dann musst du nur noch entsprechend Speicher reservieren (new, malloc) - und am Ende diesen wieder freigeben (delete[], free)



  • Ach komm ... machen wirs ordentlich 😉

    int main() 
    {
    	std::string window_name;
    	std::cout << "Please enter the Windowname: " << std::flush;
    	std::getline(std::cin, window_name);
    
    	HWND hWnd = FindWindow(NULL, window_name.c_str());
    
    	if (hWnd == NULL || IsWindow(hWnd) == FALSE)
    	{
    		std::cout << "ERROR! Could not find window!" << std::endl;
    		std::cin.clear();
    		std::cin.ignore(std::cin.rdbuf()->in_avail());
    		std::cin.get();	
    
    		return 1;
    	}
    
    	std::cout << "The window could be found!" << std::endl;
    
    	unsigned short child_windows = 0;
        for (hWnd = GetWindow(hWnd, GW_CHILD ); hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT), ++child_windows) 
    	{
            int nLen	= GetWindowTextLength(hWnd);
    		char* szBuffer = new char[nLen];
            GetWindowText(hWnd, szBuffer, nLen);
    		std::cout << "\tChildwindow [" << child_windows << "]  ->  " << szBuffer << std::endl;
    		delete [] szBuffer;
        }
    
    	std::cin.clear();
    	std::cin.ignore(std::cin.rdbuf()->in_avail());
    	std::cin.get();	
    
    	return 0;
    }
    

  • Mod

    unsigned short child_windows = 0; 
        for (hWnd = GetWindow(hWnd, GW_CHILD ); hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT), ++child_windows) 
        { 
            int nLen    = GetWindowTextLength(hWnd); 
            char* szBuffer = new char[nLen]; 
            GetWindowText(hWnd, szBuffer, nLen); 
            std::cout << "\tChildwindow [" << child_windows << "]  ->  " << szBuffer << std::endl; 
            delete [] szBuffer; 
        }
    

    Jedesmal ein alloc? Muss den wirklich so etwas sein?
    Vo rallem hast Du auch keinen Platz für das '\0' Zeichen reserviert.

    unsigned short child_windows = 0; 
        int nMaxLen = 1024;
        char* szBuffer = new char[nMaxLen];
        for (hWnd = GetWindow(hWnd, GW_CHILD ); hWnd; hWnd = GetWindow(hWnd, GW_HWNDNEXT), ++child_windows) 
        { 
            int nLen = GetWindowTextLength(hWnd)+1; 
            if (nLen>nMaxLen)
            {
                delete [] szBuffer;
                szBuffer = new char[nMaxLen=max(nMaxLen*2,nLen)];    
            }
            GetWindowText(hWnd, szBuffer, nLen); 
            std::cout << "\tChildwindow [" << child_windows << "]  ->  " << szBuffer << std::endl; 
        } 
        delete [] szBuffer;
    


  • Hmm stimmt war mir nicht sicher ob GetWindowTextLength jetzt den Terminator einbezieht ... naja ... hmm ok ist vllt so etwas performanter, allerdings hast du so selbst wenn es nur ein ganz kurzer String ist direkt 1024 reserviert ...



  • (D)Evil schrieb:

    hmm ok ist vllt so etwas performanter, allerdings hast du so selbst wenn es nur ein ganz kurzer String ist direkt 1024 reserviert ...

    Was ja immerhin 0,0001% der heutzutage üblichen 1 GB Hauptspeicher sind 🙂


Anmelden zum Antworten