-
Можно ли получить полный скриншот окна, если его определенную часть перекрывает другое окно? Или это принципиально невозможно?
-
> Bora.ru (17.09.2007 20:32:00) [0]
Принципиально не возможно, только выводить на другое окно.
-
> [1] Anatoly Podgoretsky © (17.09.07 20:33) > Принципиально не возможно,
… но есть всякие частные случаи. Можно поиграться с SendMessage(WM_PAINT, 0, DC)
-
А если попробовать получить хэндл активного окна, сделать активным нужное, снять скрин и "вернуть" активное приложение в фокус? Разве не сработает?
-
Тьфу, хэндл не активного, а перекрывающего окна...
-
> Dimaxx © (18.09.07 00:13) [4]
Ждём-с ещё одно "Тьфу" :-)
-
Хватит и одного "тьфу". Вернуть "на место" надо именно активное. :)
-
Можно. Только есть масса особенностей. Лучше всего обычно работает PrintWindow но сразу же получаем ограничение Win2000. Есть еще сообщение WM_PRINT но далеко не все окна его правильно обрабатывают. Можно попробывать еще что-то вроде такого: type
PPaintData = ^TPaintData;
TPaintData = record
Parent: HWND;
DC: HDC;
end;
procedure PaintWindowToDC(Wnd: HWND; Bmp: TBitmap);
var
R: TRect;
PD: TPaintData;
function EnumWnd(Wnd: HWND; P: PPaintData): bool; stdcall;
var
SDC: integer;
R: TRect;
PD: TPaintData;
begin
try
GetWindowRect(Wnd, R);
Windows.ScreenToClient(P.Parent, R.TopLeft);
SDC:= SaveDC(P.DC);
try
SetViewportOrgEx(P.DC, R.Left, R.Top, nil);
SendMessage(Wnd, WM_ERASEBKGND, integer(P.DC), 0);
SendMessage(Wnd, WM_PAINT, integer(P.DC), 0);
PD.Parent:= Wnd;
PD.DC:= P.DC;
EnumChildWindows(Wnd, Addr(EnumWnd), integer(@PD));
finally
RestoreDC(P.DC, SDC);
end;
Result:= true;
except
Result:= false;
end;
end;
begin
GetClientRect(Wnd, R);
Bmp.Width:= R.Right;
Bmp.Height:= R.Bottom;
PD.Parent:= Wnd;
Bmp.Canvas.Lock;
try
PD.DC:= Bmp.Canvas.Handle;
SendMessage(Wnd, WM_ERASEBKGND, integer(PD.DC), 0);
SendMessage(Wnd, WM_PAINT, integer(PD.DC), 0);
EnumChildWindows(Wnd, Addr(EnumWnd), integer(@PD));
finally
Bmp.Canvas.Unlock;
end;
end; Функция не моя (копирайт - Набережных Сергей), сам не пробовал.
-
SetViewportOrgEx(P.DC, R.Left, R.Top, nil);
SendMessage(Wnd, WM_ERASEBKGND, integer(P.DC), 0);
SendMessage(Wnd, WM_PAINT, integer(P.DC), 0); Не хватает еще, как минимум SendMessage(Wnd, WM_PRINT, integer(P.DC), PRF_CLIENT);
-
SendMessage(Wnd, WM_PRINT, integer(P.DC), PRF_CLIENT); Т.е. наоборот, PRF_NONCLIENT
-
> Не хватает еще, как минимум
Ну да, логично, но если использовать WM_PRINT, то можно вообще одной строкой кода отделаться.
-
> [10] Инс © (18.09.07 20:48) > Ну да, логично, но если использовать WM_PRINT, то можно > вообще одной строкой кода отделаться.
Как раз нельзя. Принт понимают куда меньшее количество контролов, чем WM_PAINT, integer(P.DC). И уж совсем филосовское понимание сообщений у RichEdit, которому вообще все по барабану.
-
> [11] homm © (18.09.07 21:05)
Однажды, кстати, столкнулся с проблемой, где один контрол никак не хотел себя рисовать правильно, какое бы сообщение (WM_PAINT, WM_PRINT) ему не посылать. Причем контрол какой-то самопальный. Там проблема была оказалось в том, что в обработчике WM_PAINT прорисовка осуществлялась не на DC, который был передан в качестве параметра. Автор компонента заново получал DC с помощью GetDC(Handle) и рисовал на нем. Что получалось в результате вполне понятно - возвращался пустой квадрат, а контрол перерисовывался. Но PrintWindow, как ни странно, выдавал правильный результат. Интересно, как он работает, судя по этому эксперименту, не через WM_PRINT, как можно было бы подумать...
-
> [12] Инс © (18.09.07 21:39) > Интересно, как он работает, судя по этому эксперименту, > не через WM_PRINT
Как ни странно,Ю в справке сказано, что именно через WM_PRINT. Вполне возможно врут :)
-
> Вполне возможно врут :)
Черт его знает. Видимо не врут, просто алгоритм сложнее, чем мы его себе представляем. GetWindowText тоже через WM_GETTEXT работает, но посылка сообщения почему-то дает правильный результат постабильнее...
-
> Вполне возможно врут :)
Скорее всего на более низком уровне PrintWindow работает, чем просто отослать сообщение.
-
> [14] Инс © (18.09.07 22:02) > Видимо не врут, просто алгоритм сложнее, чем мы его себе > представляем.
Помоему в описании была (лень снова открывть) фраза «similar to WM_PRINT» :)
-
> [16] homm © (18.09.07 22:13)
А уж как мне лень, блин, кто бы мог только представить... :)
Remarks
This function is similar to WM_PRINT.
Плюс, я в [7] наврал немного. В WinXP она только появилась, если верить MSDN.
-
ап. :( Приведенная функция PaintWindowToDC вообще ничего не снимает с приложения, только размеры определяет. Или я не правильно её вызываю? PaintWindowToDC(wnd,image1.Picture.Bitmap);
Как я понял, проблема топика не решена?
-
не все йогурты умеют себя выводить на произвольный DC
|