Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.09.26;
Скачать: CL | DM;

Вниз

Буфер или не буфер...   Найти похожие ветки 

 
DeadMeat ©   (2004-08-16 00:36) [0]

Здрассте всем.
У меня такая вот странная ситуация. Есть *.DLL-ка в чужом процессе (внедрена мною). Есть map файл, открытый для общего пользования. Через него мне надо передать от этой *.DLL-ке, некий hBitmap, для отрисовки его "содержимого" в своей программе.
hBitmap существует и его содержимое "реально", т.е. из самой *.DLL-ки можно его отрисовать.
Вопрос: почему он не отрисовывается у меня в программе?
Вот код *.DLL-ки:
.....
const MMFName="Window_Shooter";

type
 PBufDat=^TBufDat;
 TBufDat=packed record
  hnd:hwnd;
  bufbit:hbitmap;
  bufrect:trect;
 end;

var
 rBufDat:PBufDat=nil;
 hMapObject:THandle=0;

.....
hMapObject:=CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TBufDat), MMFName);
rBufDat:=MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TBufDat));
shotwindow (rBufDat^.hnd);
.....

procedure ShotWindow(hnd: HWND);
var hdcmem:hdc;
   bufrect:trect;
   dc:hdc;
   hold:HGDIOBJ;
   evhnd:thandle;
begin
hDCMem:=CreateCompatibleDC(0);
GetWindowRect(hnd,bufrect);

DC:=GetDC(hnd);
rbufdat^.bufbit:=CreateCompatibleBitmap(DC, bufrect.right-bufrect.left, bufrect.bottom-bufrect.top);
ReleaseDC(hnd, DC);

hOld:=SelectObject(hDCMem, rbufdat^.bufbit);
SendMessage(hnd, WM_PRINT, hDCMem, PRF_CHILDREN or PRF_CLIENT or PRF_ERASEBKGND or PRF_NONCLIENT or PRF_OWNED or PRF_CHECKVISIBLE);

//bitblt (getdc (0),0,0,bufrect.Right-bufrect.Left,bufrect.Bottom-bufrect.Top,hdcmem,0,0,srccopy); //это так... для проверки того, что он "реальный"

SelectObject(hDCMem, hOld);
DeleteObject(hDCMem);

rBufDat^.bufrect.Left:=0;
rBufDat^.bufrect.Top:=0;
rBufDat^.bufrect.Right:=bufrect.Right-bufrect.Left;
rBufDat^.bufrect.Bottom:=bufrect.Bottom-bufrect.Top;

evhnd:=openevent (EVENT_MODIFY_STATE,false,"Shotter_Event");
setevent (evhnd);
end;


Вот код в программе:
const MMFName="Window_Shooter";

type
 PBufDat=^TBufDat;
 TBufDat=packed record
  hnd:hwnd;
  bufbit:hbitmap;
  bufrect:trect;
 end;

var
 rBufDat:PBufDat=nil;
 hMapObject:THandle=0;

.....
hMapObject:=CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(TBufDat), MMFName);
rBufDat:=MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS, 0, 0, SizeOf(TBufDat));
.....

evhnd:=createevent (nil,true,false,"Shotter_Event");

hnd:=findwindow (nil, "Calculator");
if (hnd=0) or (hnd=handle) then exit;
GetWindowThreadProcessId(hnd, @PID);
rBufDat^.hnd:=hnd;

libpath:=extractfilepath (application.exename)+"sys.dll";
if inject (pid,libpath)=true then
begin
if waitforsingleobject (evhnd,1000)=WAIT_OBJECT_0 then
begin
 dc:=createcompatibledc (paintbox1.Canvas.Handle);

 hold:=selectobject (dc,rBufDat^.bufbit);

 bitblt (paintbox1.canvas.Handle,0,0,rBufDat^.bufrect.Right,rBufDat^.bufrect.Bottom,dc,0,0,srccopy);

 SelectObject(dc, hOld);
 DeleteObject(dc);
end;
eject (pid,libpath);
end;
closehandle (evhnd);
end;


Передаются размеры, но там, куда ссылается hBitmap, оказывается (как я понял) пусто...
В чем может быть проблема?

P.S. Пример самого WM_PRINT взял (и немного модифицировал) от Фень Юань-я. Там у него было ещё копирование в буфер обмена, так вот если эти строки оставить в *.DLL-ке
OpenClipboard(hnd);
EmptyClipboard;
SetClipboardData(CF_BITMAP, rbufdat^.bufbit);
CloseClipboard;

То все работает нормально. Именно это меня и смущает...


 
Кириешки ©   (2004-08-16 00:57) [1]

