-
Можно ли получить полный скриншот окна, если его определенную часть перекрывает другое окно? Или это принципиально невозможно?
-
> 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
-
интересно, на каком принципе в висте превьюшки для панели задач сделаны? одно точно, что винап, с включенным modern-skin там отображается без этого скина )
-
Ну то что не все, примем на веру, хотя поясните, какое приложение не выводит. Вышеназванная функция ВООБЩЕ ничего не выводит. Ни у какого приложения, даже не перекрытого. Ну непорядок это.
В висте то далеко, есть пример поближе. В ХР, Aston shell, тоже показывает превьюшки. Кстати от Винампа там только квадратик виден... но калькулятор, блокнот, окно прогресса тотал командера и прочее и прочее (кроме некоторых игр) выводит в актуальном состоянии. Вот КАК? На сайте Астона сказали, что не могут сказать этого. ) WinSign показывает только следующие мессаги окну, когда для него генерится миниатюра: 000443:000209FC "Заголовок" WM_PAINT Sent (0,0)-(858,955) 000444:000209FC "Заголовок" WM_NCPAINT Sent wp=00000001! 000445:000209FC "Заголовок" WM_GETTEXT Sent 510 bytes at 0012E014 000446:000209FC "Заголовок" WM_PAINT Dispatched (0,0)-(858,955) 000447:000209FC "Заголовок" WM_PAINT Dispatched (0,0)-(858,955)
Обычные сообщения, но когда я такое посылаю, WinSign показывает не тот результат, что-то вроде
000440:00140A4C "Form1" WM_PAINT Sent lp=0012F558! (0,0)-(0,0) 000441:00140A4C "Form1" WM_NCPAINT Sent wp=00000001! 000442:00140A4C "Form1" WM_PAINT Sent wp=56011EE4! (0,0)-(0,0) шлю кодом SendMessage(wnd, WM_PAINT,0,longInt(@R)); SendMessage(wnd, WM_NCPAINT,1,0);
В общем не получается. Подскажите где неправ.
-
-
Удалено модератором Примечание: Создание пустых сообщений
|