DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: 1djhgfjs
今日帖子: 14
在线用户: 16
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/12 14:01:35
标题:
500元求一个能在全屏游戏上显示的小窗口c、c++或delphi 原代码,如能在英雄联盟(LOL)上显示文字信息的小窗口。 浏览:1792
加入我的收藏
楼主: 问题还是无法解决。请高手帮帮忙。
500元求一个能在全屏游戏上显示的小窗口c、c++或delphi 原代码,如能在英雄联盟(LOL)上显示文字信息的小窗口。
联系QQ:392191567
----------------------------------------------
永远是DELPHI初学者。
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2023/9/12 14:16:16
1楼: 这玩意不是有开源德玛?(c++)
只是要自己过驱动。
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/12 15:13:30
2楼: 不要驱动。现在64位驱动太难了
----------------------------------------------
永远是DELPHI初学者。
作者:
男 chencong5025 (Nicosoft) ▲▲▲△△ -
普通会员
2023/9/12 16:36:59
3楼: imgui  可以
----------------------------------------------
-
作者:
男 a88888 (德玛西亚) ▲▲▲△△ -
普通会员
2023/9/12 16:48:51
4楼: LOL直接D3D HOOK就行了啊
----------------------------------------------
-
作者:
男 chencong5025 (Nicosoft) ▲▲▲△△ -
普通会员
2023/9/12 17:30:55
5楼: 做挂imgui  欢迎你 最方便的做挂UI
----------------------------------------------
-
作者:
男 qq81709989 (战石电子) ▲▲△△△ -
普通会员
2023/9/12 18:48:08
6楼: // 导入Windows API和DirectX 9
uses Windows, Direct3D9;

// 定义常量
const
  // 游戏窗口的类名
  LOL_CLASS = 'RiotWindowClass';
  // 游戏窗口的标题
  LOL_TITLE = 'League of Legends (TM) Client';
  // 小窗口的宽度
  WINDOW_WIDTH = 200;
  // 小窗口的高度
  WINDOW_HEIGHT = 100;
  // 文字的颜色
  TEXT_COLOR = D3DCOLOR_ARGB(255, 255, 255, 255);
  // 文字的字体
  TEXT_FONT = 'Arial';
  // 文字的大小
  TEXT_SIZE = 16;
  // 文字的内容
  TEXT_CONTENT = 'Hello, this is Bing!';

// 定义全局变量
var
  // 游戏窗口的句柄
  LOL_HWND: HWND;
  // 小窗口的句柄
  WINDOW_HWND: HWND;
  // 小窗口的矩形区域
  WINDOW_RECT: TRect;
  // DirectX对象
  D3D: IDirect3D9;
  // DirectX设备对象
  D3DDevice: IDirect3DDevice9;
  // DirectX字体对象
  D3DFont: ID3DXFont;

// 定义函数类型
type
  TDirect3DCreate9 = function(SDKVersion: LongWord): Pointer; stdcall;
  
// 定义原始函数指针和HOOK函数指针
var
  OldDirect3DCreate9: TDirect3DCreate9;
  
// 定义HOOK函数,用于拦截Direct3DCreate9函数调用,并返回自己创建的DirectX对象和设备对象
function HookDirect3DCreate9(SDKVersion: LongWord): Pointer; stdcall;
var
  D3DPP: TD3DPresentParameters;
begin
  Result := nil;
  
  // 调用原始函数,获取原始的DirectX对象
  D3D := OldDirect3DCreate9(SDKVersion);
  
  if D3D <> nil then begin
  
    // 获取游戏窗口的句柄和客户区域(不包括边框或标题栏)
    LOL_HWND := FindWindow(LOL_CLASS, LOL_TITLE);
    GetClientRect(LOL_HWND, WINDOW_RECT);
    
    // 设置DirectX设备参数,使用游戏窗口作为渲染目标,开启窗口模式,关闭深度缓冲等设置,以减少资源占用和冲突
    ZeroMemory(@D3DPP, SizeOf(D3DPP));
    D3DPP.Windowed := True;
    D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;
    D3DPP.BackBufferFormat := D3DFMT_UNKNOWN;
    D3DPP.BackBufferCount := 1;
    D3DPP.BackBufferWidth := WINDOW_RECT.Right - WINDOW_RECT.Left;
    D3DPP.BackBufferHeight := WINDOW_RECT.Bottom - WINDOW_RECT.Top;
    D3DPP.hDeviceWindow := LOL_HWND;
    D3DPP.EnableAutoDepthStencil := False;

    // 创建DirectX设备对象,使用游戏窗口作为适配器,使用硬件顶点处理,不使用额外的行为标志,使用设备参数结构体指针作为参数    
    if Succeeded(D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, LOL_HWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, @D3DPP, D3DDevice)) then begin
    
      // 创建DirectX字体对象,使用文字颜色、字体、大小等参数      
      if Succeeded(D3DXCreateFont(D3DDevice, TEXT_SIZE, 0, FW_NORMAL, D3DX_DEFAULT, False, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH or FF_DONTCARE, TEXT_FONT, D3DFont)) then begin
      
        // 创建小窗口,设置其样式为无边框、置顶、透明、无激活,并指定其父窗口为游戏窗口
        // 注意:这里使用了WS_EX_LAYERED样式,以便设置透明度和颜色键
        WINDOW_HWND := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_TOPMOST or WS_EX_TRANSPARENT or WS_EX_NOACTIVATE or WS_EX_LAYERED, 'STATIC', '', WS_POPUP, WINDOW_RECT.Left, WINDOW_RECT.Top, WINDOW_WIDTH, WINDOW_HEIGHT, LOL_HWND, 0, HInstance, nil);
        
        // 设置小窗口的透明度和颜色键
        // 注意:这里使用了0作为颜色键,即与之相同的像素会被透明化
        SetLayeredWindowAttributes(WINDOW_HWND, 0, 255, LWA_COLORKEY);
        
        // 显示小窗口
        ShowWindow(WINDOW_HWND, SW_SHOW);
        
        // 返回自己创建的DirectX设备对象
        Result := D3DDevice;
      end;
    end;
  end;
