⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 displayremotescreenunit.pas

📁 delphi源代码。iocp远控比较完整的代码
💻 PAS
📖 第 1 页 / 共 3 页
字号:
      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 + -