VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 535|回复: 4

哪位大神用过D2D1

[复制链接]
35_avatar_middle
最佳答案
0 
online_vip 发表于 2019-3-19 13:32:31 | 显示全部楼层 |阅读模式
3驿站币
自己写了一个MFCDLL
注入到一个界面上
DLL的代码如下:

HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);
        if (SUCCEEDED(hr))
        {
                hr = pFactory->CreateHwndRenderTarget(
                        D2D1::RenderTargetProperties(),
                        D2D1::HwndRenderTargetProperties(
                        hwnd,
                        D2D1::SizeU(
                        rtClient.right - rtClient.left,
                        rtClient.bottom - rtClient.top)),
                        &pRenderTarget);
                if (SUCCEEDED(hr))
                {
                        hr = pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &pBrush);
                        if (FAILED(hr))
                        {
                                MessageBox(hwnd, TEXT("Create Resource Fail!"), TEXT("Error"), MB_OK);
                                return;
                        }
                }
        }


hwnd窗口句柄不是DLL本身窗口的句柄,而是父窗口的句柄
创建 CreateHwndRenderTarget 的时候返回 error:8899000B 失败了
网上差不出到底是哪里出了问题,出错数值到底什么意思。





上一篇:《实用C++》第19课的疑问!
下一篇:opencv调整亮度问题,跟着书上写运行报错
75_avatar_middle
最佳答案
0 
在线会员 发表于 2019-3-19 16:59:02 | 显示全部楼层
代码没有错误!错误可能是窗口格式,下面用控制台测试是通过地,自己慢慢调吧.

#include "stdafx.h"
#include <d2d1.h>
#pragma comment(lib,"d2d1.lib")
#include <dwrite.h>
#pragma comment(lib,"dwrite.lib")
#include <iostream>
using namespace std;
#include <D2DErr.h>
#include <winerror.h>
int main()
{
        ID2D1Factory               *pFactory=nullptr;
        ID2D1HwndRenderTarget      *pRenderTarget=nullptr;
        ID2D1SolidColorBrush*pBrush = nullptr;
        HWND hwnd = GetConsoleWindow();
        RECT rtClient;
        GetClientRect(hwnd, &rtClient);
        HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);
        if (SUCCEEDED(hr))
        {
                hr = pFactory->CreateHwndRenderTarget(
                        D2D1::RenderTargetProperties(),
                        D2D1::HwndRenderTargetProperties(
                                hwnd,
                                D2D1::SizeU(
                                        rtClient.right - rtClient.left,
                                        rtClient.bottom - rtClient.top)),
                        &pRenderTarget);
                if (SUCCEEDED(hr))
                {
                        hr = pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &pBrush);
                        if (FAILED(hr))
                        {
                                MessageBox(hwnd, TEXT("Create Resource Fail!"), TEXT("Error"), MB_OK);
                                return -1;
                        }
                }
        }
        cout << "ok!" << endl;
        //
        if (pFactory) pFactory->Release();
        if (pRenderTarget) pRenderTarget->Release();
        if (pBrush) pBrush->Release();
    return 0;
}
//
//d3d错误前缀,见#include <D2DErr.h>中MAKE_D2DHR( sev, code )
//定义FACILITY_D2D为0x899
//窗口错误前缀#define FACILITY_WINDOWS     8
//系统错误号11,见#include <winerror.h>#define ERROR_BAD_FORMAT  11L(0xB)
//错误码 8899000B= 8(WINDOW环境错误) + 899(D2D错误) + 000B(错误类型)
//翻译过来就是:格式错误
运行结果:
ok!
按任意键继续

其中格式可以这样调:
        const float DEFAULT_DPI = 96.f;
        auto renderTargetProperties = D2D1::RenderTargetProperties();
        renderTargetProperties.dpiX = DEFAULT_DPI;
        renderTargetProperties.dpiY = DEFAULT_DPI;
        renderTargetProperties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
        auto hwndRenderTargetproperties
                = D2D1::HwndRenderTargetProperties(hwnd,
                        D2D1::SizeU(
                                rtClient.right - rtClient.left,
                                rtClient.bottom - rtClient.top));
        hr = pFactory->CreateHwndRenderTarget(
                renderTargetProperties,
                hwndRenderTargetproperties,
                &pRenderTarget);
