window平台下 实时高效打印其他窗口,并作为D3D纹理使用

工作需要,需要实现一功能,能实时后台更新并输出其他窗口图形作为D3D纹理使用。目前已经实现一个较为高效版本,并实现Unity3D插件,在U3D中使用。

下面是截图(用任务管理器窗口为例),后面会贴出部分代码,小弟不才,如有朋友需要,可以联系小弟。

下面是在U3D中的测试代码:

using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System;

[RequireComponent(typeof(Camera))]
public class DrawOtherWindow : MonoBehaviour {

[DllImport("DrawOtherWindowPlugin")]
public static extern void SetWinHWND(IntPtr hwnd);
public int PluginEventID = 0;
private RenderTexture renderTex;

void Start()
{
SetWinHWND((IntPtr)0);
camera.clearFlags = CameraClearFlags.Nothing;
camera.cullingMask = 0;
if (renderTex == null)
{
renderTex = new RenderTexture(512,512,0);
camera.targetTexture = renderTex;
renderer.material.mainTexture = renderTex;
}
}

float _time = 0;

void OnPostRender()
{
if ((_time += Time.deltaTime) > 0.1f)
{
_time = 0;
camera.DoClear();
GL.IssuePluginEvent(PluginEventID);
}
}

}

下面是插件的关键代码:


#pragma once

#include <afxwin.h>
//#include <Windows.h>
#include <gdiplus.h>
using namespace Gdiplus;

#include <dshow.h>
#include <d3dx9.h>

#pragma comment(lib,"GdiPlus.lib")

//#define TEST_PROJECT

#define SAFE_DELETE(p) {if(p!=NULL)delete p;p=NULL;}

#include <afxwin.h>


class CaptureWindow
{
public:
/*explicit*/ CaptureWindow(HWND hwd,IDirect3DDevice9*d3ddev):
_hwnd(hwd),d3dDevice(d3ddev),isExitThread(false),texture(nullptr),WinDC(NULL),MemDC(NULL),hbmp(NULL)
{
GdiplusStartupInput gdiplusStartupInput;

if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL)!=Ok)
{
printf("GdiplusStartup() Faild!");
}
}

~CaptureWindow()
{
SAFE_DELETE(WinDC)
SAFE_DELETE(MemDC)
SAFE_DELETE(hbmp)
texture->Release();
GdiplusShutdown(gdiplusToken);
}
protected:
CaptureWindow(CaptureWindow &);
CaptureWindow& operator = (CaptureWindow&);

public:
void ResetWin(HWND hwd)
{

}

template<class ClassType,void (ClassType::*ThreadFunc)()>
static DWORD WINAPI ThreadFuncUseClassFunc(void* _this)
{
(((ClassType*)_this)->*ThreadFunc)();
return 0;
}

void Start()
{
////3D Texture
if(texture!=nullptr) texture->Release();

if(!IsWindow(_hwnd))
{
printf("%d not a window!\n",_hwnd);
return;
}


isExitThread = false;

RECT rc;
GetWindowRect(_hwnd,&rc);
W = rc.right- rc.left;
H = rc.bottom - rc.top;


//if(WinDC!=NULL) DeleteDC(WinDC);
//if(MemDC!=NULL) DeleteDC(MemDC);
//if(hbmp!=NULL) DeleteBitmap(hbmp);

SAFE_DELETE(WinDC)
SAFE_DELETE(MemDC)
SAFE_DELETE(hbmp)

WinDC = GetWindowDC(_hwnd);
hbmp = CreateCompatibleBitmap(WinDC,W,H);
MemDC = CreateCompatibleDC(WinDC);
////
SelectObject(MemDC,hbmp);

//////////////////////////////////////////////
printf("W:%d:::::H:%d",W,H);
if(FAILED( d3dDevice->CreateTexture(W,H,1,D3DUSAGE_DYNAMIC,D3DFMT_X8R8G8B8 ,D3DPOOL_DEFAULT,&texture, NULL)))
{
//do something
printf("Create Texutre Faild!");
#ifndef TEST_PROJECT
DeleteObject(hbmp);
#endif
return;
}

// DWORD threadID;
// hThread = CreateThread(NULL,0, &ThreadFuncUseClassFunc<CaptureWindow,&CaptureWindow::_threadFunc>,this,0,&threadID);
// printf("启动线程完成!");
}

void updateTexture()
{

if(texture==NULL) return;

if(!IsWindow(_hwnd)) return;
if(IsIconic(_hwnd)) return; //如果窗口最小化 返回


PrintWindow(_hwnd, MemDC,0);
BITMAP bmp;
GetObject(hbmp,sizeof(BITMAP),&bmp);

Gdiplus::Bitmap* bitmap =new Gdiplus::Bitmap(hbmp,NULL);// Bitmap::FromHBITMAP(hbmp,0);
if(bitmap==NULL)
{
printf("Cannot Create bitmap!\n");
return;
}


D3DLOCKED_RECT d3dlr;

if( FAILED(texture->LockRect(0, &d3dlr, 0,D3DLOCK_DISCARD)))
{
printf("Lock Texture Rect Faild!");
texture->UnlockRect(0);
return;
}

//printf("D3DTexW:%d\n",d3dlr.Pitch/4);

Gdiplus::BitmapData bitmapdata;
Rect rc= Rect(0,0,bitmap->GetWidth(),bitmap->GetHeight());
if(bitmap->LockBits(&rc,ImageLockModeRead ,PixelFormat32bppARGB, &bitmapdata)== Gdiplus::Ok)
{
BYTE* pBit_ =(BYTE*)bitmapdata.Scan0;
BYTE* ucTexDst = (BYTE *)d3dlr.pBits;

//纹理 数据 字节对齐
for (int i = 0; i < H; i++)
memcpy(ucTexDst+i*d3dlr.Pitch,pBit_+i*W*4,W*4);

bitmap->UnlockBits(&bitmapdata);
}
texture->UnlockRect(0);

delete bitmap; 

}

IDirect3DTexture9* GetTexture()
{
updateTexture();
return texture;
}

protected:
HWND _hwnd;
bool isExitThread;
bool CanProcessTex;
int W;
int H;
IDirect3DDevice9* d3dDevice;
IDirect3DTexture9* texture;
//窗口相关
HBITMAP hbmp;
HDC WinDC;
HDC MemDC;

ULONG_PTR gdiplusToken;   
};

上述代码目前还不完善,很多功能正在后续加入,待续。。。。

原文地址:https://www.cnblogs.com/lxzCode/p/2927581.html