procedure TfrmMain.Button1Click(Sender: TObject);
var
R: Integer;
begin
with btmImage1 do {Если заменить на Image1, то все работает так как надо}
begin
PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);
Canvas.Pen.Color := clBlack;
R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
// Изменение направления координатных осей
SetWindowExtEx(Canvas.Handle, 1, 1, nil);
SetViewportExtEx(Canvas.Handle, - 1, - 1, nil);
// Изменение расположения начала координат
SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
Canvas.Rectangle(10, 10, 50, 30);
SetMapMode(Canvas.Handle, R);
end;
Image1.Canvas.Draw(0,0,btmImage1);
end;
В результате выполнения Button1Click объект Image1 просто заполяется белым цветом.
Если же выполнить рисование непосредственно на Image1, то отрисовка пройдет нормально.
В чем причина?
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
07-11-2008 02:55
нигде не нашел почему так следует делать
Это же Виндоус, так что только опытным путём. (разбираться и перечитывать MSDN времени нет)
при вызове метода SaveToFile, преобразование параметров осей у приемника btmImage2 не требуется?
Скорее всего (ну это же Виндоус), при сохранении, контект Bitmap.Canvas приводится к необходимому для сохранения виду, после чего его можно копировать в другие стандартные контексты без преобразования осей.
Для Александр Пугачёв:
Главная проблема здесь в том, что происходит смена параметров осей. Поэтому чтобы скопировать из одного Bitmap в другой необходимо, чтобы оси у них были настроены идентично.
Спасибо действительно работает, только нигде не нашел почему так следует делать и почему при вызове метода SaveToFile, преобразование параметров осей у приемника btmImage2 не требуется?
Для Антон Григорьев и ploop:
Всё было праивльно сказано. TImage - это когда надо отображать одну отдельно взятую готовую картинку. Как только вы собираете картинку из нескольких элементов, пусть даже каждый из этих элементов является bitmap'ом, про TImage лучше забыть - не приспособлен он для этого, глюков очень много.
Старожилы Круглого стола уже устали отвечать на вопросы, связанные с этими глюками. Но люди почему-то обычно предпочитают не слушать хорошие советы и выкидывать TImage на фиг, а с упорством, достойным лучшего применения, прыгать и прыгать на эти грабли.
Иля я не правильно объясняю или вы понять не можете, НЕ ИСПОЛЬЗУЮ Я В РЕАЛЬНОЙ РАБОТЕ TImage. ИСПОЛЬЗУЮ TBitmap, а TImage здесь был лишь для ИЛЛЮСТРАЦИИ.
И следующий код работает неверно и там НЕТ TImage:
with btmImage1 do
begin
PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);
Canvas.Pen.Color := clBlack;
R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
// Изменение направления координатных осей
SetWindowExtEx(Canvas.Handle, 1, 1, nil);
SetViewportExtEx(Canvas.Handle, - 1, - 1, nil);
// Изменение расположения начала координат
SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
Canvas.Rectangle(10, 10, 50, 30);
SetMapMode(Canvas.Handle, R);
end;
{ если поставить сюда btmImage1.SaveToFile('c:\test1.bmp') то все работает верно}
Главная проблема здесь в том, что происходит смена параметров осей. Поэтому чтобы скопировать из одного Bitmap в другой необходимо, чтобы оси у них были настроены идентично.
У меня всё нормально работает, предлагаю свой код:
procedure TForm1.Button1Click(Sender: TObject);
var
R, R2, R3: Integer;
begin
with btmImage1 do
begin
PatBlt(Canvas.Handle, 0, 0, Width, Height, WHITENESS);
Canvas.Pen.Color := clBlack;
R := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
// Изменение направления координатных осей
SetWindowExtEx(Canvas.Handle, 1, 1, nil);
SetViewportExtEx(Canvas.Handle, -1, -1, nil);
// Изменение расположения начала координат
SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
Canvas.Rectangle(10, 10, 50, 30);
end;
with btmImage2 do
begin
R2 := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
SetWindowExtEx(Canvas.Handle, 1, 1, nil);
SetViewportExtEx(Canvas.Handle, -1, -1, nil);
SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
BitBlt(btmImage2.Canvas.Handle, 0, 0, btmImage2.Width, btmImage2.Height,
btmImage1.Canvas.Handle, 0, 0, SRCCOPY);
end;
with Image1 do
begin
R3 := SetMapMode(Canvas.Handle, MM_ISOTROPIC);
SetWindowExtEx(Canvas.Handle, 1, 1, nil);
SetViewportExtEx(Canvas.Handle, -1, -1, nil);
SetViewportOrgEx(Canvas.Handle, Width, Height, nil);
BitBlt(Canvas.Handle, 0, 0, Width, Height,
btmImage1.Canvas.Handle, 0, 0, SRCCOPY);
end;
function TImage.GetCanvas: TCanvas;
var
Bitmap: TBitmap;
begin
if Picture.Graphic = nil then
begin
Bitmap := TBitmap.Create; // Создаётся промежуточный битмап
try
Bitmap.Width := Width;
Bitmap.Height := Height;
Picture.Graphic := Bitmap; // Битмап копируется (Assign) в новый объект Graphic
finally
Bitmap.Free;
end;
end;
if Picture.Graphic is TBitmap then
Result := TBitmap(Picture.Graphic).Canvas
// Далее идёт обращение к Canvas довольно сложного объекта Graphic, где-то там и проблема
else
raise EInvalidOperation.Create(SImageCanvasNeedsBitmap);
end;
Про это и говорят, что TImage создан для показа статичных изображений
Вы невнимательно прочли.
P.S. Данный код является лишь иллюстрацией проблемы.
Всё было праивльно сказано. TImage - это когда надо отображать одну отдельно взятую готовую картинку. Как только вы собираете картинку из нескольких элементов, пусть даже каждый из этих элементов является bitmap'ом, про TImage лучше забыть - не приспособлен он для этого, глюков очень много.
Старожилы Круглого стола уже устали отвечать на вопросы, связанные с этими глюками. Но люди почему-то обычно предпочитают не слушать хорошие советы и выкидывать TImage на фиг, а с упорством, достойным лучшего применения, прыгать и прыгать на эти грабли.
и именно для них хочется понят в чем заключается проблема и как ее решить.
Вам говорят, что проблема не с битмапами, а с выводом на TImage, т.к. он не предназначен для этого.
Такой вариант вариант работает, но не подходит по ряду причин: напрмер, если я захочу, вывести отрисовать на одном Image1 несколько объектов TBitmap.
Соберите в промежуточный битмап все остальные и отрисуйте. Но еще раз повторю, это не хороший вариант. Лучше использовать PaintBox.
Для Александр Пугачёв:
В таком случае советую использовать PaintBox и собирать итоговое изображение по событию OnPaint.
Хотя, я бы собирал итоговое изображение в промежуточный Bitmap, а потом отрисовывал бы в PaintBox.
Компонент Image плохо подходит для задач отрисовки в Runtime, я данный компонент использую в основном для показа картинок из файлов.
Вы невнимательно прочли.
P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.
P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.
В таком случае советую использовать PaintBox и собирать итоговое изображение по событию OnPaint.
Хотя, я бы собирал итоговое изображение в промежуточный Bitmap, а потом отрисовывал бы в PaintBox.
Компонент Image плохо подходит для задач отрисовки в Runtime, я данный компонент использую в основном для показа картинок из файлов.
Для ploop:
Битмап выводится куда угодно, хоть прямо на форму. Если уж так хочется TImage использовать - работает такой вариант:
Image1.Picture.Assign(btmImage1);
Такой вариант вариант работает, но не подходит по ряду причин: напрмер, если я захочу, вывести отрисовать на одном Image1 несколько объектов TBitmap.
Для Александр Пугачёв:
...Проверяется просто:
btmImage1.SaveToFile('c:\test.bmp');
Действительно все работает, и самое интересное, что если поставить вызов метода SaveToFile, перед вызовом Draw, то и отрисуется все нормально... пошел изучать таинство SaveToFile :)
P.S. Данный код является лишь иллюстрацией проблемы. Исходная же задача:
- есть несколько "теневых" слоёв, которые являются объектами TBitmap.
- есть "визуальный" слой (тоже TBitmap) который компануется из "теневых".
т.е. вся работа ведется с объектами TBitmap, и именно для них хочется понят в чем заключается проблема и как ее решить.
06-11-2008 12:34 | Комментарий к предыдущим ответам
Попробуйте сразу после создания btmImage1 сделать btmImage1.PixelFormat:=pf24Bit;
Я пробовал. И другие варианты. Ничего... А досканально разобраться времени нет.
Выяснил, если убрать SetMapMode(Canvas.Handle, R) - начинает работать. Но неправильно. В принципе код то правильный, но почему не работает - выяснять надо...
plool
Попробуйте переписать без with, может, не к тому Canvas обращение идёт.
Нет конструкция with тут не причем (результат работы без with точно такой же)
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.