Конференция "Основная" » Как получиьт изображение окна?
 
  • @!!ex © (06.12.07 21:27) [0]
    Задача.
    Есть несколько открытых окон. Некоторые видны полностью, некоторые частично перекрыты, некоторые вообще не видны под другими окнами.
    Задача в том, чтобы в программе получит скриншот для всех окон.
    Способ точно есть, но я даже не представляю куда копать.
  • Черный Шаман (06.12.07 21:42) [1]
    Тебе скриншот всего десктопа или каждого из окон?
  • @!!ex © (06.12.07 21:43) [2]
    > [1] Черный Шаман   (06.12.07 21:42)

    Каждого окна.
  • ANTPro © (06.12.07 22:02) [3]
    > [2] @!!ex ©   (06.12.07 21:43)

    Бежать по всем верхним видимым окнам и сохранять нарисованное на DC?
  • @!!ex © (06.12.07 22:03) [4]
    Нашел вот такой код:
    procedure ScreenShot(hWindow: HWND; bm: TBitmap);
    var
     Left, Top, Width, Height: Word;
     R: TRect;
     dc: HDC;
     lpPal: PLOGPALETTE;
    begin
     {Check if valid window handle}
     if not IsWindow(hWindow) then Exit;
     {Retrieves the rectangular coordinates of the specified window}
     GetWindowRect(hWindow, R);
     Left := R.Left;
     Top := R.Top;
     Width := R.Right - R.Left;
     Height := R.Bottom - R.Top;
     bm.Width  := Width;
     bm.Height := Height;
     {get the screen dc}
     dc := GetDc(0);
     if (dc = 0) then
      begin
       Exit;
     end;
     {do we have a palette device?}
     if (GetDeviceCaps(dc, RASTERCAPS) and
       RC_PALETTE = RC_PALETTE) then
      begin
       {allocate memory for a logical palette}
       GetMem(lpPal,
         SizeOf(TLOGPALETTE) +
       (255 * SizeOf(TPALETTEENTRY)));
       {zero it out to be neat}
       FillChar(lpPal^,
         SizeOf(TLOGPALETTE) +
       (255 * SizeOf(TPALETTEENTRY)),
         #0);
       {fill in the palette version}
       lpPal^.palVersion := $300;
       {grab the system palette entries}
       lpPal^.palNumEntries :=
         GetSystemPaletteEntries(dc,
         0,
         256,
         lpPal^.palPalEntry);
       if (lpPal^.PalNumEntries <> 0) then
        begin
         {create the palette}
         bm.Palette := CreatePalette(lpPal^);
       end;
       FreeMem(lpPal, SizeOf(TLOGPALETTE) +
       (255 * SizeOf(TPALETTEENTRY)));
     end;
     {copy from the screen to the bitmap}
     BitBlt(bm.Canvas.Handle,
       0,
       0,
       Width,
       Height,
       Dc,
       Left,
       Top,
       SRCCOPY);
     {release the screen dc}
     ReleaseDc(0, dc);
    end;


    Но он задачку не решает.
    Это все равно скриншот не окна, а области где это окно расположено. Соответственно, если поверх окна есть другое окно, изображение будет содержать это "другое" окно.
    Он получает область окна, но если оно перекрыто, то получается
  • @!!ex © (06.12.07 22:06) [5]
    > [3] ANTPro ©   (06.12.07 22:02)

    Не понял...
  • turbouser © (06.12.07 22:09) [6]

    > @!!ex ©   (06.12.07 22:06) [5]

    Перебираешь все окна, выставляешь их на передний план и затем скриншот.
    ps
    честно говоря, непонятная затея...
  • @!!ex © (06.12.07 22:11) [7]
    > [6] turbouser ©   (06.12.07 22:09)

    Если выставлять их на передний план, то юзер видит как это все происходит. Да и обратно окно уже не вернуть....
    Затея банальна - делаю менеджер окон.
  • turbouser © (06.12.07 22:29) [8]

    > @!!ex ©   (06.12.07 22:11) [7]
    > Затея банальна - делаю менеджер окон.

    И при этом обязательно иметь скриншот?
    В висте есть такая возможность, не спорю, в мсдн наверняка
    можно найти информацию на эту тему.
    Но вот под 2к/ХР - сильно сомневаюсь, что такое возможно.
  • @!!ex © (06.12.07 23:02) [9]
    > [8] turbouser ©   (06.12.07 22:29)

    Я же в [0] сказал что возможно... :(
    Не верите, см. TopDesk
  • Инс (06.12.07 23:06) [10]
    procedure GetWindowBitmap(Wnd: HWND; Bmp: TBitmap);
    var
    R: TRect;
    begin
    GetWindowRect(Wnd, R);
    Bmp.Width:= R.Right - R.Left;
    Bmp.Height:= R.Bottom - R.Top;
    Bmp.Canvas.Lock;
    try
      SendMessage(Wnd, WM_PRINT, Integer(Bmp.Canvas.Handle), PRF_NONCLIENT or PRF_CHECKVISIBLE or
        PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN);
    finally
      Bmp.Canvas.Unlock;
    end;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    var
     Bitmap: TBitmap;
    begin
     Bitmap:=TBitmap.Create;
     try
       GetWindowBitmap(Handle,Bitmap);
       Bitmap.SaveToFile('C:\1.bmp');
     finally
       Bitmap.Free;
     end;
    end;



    На XP и выше можно использовать функцию PrintWindow
  • @!!ex © (06.12.07 23:09) [11]
    > [10] Инс   (06.12.07 23:06)

    Хм. А вы уверены, что этот код работает?
    А если окно не обрабатывает сообщение WM_PRINT?
    Во всяком случае у меня получилось 12 белых прямоугольников после сохранения....

    PrintWindow - это что? В хелпе не нашел...
  • Ins © (06.12.07 23:12) [12]

    > Хм. А вы уверены, что этот код работает?

    С большинством окон работает, даже где-то в каком-то своем проекте использовал.


    > PrintWindow - это что? В хелпе не нашел...

    Плохо искали. В MSDN
  • @!!ex © (06.12.07 23:13) [13]
    > [10] Инс   (06.12.07 23:06)

    Ваш код действительно работает... Получает скриншот формы.
    А мой работать не хочет, сохраняет белые квадраты:
    procedure GetWindowBitmap(Wnd: HWND; Bmp: TBitmap);
    var
    R: TRect;
    begin
    GetWindowRect(Wnd, R);
    SetFocus(Wnd);
    Bmp.Width:= R.Right - R.Left;
    Bmp.Height:= R.Bottom - R.Top;
    Bmp.Canvas.Lock;
    try
     SendMessage(Wnd, WM_PRINT, Integer(Bmp.Canvas.Handle), PRF_NONCLIENT or PRF_CHECKVISIBLE or
       PRF_CLIENT or PRF_ERASEBKGND or PRF_CHILDREN);
    finally
     Bmp.Canvas.Unlock;
    end;
    end;

    Function EnumWindowsProc(WND:HWND; LParam:Integer):Boolean;
    begin
    if IsWindowVisible(WND)=True then begin
      GetWindowBitmap(WND,BitMap);
      BitMap.SaveToFile('C:\Temp\'+IntTOStr(Wnd)+'.bmp');
    end;
    Result:=True;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
     BitMap:=TBitMap.Create;
     EnumWindows(@EnumWindowsProc,0);
     BitMap.Free;
    end;
  • @!!ex © (06.12.07 23:14) [14]
    > Плохо искали. В MSDN

    НЕту MSDN под рукой. :(
    поищу в онлайн MSDN'e.
  • homm © (06.12.07 23:15) [15]
    > [9] @!!ex ©   (06.12.07 23:02)
    > Я же в [0] сказал что возможно... :(

    Ну раз сказал :)
    Жаль что майкросовт об этом не знала, когда 9х и 2к писала :(
  • @!!ex © (06.12.07 23:18) [16]
    > [15] homm ©   (06.12.07 23:15)

    Так я не от балды сказал. :)
    Есть пример работающей программы, которая это делает.
  • homm © (06.12.07 23:23) [17]
    > [16] @!!ex ©   (06.12.07 23:18)
    > Есть пример работающей программы, которая это делает.

    в ХП ?
  • @!!ex © (06.12.07 23:24) [18]
    > [17] homm ©   (06.12.07 23:23)

    Да. Вроде в 2000 она тоже работает. TopDesk
  • homm © (06.12.07 23:25) [19]
    > [18] @!!ex ©   (06.12.07 23:24)

    Вроде?
 
Конференция "Основная" » Как получиьт изображение окна?
Есть новые Нет новых   [133939   +173][b:0][p:0.002]