<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title type="html"><![CDATA[Серый форум &mdash; AHK: Хук DirectX 11 и добавление надписи]]></title>
	<link rel="self" href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=17672&amp;type=atom" />
	<updated>2023-03-12T15:00:01Z</updated>
	<generator>PunBB</generator>
	<id>http://forum.script-coding.com/viewtopic.php?id=17672</id>
		<entry>
			<title type="html"><![CDATA[AHK: Хук DirectX 11 и добавление надписи]]></title>
			<link rel="alternate" href="http://forum.script-coding.com/viewtopic.php?pid=157118#p157118" />
			<content type="html"><![CDATA[<p>Желательно запускать исходную программу в режиме suspended, после чего инжектить autohotkey.dll.<br />Потом узнавать адрес IDXGISwapChain_Present и хукать его с помощью minhook.dll.<br />inject.ahk - запускает программу в режиме suspended:<br />В TargetProgram вписываем путь к запускаемой программе.<br /></p><div class="codebox"><pre><code>TargetProgram := &quot;GFXTest.exe&quot;
AutoHotkeyDll := &quot;AutoHotkey.dll&quot;
HookFile := &quot;minhook.ahk&quot;



array := {&quot;TargetProgram&quot;: TargetProgram, &quot;AutoHotkey.dll&quot;: AutoHotkeyDll, &quot;HookFile&quot;: HookFile}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   if (key = &quot;HookFile&quot;)
      Continue
   oFile := FileOpen(value, &quot;r&quot;)
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}


#Persistent
VarSetCapacity(StartupInfo, size := 9*A_PtrSize + 32, 0)
NumPut(size, StartupInfo)
VarSetCapacity(ProcessInfo, 2*A_PtrSize + 8, 0)
DllCall(&quot;CreateProcess&quot;, &quot;ptr&quot;, 0, &quot;str&quot;, TargetProgram, &quot;ptr&quot;, 0, &quot;ptr&quot;, 0, &quot;int&quot;, 0, &quot;int&quot;, CREATE_SUSPENDED := 4, &quot;ptr&quot;, 0, &quot;ptr&quot;, 0, &quot;ptr&quot;, &amp;StartupInfo, &quot;ptr&quot;, &amp;ProcessInfo)
DllCall(&quot;CloseHandle&quot;, Ptr, hThread := NumGet(ProcessInfo))
DllCall(&quot;CloseHandle&quot;, Ptr, hProcess := NumGet(&amp;ProcessInfo + A_PtrSize))
PID := NumGet(&amp;ProcessInfo + 2*A_PtrSize, &quot;UInt&quot;)
rThread:=&quot;&quot;
rThread:=InjectAhkDll(pid, AutoHotkeyDll,, 1)
h := DllCall(&quot;OpenProcess&quot;, &quot;uint&quot;, PROCESS_ALL_ACCESS := 0x1F0FFF, &quot;int&quot;, 0, &quot;uint&quot;, PID, &quot;ptr&quot;)
DllCall(&quot;ntdll.dll\NtResumeProcess&quot;, &quot;ptr&quot;, h)
DllCall(&quot;CloseHandle&quot;, &quot;ptr&quot;, h)
FileRead,HookScript, %HookFile%
rThread.Exec(HookScript)
return



InjectAhkDll(PID,dll:=&quot;AutoHotkey64.dll&quot;,script:=0, deleteThread := false)
{
   static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
   ,hKernel32:=DllCall(&quot;LoadLibrary&quot;,&quot;Str&quot;,&quot;kernel32.dll&quot;,&quot;PTR&quot;),LoadLibraryA:=DllCall(&quot;GetProcAddress&quot;,&quot;PTR&quot;,hKernel32,&quot;AStr&quot;,&quot;LoadLibraryA&quot;,&quot;PTR&quot;)
   ,FreeLibrary:=DllCall(&quot;GetProcAddress&quot;,&quot;PTR&quot;,hKernel32,&quot;AStr&quot;,&quot;FreeLibrary&quot;,&quot;PTR&quot;)
   ,TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
   ,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:=&quot;&quot;,init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))
   base:= deleteThread ? {__Call:&quot;InjectAhkDll&quot;,__Delete:&quot;InjectAhkDll&quot;} : {__Call:&quot;InjectAhkDll&quot;}

   if IsObject(PID)
   {
      if (dll!=&quot;Exec&quot; &amp;&amp; script)
         return &quot;Only Exec method can be used here!&quot;

      hProc := DllCall(&quot;OpenProcess&quot;, &quot;UInt&quot;, PROCESS_ALL_ACCESS, &quot;Int&quot;,0, &quot;UInt&quot;, PID.PID,&quot;PTR&quot;)
      if !hProc
         return &quot;Could not open process for PID: &quot; PID.PID

      if (!script) ; Free Library in remote process (object is being deleted)
      {
         ; Terminate the thread in ahkdll
         hThread := DllCall(&quot;CreateRemoteThread&quot;, &quot;PTR&quot;, hProc, &quot;PTR&quot;, 0, &quot;PTR&quot;, 0, &quot;PTR&quot;, PID.ahkTerminate, &quot;PTR&quot;, 0, &quot;UInt&quot;, 0, &quot;PTR&quot;, 0,&quot;PTR&quot;)
         DllCall(&quot;WaitForSingleObject&quot;, &quot;PTR&quot;, hThread, &quot;UInt&quot;, 0xFFFFFFFF)
         ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hThread)

         ; Free library in remote process
         hThread := DllCall(&quot;CreateRemoteThread&quot;, &quot;PTR&quot;, hProc, &quot;UInt&quot;, 0, &quot;UInt&quot;, 0, &quot;PTR&quot;, FreeLibrary, &quot;PTR&quot;, PID.hModule, &quot;UInt&quot;, 0, &quot;UInt&quot;, 0,&quot;PTR&quot;)
         DllCall(&quot;WaitForSingleObject&quot;, &quot;PTR&quot;, hThread, &quot;UInt&quot;, 0xFFFFFFFF)
         ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hThread),DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
         return
      }

      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&amp;nScript)

      ; Reserve memory in remote process where our script will be saved
      if !pBufferRemote := DllCall(&quot;VirtualAllocEx&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, 0, &quot;PTR&quot;, nScriptLength, &quot;UInt&quot;, MEM_COMMIT, &quot;UInt&quot;, PAGE_EXECUTE_READWRITE, &quot;Ptr&quot;)
         return &quot;Could not reseve memory for process&quot;
      ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)

      ; Write script to remote process memory
      DllCall(&quot;WriteProcessMemory&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, pBufferRemote, &quot;Ptr&quot;, &amp;nScript, &quot;PTR&quot;, nScriptLength, &quot;Ptr&quot;, 0)

      ; Start execution of code
      hThread := DllCall(&quot;CreateRemoteThread&quot;, &quot;PTR&quot;, hProc, &quot;PTR&quot;, 0, &quot;PTR&quot;, 0, &quot;PTR&quot;, PID.ahkExec, &quot;PTR&quot;, pBufferRemote, &quot;UInt&quot;, 0, &quot;PTR&quot;, 0,&quot;PTR&quot;)
      if !hThread
      {
         DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nScriptLength,MEM_RELEASE)
         ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
         return &quot;Could not execute script in remote process&quot;
      }

      ; Wait for thread to finish
      DllCall(&quot;WaitForSingleObject&quot;, &quot;PTR&quot;, hThread, &quot;UInt&quot;, 0xFFFFFFFF)

      ; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
      DllCall(&quot;GetExitCodeThread&quot;, &quot;PTR&quot;, hThread, &quot;UIntP&quot;, lpExitCode)
      if !lpExitCode
         return &quot;Could not execute script in remote process&quot;

      DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hThread)
      ,DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nScriptLength,MEM_RELEASE)
      ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
      return
   }
   else if !hDll:=DllCall(&quot;LoadLibrary&quot;,&quot;Str&quot;,dll,&quot;PTR&quot;)
      return &quot;Could not find &quot; dll &quot; library&quot;, DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
   else
   {
      hProc := DllCall(&quot;OpenProcess&quot;,&quot;UInt&quot;, PROCESS_ALL_ACCESS, &quot;Int&quot;,0,&quot;UInt&quot;, DllCall(&quot;GetCurrentProcessId&quot;),&quot;PTR&quot;)
      DllCall(&quot;GetModuleFileName&quot;,&quot;PTR&quot;,hDll,&quot;PTR&quot;,&amp;ModuleName,&quot;UInt&quot;,MAX_PATH)
      DllCall(&quot;CloseHandle&quot;,&quot;PTR&quot;,hProc)
   }
   ; Open Process to PID
   hProc := DllCall(&quot;OpenProcess&quot;, &quot;UInt&quot;, PROCESS_ALL_ACCESS, &quot;Int&quot;,0, &quot;UInt&quot;, PID,&quot;PTR&quot;)
   if !hProc
      return &quot;Could not open process for PID: &quot; PID
   
   Loop, Files, %dll%, F
      dll := A_LoopFileLongPath
   ; Reserve some memory and write dll path (ANSI)
   nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
   ,StrPut(dll,&amp;nDir,&quot;CP0&quot;)

   ; Reserve memory in remote process
   if !pBufferRemote := DllCall(&quot;VirtualAllocEx&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, 0, &quot;PTR&quot;, nDirLength, &quot;UInt&quot;, MEM_COMMIT, &quot;UInt&quot;, PAGE_EXECUTE_READWRITE, &quot;Ptr&quot;)
      return &quot;Could not reseve memory for process&quot;, DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)

   ; Write dll path to remote process memory
   DllCall(&quot;WriteProcessMemory&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, pBufferRemote, &quot;Ptr&quot;, &amp;nDir, &quot;PTR&quot;, nDirLength, &quot;Ptr&quot;, 0)

   ; Start new thread loading our dll

   hThread:=DllCall(&quot;CreateRemoteThread&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,0,&quot;PTR&quot;,0,&quot;PTR&quot;,LoadLibraryA,&quot;PTR&quot;,pBufferRemote,&quot;UInt&quot;,0,&quot;PTR&quot;,0,&quot;PTR&quot;)
   if !hThread
   {
      DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nDirLength,&quot;Uint&quot;,MEM_RELEASE)
      ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
      return &quot;Could not load &quot; dll &quot; in remote process&quot;
   }
   ; Wait for thread to finish
   DllCall(&quot;WaitForSingleObject&quot;, &quot;PTR&quot;, hThread, &quot;UInt&quot;, 0xFFFFFFFF)

   ; Get Exit code returned by thread (HMODULE for our dll)
   DllCall(&quot;GetExitCodeThread&quot;, &quot;PTR&quot;, hThread, &quot;UInt*&quot;, hModule)

   ; Close Thread
   DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hThread)

   if (A_PtrSize=8)
   { ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
      hModule:=0,VarSetCapacity(me32, (A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), 0) ;W:1080:1064, A:564:548
      ;  Take a snapshot of all modules in the specified process.
      hModuleSnap := DllCall(&quot;CreateToolhelp32Snapshot&quot;,&quot;UInt&quot;, TH32CS_SNAPMODULE,&quot;UInt&quot;, PID, &quot;PTR&quot; )
      if ( hModuleSnap != INVALID_HANDLE_VALUE )
      {
         ; reset hModule and set the size of the structure before using it.
         NumPut((A_PtrSize=8?48:32)+(A_IsUnicode?1032:516), &amp;me32, 0, &quot;UInt&quot;) ;dwSize  ;W:1080:1064, A:564:548
         ;  Retrieve information about the first module,
         ;  and exit if unsuccessful
         if ( !DllCall(&quot;Module32First&quot; (A_IsUnicode?&quot;W&quot;:&quot;&quot;),&quot;PTR&quot;, hModuleSnap,&quot;PTR&quot;, &amp;me32 ) )
         {
            ; Free memory used for passing dll path to remote thread
            DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nDirLength,MEM_RELEASE)
            ,DllCall(&quot;CloseHandle&quot;,&quot;PTR&quot;, hModuleSnap ) ; Must clean up the snapshot object!
            return false
         }
         ;  Now walk the module list of the process,and display information about each module
         while(A_Index=1 || DllCall(&quot;Module32Next&quot; (A_IsUnicode?&quot;W&quot;:&quot;&quot;),&quot;PTR&quot;,hModuleSnap,&quot;PTR&quot;, &amp;me32 ) )
            if (StrGet(&amp;me32+(A_PtrSize=8?48:32)+(A_IsUnicode?512:256))=dll) ;szExePath ;W:560:544, A:304:288
            {
               hModule := NumGet(me32, A_PtrSize=8?40:28, &quot;Ptr&quot;) ;hModule
               break
            }
         DllCall(&quot;CloseHandle&quot;,&quot;PTR&quot;,hModuleSnap) ; clean up
      }
   }

   hDll:=DllCall(&quot;LoadLibrary&quot;,&quot;Str&quot;,dll,&quot;PTR&quot;)

   ; Calculate pointer to ahkdll and ahkExec functions
   ahktextdll:=hModule+DllCall(&quot;GetProcAddress&quot;,&quot;PTR&quot;,hDll,&quot;AStr&quot;,&quot;ahktextdll&quot;,&quot;PTR&quot;)-hDll
   ahkExec:=hModule+DllCall(&quot;GetProcAddress&quot;,&quot;PTR&quot;,hDll,&quot;AStr&quot;,&quot;ahkExec&quot;,&quot;PTR&quot;)-hDll
   ahkTerminate:=hModule+DllCall(&quot;GetProcAddress&quot;,&quot;PTR&quot;,hDll,&quot;AStr&quot;,&quot;ahkTerminate&quot;,&quot;PTR&quot;)-hDll

   if script
   {
      nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
      ,StrPut(script,&amp;nScript)
      ; Reserve memory in remote process where our script will be saved
      if !pBufferScript := DllCall(&quot;VirtualAllocEx&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, 0, &quot;PTR&quot;, nScriptLength, &quot;UInt&quot;, MEM_COMMIT, &quot;UInt&quot;, PAGE_EXECUTE_READWRITE, &quot;Ptr&quot;)
         return &quot;Could not reseve memory for process&quot;
      ,DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)

      ; Write script to remote process memory
      DllCall(&quot;WriteProcessMemory&quot;, &quot;Ptr&quot;, hProc, &quot;Ptr&quot;, pBufferScript, &quot;Ptr&quot;, &amp;nScript, &quot;PTR&quot;, nScriptLength, &quot;Ptr&quot;, 0)
   }
   else
      pBufferScript:=0

   ; Run ahkdll function in remote thread
   hThread := DllCall(&quot;CreateRemoteThread&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,0,&quot;PTR&quot;,0,&quot;PTR&quot;,ahktextdll,&quot;PTR&quot;,pBufferScript,&quot;PTR&quot;,0,&quot;UInt&quot;,0,&quot;PTR&quot;)
   if !hThread
   { ; could not start ahkdll in remote process
      ; Free memory used for passing dll path to remote thread
      DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nDirLength,MEM_RELEASE)
      DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)
      return &quot;Could not start ahkdll in remote process&quot;
   }
   DllCall(&quot;WaitForSingleObject&quot;, &quot;PTR&quot;, hThread, &quot;UInt&quot;, 0xFFFFFFFF)
   DllCall(&quot;GetExitCodeThread&quot;, &quot;PTR&quot;, hThread, &quot;UIntP&quot;, lpExitCode)

   ; Release memory and handles
   DllCall(&quot;VirtualFreeEx&quot;,&quot;PTR&quot;,hProc,&quot;PTR&quot;,pBufferRemote,&quot;PTR&quot;,nDirLength,MEM_RELEASE)
   DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hThread)
   DllCall(&quot;CloseHandle&quot;, &quot;PTR&quot;, hProc)

   if !lpExitCode ; thread could not be created.
      return &quot;Could not create a thread in remote process&quot;

   return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}</code></pre></div><p>minhook.ahk<br />В TargetWinTitle вписываем название окна запускаемой программы.<br /></p><div class="codebox"><pre><code>TargetWinTitle := &quot;ahk_class gfx_test&quot;
