如果不引用Graphics,Forms等巨型单元,将指定HDC保存于内存(或流)中,提供源码,千堆雪斑竹?(200分)

  • 主题发起人 主题发起人 Rocklee
  • 开始时间 开始时间
R

Rocklee

Unregistered / Unconfirmed
GUEST, unregistred user!
是这样的:
现需要写一service,定时保存电脑屏幕,由于是Service,所以无需GUI,也就不想引用
Forms等GUI单元,Service都是用API编写的,免得让别人笑话。
但如何避免使用graphics,Forms等这些units,不用TCANVAS,而直接用API保存HDC,就不
得而知了,为此我愿花200分。

To 千堆雪:
第一次在这版发问,希望斑竹支持支持。
 
不懂,什么叫用API保存HDC,
CreateMemDC
CreateBitmap
Selectobject
DelObject
GetDIBits

 
type
TBITMAP = record
bmType:LongInt;
bmWidth:LongInt;
bmHeight:LongInt;
bmWidthBytes:LongInt;
bmPlanes:Word;
bmBitsPixel:Word;
bmBits:Pointer;
end;
PBitmap=^TBitmap;

var
DC:HDC;
Bitmap:HBitmap;
P:Pointer;
Buff:Integer;
B:PBitmap;
begin
DC:=GetDC(GetDesktopWindow);
Bitmap:=CreateCompatibleBitmap(DC,GetSystemMetrics(0),GetSystemMetrics(1));
GetObject(Bitmap,Buff,P);
PBitmap(P)^.bmBits;
PBitmap(P)^.bmBitsPixel;
.....
// 于是,可以写入文件,可以用来显示
end;
 
老兄不是在写黑客程序吧![:D][8D]
HDC是设备句柄,GUI(用户图形界面),我们用的最后不都是还原成winapi吗?
 
Tocjc861:
不是,不是,只是自己有这方面的执着,因为是服务程序嘛,无需GUI,就
干脆不用FORM之类,而想用API全部完成好了,因为如果为了一小部分功能而引用那么巨型
的单元,出来的产品十分难看,想像一下,几百K的东西长期霸着用户的内存,不舒服啊,
嘿嘿...而且我写程序时一向以VC为目标对比的,速度/资源占用等等...
To小雨哥:
呵呵,小雨哥果然热心...可以详细点么?bmBits:Pointer不用申请内存吗?
 
小雨哥可以再详细一点吗?
小弟实在对图形处理一窍不通,请指点…
 
啊,300大元,居然没人愿意要??
难道这个价钱太小??
我再UP
 
BMP的文件格式:
最前面是一个TBITMAPFILEHEADER,14字节,只有两个参数可变,文件总大小,Bits的偏移量
之后是一个TBITMAPINFOHEADER,之后是相应的调色板等,大小都可以从该结构中取得
之后是位图的内容,最典型的就是BI_RGB压缩的,这是内容就是一个矩阵形式

关于内存中的形式,以HBITMAP形式存在,利用GetDIBits等函数,可以取得他的具体数据
从而自己将其写道BMP中,已经是HBITMAp自然内容已经有了,内存由GDI系统保存,也无需
申请。如果你需要改变位图的内容,如大小,颜色,你就需要生成一个新的HBITMAP

生成Bitmap。
一般是生成DIB的bitmap或屏幕兼容的DDB,然后生成memory DC,把位图选进去,利用
GDI江屏幕的德内容拷过来
StretchBlt
然后利用GetDIBits得到内容,再将其存入BMP中,

具体的操作,以可以参考MSDN和TBitmap的SetHandle,LoadFromFile,SaveToFile等函数
 
To 小雨哥:
我将你的代码改成以下:
type
TBITMAP = record
bmType:LongInt;
bmWidth:LongInt;
bmHeight:LongInt;
bmWidthBytes:LongInt;
bmPlanes:Word;
bmBitsPixel:Word;
bmBits:Pointer;
end;

PBitmap=^TBitmap;