哪位大神用过D2D1
35_avatar_middle
最佳答案
0 
ico_lz  楼主| 发表于 2019-3-19 20:00:41 | 显示全部楼层
xx_player 发表于 2019-3-19 16:59
代码没有错误!错误可能是窗口格式,下面用控制台测试是通过地,自己慢慢调吧.

#include "stdafx.h"

老哥,还是不行
本人刚学习D2D1
源码和父窗口我都打包了

如果老哥有时间的话,请贵手帮一下吧。

D2D1Game1.rar

10.74 KB, 下载次数: 1

注入DLL

父窗口.rar

10.37 KB, 下载次数: 0

父窗口

75_avatar_middle
最佳答案
0 
在线会员 发表于 2019-3-22 18:14:37 | 显示全部楼层
只下了D2D1Game1.rar,看了一下,动态库不是那么整地。动态库首先就是个库。它不是自动执行你的任务。是要你控制调用它函数。所以东西放到初始函数InitInstance()里是不合适地。那是MFC初始的地方,不是你初始的方法。没有函数库模块已加载就开始自动搞事地。这是其一。第二动态库内的函数,类和属主交互要输入输出,这好像都没懂。于是导致问题就绵绵无绝期。事情原来不是D2D1问题,而是方法问题。这个问题就不好整。我讲我的,你看听不听的进。这到处都是陷阱。最怕误人子弟。而且现在自以为是的,要用麻袋装。
动态链接库的编写一般要搞两个项目。1是动态库,2是调用程序。调用程序调用动态库指明模块有两个方法1.是传统的.def文件法,在里面编辑 2.是declspec法,它不仅能导出函数名,还能用作导出类class。
动态库的编写,你用的是MFC DLL,其实不管用什么,一条原则,不要用它的,那里面都应建自己的,它建的都不要理它。
调用程序的编写没下,我用控制台写,都能用。看1个都明白你想要干什么。去黑别人窗口。但是这不是一个简单的事。幸好遇上我,头脑发热,就开始整。一夜繁花看尽,凭想象弄了一个。有性情就自己套用吧,瞎猫有时也能逮住老鼠。不过人的精力有限,不是什么都会,廉颇老矣。
下面谈谈看你程序,重建解释参考:
一、建空MFC动态库,其中头文件内容:
// DemoMFCLibrary.h : DemoMFCLibrary DLL 的主头文件
//
#pragma once
#ifndef __AFXWIN_H__
        #error "在包含此文件之前包含“stdafx.h”以生成 PCH 文件"
#endif

#include "resource.h"                // 主符号
/************************************************/
//这部分是添加头文件和测试用的std  
#include <d2d1.h>
#include <cmath>
#include <Tlhelp32.h>
#include <dwrite.h>
#include <mmsystem.h>

#pragma comment( lib,"Dwmapi.lib" )
#pragma comment(lib,"d2d1.lib")
#pragma comment(lib,"Dwrite.lib")
#pragma comment( lib,"winmm.lib" )
#include <wincodec.h>
#pragma comment(lib,"windowscodecs.lib")
#include <iostream>
using namespace std;

#define XDEBUG 1
/************************************************/

// CDemoMFCLibraryApp
// 有关此类实现的信息,请参阅 DemoMFCLibrary.cpp
//

class CDemoMFCLibraryApp : public CWinApp
{
public:
        CDemoMFCLibraryApp();

// 重写
public:
        virtual BOOL InitInstance();

        DECLARE_MESSAGE_MAP()
};

/************************************************/
//这部分是第一种控制导入/导出                  
#ifdef IN_MFC_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
/*************************************************/
//第2种.def中符号导出地,如同函数。
void ShowText(float fx, float fy, wstring s,int color);
void ShowBitmap(float fx, float fy);
反斜杠注释包围地是我添加的,其中XDEBUG 为0 不显示跟踪数据。1为显示。class CDemoMFCLibraryApp : public CWinApp
都是系统自动生成地,不管它。要注意的就是IN_MFC_DLL这个符号定义为导入导出做准备。在库.cpp函数中定义并放在包含文件前。
在调用程序中不要。当然也可以#undefine IN_MFC_DLL,不过没试,哪有那么多闲精神。
ShowText,ShowBitmap是两个调用程序要调用的函数,主要在这里声明,就是要在.def文件里要添加的符号。
我这里.def 文件为DemoMFCLibrary.def .里面内容如下,分号是注释行,是系统自动生成地,不要不分皂白地又添加进去,复制到这里是提醒从那里添加。
   ; 此处可以是显式导出
        ShowText @1
        ShowBitmap @2
