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/archive/2013/02/25/2927581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现将D3D渲染到透明窗口上并在窗口上设置QLabel,可以按照以下步骤进行: 1. 创建一个透明窗口A,并设置窗口的透明度为0。 2. 在窗口A上添加一个QLabel,并设置其大小和位置。 3. 创建一个D3D设备,并将其与窗口A关联。 4. 在D3D中创建一个纹理,并将其绑定到窗口A的背景表面上。 5. 在渲染过程中,将D3D渲染到背景表面上,并将其绘制到窗口A上。 下面是示例代码: ```cpp #include <QtWidgets/QMainWindow> #include <QLabel> #include <d3d9.h> class TransparentWindow : public QMainWindow { Q_OBJECT public: TransparentWindow(QWidget *parent = 0); ~TransparentWindow(); private: QLabel *m_pLabel; LPDIRECT3D9 m_pD3D; LPDIRECT3DDEVICE9 m_pDevice; LPDIRECT3DTEXTURE9 m_pTexture; D3DPRESENT_PARAMETERS m_d3dpp; HWND m_hWnd; void initD3D(HWND hWnd); void render(); }; TransparentWindow::TransparentWindow(QWidget *parent) : QMainWindow(parent) { setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool); setAttribute(Qt::WA_TranslucentBackground); setAttribute(Qt::WA_NoSystemBackground, true); setAttribute(Qt::WA_PaintOnScreen, true); setAttribute(Qt::WA_NativeWindow, true); m_pLabel = new QLabel(this); m_pLabel->setGeometry(50, 50, 200, 200); m_pLabel->setText("Hello, world!"); m_hWnd = (HWND)winId(); initD3D(m_hWnd); } TransparentWindow::~TransparentWindow() { if (m_pD3D) m_pD3D->Release(); if (m_pDevice) m_pDevice->Release(); if (m_pTexture) m_pTexture->Release(); } void TransparentWindow::initD3D(HWND hWnd) { m_pD3D = Direct3DCreate9(D3D_SDK_VERSION); ZeroMemory(&m_d3dpp, sizeof(m_d3dpp)); m_d3dpp.Windowed = TRUE; m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; m_d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; m_d3dpp.EnableAutoDepthStencil = TRUE; m_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; m_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &m_d3dpp, &m_pDevice); m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); m_pDevice->CreateTexture(200, 200, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pTexture, NULL); LPDIRECT3DSURFACE9 pSurface; m_pTexture->GetSurfaceLevel(0, &pSurface); m_pDevice->SetRenderTarget(0, pSurface); pSurface->Release(); } void TransparentWindow::render() { m_pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); m_pDevice->BeginScene(); // TODO: 在这里进行 D3D 渲染 m_pDevice->EndScene(); LPDIRECT3DSURFACE9 pSurface; m_pTexture->GetSurfaceLevel(0, &pSurface); m_pDevice->GetRenderTargetData(pSurface, pSurface); m_pDevice->SetRenderTarget(0, pSurface); pSurface->Release(); m_pDevice->StretchRect(pSurface, NULL, m_d3dpp.BackBuffer, NULL, D3DTEXF_NONE); m_pDevice->Present(NULL, NULL, m_hWnd, NULL); } int main(int argc, char *argv[]) { QApplication a(argc, argv); TransparentWindow w; w.show(); return a.exec(); } ``` 在这个示例中,我们使用了Qt的QMainWindow作为透明窗口,并在窗口上添加了一个QLabel。在initD3D函数中,我们创建了一个D3D设备,并将其与窗口A的背景表面关联起来。在render函数中,我们进行D3D渲染,并将渲染结果绘制到窗口A上。注意,在渲染完成后,我们需要将背景表面的内容拷贝到纹理中,并将纹理绘制到窗口上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值