MinhookDll := &quot;MinHook.dll&quot;
Global FW1FontWrapperDll := &quot;FW1FontWrapper.dll&quot;
Global IDXGISwapChain_Present_Original, IDXGISwapChain_ResizeBuffers_Original, ResolutionChanged, widthChanged, heightChanged



array := {&quot;MinHook.dll&quot;: MinhookDll, &quot;FW1FontWrapper.dll&quot;: FW1FontWrapperDll}
For key, value in array
{
   if !FileExist(value)
   {
      msgbox %value% does not exist
      ExitApp
   }
   oFile := FileOpen(value, &quot;r&quot;)
   oFile.Seek(0x3c)
   oFile.Seek(oFile.ReadInt()+4)
   machineType := oFile.ReadUShort()
   oFile.Close()
   if (machineType = 0x14c) and (A_PtrSize = 8)
   {
      msgbox %key% 32 bit, but AutoHotkey.exe 64 bit
      ExitApp
   }
   if ((machineType = 0x8664) or (machineType = 0x200)) and (A_PtrSize = 4)
   {
      msgbox %key% 64 bit, but AutoHotkey.exe 32 bit
      ExitApp
   }
}

WinWait, % TargetWinTitle
hwnd := WinExist(TargetWinTitle)
SetWorkingDir %A_ScriptDir%
LoadDll()

VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
NumPut(60, SwapChainDesc, 8, &quot;uint&quot;)   ; DXGI_MODE_DESC DXGI_RATIONAL Numerator
NumPut(1, SwapChainDesc, 12, &quot;uint&quot;)   ; DXGI_MODE_DESC DXGI_RATIONAL Denominator
NumPut(DXGI_FORMAT_R8G8B8A8_UNORM := 28, SwapChainDesc, 16, &quot;uint&quot;)   ; DXGI_MODE_DESC Format
NumPut(1, SwapChainDesc, 28, &quot;uint&quot;)   ; DXGI_SAMPLE_DESC count
NumPut(DXGI_USAGE_RENDER_TARGET_OUTPUT := 32, SwapChainDesc, 36, &quot;uint&quot;)   ; BufferUsage
NumPut(1, SwapChainDesc, 40, &quot;uint&quot;)   ; BufferCount
NumPut(hwnd, SwapChainDesc, 40+A_PtrSize, &quot;ptr&quot;)   ; OutputWindow
NumPut(1, SwapChainDesc, 40+2*A_PtrSize, &quot;int&quot;)   ; Windowed
NumPut(DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH := 2, SwapChainDesc, 48+2*A_PtrSize, &quot;uint&quot;)   ; Flags

VarSetCapacity(D3D_FEATURE_LEVEL, 4, 0)
NumPut(D3D_FEATURE_LEVEL_11_0 := 0xb000, D3D_FEATURE_LEVEL, 0, &quot;uint&quot;)
D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE := 1, 0, 0, &amp;D3D_FEATURE_LEVEL, 1, D3D11_SDK_VERSION := 7, &amp;SwapChainDesc, IDXGI_SwapChain, ID3D11Device, 0, ID3D11DeviceContext)
IDXGISwapChain_Present := IDXGISwapChain_Present_Get(IDXGI_SwapChain)
IDXGISwapChain_ResizeBuffers := IDXGISwapChain_ResizeBuffers_Get(IDXGI_SwapChain)
Release(IDXGI_SwapChain)
Release(ID3D11DeviceContext)
Release(ID3D11Device)
IDXGI_SwapChain := ID3D11DeviceContext := ID3D11Device := &quot;&quot;