2.库.cpp文件。
主要添加类和这个类的唯一实例CD2D1 d2d1app,作用就是把所有自己函数,数据放在一起。
因为有内存指针数据,还能在析构时自动释放。
/**********************************************************/
/*这部分是用户在动态库的动作,都放在一起,唯一的一个实例d2d1*/
/**********************************************************/
class CD2D1 {
        ID2D1Factory *pFactory = NULL;
        ID2D1HwndRenderTarget *pRenderTarget = NULL;
        ID2D1SolidColorBrush *pRedBrush = NULL;
        ID2D1SolidColorBrush *pYellowBrush = NULL;
        HWND gamehwnd = (HWND)0x0;
        HWND hWnd = NULL;
    //
        IDWriteFactory* pDWriteFactory = NULL;
        ID2D1BitmapRenderTarget*pBitmapRenderTarget = NULL;
public:
        CD2D1() {};
        ~CD2D1();
        HRESULT Init(HWND hWnd);
        HRESULT LoadD2d1Bitmap(wstring FileBitmapName);
        void DWriteDrawText(float fx,float fy,wstring str, int color);
        void D2d1DrawBitmap(float fx,float fy);
        void renderText(float fx,float fy,wstring str, int color);
        void renderBitmap(float fx, float fy);
};
CD2D1 d2d1app;
/*********************************************************/
成员具体做什么在后面讲。成员方法的描述较多,就不在这粘贴了。看代码吧,没人下,还是很孤独地。
就是人们常说地:自古XX很寂寞。人在高处不胜寒。
其次添加 4个任务需要的公共函数。注意是4个,两个是.def输出,两个是extern "C" DLL_EXPORT
这样输出的。这样输出的不需要在.def文件中描述。一样两个,再看不会就该打板子。
/********************************************************************************************/
/*动态库输出的公共函数 ,一样两个.                                                                     */
/*输出有两种方式:                                                                          */
/*1、用 __declspec(dllexport),__declspec(dllimport)交替直接输出,注意定义DLL_EXPORT自动转换 */
/*2、在动态库.def文件中定义                                                                 */
/********************************************************************************************/
//按第1种方式输出,动态库.h文件中不需要函数声明,调用程序需声明                  
extern "C" DLL_EXPORT void  Initialize(HWND hWnd)
{
        d2d1app.Init(hWnd);
        if(XDEBUG) wcout << "d2d1 is ready!" << endl;
}
extern "C" DLL_EXPORT HRESULT LoadD2d1Image(wstring s) {

        HRESULT hr=d2d1app.LoadD2d1Bitmap(s);
        if (XDEBUG) wcout << "LoadD2d1Bitmap "<<s.c_str()<<" status=" <<hex<<hr<< endl;
        return hr;
}
//按第2种方式输出.h文件需要有声明
void ShowText(float fx, float fy, wstring s,int color)
{
        if (XDEBUG) wcout << "d2d1 draw str !" <<s.c_str()<< endl;
        d2d1app.renderText(fx,fy, s,color);
}
void ShowBitmap(float fx, float fy)
{
        if (XDEBUG) wcout << "d2d1 draw bitmap !" << endl;
        d2d1app.renderBitmap(fx, fy);
}

直此就库就完毕了。

二、调用程序
编写动态库,一般就要写调用程序,并且放在一起。不会分开写。所以就没下你的,库的内容只那么多,主程序也不会多。猜。
我人太懒了,主观意识强,真懒的看。控制台不很长,都粘贴在这

#include "stdafx.h"
#include <iostream>
#include <unordered_map>
#include "resource.h"
using namespace std;
#include <afxwin.h>
#include"..\DemoMFCLibrary\DemoMFCLibrary.h"
#pragma comment(lib,"DemoMFCLibrary.lib")
extern "C" DLL_EXPORT void Initialize(HWND hWnd);
extern "C" DLL_EXPORT HRESULT LoadD2d1Image(wstring s);
#define XDEBUG 1

