Захват скриншота точно по границе окна.
Модератор: Модераторы
Захват скриншота точно по границе окна.
В общем раньше мене это было не очень важно . А тут программу в программу нужно добыть точный скрин без лишних сущностей в виде непонятных рамок (Похоже что оставленных для рисования тени ) по краям .
Зы
Можно конечно обрезать края самостоятельно ( размеры окна известны заранее ) но это явный "костыль" котрого хотелось бы избежать.
Зы
Можно конечно обрезать края самостоятельно ( размеры окна известны заранее ) но это явный "костыль" котрого хотелось бы избежать.
Re: Захват скриншота точно по границе окна.
НАйти форму, узнать размеры и координаты, преобразовать координаты в координаты экрана, сделать скриншот и обработать его по уже известной геометрии. Ну или сделать фокус на форму и имитировать нажатие Alt+PrtScr
Re: Захват скриншота точно по границе окна.
Спасибо, за отзыв но рецепт немного не годится так-как нужно получить скрин свернутой или перекрытой формы. (хочу использовать для создания простого "пространственного" GUI интерфейса в OpenGL )
Select3D_test05_8_6_01_500.jpg
Свернутое окно пока не видит, но перекрытое или "спрятанное" например "по отрицательным координатам" видно отлично.(однако "рамка" все равно напрягает )
Select3D_test05_8_6_01_500.jpg
Свернутое окно пока не видит, но перекрытое или "спрятанное" например "по отрицательным координатам" видно отлично.(однако "рамка" все равно напрягает )
Последний раз редактировалось Alex2013 03.05.2023 22:58:12, всего редактировалось 1 раз.
Re: Захват скриншота точно по границе окна.
Если в окне уже контекст OpenGL, просто сделай скрин с помощью него.
Ну... или обрежь этот скрин...
Ну... или обрежь этот скрин...
Re: Захват скриншота точно по границе окна.
Снапшотить GUI окно это еще тот прикол.
не проще рисовать само окно в OGL
не проще рисовать само окно в OGL
Re: Захват скриншота точно по границе окна.
Seenkao писал(а):Если в окне уже контекст OpenGL, просто сделай скрин с помощью него.
Ну... или обрежь этот скрин...
1 "А что так можно?"
2 Обрезать можно но есть сомнения, что при включенном масштабировании и прочих приколах винды это будет работать всегда .
.
Мне бы найти что-то вроде Си-шного "Control.DrawToBitmap" .
То есть запустить прорисовку окна в место стандартного "дисплейного контекста" на контекст Bitmap .
Зы
Вообще то это разумеется изрядная блаж и вывод GUI форм в OpenGL делается совсем иначе...
FGL_240.jpg
.. но идея что называется "подкупает простотой".
Добавлено спустя 27 минут 3 секунды:
olegy123 писал(а):не проще рисовать само окно в OGL
Именно ! Просто кажется что скриншотить окно "вроде как проще", а на поверку "хрен его знает" .
Для теста сделал захват по таймеру + рисовал курсор мыши (причем по глобальным координатам).
Если идея окажется рабочей буду транслировать нужные события непосредственно в форму.
(Принципе если спрятать окно по отрицательным координатам то рамка всегда будет черная и можно или обрезать окно по черным краям или сделать "прозрачный цвет" но это все равно как-то "костыльно получается" )
Последний раз редактировалось Alex2013 03.05.2023 22:59:23, всего редактировалось 1 раз.
Re: Захват скриншота точно по границе окна.
А вот такую процедурку не пробовал?
Емнип, если окно свёрнуто, она нарисует картину малевича.
Код: Выделить всё
uses
..., LclType, LclIntf;
...
procedure TForm1.Screenshot;
var
pic: TPicture;
dc: hdc;
begin
pic := TPicture.Create;
try
dc := GetDC(Handle);
if dc <> 0 then
begin
pic.Bitmap.LoadFromDevice(dc);
ReleaseDC(Handle, dc);
pic.SaveToFile('screen.png');
end;
finally
pic.Free;
end;
end;
Емнип, если окно свёрнуто, она нарисует картину малевича.
Re: Захват скриншота точно по границе окна.
У меня похожая штуковина...
А LoadFromDevice у меня не работает (То есть возможно на запись в файл все идет нормально но "текстуру не подхватывает" совсем )
Зы
Ещё пробовал PrintWindow вместо BitBlt (или StretchBlt) использовать ...
(Как-то так PrintWindow(wnd, B.Canvas.Handle, 0); )
Но от использования PrintWindow что-то нездоровое на исходной форме происходит....
Зы Зы
Вообщем похоже что там какие-то заморочки с форматом ( то что получается при чтении по HDC или HWND не заполняет всех нужных полей в ТBitmap даже мой "фирменный" захват через BitBlt работает как источник текстур только после странной "само-перерисовки " типа этой bmp.Canvas.Draw(0,0,bmp);)
Код: Выделить всё
procedure TCaptureForm.CreateSnapshotPlusWH (var B:TBitmap;W,H:Integer;WindowHD:HWND;Sbs:Integer);
var
wnd:HWND;
dc:HDC;
r:TRect;
X,WS,HS:Longint;
begin
If B=Nil then exit;
wnd :=WindowHD;
if wnd = 0 then
begin
dc := GetDC(0);
Ws:=Screen.Width;
Hs:=Screen.Height;
end
else
begin
dc := GetWindowDC(wnd);
GetWindowRect(wnd,r);
Ws:=r.Right-r.Left;
Hs:=r.Bottom-r.Top;
end;
if SBS in [1,2] then ws:=ws div 2;
if SBS in [0,1] then X:=0;
if SBS = 2 then x:=ws;
b.SetSize(W,H);
StretchBlt(B.Canvas.Handle,0,0,B.Width,B.Height,DC,x,0,WS,HS,SRCCOPY);
ReleaseDC(wnd,dc);
end;
А LoadFromDevice у меня не работает (То есть возможно на запись в файл все идет нормально но "текстуру не подхватывает" совсем )
Зы
Ещё пробовал PrintWindow вместо BitBlt (или StretchBlt) использовать ...
(Как-то так PrintWindow(wnd, B.Canvas.Handle, 0); )
Но от использования PrintWindow что-то нездоровое на исходной форме происходит....
Зы Зы
Вообщем похоже что там какие-то заморочки с форматом ( то что получается при чтении по HDC или HWND не заполняет всех нужных полей в ТBitmap даже мой "фирменный" захват через BitBlt работает как источник текстур только после странной "само-перерисовки " типа этой bmp.Canvas.Draw(0,0,bmp);)
Re: Захват скриншота точно по границе окна.
Alex2013 писал(а):Спасибо, за отзыв но рецепт немного не годится так-как нужно получить скрин свернутой или перекрытой формы. (хочу использовать для создания простого "пространственного" GUI интерфейса в OpenGL )
Ну так надо было говорить, что все должно быть супер круто как в кино))
Re: Захват скриншота точно по границе окна.
Sharfik писал(а):Ну так надо было говорить, что все должно быть супер круто как в кино))
У меня сейчас даже немного круче чем "в кино"... по тому что проект крутится вокруг ВиАр-технологии что неплохо его стимулирует . ("просто трехмерный интерфейс" на экране компьютера это сейчас довольно банально и чуть уныло ) Правда это не отменяет того факта что я еще даже в OpenGL еще "плаваю" почти по полной программе. (Весь "редер" моей "типа ВиАр" техно-демки занимает пока от силы пару сот строк кода )
Но "дорогу осилит идущий" ...
(Кстати глядя на этот скрин уже можно догадаться куда идет разработка... )
Select3D_test05_8_6_02_800.jpg
"Лазарус ВР" ?
Последний раз редактировалось Alex2013 03.05.2023 23:01:08, всего редактировалось 1 раз.
Re: Захват скриншота точно по границе окна.
Код: Выделить всё
type
TWindowManagerRect = record left, top, width, height: longint end;
function TWinApiFramework.GetWindowClientRect(): TWindowManagerRect;
var
r: TRect; //winapi type
point: TPoint; //winapi type
begin
point.x:= 0;
point.y:= 0;
with Framework as TWinApiFramework do begin
GetClientRect(WindowHandle, r); //winapi. This syka always returns 0,0 for the top left corner!
ScreenToClient(WindowHandle, point); //winapi
end;
Result:= WindowsRectToWmRect(r); //
Result.Top-= point.y;
Result.Left-= point.x;
end;
function WindowsRectToWmRect(r: TRect): TWindowManagerRect;
begin
Result.left:= r.left;
Result.top:= r.top;
Result.width:= r.Right - r.left;
Result.height:= r.Bottom - r.top;
end;
function TWinApiFramework.GetWindowOuterRect(): TWindowManagerRect;
var r: TRect;
begin
GetWindowRect(WindowHandle, r); // winapi
Result:= WindowsRectToWmRect(r);
end;
Добавлено спустя 9 минут 33 секунды:
Также,
To get the window bounds excluding the drop shadow, use DwmGetWindowAttribute, specifying DWMWA_EXTENDED_FRAME_BOUNDS. Note that unlike the Window Rect, the DWM Extended Frame Bounds are not adjusted for DPI. Getting the extended frame bounds can only be done after the window has been shown at least once.
Добавлено спустя 2 минуты 3 секунды:
Также,
In conformance with conventions for the RECT structure, the bottom-right coordinates of the returned rectangle are exclusive. In other words, the pixel at (right, bottom) lies immediately outside the rectangle.
Re: Захват скриншота точно по границе окна.
Спасибо, попробую ! 
Re: Захват скриншота точно по границе окна.
Нашел я вот такую штуку на Си ...
Код: Выделить всё
public static Bitmap CaptureWindow(IntPtr wnd, WindowSettings settings, out SIZE size, out Win32Stuff.WINDOWINFO info)
{
IntPtr hBitmap;
IntPtr hDC = Win32Stuff.GetDC(Win32Stuff.GetDesktopWindow());
IntPtr hMemDC = GDIStuff.CreateCompatibleDC(hDC);
info = new Win32Stuff.WINDOWINFO();
info.cbSize = (uint)Marshal.SizeOf(info);
Win32Stuff.GetWindowInfo(wnd, ref info);
size.cx = Math.Max(1, info.rcClient.Width + settings.offsetRight - settings.offsetLeft);
size.cy = Math.Max(1, info.rcClient.Height + settings.offsetBottom - settings.offsetTop);
hBitmap = GDIStuff.CreateCompatibleBitmap(hDC, size.cx, size.cy);
if (hBitmap != IntPtr.Zero)
{
IntPtr hOld = (IntPtr)GDIStuff.SelectObject(hMemDC, hBitmap);
GDIStuff.BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, info.rcWindow.X + settings.offsetLeft, info.rcWindow.Y + settings.offsetTop, GDIStuff.SRCCOPY);
GDIStuff.SelectObject(hMemDC, hOld);
GDIStuff.DeleteDC(hMemDC);
Win32Stuff.ReleaseDC(Win32Stuff.GetDesktopWindow(), hDC);
Bitmap bmp = System.Drawing.Image.FromHbitmap(hBitmap);
GDIStuff.DeleteObject(hBitmap);
GC.Collect();
return bmp;
}
return null;
}
Re: Захват скриншота точно по границе окна.
А возможно создать сферу и натянуть на внутреннюю поверхность картинку? Разместив тв центре камеру?