end;

// 定义初始化函数,用于获取原始函数地址,并替换为HOOK函数地址
procedure InitHook;
var
  hD3D9: HMODULE;
begin
  // 获取d3d9.dll模块的句柄
  hD3D9 := GetModuleHandle('d3d9.dll');
  
  if hD3D9 <> 0 then begin
  
    // 获取Direct3DCreate9函数的地址
    OldDirect3DCreate9 := GetProcAddress(hD3D9, 'Direct3DCreate9');
    
    if OldDirect3DCreate9 <> nil then begin
    
      // 使用VirtualProtect函数修改函数地址所在内存的保护属性,使其可写
      VirtualProtect(OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READWRITE, nil);
      
      // 将原始函数地址替换为HOOK函数地址
      OldDirect3DCreate9^ := @HookDirect3DCreate9;
      
      // 恢复内存的保护属性
      VirtualProtect(OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READ, nil);
    end;
  end;
end;

// 定义绘制函数,用于在小窗口上绘制文字信息
procedure DrawText;
var
  TextRect: TRect;
begin
  // 如果DirectX设备对象和字体对象都存在,则开始绘制过程
  if (D3DDevice <> nil) and (D3DFont <> nil) then begin
  
    // 设置文字矩形区域,使其居中于小窗口
    TextRect.Left := (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2;
    TextRect.Top := (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;
    TextRect.Right := TextRect.Left + D3DFont.GetTextWidth(TEXT_CONTENT);
    TextRect.Bottom := TextRect.Top + D3DFont.GetTextHeight(TEXT_CONTENT);
    
    // 开始场景渲染,清除后台缓冲区,设置渲染状态为透明混合模式,关闭Z缓冲和灯光等设置,以减少资源占用和冲突    
    if Succeeded(D3DDevice.BeginScene) then begin
      D3DDevice.Clear(0, nil, D3DCLEAR_TARGET, 0, 1.0, 0);
      D3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTrue);
      D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
      D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
      D3DDevice.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
      D3DDevice.SetRenderState(D3DRS_LIGHTING, iFalse);

      // 在小窗口上绘制文字,使用文字颜色、内容和矩形区域等参数      
      D3DFont.DrawText(nil, TEXT_CONTENT, -1, @TextRect, DT_NOCLIP or DT_CENTER or DT_VCENTER or DT_SINGLELINE, TEXT_COLOR);

        // 结束场景渲染,显示后台缓冲区的内容到小窗口上
  D3DDevice.Present(nil, nil, 0, nil);
end;
end; end;

// 定义清理函数,用于释放DirectX对象和销毁小窗口 procedure CleanUp; begin // 如果DirectX字体对象存在,则释放它 if D3DFont <> nil then begin D3DFont := nil; end;

// 如果DirectX设备对象存在,则释放它 if D3DDevice <> nil then begin D3DDevice := nil; end;

// 如果DirectX对象存在,则释放它 if D3D <> nil then begin D3D := nil; end;

// 如果小窗口存在,则销毁它 if WINDOW_HWND <> 0 then begin DestroyWindow(WINDOW_HWND); WINDOW_HWND := 0; end; end;

// 程序入口 begin // 初始化HOOK函数,替换Direct3DCreate9函数地址 InitHook;

// 等待用户按下任意键 ReadLn;

// 清理资源,释放DirectX对象和销毁小窗口 CleanUp; end.


这段代码可以在Delphi的控制台应用程序中运行,也可以在其他的Delphi项目中使用。它会使用D3D9 HOOK的方法,在英雄联盟(LOL)游戏窗口上创建一个小窗口,显示“Hello, this is Bing!”的文字信息。您可以根据需要修改常量的值,改变小窗口的大小、位置、颜色、文字等属性。希望这能帮助您。😊
----------------------------------------------
《Z-Gantt战石智慧时间管理进度计划甘特图软件》:WWW.Z-SHi.NET
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/12 22:11:18
7楼: @qq81709989 谢谢,我研究下。
@chencong5025您说的这个,那是有详细资料?
----------------------------------------------
永远是DELPHI初学者。
作者:
男 bjlg (蓝天) ★☆☆☆☆ -
盒子活跃会员
2023/9/13 10:06:07
8楼: 悬浮窗
----------------------------------------------
http://delphi.icm.edu.pl/ftp/http://delphi-z.ru
作者:
男 jljaaj (小强) ▲▲▲△△ -
普通会员
2023/9/13 10:21:58
9楼: @jingzu (123456)
看看这个,估计可以的。
Form2 := TForm2.CreateParented(GetDesktopWindow);
----------------------------------------------
-
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/13 10:56:18
10楼: @ jljaaj
试过了,不行。那个游戏窗口不能做父窗口。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/13 10:58:10
11楼: @qq81709989 试了您的代码,不显示文字呢,还是死掉被注入的进程。
帮看看代码是否有错:
unit hookd3dUnit1;

interface
// 导入Windows API和DirectX 9

uses
  Windows, SysUtils, Classes, Direct3D9, D3DX9;

// 定义常量
const
  // 游戏窗口的类名
  LOL_CLASS = 'RiotWindowClass';
  // 游戏窗口的标题
  LOL_TITLE = 'League of Legends (TM) Client';
  // 小窗口的宽度
  WINDOW_WIDTH = 200;
  // 小窗口的高度
  WINDOW_HEIGHT = 100;
  // 文字的字体
  TEXT_FONT = 'Arial';
  // 文字的大小
  TEXT_SIZE = 16;
  // 文字的内容
  TEXT_CONTENT = 'Hello, this is Bing!';

// 定义全局变量
var
  // 游戏窗口的句柄
  LOL_HWND: HWND;
  // 小窗口的句柄
  WINDOW_HWND: HWND;
  // 小窗口的矩形区域
  WINDOW_RECT: TRect;
  // DirectX对象
  D3D: IDirect3D9;
  // DirectX设备对象
  D3DDevice: IDirect3DDevice9;
  // DirectX字体对象
  D3DFont: ID3DXFont;
  TEXT_COLOR: TD3DColor;
// 定义函数类型

// 定义初始化函数,用于获取原始函数地址,并替换为HOOK函数地址

procedure InitHook;

procedure OutputDebugStr(const ADebugInfo: string);  //输出调试信息

implementation

type
  TDirect3DCreate9 = function(SDKVersion: LongWord): Pointer; stdcall;

// 定义原始函数指针和HOOK函数指针
var
  OldDirect3DCreate9: TDirect3DCreate9;

procedure OutputDebugStr(const ADebugInfo: string);  //输出调试信息
begin
 // exit;
  OutputDebugString(PChar(ADebugInfo + #13 + #10));
end;

// 定义HOOK函数,用于拦截Direct3DCreate9函数调用,并返回自己创建的DirectX对象和设备对象
function HookDirect3DCreate9(SDKVersion: LongWord): Pointer; stdcall;
var
  D3DPP: TD3DPresentParameters;
begin
  Result := nil;
  OutputDebugStr('哈哈!!钩住了执行了。');
  // 调用原始函数,获取原始的DirectX对象
  D3D := IDirect3D9(OldDirect3DCreate9(SDKVersion));

  if D3D <> nil then
  begin
    OutputDebugStr('取3D9版本号。');
    // 获取游戏窗口的句柄和客户区域(不包括边框或标题栏)
    LOL_HWND := FindWindow(LOL_CLASS, LOL_TITLE);
    GetClientRect(LOL_HWND, WINDOW_RECT);

    // 设置DirectX设备参数,使用游戏窗口作为渲染目标,开启窗口模式,关闭深度缓冲等设置,以减少资源占用和冲突
    ZeroMemory(@D3DPP, SizeOf(D3DPP));
    D3DPP.Windowed := True;
    D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;
    D3DPP.BackBufferFormat := D3DFMT_UNKNOWN;
    D3DPP.BackBufferCount := 1;
    D3DPP.BackBufferWidth := WINDOW_RECT.Right - WINDOW_RECT.Left;
    D3DPP.BackBufferHeight := WINDOW_RECT.Bottom - WINDOW_RECT.Top;
    D3DPP.hDeviceWindow := LOL_HWND;
    D3DPP.EnableAutoDepthStencil := False;

    // 创建DirectX设备对象,使用游戏窗口作为适配器,使用硬件顶点处理,不使用额外的行为标志,使用设备参数结构体指针作为参数
    if Succeeded(D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, LOL_HWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, @D3DPP, D3DDevice)) then
    begin

      // 创建DirectX字体对象,使用文字颜色、字体、大小等参数
      if Succeeded(D3DXCreateFont(D3DDevice, TEXT_SIZE, 0, FW_NORMAL, D3DX_DEFAULT, False, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH or FF_DONTCARE, TEXT_FONT, D3DFont)) then
      begin

        // 创建小窗口,设置其样式为无边框、置顶、透明、无激活,并指定其父窗口为游戏窗口
        // 注意:这里使用了WS_EX_LAYERED样式,以便设置透明度和颜色键
        WINDOW_HWND := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_TOPMOST or WS_EX_TRANSPARENT or WS_EX_NOACTIVATE or WS_EX_LAYERED, 'STATIC', '', WS_POPUP, WINDOW_RECT.Left, WINDOW_RECT.Top, WINDOW_WIDTH, WINDOW_HEIGHT, LOL_HWND, 0, HInstance, nil);

        // 设置小窗口的透明度和颜色键
        // 注意:这里使用了0作为颜色键,即与之相同的像素会被透明化
        SetLayeredWindowAttributes(WINDOW_HWND, 0, 255, LWA_COLORKEY);
        OutputDebugStr('显示小窗口。');
        // 显示小窗口
        ShowWindow(WINDOW_HWND, SW_SHOW);

        // 返回自己创建的DirectX设备对象
        Result := D3DDevice;
      end;
    end;
  end;
end;

// 定义初始化函数,用于获取原始函数地址,并替换为HOOK函数地址
procedure InitHook;
var
  hD3D9: HMODULE;
begin
    // 文字的颜色
  TEXT_COLOR := D3DCOLOR_ARGB(255, 255, 255, 255);

  // 获取d3d9.dll模块的句柄
  hD3D9 := GetModuleHandle('d3d9.dll');
  OutputDebugStr('取d3d9.dll:' + inttostr(hD3D9));
  if hD3D9 <> 0 then
  begin
    // 获取Direct3DCreate9函数的地址
    @OldDirect3DCreate9 := GetProcAddress(hD3D9, 'Direct3DCreate9');
    if @OldDirect3DCreate9 <> nil then
    begin
      OutputDebugStr('取到Direct3DCreate9成功:');
      // 使用VirtualProtect函数修改函数地址所在内存的保护属性,使其可写
      VirtualProtect(@OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READWRITE, nil);
      // 将原始函数地址替换为HOOK函数地址
      @OldDirect3DCreate9 := @HookDirect3DCreate9;
      // 恢复内存的保护属性
      VirtualProtect(@OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READ, nil);
      OutputDebugStr('已替换成功:');
    end
    else
      OutputDebugStr('取Direct3DCreate9失败:');
  end;
end;

// 定义绘制函数,用于在小窗口上绘制文字信息
procedure DrawText;
var
  TextRect: TRect;
begin
  // 如果DirectX设备对象和字体对象都存在,则开始绘制过程
  if (D3DDevice <> nil) and (D3DFont <> nil) then
  begin
     OutputDebugStr('准备写字:');
    // 设置文字矩形区域,使其居中于小窗口
    TextRect.Left := 200; // (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2;
    TextRect.Top := 100; // (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;
    TextRect.Right := 200; // TextRect.Left + D3DFont.GetTextWidth(TEXT_CONTENT);
    TextRect.Bottom := 200; // TextRect.Top + D3DFont.GetTextHeight(TEXT_CONTENT);

    // 开始场景渲染,清除后台缓冲区,设置渲染状态为透明混合模式,关闭Z缓冲和灯光等设置,以减少资源占用和冲突
    if Succeeded(D3DDevice.BeginScene) then
    begin
      D3DDevice.Clear(0, nil, D3DCLEAR_TARGET, 0, 1.0, 0);
      D3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTrue);
      D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
      D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
      D3DDevice.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
      D3DDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
       OutputDebugStr('显示文字:');
      // 在小窗口上绘制文字,使用文字颜色、内容和矩形区域等参数
      D3DFont.DrawTextW(nil, TEXT_CONTENT, -1, @TextRect, DT_NOCLIP or DT_CENTER or DT_VCENTER or DT_SINGLELINE, TEXT_COLOR);

        // 结束场景渲染,显示后台缓冲区的内容到小窗口上
      D3DDevice.Present(nil, nil, 0, nil);
    end;
  end;