namespace xx_demo {
        //本地测试部分
    void Show();
        //找进程的一类放在一起
        namespace lookup
        {
                wstring defaultExestr = L"notepad.exe";
        HWND search_for_one_window(wstring s);
                struct ProcessWindowData
                {
                        HWND hWnd;
                        unsigned long lProcessId;
                };
                BOOL CALLBACK EnumWindowCallback(HWND hWnd, LPARAM lParam);
                HWND GetMainWindowHwnd(unsigned long lProcessId);
        }
};
using namespace xx_demo;
using namespace xx_demo::lookup;

int main()
{
        HWND hWnd = search_for_one_window(defaultExestr);
        if (!hWnd)
        {
                cout << "没有找到指定程序的窗口,使用控制台窗口!" << endl;
        hWnd = GetConsoleWindow();
        }
    //调用初始化
        Initialize(hWnd);

        unordered_map<string,wstring> img;
        img["bird"]   = L"bird.jpg";
        img["female"] = L"female.jpg";
        BOOL bSwapBitmap = FALSE;

        Show();

        //控制按键速度300ms以外
        DWORD lastTick, thisTick;
        DWORD checkLastTick,checkThisTick;
        lastTick  = GetTickCount();
        checkLastTick = GetTickCount();
        while (!GetAsyncKeyState(VK_ESCAPE)) {
                SHORT key;
                key = GetAsyncKeyState(VK_F1);
                if (key&0x8000) {
                        thisTick = GetTickCount();
                        if(thisTick-lastTick>300){
                                Show();
                                lastTick = thisTick;
                        }
                }
                key = GetAsyncKeyState(VK_F2);
                if (key & 0x8000) {
                        thisTick = GetTickCount();
                        if (thisTick - lastTick>1000) {
                                bSwapBitmap = !bSwapBitmap;
                                if (bSwapBitmap) LoadD2d1Image(img["bird"]);
                                else             LoadD2d1Image(img["female"]);
                                lastTick = thisTick;
                        }
                }
                //15秒检查窗口是否关闭
                checkThisTick = GetTickCount();
                if (checkThisTick - checkLastTick > 15000)
                {
                        checkLastTick = GetTickCount();
                        if (GetConsoleWindow() != hWnd) {
                                HWND hWndNew = search_for_one_window(defaultExestr);
                                if(!hWndNew)
                                {
                                        cout << "所黑窗口已退出,再见!" << endl;
                                        SleepEx(5, TRUE);
                                        break;
                                }
                        }
                }
        }
    return 0;
}
void xx_demo::Show() {
        //在该窗口涂鸦
        ShowBitmap(10, 10);
        ShowText(0, 0, L"Hello! ",0);
        ShowText(0, 50, L"I come here MFC-D2D1. ",1);
        cout << "按1次F2切换位图,再按F1刷新" << endl;
        cout << "按F1再黑一遍" << endl;
        cout << "按ESC退出" << endl;
}


BOOL CALLBACK xx_demo::lookup::EnumWindowCallback(HWND hWnd, LPARAM lParam)
{
        ProcessWindowData& wndData = *(ProcessWindowData*)lParam;
        unsigned long lProcessId = 0;
        GetWindowThreadProcessId(hWnd, &lProcessId);
        TCHAR szClassName[MAX_PATH];
        TCHAR szWindowName[MAX_PATH];
        GetClassName(hWnd, szClassName, MAX_PATH);//获取窗口类名
        //获取窗口名,好像不能取得正确结果
        //GetWindowText(hWnd, szTitle, MAX_PATH);
        SendMessage(hWnd, WM_GETTEXT, MAX_PATH, (LPARAM)szWindowName);
        if ((wndData.lProcessId != lProcessId) || (GetWindow(hWnd, GW_OWNER) != (HWND)0) || !IsWindowVisible(hWnd))
        {
                if (XDEBUG) {
                        wcout << "hWnd=0x" << hex << hWnd << " id=" << dec << lProcessId << " ClassName=";
                        wcout << (TCHAR*)szClassName /*<< " WindowTitleName=" << (TCHAR*)szWindowName*/ << endl;
                }
                return 1;
        }
        wndData.hWnd = hWnd;
        if (XDEBUG) {
                wcout << "找到 hWnd=0x" << hex << hWnd << " id=" << dec << lProcessId << " ClassName=";
                wcout << (TCHAR*)szClassName/* << " WindowTitleName=" << (TCHAR*)szWindowName */ << endl;
        }
        return 0;
}

