📄 displayremotescreenunit.pas
字号:
tmpHCURSOR := LoadCursor(0, IDC_SIZENS);
12:
tmpHCURSOR := LoadCursor(0, IDC_SIZENWSE);
13:
tmpHCURSOR := LoadCursor(0, IDC_SIZEWE);
14:
tmpHCURSOR := LoadCursor(0, IDC_UPARROW);
15:
tmpHCURSOR := LoadCursor(0, IDC_WAIT);
else
tmpHCURSOR := LoadCursor(0, IDC_ARROW);
end;
Icon := CopyIcon(tmpHCURSOR);
try
DrawIcon(hMemDC, MouseX - 8 , MouseY - 8, Icon);
finally
DestroyIcon(tmpHCURSOR);
DestroyIcon(Icon);
end;
end;
//相应wmpaint消息,重绘图像
procedure TDisplayRemoteScreen.DrawClientDC(hWndDc : HDC;
const nXOriginSrc, nYOriginSrc : integer);
begin
case ShowImageStyle of
IDM_Orignal:
begin
DrawDibDraw(
EntireDrawDibHandle,
hWndDc,
nXOriginSrc, nYOriginSrc,
-1,
-1,
ImageInforHeaderData^.bmiHeader, //
ImageBitsData,
0, 0,
ImageInforHeaderData^.bmiHeader.biWidth,
ImageInforHeaderData^.bmiHeader.biHeight,
DDF_SAME_DRAW or DDF_SAME_HDC
);
end;
IDM_Stretch:
begin
SetStretchBltMode(hWndDc, HALFTONE);//使用这个模式,使得过度平滑
DrawDibDraw(
EntireDrawDibHandle,
hWndDc, 0, 0, ClientWidth, ClientHeight,
ImageInforHeaderData^.bmiHeader,
ImageBitsData,// Pointer to the buffer that contains the bitmap bits
0, 0,
ImageInforHeaderData^.bmiHeader.biWidth,
ImageInforHeaderData^.bmiHeader.biHeight,
DDF_SAME_DRAW or DDF_SAME_HDC
);
end;
end;
end;
//绘制图像
procedure TDisplayRemoteScreen.DrawMemDC;
var
//描述表指针--不需要申请内存
BlockChangeRecordTabel : PByte;
//直接赋值,没有申请空间
PerWidthImageBitsDataBaseP, PerBlockDataBaseP : Pointer;
//每块数据的内存--系统自动分配的
PerBlockData : Pointer;
//循环变量
i, j : Word;
ByteIndex, ByteWriteSize, LineCount : Word;
BlockStartPos : TPoint;
begin
//读取数据头
MoveMemory(@ReceivedDataHeader, ReceivedData, SizeOf(ReceivedDataHeader));
//如果是全屏的数据,则先将图像头读出
if ReceivedDataHeader.ImageHeaderSize <> 0 then
begin
GdiFlush;
//取得屏幕的图像头数据
if ImageInforHeaderData <> nil then
FreeMem(ImageInforHeaderData);
//取得图像头数据内存
GetMem(ImageInforHeaderData, ReceivedDataHeader.ImageHeaderSize);
MoveMemory(ImageInforHeaderData, Pointer(DWORD(ReceivedData)
+ ReceivedDataHeader.ImageHeaderOffset), ReceivedDataHeader.ImageHeaderSize);
if hWndDc <> 0 then ReleaseDC(Self.Handle, hWndDc);
hWndDc := GetDC(Self.Handle);
if hBitmap <> 0 then DeleteObject(hBitmap);
//这个地方系统会自动申请图像内存,并在deleteobject以后自动释放内存的
hBitmap := CreateDIBSection(hWndDc, ImageInforHeaderData^, DIB_RGB_COLORS, ImageBitsData, 0, 0);
SelectObject(hWndDc, hBitmap);
if (EntireDrawDibHandle <> 0) and (ImageInforHeaderData <> nil) then
begin
DrawDibEnd(EntireDrawDibHandle);
DrawDibBegin(
EntireDrawDibHandle, hWndDc, -1, -1,
ImageInforHeaderData^.bmiHeader,
ImageInforHeaderData^.bmiHeader.biWidth,
ImageInforHeaderData^.bmiHeader.biHeight,
0
);
end;
//取得每个小块的图像头数据
if ImageInforPerBlockHeaderData <> nil then
FreeMem(ImageInforPerBlockHeaderData);
GetMem(ImageInforPerBlockHeaderData, ReceivedDataHeader.ImageHeaderSize);
MoveMemory(ImageInforPerBlockHeaderData, Pointer(DWORD(ReceivedData)
+ ReceivedDataHeader.ImageHeaderOffset), ReceivedDataHeader.ImageHeaderSize);
//重整小块使用的图像头
ImageInforPerBlockHeaderData^.bmiHeader.biWidth := BlockLength;
ImageInforPerBlockHeaderData^.bmiHeader.biHeight := BlockLength;
ImageInforPerBlockHeaderData^.bmiHeader.biSizeImage := (BlockLength * BlockLength) *
ImageInforPerBlockHeaderData^.bmiHeader.biBitCount div 8;
//为显示小快图象准备
if hMemDC <> 0 then DeleteDC(hMemDC);
hMemDC := CreateCompatibleDC(hWndDc);
if hMemBitmap <> 0 then DeleteObject(hMemBitmap);
hMemBitmap := CreateDIBSection(hMemDC, ImageInforPerBlockHeaderData^, DIB_RGB_COLORS, PerBlockData, 0, 0);
SelectObject(hMemDC, hMemBitmap);
if (PerBlockDrawDibHandle <> 0) and (ImageInforPerBlockHeaderData <> nil) then
begin
DrawDibEnd(PerBlockDrawDibHandle);
DrawDibBegin(
PerBlockDrawDibHandle, hMemDC, -1, -1,
ImageInforPerBlockHeaderData^.bmiHeader,
ImageInforPerBlockHeaderData^.bmiHeader.biWidth,
ImageInforPerBlockHeaderData^.bmiHeader.biHeight,
0
);
end;
//保存图象大小
RemoteScreenWidth := ImageInforHeaderData^.bmiHeader.biWidth;
RemoteScreenHeight := Abs(ImageInforHeaderData^.bmiHeader.biHeight);
//得到每行的图象数据的大小
ByteWidthSize := ImageInforHeaderData^.bmiHeader.biSizeImage div RemoteScreenHeight;
//得到每小块的每行的数据大小
if ImageInforHeaderData^.bmiHeader.biBitCount >= 8 then
ByteWidthSizePerBlock := ByteWidthSize * BlockLength div RemoteScreenWidth
else if ImageInforHeaderData^.bmiHeader.biBitCount = 4 then
ByteWidthSizePerBlock := BlockLength div 2
else if ImageInforHeaderData^.bmiHeader.biBitCount = 1 then
ByteWidthSizePerBlock := BlockLength div 8;
//得到分块数和总分块数
WidthBlockCount := (ImageInforHeaderData^.bmiHeader.biWidth + (BlockLength - 1)) div BlockLength;
HeightBlockCount := (Abs(ImageInforHeaderData^.bmiHeader.biHeight) + (BlockLength - 1)) div BlockLength;
TotalBlockCount := WidthBlockCount * HeightBlockCount;
end;
//得到描述表指针
BlockChangeRecordTabel := PByte(DWORD(ReceivedData) + ReceivedDataHeader.BlockChangeRecordTabelOffset);
//设置数据指针到图象数据开始处
PerBlockDataBaseP := Pointer(DWORD(ReceivedData) + ReceivedDataHeader.ImageDataOffset);
//按照描述表的方式读取变化了的块的数据,对图象数据进行重整
ByteIndex := 0;
LineCount := BlockLength;
//首先定位到倒数第一行(块组成的行)的开始处,然后逐行向上走就可以了
PerWidthImageBitsDataBaseP := Pointer(DWORD(ImageBitsData)
//直接定位到图像的最后一块的数据上
+ (ImageInforHeaderData^.bmiHeader.biSizeImage - ByteWidthSize * BlockLength));
try
i := 0;
while i < TotalBlockCount do
begin
//检查行上的最右边的块的数据是否超出了图象行宽
if (ByteIndex + ByteWidthSizePerBlock) > ByteWidthSize then
ByteWriteSize := ByteWidthSize - ByteIndex
else
ByteWriteSize := ByteWidthSizePerBlock;
//如果bit=1,则说明对应的块有变化,写入数据
if BlockChangeRecordTabel^ and (1 shl (i mod 8)) <> 0 then
begin
//逐行写入
for j := 0 to LineCount - 1 do
begin
MoveMemory(Pointer(DWORD(PerWidthImageBitsDataBaseP) + (j * ByteWidthSize)),
Pointer(DWORD(PerBlockDataBaseP) + (j * ByteWidthSizePerBlock)), ByteWriteSize);
end;
if ReceivedDataHeader.ImageHeaderSize = 0 then
begin
case ShowImageStyle of
IDM_Orignal:
begin
BlockStartPos.X := (i mod WidthBlockCount) * BlockLength;
BlockStartPos.Y := (i div WidthBlockCount) * BlockLength;
if (BlockStartPos.X + xPaintBeg >= 0) and (BlockStartPos.Y + yPaintBeg >= 0) then
begin
DrawDibDraw(
PerBlockDrawDibHandle,
hWndDc,
BlockStartPos.X + xPaintBeg,
BlockStartPos.Y + yPaintBeg,
BlockLength,
BlockLength,
ImageInforPerBlockHeaderData^.bmiHeader,
PerBlockDataBaseP, //
0, 0,
ImageInforPerBlockHeaderData^.bmiHeader.biWidth,
ImageInforPerBlockHeaderData^.bmiHeader.biHeight,
DDF_SAME_DRAW or DDF_SAME_HDC
);
end;
end;
IDM_Stretch:
begin
SetStretchBltMode(hWndDc, HALFTONE);
{if (BlockLength * ClientWidth mod RemoteScreenWidth) <> 0 then
BlockStartPos.X := (BlockLength * ClientWidth div RemoteScreenWidth) + 1
else
BlockStartPos.X := (BlockLength * ClientWidth div RemoteScreenWidth);
if (BlockLength * ClientHeight mod RemoteScreenHeight) <> 0 then
BlockStartPos.Y := (BlockLength * ClientHeight div RemoteScreenHeight) + 1
else
BlockStartPos.Y := (BlockLength * ClientHeight div RemoteScreenHeight);
}
BlockStartPos.X := Round(BlockLength * ClientWidth / RemoteScreenWidth);
BlockStartPos.Y := Round(BlockLength * ClientHeight / RemoteScreenHeight);
DrawDibDraw(
PerBlockDrawDibHandle,
hWndDc,
(i mod WidthBlockCount) * BlockStartPos.X,
(i div WidthBlockCount) * BlockStartPos.Y,
BlockStartPos.X,
BlockStartPos.Y,
ImageInforPerBlockHeaderData^.bmiHeader,
PerBlockDataBaseP,
0, 0,
ImageInforPerBlockHeaderData^.bmiHeader.biWidth,
ImageInforPerBlockHeaderData^.bmiHeader.biHeight,
DDF_SAME_DRAW or DDF_SAME_HDC
);
end;
end;
end;
//向下移动未重整的图象数据指针
PerBlockDataBaseP := Pointer(DWORD(PerBlockDataBaseP) + ReceivedDataHeader.PerBlockDataSize);
end;
Inc(ByteIndex, ByteWriteSize);
if ByteIndex < ByteWidthSize then
begin
//行开头指针向右移动ByteWriteSize个byte(这里的行是真正的图象数据的行)
PerWidthImageBitsDataBaseP := Pointer(DWORD(PerWidthImageBitsDataBaseP) + ByteWriteSize);
end
else
begin
//此时的移动导致指针指向了下一行的开头了(真正的图象数据行),因此在下面计算的时候要多减去一个ByteWidthSize
PerWidthImageBitsDataBaseP := Pointer(DWORD(PerWidthImageBitsDataBaseP) + ByteWriteSize);
//检查最后一块的数据是否超出高度的边界
if DWORD(PerWidthImageBitsDataBaseP) - ByteWidthSize * Byte(BlockLength + 1) >= DWORD(ImageBitsData) then
begin
PerWidthImageBitsDataBaseP := Pointer(DWORD(PerWidthImageBitsDataBaseP) - ByteWidthSize * Byte(BlockLength + 1));
LineCount := BlockLength;
end
else
begin
PerWidthImageBitsDataBaseP := ImageBitsData;
LineCount := RemoteScreenHeight mod BlockLength;
end;
//重新开启新行(这里的行是BlockLength高度的行数据组成的行)
ByteIndex := 0;
end;
//读下一个字节的数据
if ((i + 1) mod 8) = 0 then
BlockChangeRecordTabel := PByte(DWORD(BlockChangeRecordTabel) + 1);
Inc(i);
end;
case ShowImageStyle of
IDM_Orignal:
begin
//如果是第一帧数据,则需要调用一下InvalidateRect函数
if (ReceivedDataHeader.ImageHeaderSize <> 0) or (RemoteScreenCountIndex = 0)then
begin
InvalidateRect(Self.Handle, nil, False);
end;
//每FreameCountRepaint帧,刷新全屏一次
Inc(RemoteScreenCountIndex);
if RemoteScreenCountIndex > FreameCountRepaint then RemoteScreenCountIndex := 0;
end;
IDM_Stretch:
begin
//如果是第一帧数据,则需要调用一下InvalidateRect函数
if (ReceivedDataHeader.ImageHeaderSize <> 0) or (StretchRemoteScreenCountIndex = 0)then
begin
InvalidateRect(Self.Handle, nil, False);
end;
//每8帧,刷新全屏一次
Inc(StretchRemoteScreenCountIndex);
if StretchRemoteScreenCountIndex > 10 then StretchRemoteScreenCountIndex := 0;
end;
end;
except
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -