![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Буфер или не буфер... [D6, Win95/98, WinME, NT4, Win2k, WinXP]
DeadMeat © (2004-08-16 00:36:00)Здрассте всем.
У меня такая вот странная ситуация. Есть *.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;
То все работает нормально. Именно это меня и смущает...
Digitman (2004-08-17 13:03:00) [1]
> посмотрел в исходниках TBitmap.SaveToStream, дык там столько
> всего пишется, что просто так реализовать будет тяжело
а зачем все подряд оттуда тащить ? только ключевые моменты, в которых производится вызов минимально необходимого числа ВинАПИ-ф-ций, реализующих центральную функц-ть метода
DeadMeat (2004-08-17 12:58:00) [2]Это та понятно, но есть одна вещ, из-за которой этого делать не выйдет - надо на чистом API. А Graphics и Classes - это ещё пару сотен киллобайт. А *.DLL-ка размером 300 кб., (да и ещё ее надо внедрять в разные процессы) ИМХО, выглядит не очень та...
Я посмотрел в исходниках TBitmap.SaveToStream, дык там столько всего пишется, что просто так реализовать будет тяжело.
Рядом где-то нашел GetObject, GetDIBits. Мож они помогут?
---
...Death Is Only The Begining...
Digitman (2004-08-17 12:34:00) [3]есть класс TBitmap, у которого есть св-во Handle, которому ты можешь назначить полученный тобой hBitmap, и метод SaveToStream(), который скопирует в стрим битмап, хэндл которого ты назначил св-ву Handle
в кач-ве стрима можно задействовать TMemoryStream
после сохранения битмапа в стрим его св-во Size даст инфу о размере блока данных, полностью описывающих картинку, а св-во Memory - указатель на буфер, где лежат данные размером Size, описывающие сохраненную картинку
DeadMeat (2004-08-17 12:15:00) [4]
> [5] Digitman © (17.08.04 08:23)
В таком случае ещё два вопроса:
2.1) Как узнать, где находится сама картинка, чтобы ее скопировать, т.е. адрес на блок памяти?
2.2) А можно ли сделать так, чтобы при создании, вся картинка изначально располагалась в нужном мне блоке памяти?
Понимаю, что достал, но если укажете просто куда рыть, то и это будет хорошо...
---
...Death Is Only The Begining...
Digitman (2004-08-17 08:23:00) [5]
> DeadMeat © (16.08.04 18:10) [3]
> передается только ссылка на саму картинку
хэндл - это не ссылка, это просто некое "число", являющее собой дескриптор (описатель) объекта
1) потому что в клипборд копируется не хэндл битмапа, а его содержимое
2) например, предусмотри в TBufDat поле-массив достаточного размера и копируй туда содержимое битмапа, а в приложении считывай его и отрисовывай
DeadMeat (2004-08-16 18:26:00) [6]
> в самом конце процедуры Sho wWindow, в *.DLL-ке
Пардон... Sho tWindow
---
...Death Is Only The Begining...
DeadMeat (2004-08-16 18:10:00) [7]
> [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...
Digitman (2004-08-16 08:26:00) [8]
> DeadMeat
хэндл (в дан.случае - hBitmap) не является глобально уникальным и имеет смысл только для процесса, создавшего этот хэндл
Кириешки (2004-08-16 00:57:00) [9]А почему надо именно из dll ки рисовать? Нельзя тот же код поместить в программу? Занимать из за него программа много не будет. А вообще если с dll кой приспичило - грузи ее в bitmap и передавай ей хендл этого битмапа вместе с параметрами. Хотя можно и без них. Или хотябы ссылку на файл передай, а в дллке будешь его грузить уже куда хочешь. IMHO если ничего не путаю, и правильно понял вопрос.