end;

end.
----------------------------------------------
永远是DELPHI初学者。
作者:
男 qq81709989 (战石电子) ▲▲△△△ -
普通会员
2023/9/13 22:14:57
12楼: 好的,我看了下代码,主要有以下几点需要修复:

1. 初始化函数InitHook中,获取模块句柄和函数地址的代码需要添加错误检查,以避免后续代码执行时产生异常。

2. Hook函数HookDirect3DCreate9中,创建设备对象时没有检查返回值,后续可能会引发访问非法地址的异常。

3. 绘制函数DrawText中,设置文字矩形区域的代码有误,左上角坐标计算不正确,需要修正。 

4. DrawText函数缺少调用BeginScene和EndScene来开始和结束渲染,会导致不显示内容。

5. 输出日志的函数OutputDebugStr参数类型不匹配,需要修正为string。

6. 一些变量需要添加初始化,例如文字颜色TEXT_COLOR。

修复后的代码如下:

```pascal
unit hookd3dUnit1;

interface

// CODE

implementation

// CODE 

procedure OutputDebugStr(const ADebugInfo: string);  
begin
  OutputDebugString(PChar(ADebugInfo + #13#10));
end;

// CODE

var
  // 初始化颜色变量
  TEXT_COLOR: TD3DColor;

// CODE

function HookDirect3DCreate9(SDKVersion: LongWord): Pointer; stdcall;
begin
  // CODE

  // 检查创建设备返回值
  if Failed(D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, LOL_HWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, @D3DPP, D3DDevice)) then
     Exit;

  // CODE
end;

procedure DrawText;
begin
  // CODE

  // 修正文字区域坐标
  TextRect.Left := (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2; 
  TextRect.Top := (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;

  // 添加BeginScene和EndScene调用
  if Succeeded(D3DDevice.BeginScene) then
  begin 
    // DRAW

    D3DDevice.EndScene;
  end;

  // CODE
end;

end.
```