var
DC:HDC;
Bitmap:HBitmap;
P:Pointer;
Buff:Integer;
B:PBitmap;
m:Tmemorystream;
begin
DC:=GetDC(0);
Bitmap:=CreateCompatibleBitmap(DC,screen.Width ,screen.Height );
Buff:=sizeof(TBitmap); //好像是先赋初值的吧?不清楚
GetObject(Bitmap,Buff,P);
releasedc(0,dc); //释放dc
m:=tmemorystream.Create ;
try
调试时P的值:
PBitmap(P)^.bmwidth=-685053757,
PBitmap(P)^.bmwidth=-1065025535,
PBitmap(P)^.bmwidthbytes=-1819603852,
PBitmap(P)^.bmbitspixcel=0;
说明调用失败
m.WriteBuffer(PBitmap(P)^.bmBits ^,PBitmap(P)^.bmBitsPixel );
m.Position :=0;
memo1.Lines.LoadFromStream(m);
finally
m.free;
end;
// 于是,可以写入文件,可以用来显示
end;
请各位大虾再指教!
 
高手们啊...
procedure GraspScreen(left, top, right, bottom: Integer);
Type
tagBITMAP = packed record
bmType: Longint;
bmWidth: Longint;
bmHeight: Longint;
bmWidthBytes: Longint;
bmPlanes: Word;
bmBitsPixel: Word;
bmBits: Pointer;
end;

var
RWidth,RHeight:Integer;
SourceDC,DestDC,BmpHandle:Integer;
sBitmap:TBitmap;
Buff:integer;
pBmp:^tagBITMAP;
m:Tmemorystream;
BInfo:TBitmapInfo;
DebugStr:String;
begin
RWidth:=Right-Left;
RHeight:=Bottom-Top;
SourceDc:=GetDC(0);
DestDC:=CreateCompatibleDC(SourceDC);
BmpHandle:=CreateCompatibleBitmap(SourceDC,Rwidth,RHeight);
SelectObject(DestDc,BmpHandle);
//以下的语句成功,DebugStr='1'
DebugStr:=inttostr(Integer(Bitblt(DestDC,0,0,RWidth,RHeight,SourceDC,Left,Top,SRCCOPY)));
Buff:=sizeof(pBmp^);
//以下的语句也成功,不过pBmp^.bmBits是否就是指向其内存?
GetObject(BmpHandle,Buff,pBmp);
//以下的语句失败。 应该如果写?
DebugStr:=inttostr(GetDIBits(SourceDc,BmpHandle,0,RHeight,pBmp^.bmBits , BInfo,DIB_RGB_COLORS));
m:=tmemorystream.Create ;
try
//假如GetDIBits一句成功,是不是以下语句就完成了内存转存的工作?
m.WriteBuffer( pBmp^.bmBits ^,BInfo.bmiHeader.biSize);
....
finally
m.free;
end;
DeleteDC(DestDc);
ReleaseDC(0,SourceDC);
end;
 
诶,居然没人对这个有兴趣了,是不是全都成了大富翁?呵呵

经最近几天的研究,问题差不多都解决了,已经还知道如何将内存的bitmap保存成一副
bitmap格式的文件,但还是有一些疑问:
To zjan521:
原理跟你说的差不多,建立hbitmap句柄时那个BITMAPINFO.bmiHeader.biHeight 应该是
负的height啊,然后就CreateDIBSection建立句柄
调用下面这个API时, BmpInfo里面的bmiHeader.biHeight 是否仍然是负数?
GetDIBits(l_DC, Bitmap, 0, Y, Bits, BmpInfo, DIB_RGB_COLORS);
假如答案是肯定的话,执行如 StretchDIBits(hDC,
x, y, Width, Height,
0, 0, Width, Height,
Bits,
BmpInfo,
DIB_RGB_COLORS,
SRCCOPY);这些API时,那个值也应该是负的吧,呵呵
我做的时候,一直是负的,而且一直正常,只是在保存成memorystream时,如果还是
让其为负值的话,好像win98的画笔不认为是有效的bitmap文件,但win me/2000/xp就认,而acdsee
无论在什么版本的windows下浏览都认,delphi的timage也认,但是如果让画笔打开后再保存
为别一个文件,然后用16位二进制编辑器打开前后两个文件比较,发现后者里面的biHeight (指的是文件头)
是正数的,而前者是负数的。更奇怪的是,如果再次用画笔或acdsee打开后者,发现图像全倒过来。
有兴趣的富翁试试看。
因为这不是大问题,如果你们没兴趣也没所谓,这贴子如果再过一阵没人回应,就结束之。
 
BMP就是一个DIB位图,对于DIB位图,biHeight为正为负都可以,内容可以完全相同,差别就在
后边的数据的排列方式不同,
 
a_wen@163.com
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
951
SUNSTONE的Delphi笔记
S
I
回复
0
查看
788
import
I
I
回复
0
查看
821
import
I
后退
顶部