• 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;   
    };

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

  • 相关阅读:
    实验-继承&super.doc
    Python库
    Github高级搜索
    代码报错记录
    编程问题解决
    百科
    【Android】添加依赖包
    【Android】导航栏(加图片icon)和不同页面的实现(viewpager+tablayout)
    【Android】Android Studio真机调试的问题统整
    【AD】自己画板的备忘
  • 原文地址:https://www.cnblogs.com/lxzCode/p/2927581.html
Copyright © 2020-2023  润新知