HWND xx_demo::lookup::GetMainWindowHwnd(unsigned long lProcessId)
{
        ProcessWindowData wndData;
        wndData.hWnd = 0;
        wndData.lProcessId = lProcessId;
        EnumWindows(EnumWindowCallback, (LPARAM)&wndData);
        return wndData.hWnd;
}
HWND xx_demo::lookup::search_for_one_window(wstring s)
{
        //查找进程ID
        PROCESSENTRY32 pe;
        pe.dwSize = sizeof(PROCESSENTRY32);
        HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (!Process32First(hSnapshot, &pe)) return NULL;
        do {
                if (XDEBUG) wcout << (TCHAR*)pe.szExeFile << endl;
                if (!Process32Next(hSnapshot, &pe))        return NULL;
        } while (StrCmp(pe.szExeFile, defaultExestr.c_str()));
        DWORD id = pe.th32ProcessID;
        if (XDEBUG) cout << "id=" << dec << id << endl;
        //查找窗口
        return GetMainWindowHwnd(id);
}

域名xx_demo用来把闲散变量,函数整合到一起,域名xx_demo::lookup把找窗口的整在一起。
#include"..\DemoMFCLibrary\DemoMFCLibrary.h"
#pragma comment(lib,"DemoMFCLibrary.lib")
extern "C" DLL_EXPORT void Initialize(HWND hWnd);
extern "C" DLL_EXPORT HRESULT LoadD2d1Image(wstring s);
是动态库应用包含和两个非.def文件输出的库函数。它和那两个showXX是有点区别地。
三、任务说明
   任务就是程序要做什么,程序第一在进程中找exe文件,找到后根据id找窗口。找到窗口,就黑它。
怎么黑,就是输出东西。先文字,再图片,变脸。
   注意找窗口,取窗口文本好像不对,但是Spy++又找的到,这技巧还是从网上扒吧,我只列出窗口,类名和ID。
找到窗口,用什么写,用D2D1。怎么写,又成问题。一个句柄就会折腾那么久,遇到问题还会更多。
为杜绝这个问题。我把D2D1写文本DWrite写位图都给你做了,或多或少有些帮助。再应该没有问题了。有点怕,特别
是一长串代码后还是没解决,是绝望。画蛇添足。

四、运行
  下载的代码是12版本,我是14版本,如果用先前版本打开不能编译,应该选项目右键属性->常规中平台工具集,把版本降下来就可以了。
打开解包所在目录中的ConMFCDemo.sln即可,一个解决方案下有两项目,1个是调用程序,1个是库,库不能单独运行。
运行流程:
1 打开记事本。不输内容就可以。主要黑它,学会了以后再黑别人。练习嘛。
2 查找窗口,没找到就黑自己本窗,不过点一下就刷新了。找到init执行库里面实例初始化,建相关联的D2D1环境,对象,位图渲染环境 等.
3 输出位图到窗口
4 输出文本到窗口
5 等待ESC按键退出,其中15秒检查该窗口是否关闭,本窗口忽略
    每按F1就再画一次。点击记事本,就会消失,按一下就能再看到
    按F2重新载入位图。要按F1才会显示,它只是后台更新完。不主动显示。

五、演示图
启动后图
    哪位大神用过D2D1
按F2后再按F1图
   哪位大神用过D2D1
Spy的窗口标题
哪位大神用过D2D1
六、代码
  工程全代码,含源代码和执行代码。如果不能编译,内有已编译好的执行码。
  编译环境window10 + vs2015

哪位大神用过D2D1 MFCDLLDemo.rar (418.19 KB, 下载次数: 1)
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

×【发帖 友情提示】
1、请回复有意义的内容,请勿恶意灌水;
2、纯数字、字母、表情等无意义的内容系统将自动删除;
3、若正常回复后帖子被自动删除,为系统误删的情况,请重新回复其他正常内容或等待管理员审核通过后会自动发布;
4、感谢您对VC驿站一如既往的支持,谢谢合作!

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号 )|网站地图wx_jqr

GMT+8, 2020-11-24 23:54

Powered by CcTry.CoM

© 2009-2020 cctry.com

快速回复 返回顶部 返回列表