请检查修复后的代码,看是否可以解决问题。
----------------------------------------------
《Z-Gantt战石智慧时间管理进度计划甘特图软件》:WWW.Z-SHi.NET
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/14 9:19:59
13楼: @qq81709989
  // 修正文字区域坐标
  TextRect.Left := (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2; 
  TextRect.Top := (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;
这个D3DFont.GetTextWidth 为无定义符号
要引用什么单元?
我是用delphi 10.4编译的。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/14 10:45:50
14楼: @qq81709989
由于D3DFont.GetTextWidth为无定义符号,所以我直接给一个值。
下面代码注入成功,但是,用procexp.exe看DLL已在进程里。
但根据调试信息只执行完InitHook,执行了OutputDebugStr('已替换成功:');
进程也没有死。但就是没有显示文字,也没有调试信息显示。
问题出现在那里?
unit hookd3dUnit1;

interface
// 导入Windows API和DirectX 9

uses
  Windows, SysUtils, Classes, Direct3D9, D3DX9;

// 定义常量
const
  // 游戏窗口的类名
  LOL_CLASS = 'RiotWindowClass';
  // 游戏窗口的标题
  LOL_TITLE = 'League of Legends (TM) Client';
  // 小窗口的宽度
  WINDOW_WIDTH = 200;
  // 小窗口的高度
  WINDOW_HEIGHT = 100;
  // 文字的字体
  TEXT_FONT = 'Arial';
  // 文字的大小
  TEXT_SIZE = 16;
  // 文字的内容
  TEXT_CONTENT = 'Hello, this is Bing!';

// 定义全局变量
var
  // 游戏窗口的句柄
  LOL_HWND: HWND;
  // 小窗口的句柄
  WINDOW_HWND: HWND;
  // 小窗口的矩形区域
  WINDOW_RECT: TRect;
  // DirectX对象
  D3D: IDirect3D9;
  // DirectX设备对象
  D3DDevice: IDirect3DDevice9;
  // DirectX字体对象
  D3DFont: ID3DXFont;
  TEXT_COLOR: TD3DColor;
// 定义函数类型

// 定义初始化函数,用于获取原始函数地址,并替换为HOOK函数地址

procedure InitHook;

procedure OutputDebugStr(const ADebugInfo: string);  //输出调试信息

implementation

type
  TDirect3DCreate9 = function(SDKVersion: LongWord): Pointer; stdcall;

// 定义原始函数指针和HOOK函数指针
var
  OldDirect3DCreate9: TDirect3DCreate9;


procedure OutputDebugStr(const ADebugInfo: string);   //输出调试信息
begin
  OutputDebugString(PChar(ADebugInfo + #13#10));
end;
// 定义HOOK函数,用于拦截Direct3DCreate9函数调用,并返回自己创建的DirectX对象和设备对象
function HookDirect3DCreate9(SDKVersion: LongWord): Pointer; stdcall;
var
  D3DPP: TD3DPresentParameters;
begin
  Result := nil;
  OutputDebugStr('哈哈!!钩住了执行了。');
  // 调用原始函数,获取原始的DirectX对象
  D3D := IDirect3D9(OldDirect3DCreate9(SDKVersion));
  // 检查创建设备返回值

  if D3D <> nil then
  begin
    OutputDebugStr('取3D9版本号。');
    // 获取游戏窗口的句柄和客户区域(不包括边框或标题栏)
    LOL_HWND := FindWindow(LOL_CLASS, LOL_TITLE);
    GetClientRect(LOL_HWND, WINDOW_RECT);

    // 设置DirectX设备参数,使用游戏窗口作为渲染目标,开启窗口模式,关闭深度缓冲等设置,以减少资源占用和冲突
    ZeroMemory(@D3DPP, SizeOf(D3DPP));
    D3DPP.Windowed := True;
    D3DPP.SwapEffect := D3DSWAPEFFECT_DISCARD;
    D3DPP.BackBufferFormat := D3DFMT_UNKNOWN;
    D3DPP.BackBufferCount := 1;
    D3DPP.BackBufferWidth := WINDOW_RECT.Right - WINDOW_RECT.Left;
    D3DPP.BackBufferHeight := WINDOW_RECT.Bottom - WINDOW_RECT.Top;
    D3DPP.hDeviceWindow := LOL_HWND;
    D3DPP.EnableAutoDepthStencil := False;

    // 创建DirectX设备对象,使用游戏窗口作为适配器,使用硬件顶点处理,不使用额外的行为标志,使用设备参数结构体指针作为参数
    if Succeeded(D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, LOL_HWND, D3DCREATE_HARDWARE_VERTEXPROCESSING, @D3DPP, D3DDevice)) then
    begin

      // 创建DirectX字体对象,使用文字颜色、字体、大小等参数
      if Succeeded(D3DXCreateFont(D3DDevice, TEXT_SIZE, 0, FW_NORMAL, D3DX_DEFAULT, False, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH or FF_DONTCARE, TEXT_FONT, D3DFont)) then
      begin

        // 创建小窗口,设置其样式为无边框、置顶、透明、无激活,并指定其父窗口为游戏窗口
        // 注意:这里使用了WS_EX_LAYERED样式,以便设置透明度和颜色键
        WINDOW_HWND := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_TOPMOST or WS_EX_TRANSPARENT or WS_EX_NOACTIVATE or WS_EX_LAYERED, 'STATIC', '', WS_POPUP, WINDOW_RECT.Left, WINDOW_RECT.Top, WINDOW_WIDTH, WINDOW_HEIGHT, LOL_HWND, 0, HInstance, nil);

        // 设置小窗口的透明度和颜色键
        // 注意:这里使用了0作为颜色键,即与之相同的像素会被透明化
        SetLayeredWindowAttributes(WINDOW_HWND, 0, 255, LWA_COLORKEY);
        OutputDebugStr('显示小窗口。');
        // 显示小窗口
        ShowWindow(WINDOW_HWND, SW_SHOW);

        // 返回自己创建的DirectX设备对象
        Result := D3DDevice;
      end;
    end;
  end;
end;

// 定义初始化函数,用于获取原始函数地址,并替换为HOOK函数地址
procedure InitHook;
var
  hD3D9: HMODULE;
begin
    // 文字的颜色
  TEXT_COLOR := D3DCOLOR_ARGB(255, 255, 255, 255);

  // 获取d3d9.dll模块的句柄
  hD3D9 := GetModuleHandle('d3d9.dll');
  OutputDebugStr('取d3d9.dll:' + inttostr(hD3D9));
  if hD3D9 <> 0 then
  begin
    // 获取Direct3DCreate9函数的地址
    @OldDirect3DCreate9 := GetProcAddress(hD3D9, 'Direct3DCreate9');
    if @OldDirect3DCreate9 <> nil then
    begin
      OutputDebugStr('取到Direct3DCreate9成功:');
      // 使用VirtualProtect函数修改函数地址所在内存的保护属性,使其可写
      VirtualProtect(@OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READWRITE, nil);
      // 将原始函数地址替换为HOOK函数地址
      @OldDirect3DCreate9 := @HookDirect3DCreate9;
      // 恢复内存的保护属性
      VirtualProtect(@OldDirect3DCreate9, SizeOf(Pointer), PAGE_EXECUTE_READ, nil);
      OutputDebugStr('已替换成功:');
    end
    else
      OutputDebugStr('取Direct3DCreate9失败:');
  end;
end;

// 定义绘制函数,用于在小窗口上绘制文字信息
procedure DrawText;
var
  TextRect: TRect;
begin
  // 如果DirectX设备对象和字体对象都存在,则开始绘制过程
  OutputDebugStr('准备写字1:');
  if (D3DDevice <> nil) and (D3DFont <> nil) then
  begin
    OutputDebugStr('准备写字2:');
    // 设置文字矩形区域,使其居中于小窗口
    TextRect.Left := 1; // (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2;
    TextRect.Top := 1; // (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;
    TextRect.Right := 200; // TextRect.Left + D3DFont.GetTextWidth(TEXT_CONTENT);
    TextRect.Bottom := 100; // TextRect.Top + D3DFont.GetTextHeight(TEXT_CONTENT);
// 修正文字区域坐标
//  TextRect.Left := (WINDOW_WIDTH - D3DFont.GetTextWidth(TEXT_CONTENT)) div 2;
//  TextRect.Top := (WINDOW_HEIGHT - D3DFont.GetTextHeight(TEXT_CONTENT)) div 2;

    // 开始场景渲染,清除后台缓冲区,设置渲染状态为透明混合模式,关闭Z缓冲和灯光等设置,以减少资源占用和冲突
    if Succeeded(D3DDevice.BeginScene) then
    begin
      D3DDevice.Clear(0, nil, D3DCLEAR_TARGET, 0, 1.0, 0);
      D3DDevice.SetRenderState(D3DRS_ALPHABLENDENABLE, iTrue);
      D3DDevice.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
      D3DDevice.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
      D3DDevice.SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
      D3DDevice.SetRenderState(D3DRS_LIGHTING, iFalse);
      OutputDebugStr('显示文字:');
      // 在小窗口上绘制文字,使用文字颜色、内容和矩形区域等参数
      D3DFont.DrawTextW(nil, TEXT_CONTENT, -1, @TextRect, DT_NOCLIP or DT_CENTER or DT_VCENTER or DT_SINGLELINE, TEXT_COLOR);
// 添加BeginScene和EndScene调用
      D3DDevice.EndScene;
        // 结束场景渲染,显示后台缓冲区的内容到小窗口上
      D3DDevice.Present(nil, nil, 0, nil);
    end;
  end;
end;

end.
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/14 10:47:02
15楼: 根据调试信息判定,其它地方没有执行。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/16 19:41:51
16楼: 看来,这问题真的很难。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 bestfw (bestfw) ▲▲▲▲▲ -
普通会员
2023/9/17 9:38:02
17楼: 20年前,写过游戏外挂,就是xp,挂钩子
----------------------------------------------
-
作者:
男 lr46752881 (Anuo) ★☆☆☆☆ -
普通会员
2023/9/17 15:13:09
18楼: 参考这个 discord 他可以在lol显示
----------------------------------------------
123
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/19 7:07:24
19楼: 今天用百度,必应搜索,很多人都需要这个功能呢,有能力的弄出来啊,有钱赚啊。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/19 7:14:31
20楼: 最好不要用HOOK,以适应以后操作系统。请能人弄弄,我想思路就是按ctrl+shift那种方法(是输入法选择菜单,也是应该是窗口吧,它就能在任何屏屏幕显示出来)。酬金可以商量。
此帖子包含附件:
PNG 图像
大小:1.55M
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/19 7:16:32
21楼: 详细就是做一个DLL,通过以给定文字参数、显示位置参数调用DLL接口,直接显示给定文字小窗口。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 qq81709989 (战石电子) ▲▲△△△ -
普通会员
2023/9/21 14:11:25
22楼: 没有安装英雄联盟测试,请在DrawText 函数中将  D3DDevice.EndScene 函数调用移动到 D3DFont.DrawTextW 函数之前试试,或者没有正确设置文字矩形区域,绘制的文字绘制在小窗口外面了,请详细测试排查一下。
您好,这是Bing。我根据您的要求,尝试了一下用Delphi写一个示例代码,让窗口form表单能总是显示在全屏游戏画面的最上层。我参考了一些网上的资料,发现有以下几个步骤:

- 首先,您需要获取全屏游戏的窗口句柄,可以使用 FindWindow 或者 EnumWindows 函数来实现。您可以参考 [Delphi如何获取当前运行的全屏游戏的窗口句柄](^1^) 这篇博客中的示例代码,了解如何使用这些函数。
- 其次,您需要设置您的窗口form表单为无边框模式,并且调整其大小和位置,使其与全屏游戏的窗口相同。您可以使用 SetWindowLong 和 SetWindowPos 函数来实现。您可以参考 [Delphi7 实现窗体全屏方法](^2^) 这篇博客中的示例代码,了解如何使用这些函数。
- 最后,您需要设置您的窗口form表单为置顶模式,并且在全屏游戏切换或者最小化时,能够自动隐藏或者显示。您可以使用 SetWindowPos 和 RegisterHotKey 函数来实现。您可以参考 [解析Delphi 窗口置顶,及非主窗口置顶](^3^) 这篇博客中的示例代码,了解如何使用这些函数。

综合以上步骤,我写了一个简单的示例代码,如下:

```delphi
// 定义全局变量
var
  hGame: HWND; // 全屏游戏的窗口句柄
  rGame: TRect; // 全屏游戏的窗口矩形区域
  isShow: Boolean; // 窗口form表单是否显示的标志

// 获取全屏游戏的窗口句柄和矩形区域
procedure GetGameWindow;
begin
  // 这里假设全屏游戏的类名为 GameClass,标题为 GameTitle
  // 您可以根据实际情况修改或者使用其他方法获取
  hGame := FindWindow('GameClass', 'GameTitle');
  if hGame <> 0 then
  begin
    GetWindowRect(hGame, rGame);
  end;
end;

// 设置窗口form表单为无边框模式,并且调整其大小和位置
procedure SetFormWindow;
begin
  // 设置窗口form表单为无边框模式
  SetWindowLong(Form1.Handle, GWL_STYLE, WS_POPUP);
  // 调整窗口form表单的大小和位置,使其与全屏游戏的窗口相同
  SetWindowPos(Form1.Handle, HWND_TOPMOST, rGame.Left, rGame.Top, rGame.Right - rGame.Left, rGame.Bottom - rGame.Top, SWP_SHOWWINDOW);
end;

// 设置窗口form表单为置顶模式,并且在全屏游戏切换或者最小化时,能够自动隐藏或者显示
procedure SetFormTop;
begin
  // 设置窗口form表单为置顶模式
  SetWindowPos(Form1.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW);
  // 注册一个热键 F12,用于控制窗口form表单的显示或者隐藏
  RegisterHotKey(Form1.Handle, 100, MOD_NOREPEAT, VK_F12);
end;

// 处理热键消息和全屏游戏状态变化消息
procedure TForm1.WndProc(var Message: TMessage);
begin
  inherited WndProc(Message);
  case Message.Msg of
    WM_HOTKEY: // 热键消息
      begin
        if Message.WParam = 100 then // 如果按下 F12 键
        begin
          isShow := not isShow; // 切换窗口form表单的显示标志
          if isShow then // 如果显示
          begin
          ShowWindow(Form1.Handle, SW_SHOW); // 显示窗口form表单
          SetWindowPos(Form1.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_SHOWWINDOW); // 设置窗口form表单为置顶模式
          end
          else // 如果隐藏
          begin
          ShowWindow(Form1.Handle, SW_HIDE); // 隐藏窗口form表单
          end;
        end;
      end;
    WM_ACTIVATEAPP: // 应用程序激活或者失去激活消息
      begin
        if Message.WParam = 0 then // 如果应用程序失去激活,即全屏游戏切换或者最小化
        begin
          isShow := False; // 设置窗口form表单的显示标志为 False
          ShowWindow(Form1.Handle, SW_HIDE); // 隐藏窗口form表单
        end;
      end;
  end;
end;

// 窗口form表单的创建事件
procedure TForm1.FormCreate(Sender: TObject);
begin
  GetGameWindow; // 获取全屏游戏的窗口句柄和矩形区域
  SetFormWindow; // 设置窗口form表单为无边框模式,并且调整其大小和位置
  SetFormTop; // 设置窗口form表单为置顶模式,并且在全屏游戏切换或者最小化时,能够自动隐藏或者显示
  isShow := True; // 设置窗口form表单的显示标志为 True
end;
```
----------------------------------------------
《Z-Gantt战石智慧时间管理进度计划甘特图软件》:WWW.Z-SHi.NET
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/21 14:49:24
23楼: @qq81709989,这些方法我都试过,游戏会被最小化。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 qq81709989 (战石电子) ▲▲△△△ -
普通会员
2023/9/21 20:35:28
24楼: 建议楼主下载一款开源输入法代码看看输入法软件是如何实现的
----------------------------------------------
《Z-Gantt战石智慧时间管理进度计划甘特图软件》:WWW.Z-SHi.NET
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/22 7:10:34
25楼: 输入法早测试节,也只是可以加入菜单项,其它如菜单怎么实现的,没有这方面的细节。响应ctrl+shift是那个进程或DLL?可以研究下。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 yam (yam) ★☆☆☆☆ -
盒子活跃会员
2023/9/24 8:34:24
26楼: https://github.com/Sh0ckFR/Universal-ImGui-D3D11-Hook
这个似乎可以,老兄研究好了分享出来呀
----------------------------------------------
-
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/24 12:46:59
27楼: 感觉很难,查到资料:
SetCooperativeLevel(GetActiveWindow(),DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN) != DD_OK)

请求独占级别,该标志必须和DDSCL_FULLSCREEN 一起使用。

表示需要全屏模式。其他程序中的GDI将不允许在屏幕上画图。这个标志必须和DDSCL_EXCLUSIVE 一起使用。

是不是全屏游戏都进行了这样设置。
----------------------------------------------
永远是DELPHI初学者。
作者:
男 jingzu (123456) ★☆☆☆☆ -
盒子活跃会员
2023/9/24 13:04:11
28楼: 全屏模式。其他程序中的GDI将不允许在屏幕上画图,那还有什么方法在屏幕上绘画?
----------------------------------------------
永远是DELPHI初学者。
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行703.125毫秒 RSS