MinHook_Init(MinhookDll)
MH_CreateHook(IDXGISwapChain_Present, RegisterCallback(&quot;IDXGISwapChain_Present_Hook&quot;, &quot;F&quot;), IDXGISwapChain_Present_Original)
MH_CreateHook(IDXGISwapChain_ResizeBuffers, RegisterCallback(&quot;IDXGISwapChain_ResizeBuffers_Hook&quot;, &quot;F&quot;), IDXGISwapChain_ResizeBuffers_Original)
MH_EnableHook()
return


IDXGISwapChain_Present_Hook(SwapChain, SyncInterval, Flags)
{
   Critical
   static Init, iFontWrapper, ImmediateContext, ResolutionOK, width, height
   if (ResolutionChanged = 1)
      ResolutionOk := ResolutionChanged := &quot;&quot;, width := widthChanged, height := heightChanged
   if (ResolutionOK = &quot;&quot;)
   {
      if ImmediateContext
      {
         Release(ImmediateContext)
         ImmediateContext := &quot;&quot;
      }
      IDXGISwapChain_GetDevice(SwapChain, ID3D11Device)
      ID3D11Device_GetImmediateContext(ID3D11Device, ImmediateContext)
      if (Init = &quot;&quot;)
      {
         if (width = &quot;&quot;)
         {
            VarSetCapacity(SwapChainDesc, 48+A_PtrSize*3, 0)
            IDXGISwapChain_GetDesc(SwapChain, &amp;SwapChainDesc)
            width := NumGet(SwapChainDesc, 0, &quot;uint&quot;)
            height := NumGet(SwapChainDesc, 4, &quot;uint&quot;)
         }
         FW1CreateFactory(pFW1Factory)
         iFW1Factory := FW1Factory_Query(pFW1Factory)
         IFW1Factory_CreateFontWrapper(iFW1Factory, ID3D11Device, &quot;Arial&quot;, pFontWrapper)
         iFontWrapper := FW1FontWrapper_Query(pFontWrapper)
         ObjRelease(iFW1Factory)
         iFW1Factory := &quot;&quot;
         Init := 1
      }
      ResolutionOK := 1
   }
   IFW1FontWrapper_DrawString(iFontWrapper, ImmediateContext, &quot;Hello, World!&quot;, width*0.1, width/2, height/2, 0xFFFFFFFF, 0x1|0x4|0x800)   ; FW1_CENTER|FW1_VCENTER|FW1_RESTORESTATE
   DllCall(IDXGISwapChain_Present_Original, &quot;ptr&quot;, SwapChain, &quot;uint&quot;, SyncInterval, &quot;uint&quot;, Flags)
   return 
}

