![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос про Canvas.CopyRect и фактическую ширину формы. [D7, XP]
igorium © (2011-10-07 15:41:00)Всем привет.
Задача сохранить все, что видно на форме в графический файл.
Грубо говоря сделать принтскрин формы, но проблема усугубляется тем, что форма не помещается на экране, а для её просмотра нужно использовать скрулеры.
Я делаю так:
procedure TTreeForm.bbClick(Sender: TObject);
var Bit : TBitmap;
begin
Bit := TBitmap.Create;
Bit.Width := TreeForm.ClientWidth;
Bit.Height := TreeForm.ClientHeight;
Bit.Canvas.CopyRect(Rect(0, 0, TreeForm.ClientWidth, TreeForm.ClientHeight), TreeForm.Canvas, Rect(0, 0, TreeForm.ClientWidth, TreeForm.ClientHeight));
Bit.SaveToFile('d:\screen.bmp');
end;
Но сохраняется только видимая на экране часть формы.
А у меня форма занимает несколько экранов и нужно, чтобы ВСЯ форма сохранилась в файл.
Что интересно - у меня разрешение экрана 1024х768.
Я пробовал ручками увеличить ширину формы в инспекторе объектов - максимальная длина, которую он выдает - это 1036 пикселей.
Хотя реальная ширина формы у меня будет ~2400 (специально ставлю кнопку с left=400, width=2000)
я (2011-10-10 11:12:00) [1]
> Но опять 25 - сохраняется только ВИДИМАЯ часть формы.
> Вот результат твоего кода - http://i033.radikal.ru/1110/5a/0045b702572d.
> jpg
ну это да, сохраняет он область ограниченную самой формой это факт. Я на 80% уверен, что та часть которая не попала в форму - ее просто не существует в памяти, и если не вывести ее на форму соскринить ее не получится.
я (2011-10-10 11:06:00) [2]Мой код также сделает скрин если форма задвинута за край экрана, это к вопросу о невидимом )
ну если никто не знает как сделать форму шире экрана, то вариантов остается 2:
1) Сделать пустой BMP нужного размера. Программно скролить форму и делать каждый раз срин шот и добавлять каждый кусок в созданый бмп. вместо GetWindowRect(HWND, r); можно юзать GetClientRect(HWND, r);(пишу по памяти, на как то так) - тогда будет скринится только клиентская часть, а рамку пририсовать отдельно.
2)Подумать действительно ли все это так нужно и возможно сделать все как нибудь подругому )
igorium (2011-10-10 10:55:00) [3]
> я (10.10.11 10:42) [23]
> form2.Width:=50000;
>
> ха, форма действительно не становится шире экрана. А что
> на ней на этой форме размещается?
На форме размещается большое количество (~50-100) динамических панелей, каждую из них можно изменять, удалять.
> sniknik © (10.10.11 10:45) [24]
> развернуть, сохранить, свернуть на место...
Как "развернуть, сохранить, свернуть на место" ???
> sniknik © (10.10.11 10:45) [24]
> или создать канвас по размеру и нарисовать на нем самому.
Да на крайний случай буду делать так.
Просто нужно будет отрисовывать большое количество панелей, на каждом расположено несколько лабелов и картинка.
igorium (2011-10-10 10:47:00) [4]
> я (10.10.11 08:32) [21]
> > HWN := FindWindow(nil, windowName);
> может тут все таки ошибка по поводу "windowName"? т.к. у
> меня это переменная, в которую передается строка с названием
> окна. Впрочем у меня все сделано для любого приложения,
> а хендл своей формы думаю можно и подругому получать, если
> уж никак не работает )
Спасибо, разобрался.
Но опять 25 - сохраняется только ВИДИМАЯ часть формы.
Вот результат твоего кода - http://i033.radikal.ru/1110/5a/0045b702572d.jpg
sniknik (2011-10-10 10:45:00) [5]> Но КАК ИХ СОХРАНИТЬ ???
развернуть, сохранить, свернуть на место... ну или типа, т.к. вряд ли винда "рисует" не видимые/не нужные в данный момент контролы. (выйдет за границы экрана тоже не будет отрисовывать, ИМХО по логике, не занимался)
или создать канвас по размеру и нарисовать на нем самому... ну как с принтерным делают, формы же печатают. ну или типа, по логике, не занимался т.что кода для "копипаста" нет.
я (2011-10-10 10:42:00) [6]
form2.Width:=50000;
ха, форма действительно не становится шире экрана. А что на ней на этой форме размещается?
igorium (2011-10-10 10:24:00) [7]
> Игорь Шевченко © (09.10.11 23:30) [18]
> форму можно растянуть, подвигать...
Ну а толку с этой возможности...
Да, я могу растянуть форма по размеру экрана и WIDTH у меня будет равна разрешению экрана по горизонтали. А что мне это дает???
> sniknik © (09.10.11 23:46) [19]
> if HorzScrollBar.Tracking
> then Label1.Caption := Format('Form.Width = %d', [HorzScrollBar.
> Range])
> else Label1.Caption := Format('Form.Width = %d', [ClientWidth]);
Вот тут теплее - теперь я могу знать реальные размеры формы.
Но КАК ИХ СОХРАНИТЬ ???
я (2011-10-10 08:32:00) [8]
> HWN := FindWindow(nil, windowName);
может тут все таки ошибка по поводу "windowName"? т.к. у меня это переменная, в которую передается строка с названием окна. Впрочем у меня все сделано для любого приложения, а хендл своей формы думаю можно и подругому получать, если уж никак не работает )
я (2011-10-10 08:24:00) [9]
> Пробовал, но программа не смогла скомпилиться.
> Ошибка в 2-х местах -
> HWN := FindWindow(nil, windowName);
> PrintWindow(HWN, hSrcDC, 0);
> Программа не знает, что такое windowName и PrintWindow.
> Хотя в uses стоит Windows...
ПринтВиндовс нужно объявить сначала, это АПИ функция, а не функция делфи.
function PrintWindow(HWND: HWND; hdcBlt: HDC; nFlags: DWORD): BOOL; stdcall;
external 'user32.dll';
Если стоит Windows в юзес, то FindWindow должно работать, в сравке написано, что оно объявлено там. Хз в чем проблемма. Код 100% рабочий, т.к. я его из работающей свой проги скопировал.
Ну я уверен на 100% что программно форму можно расширить, выше даже чего то об этом написали уже.
sniknik (2011-10-09 23:46:00) [10]igorium ©
if HorzScrollBar.Tracking
then Label1.Caption := Format('Form.Width = %d', [HorzScrollBar.Range])
else Label1.Caption := Format('Form.Width = %d', [ClientWidth]);
Игорь Шевченко (2011-10-09 23:30:00) [11]
> И что я должен увидеть?
форму можно растянуть, подвигать...
igorium (2011-10-09 23:22:00) [12]
> Игорь Шевченко © (09.10.11 22:41) [16]
> Скомпилируй и проверь
И что я должен увидеть?
Label пишет
"Form.Width = ширина видимой части формы"
Игорь Шевченко (2011-10-09 22:41:00) [13]
> Банальное form1.width - это не ширина всей формы, а ширина
> видимой формы.
Это даже не смешно.
Скомпилируй и проверь
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
private
procedure WMSize (var Message: TMessage); message WM_SIZE;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{ TForm1 }
procedure TForm1.WMSize(var Message: TMessage);
begin
inherited;
Label1.Caption := Format('Form.Width = %d', [Width]);
end;
end.
igorium (2011-10-09 17:03:00) [14]Тут еще проблема в том, что Дельфи понимает под формой то, что видно на экране. Банальное form1.width - это не ширина всей формы, а ширина видимой формы.
Может можно извратиться и программно смещать форму, каждый раз делаю снимок экрана, а потом эти экраны склеивать?
igorium (2011-10-09 16:43:00) [15]Кстати не у меня одного такие проблемы.
В интернете нашел с десяток тем с подобными вопросами и не в одной не было решение данной проблемы :(
Здесь же у человека та же проблема, только с печатью - http://www.cyberforum.ru/delphi-beginners/thread170892.html
Неужели решения нет ???
igorium (2011-10-09 16:36:00) [16]Почему-то в ссылке в конце добавилась точка.
Исправляю адрес - http://narod.ru/disk/27792385001/delphi.rar.html
igorium (2011-10-09 16:33:00) [17]
> Loginov Dmitry © (08.10.11 22:41) [8]
> Должно работать.
> Может с файлами напутал?
Пробовал создать новую форму и играться с ней - такая же ерунда получается. Сохраняется только ВИДИМАЯ часть формы.
Можете посмотреть. Я скинул форму и проект на файлообменник - http://narod.ru/disk/27792385001/delphi.rar.html.
Заодно там есть BMP-файл, который получается.
> Cobalt © (08.10.11 23:37) [9]
> пройдись внутрь процедурки.
Какой процедурки?
Как пройтись?
Ничего не понял :(
> я (09.10.11 08:30) [10]
>...
> скрин окна приложения, если оно не свернуто, то скрин будет
> в не зависимости где оно находится и чем закрыто. Бегины
> не закрыты. Можно без DC делать, тогда код проще.
Пробовал, но программа не смогла скомпилиться.
Ошибка в 2-х местах -
HWN := FindWindow(nil, windowName);
PrintWindow(HWN, hSrcDC, 0);
Программа не знает, что такое windowNameи PrintWindow.
Хотя в uses стоит Windows...
> я (09.10.11 08:36) [11]
> ох, че то я сомневаюсь что то что не влезло можно спринтить.
> может программно расширять перед копированием, копировать
> и снова сжимать до экрана )
Как расширить и сжать?
Я на все согласен.
Главное, чтоб заработало...
я (2011-10-09 08:36:00) [18]
> тем, что форма не помещается на экране, а для её просмотра
> нужно использовать скрулеры.
ох, че то я сомневаюсь что то что не влезло можно спринтить. может программно расширять перед копированием, копировать и снова сжимать до экрана )
я (2011-10-09 08:30:00) [19]
var
tBmp2: TBitmap;
r: Trect;
hDC1: HDC;
hSrcDC: HDC;
hBmp: HBITMAP;
HWN: HWND;
begin
HWN := FindWindow(nil, windowName);
if (HWN > 32) then
begin
// GetWindowRect(HWND, r); //отыскивает размеры рамки ограничивающей прямоугольник определяемого окна
while (IsIconic(HWN)) do
ShowWindow(HWN, SW_SHOWNORMAL); // делает окно активным
sleep(200);
tBmp2 := TBitmap.Create;
tBmp2.PixelFormat := pf24bit;
GetWindowRect(HWN, r);
hDC1 := GetDC(HWN);
hSrcDC := CreateCompatibleDC(hDC1);
hBmp := CreateCompatibleBitmap(hDC1, r.right - r.left, r.bottom - r.top);
SelectObject(hSrcDC, hBmp);
PrintWindow(HWN, hSrcDC, 0);
BitBlt(hDC1, 0, 0, r.right - r.left, r.bottom - r.top, hSrcDC, 0,
0, SRCCOPY);
tBmp2.Handle := hBmp;
tBmp2.PixelFormat := pf24bit;
tBmp2.SaveToFile('E:\testscreen.bmp');
скрин окна приложения, если оно не свернуто, то скрин будет в не зависимости где оно находится и чем закрыто. Бегины не закрыты. Можно без DC делать, тогда код проще.
Cobalt (2011-10-08 23:37:00) [20]пройдись внутрь процедурки.