Hello! Help if you can. You need to write a program through WinApi: hide all the child windows of the calculator and after a while display them. I wrote, but the program only works with one window (if you run two or more calculators, only one of them will be used). Tell me how to fix it.

program Project3; uses SysUtils, Windows; var h: HWnd; function Callback(h:hWnd; lParam: LPARAM): Bool; stdcall; begin ShowWindow(H, SW_HIDE); Result := True; end; function Callback1(h:hWnd; lParam: LPARAM): Bool; stdcall; begin ShowWindow(H, SW_SHOW); Result := True; end; begin h := FindWindow(nil, 'Калькулятор'); EnumChildWindows(h,@Callback,0); Sleep(1000); EnumChildWindows(h,@Callback1,0); end. 
  • @ Vladimir1234567, you did something wrong there. When I started this code, I first closed all the windows that were, and then all the child windows of all the programs hidden in the system opened. It is necessary to do the check h <> 0. - TimKruz

3 answers 3

You need to run 2 iterations - one on the windows of the top-level calculator, and the second, which will hide the child windows - obviously, on the child windows of each of the calculators.


Ie the code should look like this:

 handle := 0 EnumWindows(handle, @TopLevelHideCallback, 0); 

Next - TopLevelHideCallback has approximately the following logic

 { Получение заголовка делается с помощью последовательного применения функций GetWindowTextLength и GetWindowText } if GetWindowCaption(handle, ...) = 'Калькулятор' EnumChildWindows(handle, @ChildLevelHideCallback, 0) 

You can do the same for ShowCallback (when you need to display windows).

    And now we read attentively MSDN here and here . And we conclude that you do not have a window with the name "Calculator" at the time of launching the program, so the main code is equivalent to this

     h := null; // FindWindow(nil, 'Калькулятор'); EnumWindows(h,@Callback,0); Sleep(1000); EnumWindows(h,@Callback1,0); 

    That is, you just run through all the windows. Check <>null need only one.

     h := FindWindow(nil, 'Калькулятор'); if (h<>0) then begin EnumChildWindows(h,@Callback,0); Sleep(1000); EnumChildWindows(h,@Callback1,0); end else writeln('Калькулятор не найден.'); 

      I think we need to change the body of the program as follows:

       begin h:=FindWindow(nil, 'Калькулятор'); while h<>0 do begin //Что-нибудь делаем с окном, например, закрываем h:=FindWindow(nil, 'Калькулятор'); end; end. 

      Those. look for the window with the Calculator title, and while we find something (i.e., the pointer is not zero), we perform the necessary operation and look for such a window again. So we will process all windows. That's just it will work if the window closes. Because we do not close the windows, then we need to write to the database (a list, for example) all pointers that have already been processed. Then instead of "h <> 0" we write "(h <> 0) and (not already-is-in-base (pointer))", where "already-is-in-base (pointer)" is the function that performs the search on all processed pointers.
      But this is only one of the options.

      • one
        Have you tried this code?) I will bring the analogue: h: = 15; while h <> 0 do begin {* code code } h: = 15; end; And a shorter analogue: while 15 <> 0 do begin { code code *} end; - Sh4dow pm
      • Why won't this work? If the window is not found, then the pointer is zero. But I meant, if in the end all these windows are hidden. - TimKruz
      • You corrected after the comment, aha) and if the window is found, the cycle will close. - Sh4dow
      • And the difference, is it open or hidden? The window will not be found if 1) the window was closed, 2) changed the name. The author of the question neither wants one nor the other. - Sh4dow