IDXGISwapChain_ResizeBuffers_Hook(SwapChain, BufferCount, SwapChainWidth, SwapChainHeight, NewFormatBuf, SwapChainFlags)
{
   widthChanged := SwapChainWidth, heightChanged := SwapChainHeight
   ResolutionChanged := 1
   DllCall(IDXGISwapChain_ResizeBuffers_Original, &quot;ptr&quot;, SwapChain, &quot;uint&quot;, BufferCount, &quot;uint&quot;, SwapChainWidth, &quot;uint&quot;, SwapChainHeight, &quot;uint&quot;, NewFormatBuf, &quot;uint&quot;, SwapChainFlags)
   return 
}



LoadDll()
{
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;DXGI&quot;, &quot;ptr&quot;)
   {
      MsgBox, 16, Error, DXGI failed.
      ExitApp
   }
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;D3D11&quot;, &quot;ptr&quot;)
   {
      MsgBox, 16, Error, D3D11 failed.
      ExitApp
   }
   if !DllCall(&quot;GetModuleHandle&quot;,&quot;str&quot;,&quot;FW1FontWrapper&quot;)
      DllCall(&quot;LoadLibrary&quot;,&quot;Str&quot;, FW1FontWrapperDll, &quot;ptr&quot;)
   return
}


FW1CreateFactory(ByRef ppFactory)
{
   hr := DllCall(FW1FontWrapperDll &quot;\FW1CreateFactory&quot;, &quot;uint&quot;, FW1_VERSION := 0x110f, &quot;ptr*&quot;, ppFactory)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

FW1Factory_Query(pFactory)
{ 
   hr := ComObjQuery(pFactory, &quot;{8004DB2B-B5F9-4420-A6A2-E17E15E4C336}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

IFW1Factory_CreateFontWrapper(this, pDevice, pszFontFamily, ByRef ppFontWrapper)
{
   hr := DllCall(NumGet(NumGet(this+0)+5*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDevice, &quot;str&quot;, pszFontFamily, &quot;ptr*&quot;, ppFontWrapper)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

FW1FontWrapper_Query(pFontWrapper)
{ 
   hr := ComObjQuery(pFontWrapper, &quot;{83347A5C-B0B1-460e-A35C-427E8B85F9F4}&quot;)
   if !hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
   return hr
}

IFW1FontWrapper_DrawString(this, pContext, pszString, FontSize, X, Y, Color, Flags)
{
   hr := DllCall(NumGet(NumGet(this+0)+14*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pContext, &quot;str&quot;, pszString, &quot;float&quot;, FontSize, &quot;float&quot;, X, &quot;float&quot;, Y, &quot;uint&quot;, Color, &quot;uint&quot;, Flags)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}



D3D11CreateDeviceAndSwapChain(pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion, SwapChainDesc, ByRef ppSwapChain, ByRef ppDevice, pFeatureLevel, ByRef ppImmediateContext)
{
   hr := DllCall(&quot;D3D11\D3D11CreateDeviceAndSwapChain&quot;, &quot;ptr&quot;, pAdapter, &quot;int&quot;, DriverType, &quot;ptr&quot;, Software, &quot;uint&quot;, Flags, &quot;ptr&quot;, pFeatureLevels, &quot;uint&quot;, FeatureLevels, &quot;uint&quot;, SDKVersion, &quot;ptr&quot;, SwapChainDesc, &quot;ptr*&quot;, ppSwapChain, &quot;ptr*&quot;, ppDevice, &quot;ptr&quot;, pFeatureLevel, &quot;ptr*&quot;, ppImmediateContext)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGISwapChain_GetDevice(this, ByRef ppDevice)
{
   GUID(riid, &quot;{db6f6ddb-ac77-4e88-8253-819df9bbf140}&quot;)
   hr := DllCall(NumGet(NumGet(this+0)+7*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, &amp;riid, &quot;ptr*&quot;, ppDevice)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

ID3D11Device_GetImmediateContext(this, ByRef ppImmediateContext)
{
   DllCall(NumGet(NumGet(this+0)+40*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr*&quot;, ppImmediateContext)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGISwapChain_GetDesc(this, pDesc)
{
   hr := DllCall(NumGet(NumGet(this+0)+12*A_PtrSize), &quot;ptr&quot;, this, &quot;ptr&quot;, pDesc)
   if hr or ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

IDXGISwapChain_Present_Get(this)
{
   return NumGet(NumGet(this+0)+8*A_PtrSize)
}

IDXGISwapChain_ResizeBuffers_Get(this)
{
   return NumGet(NumGet(this+0)+13*A_PtrSize)
}

Release(this)
{
   DllCall(NumGet(NumGet(this+0)+2*A_PtrSize), &quot;ptr&quot;, this)
   if ErrorLevel
      _Error(A_ThisFunc &quot; error: &quot; hr &quot;`nErrorLevel: &quot; ErrorLevel)
}

GUID(ByRef GUID, sGUID)
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall(&quot;ole32\CLSIDFromString&quot;, &quot;WStr&quot;, sGUID, &quot;Ptr&quot;, &amp;GUID) &gt;= 0 ? &amp;GUID : &quot;&quot;
}

_Error(val)
{
   msgbox % val
   ExitApp
}


MinHook_Init(MinhookDll)
{
   Static h
   If Not h
   {
      h:=DllCall(&quot;LoadLibrary&quot;,&quot;Str&quot;,MinhookDll, &quot;Ptr&quot;)
      MH_Initialize()
   }
}

; Creates a Hook for the specified target function, in disabled state.
; Parameters:
;   pTarget    [in]  A pointer to the target function, which will be
;                    overridden by the detour function.
;   pDetour    [in]  A pointer to the detour function, which will override
;                    the target function.
;   ppOriginal [out] A pointer to the trampoline function, which will be
;                    used to call the original target function.
;                    This parameter can be NULL.
MH_CreateHook(pTarget, pDetour, ByRef ppOriginal := 0) {
	return DllCall(&quot;MinHook\MH_CreateHook&quot;
	               , &quot;ptr&quot;, pTarget
	               , &quot;ptr&quot;, pDetour
	               , &quot;uptr*&quot;, ppOriginal )
}

; Initialize the MinHook library. You must call this function EXACTLY ONCE
; at the beginning of your program.
MH_Initialize() {
	return DllCall(&quot;MinHook\MH_Initialize&quot;)
}

; Uninitialize the MinHook library. You must call this function EXACTLY
; ONCE at the end of your program.
MH_Uninitialize() {
	return DllCall(&quot;MinHook\MH_Uninitialize&quot;)
}

; Removes an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
MH_RemoveHook(pTarget) {
	return DllCall(&quot;MinHook\MH_RemoveHook&quot;, &quot;ptr&quot;, pTarget)
}

/*
	#define MH_ALL_HOOKS NULL
*/

; Enables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                enabled in one go.
MH_EnableHook(pTarget := 0) {
	return DllCall(&quot;MinHook\MH_EnableHook&quot;, &quot;ptr&quot;, pTarget)
}

; Disables an already created hook.
; Parameters:
;   pTarget [in] A pointer to the target function.
;                If this parameter is MH_ALL_HOOKS, all created hooks are
;                disabled in one go.
MH_DisableHook(pTarget := 0) {
	return DllCall(&quot;MinHook\MH_DisableHook&quot;, &quot;ptr&quot;, pTarget)
}</code></pre></div><p>Так как в DirectX11 отсутствует поддержка Direct2D / Fonts, то можно использовать FW1FontWrapper библиотеку, что я и сделал.<br />dll и саму программу прикрепил в приложении.<br /><a href="http://forum.script-coding.com/viewtopic.php?id=14978">Тема для обсуждения</a></p>]]></content>
			<author>
				<name><![CDATA[Malcev]]></name>
				<uri>http://forum.script-coding.com/profile.php?id=26930</uri>
			</author>
			<updated>2023-03-12T15:00:01Z</updated>
			<id>http://forum.script-coding.com/viewtopic.php?pid=157118#p157118</id>
		</entry>
</feed>