А почему надо именно из dll ки рисовать? Нельзя тот же код поместить в программу? Занимать из за него программа много не будет. А вообще если с dll кой приспичило - грузи ее в bitmap  и передавай ей хендл этого битмапа вместе с параметрами. Хотя можно и без них. Или хотябы ссылку на файл передай, а в дллке будешь его грузить уже куда хочешь. IMHO если ничего не путаю, и правильно понял вопрос.


 
Digitman ©   (2004-08-16 08:26) [2]


> DeadMeat


хэндл (в дан.случае - hBitmap) не является глобально уникальным и имеет смысл только для процесса, создавшего этот хэндл


 
DeadMeat ©   (2004-08-16 18:10) [3]


> [1] Кириешки ©   (16.08.04 00:57)

В *.DLL-ку надо, потомучто WM_PRINT не делает снимок в HDC, который был создан в другом приложении. А TBitmap не хочу использовать, из-за лишних в нем функций..., да и размеру он прибавляет килов так на 100.


> [2] Digitman ©   (16.08.04 08:26)

Если я правильно понял, то выходит что передается только ссылка на саму картинку, а она находится в другом процессе... Если так, то 2-два вопроса:
1) Почему картинка все же отрисовывается в моей проге, если строки про буфер обмена вернуть на место (в самом конце процедуры ShowWindow, в *.DLL-ке)?
2) Как все таки передать содержимое этой картинки?

---
...Death Is Only The Begining...


 
DeadMeat ©   (2004-08-16 18:26) [4]


> в самом конце процедуры ShowWindow, в *.DLL-ке

Пардон... ShotWindow

---
...Death Is Only The Begining...


 
Digitman ©   (2004-08-17 08:23) [5]


> DeadMeat ©   (16.08.04 18:10) [3]


>  передается только ссылка на саму картинку


хэндл - это не ссылка, это просто некое "число", являющее собой дескриптор (описатель) объекта

1) потому что в клипборд копируется не хэндл битмапа, а его содержимое

2) например, предусмотри в TBufDat поле-массив достаточного размера и копируй туда содержимое битмапа, а в приложении считывай его и отрисовывай


 
DeadMeat ©   (2004-08-17 12:15) [6]


> [5] Digitman ©   (17.08.04 08:23)

В таком случае ещё два вопроса:
2.1) Как узнать, где находится сама картинка, чтобы ее скопировать, т.е. адрес на блок памяти?
2.2) А можно ли сделать так, чтобы при создании, вся картинка изначально располагалась в нужном мне блоке памяти?

Понимаю, что достал, но если укажете просто куда рыть, то и это будет хорошо...

---
...Death Is Only The Begining...


 
Digitman ©   (2004-08-17 12:34) [7]

есть класс TBitmap, у которого есть св-во Handle, которому ты можешь назначить полученный тобой hBitmap, и метод SaveToStream(), который скопирует в стрим битмап, хэндл которого ты назначил св-ву Handle

в кач-ве стрима можно задействовать TMemoryStream

после сохранения битмапа в стрим его св-во Size даст инфу о размере блока данных, полностью описывающих картинку, а св-во Memory - указатель на буфер, где лежат данные размером Size, описывающие сохраненную картинку


 
DeadMeat ©   (2004-08-17 12:58) [8]

Это та понятно, но есть одна вещ, из-за которой этого делать не выйдет - надо на чистом API. А Graphics и Classes - это ещё пару сотен киллобайт. А *.DLL-ка размером 300 кб., (да и ещё ее надо внедрять в разные процессы) ИМХО, выглядит не очень та...
Я посмотрел в исходниках TBitmap.SaveToStream, дык там столько всего пишется, что просто так реализовать будет тяжело.
Рядом где-то нашел GetObject, GetDIBits. Мож они помогут?

---
...Death Is Only The Begining...


 
Digitman ©   (2004-08-17 13:03) [9]


> посмотрел в исходниках TBitmap.SaveToStream, дык там столько
> всего пишется, что просто так реализовать будет тяжело


а зачем все подряд оттуда тащить ? только ключевые моменты, в которых производится вызов минимально необходимого числа ВинАПИ-ф-ций, реализующих центральную функц-ть метода



Страницы: 1 вся ветка

Текущий архив: 2004.09.26;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.052 c
1-1094728927
Маяк_
2004-09-09 15:22
2004.09.26
Memo


6-1090150783
banderas
2004-07-18 15:39
2004.09.26
Список всех подключившихся к серваку idTCPServer


1-1094630874
Heretic
2004-09-08 12:07
2004.09.26
Ищу инфу на программирование дочерних окон


4-1092735230
surkis
2004-08-17 13:33
2004.09.26
Cлужбы и БД


14-1094238166
KilkennyCat
2004-09-03 23:02
2004.09.26
Предложение модераторам.